diff --git a/desktop/src/__tests__/pluginsSettings.test.tsx b/desktop/src/__tests__/pluginsSettings.test.tsx
index 6c174e0f..64d52c43 100644
--- a/desktop/src/__tests__/pluginsSettings.test.tsx
+++ b/desktop/src/__tests__/pluginsSettings.test.tsx
@@ -661,4 +661,52 @@ describe('Settings > Plugins tab', () => {
expect(screen.getByRole('button', { name: /codex-rescue/i })).toBeDisabled()
expect(screen.getByRole('button', { name: /gpt-5-4-prompting/i })).toBeDisabled()
})
+
+ // The store records a failed post-change runtime reload in `refreshWarning`
+ // and still resolves, so the action itself reads as a success. Without the
+ // warning surfacing, "disabled the plugin but the runtime never reloaded"
+ // looks identical to a clean success.
+ it('warns when a plugin change succeeds but the runtime reload fails', async () => {
+ usePluginStore.setState({
+ selectedPlugin: {
+ id: 'github@claude-plugins-official',
+ name: 'github',
+ marketplace: 'claude-plugins-official',
+ scope: 'user',
+ enabled: true,
+ hasErrors: false,
+ isBuiltin: false,
+ description: 'GitHub integration',
+ componentCounts: {
+ commands: 0, agents: 0, skills: 0, hooks: 0, mcpServers: 0, lspServers: 0,
+ },
+ capabilities: {
+ commands: [], agents: [], skills: [], hooks: [], mcpServers: [], lspServers: [],
+ },
+ commandEntries: [],
+ agentEntries: [],
+ hookEntries: [],
+ skillEntries: [],
+ mcpServerEntries: [],
+ errors: [],
+ },
+ disablePlugin: async () => {
+ usePluginStore.setState({ refreshWarning: 'runtime refresh failed' })
+ return 'Plugin disabled'
+ },
+ })
+
+ render()
+ switchToPluginsTab()
+
+ fireEvent.click(screen.getByRole('button', { name: 'Disable' }))
+
+ await waitFor(() => {
+ const toasts = useUIStore.getState().toasts
+ expect(
+ toasts.some(t => t.type === 'warning' && t.message.includes('runtime refresh failed')),
+ `expected a warning toast, got ${JSON.stringify(toasts)}`,
+ ).toBe(true)
+ })
+ })
})
diff --git a/desktop/src/components/plugins/PluginDetail.tsx b/desktop/src/components/plugins/PluginDetail.tsx
index 552633be..4b41fd4e 100644
--- a/desktop/src/components/plugins/PluginDetail.tsx
+++ b/desktop/src/components/plugins/PluginDetail.tsx
@@ -68,7 +68,20 @@ export function PluginDetail() {
setActionKey(key)
try {
const message = await fn()
- addToast({ type: 'success', message })
+ // The store applies the change, then reloads the runtime, and resolves
+ // either way -- a failed reload only lands in `refreshWarning`. Reporting
+ // a plain success here would make "applied but never reloaded" look
+ // identical to a clean run. Read it after the call: the store clears it
+ // when the mutation starts, so anything present belongs to this action.
+ const refreshWarning = usePluginStore.getState().refreshWarning
+ if (refreshWarning) {
+ addToast({
+ type: 'warning',
+ message: t('settings.plugins.reloadWarning', { message: refreshWarning }),
+ })
+ } else {
+ addToast({ type: 'success', message })
+ }
} catch (err) {
addToast({
type: 'error',
diff --git a/desktop/src/i18n/locales/en.ts b/desktop/src/i18n/locales/en.ts
index ea7427c0..664ce414 100644
--- a/desktop/src/i18n/locales/en.ts
+++ b/desktop/src/i18n/locales/en.ts
@@ -1098,6 +1098,7 @@ export const en = {
'settings.plugins.applyHint': 'Enable, disable, and update changes become active after applying them to the current desktop runtime.',
'settings.plugins.lastReload': 'Last apply: {enabled} active plugins, {skills} plugin skills, {errors} errors.',
'settings.plugins.reloadToast': 'Applied plugin changes: {enabled} active plugins, {skills} skills, {errors} errors.',
+ 'settings.plugins.reloadWarning': 'Plugin change applied, but reloading the runtime failed: {message}',
'settings.plugins.marketplacesTitle': 'Known marketplaces',
'settings.plugins.marketplacesHint': 'Read-only summary of marketplace sources already configured for this machine.',
'settings.plugins.marketplaceAutoUpdateOn': 'Auto-update on',
diff --git a/desktop/src/i18n/locales/jp.ts b/desktop/src/i18n/locales/jp.ts
index a570edc6..478173e0 100644
--- a/desktop/src/i18n/locales/jp.ts
+++ b/desktop/src/i18n/locales/jp.ts
@@ -1100,6 +1100,7 @@ export const jp: Record = {
'settings.plugins.applyHint': '有効化、無効化、更新の変更は、現在のデスクトップランタイムに適用した後で有効になります。',
'settings.plugins.lastReload': '前回の適用: アクティブなプラグイン {enabled} 個、プラグインスキル {skills} 個、エラー {errors} 件。',
'settings.plugins.reloadToast': 'プラグインの変更を適用しました: アクティブなプラグイン {enabled} 個、スキル {skills} 個、エラー {errors} 件。',
+ 'settings.plugins.reloadWarning': 'プラグインの変更は適用されましたが、ランタイムの再読み込みに失敗しました: {message}',
'settings.plugins.marketplacesTitle': '既知のマーケットプレイス',
'settings.plugins.marketplacesHint': 'このマシンに既に設定済みのマーケットプレイスソースの読み取り専用の概要です。',
'settings.plugins.marketplaceAutoUpdateOn': '自動更新オン',
diff --git a/desktop/src/i18n/locales/kr.ts b/desktop/src/i18n/locales/kr.ts
index 225607d9..eb51848e 100644
--- a/desktop/src/i18n/locales/kr.ts
+++ b/desktop/src/i18n/locales/kr.ts
@@ -1100,6 +1100,7 @@ export const kr: Record = {
'settings.plugins.applyHint': '사용, 사용 안 함, 업데이트 변경 사항은 현재 데스크톱 런타임에 적용한 후 적용됩니다.',
'settings.plugins.lastReload': '마지막 적용: 활성 플러그인 {enabled}개, 플러그인 스킬 {skills}개, 오류 {errors}건.',
'settings.plugins.reloadToast': '플러그인 변경 사항을 적용했습니다: 활성 플러그인 {enabled}개, 스킬 {skills}개, 오류 {errors}건.',
+ 'settings.plugins.reloadWarning': '플러그인 변경 사항은 적용되었지만 런타임 다시 불러오기에 실패했습니다: {message}',
'settings.plugins.marketplacesTitle': '알려진 마켓플레이스',
'settings.plugins.marketplacesHint': '이 컴퓨터에 이미 구성된 마켓플레이스 소스의 읽기 전용 요약입니다.',
'settings.plugins.marketplaceAutoUpdateOn': '자동 업데이트 켜짐',
diff --git a/desktop/src/i18n/locales/zh-TW.ts b/desktop/src/i18n/locales/zh-TW.ts
index 76d865bb..dd31b029 100644
--- a/desktop/src/i18n/locales/zh-TW.ts
+++ b/desktop/src/i18n/locales/zh-TW.ts
@@ -1100,6 +1100,7 @@ export const zh: Record = {
'settings.plugins.applyHint': '啟用、禁用或更新後,需要把外掛變更重新應用到當前桌面端執行時。',
'settings.plugins.lastReload': '最近一次應用:{enabled} 個活躍外掛,{skills} 個外掛技能,{errors} 個錯誤。',
'settings.plugins.reloadToast': '外掛變更已應用:{enabled} 個活躍外掛,{skills} 個技能,{errors} 個錯誤。',
+ 'settings.plugins.reloadWarning': '外掛變更已應用,但執行階段重新載入失敗:{message}',
'settings.plugins.marketplacesTitle': '已知外掛市場',
'settings.plugins.marketplacesHint': '這裡只展示當前機器已經配置好的 marketplace 來源摘要。',
'settings.plugins.marketplaceAutoUpdateOn': '自動更新開',
diff --git a/desktop/src/i18n/locales/zh.ts b/desktop/src/i18n/locales/zh.ts
index 4f910dfd..5c5fabde 100644
--- a/desktop/src/i18n/locales/zh.ts
+++ b/desktop/src/i18n/locales/zh.ts
@@ -1100,6 +1100,7 @@ export const zh: Record = {
'settings.plugins.applyHint': '启用、禁用或更新后,需要把插件变更重新应用到当前桌面端运行时。',
'settings.plugins.lastReload': '最近一次应用:{enabled} 个活跃插件,{skills} 个插件技能,{errors} 个错误。',
'settings.plugins.reloadToast': '插件变更已应用:{enabled} 个活跃插件,{skills} 个技能,{errors} 个错误。',
+ 'settings.plugins.reloadWarning': '插件变更已应用,但运行时重载失败:{message}',
'settings.plugins.marketplacesTitle': '已知插件市场',
'settings.plugins.marketplacesHint': '这里只展示当前机器已经配置好的 marketplace 来源摘要。',
'settings.plugins.marketplaceAutoUpdateOn': '自动更新开',