feat: one-click Claude CLI login from Settings - #121
Merged
Merged
Conversation
A "Log in to Claude CLI" button (Settings -> App -> Claude + the Claude widget's unavailable panel) opens a real terminal window running `claude auth login --claudeai` (dedicated login command verified against CLI 2.1.201 - opens the browser, waits for the OAuth callback, exits). The main process (apps/main/src/claudeLogin.ts) watches for fresh CLI credentials - ~/.claude/.credentials.json mtime on Windows/Linux, keychain "mdat" metadata on macOS (secret never read) - then auto-closes the terminal (Windows: taskkill /T on the Start-Process-spawned cmd PID; macOS: best-effort Terminal.app window close by id) and pushes claude:login-finished so the widget refetches /api/claude/status immediately. Windows deliberately avoids wt.exe: the alias hands off to WindowsTerminal.exe and exits, leaving no killable PID (and killing WindowsTerminal.exe would close every open tab). The PowerShell Start-Process cmd /k path guarantees a new visible window in both dev and packaged contexts and was verified live (spawn + tree-kill). New IPC: claude:open-login (invoke) + claude:login-finished (push), typed end-to-end in packages/shared. Unit tests cover the spawn-spec builder, PID/window-id/keychain parsers, and change detection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nishant
force-pushed
the
feat/claude-login-button
branch
from
July 14, 2026 06:02
e82cfd5 to
0066ecd
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A "Log in to Claude CLI" button in Settings → App → Claude (and in the Claude widget's "not available" panel) that opens a terminal running the CLI login flow and cleans up after itself — no more opening a terminal by hand when the widget needs a login.
The flow
claude auth login --claudeai.claude auth logincommand — it opens the browser, waits for the OAuth callback, prints success, and exits. No interactive/loginsession, no keystroke injection needed.--claudeaipins subscription (Max plan) billing, never Console/API keys.apps/main/src/claudeLogin.ts) watches for fresh CLI credentials every 2 s (5 min timeout):~/.claude/.credentials.jsonmtime bump (verified — that's where the CLI writes tokens on this machine).security find-generic-password -s "Claude Code-credentials"without-wand diffs themdat(modified date) attribute — metadata only, the secret never enters the process. Same service namepackages/server'sclaudeUsage.tsalready uses.claude:login-finishedis broadcast →useClaudeStatusinvalidatesclaude-status+claude-usageso the widget flips available immediately (listener lives in the hook, so popouts work too).Auto-close mechanics (and the wt decision)
Start-Process cmd -ArgumentList '/k',… -PassThru— ShellExecute guarantees a new visible console in both dev and packaged contexts (a directspawn('cmd')would attach to the parent console underpnpm dev), and-PassThrureturns the cmd PID: the killable root of the window's tree. On login,taskkill /PID <pid> /T /Fcloses the window. Verified live on this machine (spawn → PID captured → window visible → tree-killed → window gone).wt.exe: the wt alias hands off to WindowsTerminal.exe and exits — its PID can't close the window, and killing WindowsTerminal.exe would nuke every open terminal tab. On Win11 the default-terminal setting routes the spawned cmd window into Windows Terminal anyway, so you still get a WT-looking window.osascript→ Terminal.appdo script+activate; the returned "tab 1 of window id N" is parsed and that exact window is closed by id on success (best-effort). Caveat: if the keychainmdatdoesn't change on a re-login, the watcher times out after 5 min and the window just stays open showing the CLI's success output.'already-open'toast, no second terminal; user closes the window themselves → Windows liveness probe stops the watcher; timeout → watcher stops quietly, terminal left open. Already logged in → re-running the login is harmless; fresh creds still trigger auto-close.Plumbing
claude:open-login(invoke) +claude:login-finished(push) inIpcChannels/ElectronAPI,ClaudeLoginOpenResultexported from@dash/shared; preload wrappers follow the popout/clipboard patterns; handler inregisterIpcHandlers.openClaudeCliLogin()helper inuseClaude.ts(toasts results); buttons inSettingsModalandClaudeWidget.claudeLogin.test.ts): platform spawn-spec shapes, PID / Terminal-window-id / keychain-mdatparsers, credentials-change detection.Gates
pnpm test✅ (all 4 packages; main now 33 tests incl. 14 new)pnpm typecheck✅pnpm lint✅🤖 Generated with Claude Code