# Claude Code slash commands: a full inventory (source investigation notes)

> Based on `claude-code/src/commands/` (about 101 files) + `src/commands.ts`.
> Registration: the `COMMANDS()` array (`commands.ts:258`) exposes about 60; `INTERNAL_ONLY_COMMANDS` (`:225`) is internal-only; `feature()` gates a batch. `loadAllCommands()` (`:449`) = bundledSkills → built-in plugin skills → directory skills → workflows → plugin commands → plugin skills → hard-coded commands.
> Types (`types/command.ts`): `local-jsx` (render terminal UI) / `local` (local function) / `prompt` (generate a prompt and send it to the model).
> Dispatch: `processUserInput` → `parseSlashCommand` → `findCommand` (exact match, `commands.ts:688`) → `getMessagesForSlashCommand` (`processSlashCommand.tsx:525`). Every command is lazy-loaded (`index.ts` stores only metadata, `load: () => import(...)`).

## 1. Master table of all built-in commands

### 1. Session management
| Command | Type | Description |
|---|---|---|
| /clear (aliases reset/new) | local | Clear conversation history and start a new session (in substance a "soft restart"; see the deep dive) |
| /compact | local | Clear history but keep a summary; can take an argument as a custom summary instruction |
| /resume (alias continue) | local-jsx | Resume a previous conversation: pop a picker or search by ID/title |
| /branch (alias fork) | local-jsx | Fork a conversation branch at the current node |
| /rewind (alias checkpoint) | local | Roll code and/or conversation back to a previous checkpoint |
| /rename | local-jsx · immediate | Rename the current conversation; with no argument, auto-generate a name |
| /export | local-jsx | Export the conversation as .txt or copy to the clipboard |
| /copy | local-jsx | Copy the last reply; `/copy N` takes the Nth from the end |
| /exit (alias quit) | local-jsx · immediate | Leave the REPL |
| /session (alias remote) | local-jsx | Show the remote-session URL and QR code |
| /btw | local-jsx · immediate | Ask a side-quest question quickly, without interrupting the main conversation |
| /plan | local-jsx | Enter plan mode or view the current plan |
| /share /summary /teleport /onboarding /backfill-sessions | internal stub | Internal-only; empty shells in the external build |

### 2. Model and configuration
| Command | Type | Description |
|---|---|---|
| /model | local-jsx | Set the main-loop model; no argument pops a picker, with an argument switches directly |
| /effort | local-jsx | Set the model's effort grade low/medium/high/max/auto |
| /fast | local-jsx | Toggle fast mode |
| /advisor | local | Set/unset the advisor model |
| /config (alias settings) | local-jsx | Open the settings panel |
| /output-style | local-jsx (deprecated) | Tells you to use /config instead |
| /statusline | prompt | Dispatch a statusline-setup sub-agent to configure the status bar |
| /theme | local-jsx | Change the terminal theme |
| /color | local-jsx · immediate | Set this session's prompt-bar color |
| /vim | local | Toggle Vim/Normal editing mode |
| /keybindings | local | Open or create the keybinding config file |
| /terminal-setup | local-jsx | Install the Shift+Enter newline keybinding |
| /voice | local (feature-gated) | Toggle voice mode |
| /brief | local-jsx · immediate (KAIROS) | Toggle ultra-brief reply mode |

### 3. Context and memory
| Command | Type | Description |
|---|---|---|
| /memory | local-jsx | Pick a memory file (the CLAUDE.md family) and open it in an editor |
| /init | prompt | Scan the codebase, generate/improve CLAUDE.md (the new version can also generate skills and hooks) |
| /context | local-jsx | A color grid visualizing current context occupancy |
| /add-dir | local-jsx | Add a new working directory |
| /insights | prompt | Analyze all sessions and generate an HTML insights report (115KB, lazy-loaded) |
| /files | local (internal) | List every file in context |

### 4. Tasks and code
| Command | Type | Description |
|---|---|---|
| /review | prompt | Review a PR (locally runs `gh pr diff` and has the model write a review) |
| /ultrareview | local-jsx | Run a 10–20 minute deep bug hunt on Claude Code on the web |
| /security-review | prompt | Security-review uncommitted changes |
| /commit | prompt (internal-only in this snapshot) | Analyze changes and create a git commit |
| /commit-push-pr | prompt (internal) | Commit, push, and open a PR in one shot |
| /pr-comments | prompt | Pull PR comments (a transitional shell already moved to a plugin) |
| /diff | local-jsx | View uncommitted changes and per-turn diffs |
| /tasks (alias bashes) | local-jsx | List and manage background tasks |
| /agents | local-jsx | Manage sub-agent config |
| /skills | local-jsx | List available skills |
| /hooks | local-jsx · immediate | View hook config |
| /mcp | local-jsx · immediate | Manage MCP servers |
| /plugin (aliases plugins/marketplace) | local-jsx · immediate | Manage plugins and the marketplace (10+ sub-UIs) |
| /reload-plugins | local | Apply pending plugin changes |
| /ultraplan | local-jsx (gated) | Draft a 10–30 minute advanced plan in the cloud |
| /ide | local-jsx | Manage IDE integration |
| /sandbox | local-jsx · immediate | Sandbox on/off and config |

### 5. Permissions and security
| Command | Type | Description |
|---|---|---|
| /permissions (alias allowed-tools) | local-jsx | Manage allow/ask/deny rules (including "retry a denied operation") |
| /privacy-settings | local-jsx | Privacy settings |
| /doctor | local-jsx | Diagnose the install and settings |
| /login | local-jsx | Log in / switch Anthropic account (OAuth2+PKCE) |
| /logout | local-jsx | Log out |

### 6. Remote and collaboration
| Command | Type | Description |
|---|---|---|
| /desktop (alias app) | local-jsx | Continue the session in Claude Desktop |
| /mobile (aliases ios/android) | local-jsx | Show a QR code to download the mobile App |
| /chrome | local-jsx | Claude in Chrome settings |
| /install-github-app | local-jsx | Configure Claude GitHub Actions (full wizard) |
| /install-slack-app | local | Install the Slack app |
| /remote-env | local-jsx | Configure a remote environment |
| /web-setup | local-jsx | Set up Claude Code on the web |
| /bridge | local-jsx (gated) | Remote Control bridge |
| /feedback (alias bug) | local-jsx | Submit product feedback |

### 7. Info and help
| Command | Type | Description |
|---|---|---|
| /help | local-jsx | Help and every command (renders the runtime command registry) |
| /status | local-jsx · immediate | Version, model, account, API connectivity |
| /cost | local | Session total cost and duration (a purely local ledger) |
| /usage | local-jsx | Plan usage limits |
| /extra-usage | local-jsx | Extra-usage config after the quota is exhausted |
| /stats | local-jsx | Usage stats and activity |
| /release-notes | local | Version changelog |
| /upgrade | local-jsx | Upgrade to the Max plan |
| /passes | local-jsx | Share a free week with a friend |
| /stickers | local | Order stickers (easter egg) |
| /think-back | local-jsx (gated) | Year in review |
| /heapdump | local (hidden) | Dump the JS heap to the desktop |

### 8. Other notes
- `createMovedToPluginCommand.ts`: a compatibility-shell factory for commands that moved to plugins (`/pr-comments`, `/security-review` use it)
- Feature-gated commands that do not exist in this snapshot: `/proactive`, `/assistant`, `/fork` (standalone edition), `/workflows`, `/subscribe-pr`, `/torch`, `/peers`, `/buddy`, etc.
- `REMOTE_SAFE_COMMANDS` (`commands.ts:619`): remote mode keeps only 17 purely local UI commands; `BRIDGE_SAFE_COMMANDS` (`:651`): phone/web can remotely trigger 6: `/compact`, `/clear`, `/cost`, `/summary`, `/release-notes`, `/files`
- In the external build, 19 `.js` command directories are dead-code empty shells (`isEnabled:()=>false`)

## 2. Deep dives of representative commands

### /clear — not just "clear the screen"
Entry `clear/clear.ts:4` → `conversation.ts:49 clearConversation()`:
1. First run SessionEnd hooks (1.5s timeout, `:68-74`)
2. Report `tengu_cache_eviction_hint` telling the server to evict the prompt cache (`:77-85`)
3. Background agent tasks and main-session tasks (Ctrl+B) survive; foreground tasks are all killed (`:93-107`, `135-166`)
4. `setMessages([])` clears messages; update `conversationId` to force a redraw (`:109-122`)
5. `clearSessionCaches()` clears session caches (keeps surviving agents' private state), resets cwd, clears file-read cache / discovered skills / nested-memory paths (`:124-132`)
6. Reset AppState: file-history snapshots, attribution, MCP clients all reset (triggering reconnect); keep `pluginReconnectKey` (`:168-191`)
7. `regenerateSessionId({setCurrentAsParent:true})` a new session ID (old ID recorded as parent for lineage analysis); surviving tasks' TaskOutput symlinks point at the new session directory (`:203-224`)
8. Re-persist mode/worktree state; run SessionStart hooks to inject messages (`:230-250`)
In one sentence: a "soft restart" without restarting the process, accounting for lineage analysis, surviving background tasks, and the hook lifecycle.

### /compact — dispatch a fork agent to write a summary
Entry `compact/compact.ts:40`:
1. Project away snipped messages; a user argument becomes a custom summary instruction (`:46-52`)
2. With no custom instruction, first try session-memory compaction (a cheaper incremental path `:57-83`)
3. Traditional path: first microcompact (in-place compact of old tool results), then `compactConversation()` (`services/compact/compact.ts:387`)
4. PreCompact hooks can inject extra summary instructions (`mergeHookInstructions`); `streamCompactSummary` (`:451`); on prompt-too-long, drop the oldest turns and retry, up to `MAX_PTL_RETRIES` (`:460-491`)
5. **Fork-agent cache-sharing path** (`:1151-1203`): `runForkedAgent` dispatches a sub-agent that runs only 1 turn (`maxTurns:1`) with no tools, carrying a system prompt / tools / message prefix identical to the main thread so it hits the prompt cache (comment: the old path had a 98% cache miss, wasting about 38B tokens a day); on failure, fall back to ordinary streaming (`:1280-1326`)
6. Summary template `BASE_COMPACT_PROMPT` (`services/compact/prompt.ts:61`): 9 fixed sections (Primary Request/Key Technical Concepts/Files and Code Sections/Errors and fixes/Problem Solving/All user messages/Pending Tasks/Current Work/Optional Next Step)
7. `buildPostCompactMessages` rebuilds the message sequence: compact boundary + summary + kept recent messages
In one sentence: it does not delete messages; it "uses a cache-friendly fork sub-agent to write the old conversation into a structured summary, then rebuilds the session with that summary as the new foundation."

### /init — an extra-long "interview script"
Entry `commands/init.ts:226` (prompt type). The command itself does not scan — it returns a prompt and lets the main model do the work:
- Old version (`:6-26`): have the model analyze the codebase and write CLAUDE.md, with a clear "should write" (build/lint/test commands, high-level architecture) and "should not write" (obvious advice, a per-file inventory)
- New version (`:28-224`): an 8-stage script — P1 AskUserQuestion about building project/personal files; P2 dispatch a sub-agent to survey the codebase; P3 interview the user to fill blinds; P4/5 write files (every line passes a "if we deleted this, would Claude make a mistake?" test); P6 create skills; P7 create hooks; P8 summarize
In one sentence: the extreme form of a prompt-type command — "the command *is* the script."

### /memory — open an editor, not a conversation
Entry `memory/memory.tsx:83`: `clearMemoryFileCaches()` warms `getMemoryFiles()`, renders `MemoryFileSelector`; after a pick, `mkdir -p`, create with the `wx` flag, `editFileInEditor()` opens it with `$VISUAL`/`$EDITOR` (`:21-58`).
Note: this snapshot **has no `#` quick-memory prefix** — `inputModes` only has `!`/ordinary etc.; the memory system = `/memory` command + memdir auto-memory + SessionMemory.

### /model — picker + two-layer persistence
`model/model.tsx`: with no argument, render `ModelPicker`; `setAppState` updates `mainLoopModel` (in-memory `:50-56`) and `updateSettingsForSource("userSettings",{effortLevel})` (`ModelPicker.tsx:234`) persists; with an argument, go through `SetModelAndClose`: `isModelAllowed` org allowlist → entitlement check → `validateModel` → persist; `/model default` restores the default.

### /permissions — rule panel + "retry a denied operation"
`permissions/permissions.tsx`: `PermissionRuleList` five tabs (recent/allow/ask/deny/workspace); rules come from layered settings and are tagged with their source; `applyPermissionUpdate` takes effect in memory + `persistPermissionUpdate` writes the file; detects shadowed rules; `onRetryDenials` wraps recently denied commands as `createPermissionRetryMessage` and stuffs them back on the queue so the model retries.

### /login — PKCE OAuth + local loopback listener
`login/login.tsx:19` → `ConsoleOAuthFlow` (`components/ConsoleOAuthFlow.tsx`):
1. `OAuthService` generates a PKCE `code_challenge`+`state`, concatenates the authorize URL (`services/oauth/client.ts:47-87`)
2. Start a temporary localhost HTTP server listening on `/callback` (`auth-code-listener.ts:10-16`); after the browser authorizes, automatically capture the code and check `state`; if there is no jump in 3 seconds, show a manual-paste box (`:157-181`)
3. After swapping for a token, `installOAuthTokens` stores it in secure storage
4. Wrap-up (`login.tsx:25-55`): `onChangeAPIKey()` rebuilds the client, `stripSignatureBlocks` peels old thinking signatures, `resetCostState()`, refresh managed settings/feature flags, re-`enrollTrustedDevice`, `authVersion+1` triggers a re-fetch of auth data
In one sentence: standard OAuth2+PKCE, dual channel (loopback automatic / manual paste) so an SSH environment with no browser can still finish.

### /resume — conversation archaeologist
`resume/resume.tsx`: with no argument, `getWorktreePaths`+`loadSameRepoMessageLogs`+`filterResumableSessions` render `LogSelector` (supports semantic search); after a pick, `checkCrossProjectResume` — same-repo worktree resumes directly; a **different project is not resumed**, instead a `claude --resume ...` command is concatenated and copied to the clipboard (`:145-164`); with an argument, first exact UUID match then search by title; what it reads is the `~/.claude/projects/<project>/<sessionId>.jsonl` transcript file.

### /cost — a purely local ledger
`cost/cost.ts:6`: subscribers see a subscription hint; API users `formatTotalCost()` (`cost-tracker.ts:228`) output total cost/duration/lines added-deleted/token usage grouped by model (including cache read/write); data all comes from in-process accumulators, no network request. Typical of a `local` command: a pure function formatting in-memory counters.

### /help — render the command table as tabs
`help/help.tsx` returns `<HelpV2 commands={commands}/>`: two tabs, General (shortcuts) + Commands, iterating the full command set after `getCommands()` filtering (built-in + skills + plugins + MCP), `formatDescriptionWithSource` tagging the source. It has no static help text; it is a mirror of the runtime command registry.

### /doctor — install-environment physical
`doctor/doctor.tsx` → `getDoctorDiagnostic()` (`utils/doctorDiagnostic.ts:514`): probe install type (npm-global/native/package-manager/development), version, multiple-install conflicts (gives a concrete uninstall command), auto-update permissions, ripgrep status, sandbox dependencies, shell aliases, context warnings. Entirely local, "a self-check script given a UI."

### /review and /ultrareview — local and cloud twins
`/review` (prompt type, `review.ts:34-47`): `LOCAL_REVIEW_PROMPT` has the model itself run `gh pr list/view/diff` and output under "overview/code quality/improvement suggestions/risks" — inject an SOP.
`/ultrareview` (local-jsx, `review/ultrareviewCommand.tsx`): `checkOverageGate` checks balance → `launchRemoteReview` creates a CCR remote session, sends the review prompt, registers a `RemoteAgentTask` that polls and pours cloud results back locally as a `task-notification`.

### /commit — the textbook prompt command (internal-only in this snapshot)
`commands/commit.ts:76`: the prompt embeds four `` !`...` `` pre-executions: `git status`, `git diff HEAD`, `git branch --show-current`, `git log --oneline -10` (`:16-19`) — executed locally before sending to the model, output substituted into the text; `allowedTools` whitelist only admits `git add/status/commit`; the prompt body is a "Git safety protocol" (do not change config, do not skip hooks, do not amend, do not commit suspected secrets) + a two-stage task (draft a message focused on *why* → HEREDOC a single message that stages+commits+signs off).

## 3. Custom-command mechanism

### Load locations (`skills/loadSkillsDir.ts:638-803`)
Four sources: the managed-policy directory, `~/.claude/`, the project directory (every `.claude/` walking cwd up to home), `--add-dir`; plus plugin commands (`loadPluginCommands.ts:414`).
Two formats: the new format `.claude/skills/<name>/SKILL.md` (directory only, `:407`); the old format `.claude/commands/*.md` (`:566` tagged `commands_DEPRECATED`).
Namespace: subdirectories become a colon prefix — `.claude/commands/frontend/lint.md` → `/frontend:lint` (`buildNamespace :523-552`); plugin commands carry a `plugin:command` prefix. Same names: first `realpath` wins (`:725-763`).

### Template capabilities (`getPromptForCommand :344-399`)
1. **Argument substitution** (`utils/argumentSubstitution.ts`): `$ARGUMENTS` all arguments; `$ARGUMENTS[0]`/`$0` the Nth; named arguments after frontmatter `arguments: ticketId priority` then `$ticketId`; with no placeholder, automatically append `\n\nARGUMENTS: <args>` (`:140-142`)
2. **Shell pre-execution** (`utils/promptShellExecution.ts:69`): two syntaxes, inline `` !`cmd` `` and block-level ` ```! `; before send, executed by BashTool (or `shell:powershell`), stdout/stderr substituted into the text; execution first goes through `hasPermissionsToUseTool`; the skill's `allowed-tools` is temporarily merged into always-allow; **safety red line**: skills loaded from MCP always skip shell pre-execution (`:371-374`) — remote content is untrusted
3. **Variable injection**: `${CLAUDE_SKILL_DIR}`, `${CLAUDE_SESSION_ID}`
4. **How it runs**: default inline expansion into the current conversation; with frontmatter `context:fork` it runs as a sub-agent (`executeForkedSlashCommand`, `processSlashCommand.tsx:62`), optionally with `agent:` to specify the type

### Full frontmatter field table (`parseSkillFrontmatterFields :185-265`)
description / allowed-tools / argument-hint / arguments / when_to_use / version / model (may inherit) / effort / disable-model-invocation (the model cannot invoke) / user-invocable (the user cannot type it) / hooks / context(fork) / agent / paths (conditional-skill glob) / shell / name

### Full lifecycle of a prompt command
User types `/my-cmd arg1` → `getMessagesForPromptSlashCommand` (`processSlashCommand.tsx:827`) → register skill hooks → `addInvokedSkill` records → generate a command-metadata message + `isMeta` expanded body → parse `@file` attachments → attach a `command_permissions` attachment → `shouldQuery:true` send to the model.

## 4. The specialness of `immediate: true`
- Definition: execute immediately without waiting for a stop point (bypass the queue)
- Why: ordinary input queues while the model is busy, but a purely local UI command (change theme, look at status) waiting feels bad
- Implementation: `REPL.tsx:3158-3184` — `shouldTreatAsImmediate = queryGuard.isActive && (command.immediate || fromKeybinding)`; a hit calls `load().call()` directly, bypassing the queue pipeline, and reports `tengu_immediate_command_executed`
- Owners: `/btw`, `/color`, `/exit`, `/hooks`, `/mcp`, `/plugin`, `/rename`, `/sandbox`, `/status`, `/brief`; `/model`, `/effort`, `/fast` are conditionally enabled (`shouldInferenceConfigCommandBeImmediate`, `utils/immediateCommand.ts:11`); **any command triggered from a keybinding is always immediate**
- Guardrail: remote-bridge (phone/web) input has a separate `isBridgeSafeCommand` (`commands.ts:672`): `local-jsx` is always refused, `prompt` is admitted, `local` needs a whitelist — to keep the phone from popping a local Ink picker (the lesson of PR #19134)
