feat(cli): add /exit slash command - #1201
Conversation
Implementation NotesTask: implement the issue #1200 Running Notes
Iteration 1 Implementation Notes (2026-06-02)Preflight
Decisions and tradeoffs
Validation outcomes
Blockers
Iteration 2 Implementation Notes (2026-06-02)Preflight
Decisions and tradeoffs
Validation outcomes
Blockers
|
…it-command # Conflicts: # packages/coding-agent/CHANGELOG.md
PR Review:
|
Assistant-model: GPT-5.5
PR Review:
|
| Context | /exit behavior |
|---|---|
| Main TUI | Graceful shutdown |
| Workflow stage chat | Sent to the sub-agent as a literal /exit prompt |
So exact /exit in a stage went from "close the overlay" (previous behavior) to "submit /exit as a prompt to the agent." A user who previously used /exit to leave a stage overlay will now silently send a confusing message to the agent and have to discover /quit instead. This is a defensible trade-off (it cleanly fixes the /exit now destructive-shutdown bug with minimal surface area), but it's worth confirming it's the intended product call, since it's a slight UX regression for that specific path and is in tension with the "consistent everywhere" criterion. A one-line note in the changelog/docs that /exit is main-chat-only would help set expectations.
🟢 Minor
- Changelog attribution: per
CLAUDE.md, issue-driven entries should link the issue, e.g.… from the main chat ([#1200](https://github.com/bastani-inc/atomic/issues/1200)).The new entry omits the link. anyin tests:interactive-mode-status.test.ts'sinstallSubmitHandlerleans onfakeThis: anyand(InteractiveMode as any).prototype….CLAUDE.mddiscouragesany; a small typed shape for the fakedthis(even a localinterface) would catch drift if the real handler starts reading new fields. Acceptable for private-method testing, just flagging.- The
text = text.trim()at the top of the submit handler means/exit(trailing space) also exits — consistent with/quit, so no action needed, just noting it's covered.
Tests
Good coverage of the matrix: built-in metadata, autocomplete dedup of a conflicting extension exit, exact-vs-args routing in main TUI, and stage-chat / attach-pane fall-through for /exit, /exit now, /exit 1 plus /quit still closing the overlay. (I couldn't execute bun test in this environment due to sandbox restrictions — relying on CI here.) Consider one extra assertion documenting that /exit reaching the agent as a prompt is the intended stage-chat contract, since that's the surprising part of the new behavior.
Overall: solid, mergeable once the spec is reconciled with the implementation and the consistency trade-off is confirmed as intended.
* feat(cli): add exit slash command * fix(workflows): keep exit scoped to main chat * docs(coding-agent): update exit command branding Assistant-model: GPT-5.5
Summary
Adds
/exitas a built-in interactive slash command that routes to the same graceful shutdown path as/quit. Also fixes a pre-existing inconsistency where/exitin workflow attached-stage chat would close the overlay — it now falls through as normal text, matching the behavior of/exit <args>in the main TUI.Changes
Core
slash-commands.ts: RegistersexitinBUILTIN_SLASH_COMMANDSso it appears in autocomplete and is reserved as a built-in name, hiding any extension command namedexit(consistent with other built-ins).interactive-mode.ts: Extends the submit-handler condition fromtext === "/quit"totext === "/quit" || text === "/exit", routing exact/exittoInteractiveMode.shutdown(). Argument-bearing forms like/exit nowfall through to normal input handling.stage-chat-view.ts: Removes/exitfrom the workflow stage-chat switch — it was previously closing the stage overlay. Now/exit(exact or with args) falls through as normal stage-chat text; only/quitcloses the overlay.Documentation
/exitto the slash command tables inREADME.mdanddocs/usage.md.[Unreleased] → Added.Tests
test/unit/slash-commands.test.ts— asserts/exitis inBUILTIN_SLASH_COMMANDSwith the correct description.packages/coding-agent/test/interactive-mode-status.test.ts— verifies exact/exitand/quitboth call graceful shutdown;/exit nowdoes not; autocomplete for/exincludes built-inexitand deduplicates conflicting extension commands.test/unit/stage-chat-view.test.ts— confirms/exit,/exit now, and/exit 1do not close the stage overlay and are instead submitted as prompts;/quitstill closes the overlay.test/unit/workflow-attach-pane.test.ts— confirms/exitand/exit nowfrom an attached stage reach the stage handle as normal prompts, not as shutdown signals.Behavior Summary
/exit/quit)/exit <args>/exit/exit <args>/quitCloses #1200