Brooklyn Nicholson a0ec4f52b9 feat(desktop): disconnect external (CLI-managed) providers
External providers (Claude Code) store creds outside Hermes, so the
disconnect API refuses them. The backend now hands the GUI a per-OS
`disconnect_command` that clears the credential the same way the CLI's
logout does (macOS Keychain entry + ~/.claude/.credentials.json), and
the misleading "use claude setup-token" hint is corrected.

Settings → Providers offers a Disconnect button for these: it confirms,
leaves Settings, and runs the removal command in the embedded terminal
via a new runInTerminal() (queues onto $terminalInjection; the terminal
pane flushes and clears it once its session is live). The expanded list
also gets its own "Other providers" header so it no longer reads as
grouped under "Connected". API-managed providers keep the one-click
(trash) disconnect.
2026-06-16 00:08:21 -05:00

31 lines
1.1 KiB
TypeScript

import { atom } from 'nanostores'
import { persistBoolean, storedBoolean } from '@/lib/storage'
const TAKEOVER_KEY = 'hermes.desktop.terminalTakeover'
export const $terminalTakeover = atom(storedBoolean(TAKEOVER_KEY, false))
$terminalTakeover.subscribe(active => persistBoolean(TAKEOVER_KEY, active))
export const setTerminalTakeover = (active: boolean) => $terminalTakeover.set(active)
/** A command queued to run in the embedded terminal. The terminal pane flushes
* (and clears) it once its session is live, so a value set before the pane
* mounts still runs. Cleared after flush so a later remount can't replay it. */
export const $terminalInjection = atom<null | string>(null)
/** Open the terminal pane and run a command in it. Used to disconnect external
* (CLI-managed) providers, which Hermes can't clear via the API — the user
* sees exactly what runs instead of Hermes silently deleting their creds. */
export const runInTerminal = (command: string) => {
const trimmed = command.trim()
if (!trimmed) {
return
}
setTerminalTakeover(true)
$terminalInjection.set(trimmed)
}