commands — Slash Command System
Slash Command System
80+ slash commands orchestrating the complete command lifecycle from registration through parsing to execution. Three command types: PromptCommand (model-invoked skills), LocalJSXCommand (React UI), LocalCommand (pure function). Extensible via skills, plugins, and MCP.
🔵 Slash Commands 🟢 Skills & Plugins 🟡 Lazy Loading 🔴 Auth-Gated
What are commands? Commands are the primary interface between the user and Claude Code's capabilities. When a user types /commit or /config, the commands module resolves the input to a registered handler, validates permissions, assembles context, and dispatches execution—either locally or through the model.
💡 Analogy: Think of commands as the speed-dial buttons on an office phone. Each button is labeled, pre-configured for a specific destination, and handles all the dialing complexity behind a single press. Some buttons connect you internally (LocalCommand), some patch you through to an operator (PromptCommand), and some light up a fancy display panel (LocalJSXCommand).
Architecture
flowchart LR User[" User Input
/command args"] subgraph Registry["Command Registry"] findCmd["findCommand()"] Validate["validateAuth()"] end subgraph Types["Command Types"] Prompt["PromptCommand
Model-invoked skill"] JSX["LocalJSXCommand
React UI render"] Local["LocalCommand
Pure function"] end subgraph Categories["Command Categories"] Git["/commit /diff /review"] Session["/session /resume /branch"] Config["/config /theme /model"] MCP["/mcp /skills /plugin"] Dev["/doctor /status /stats"] end subgraph Execution["Execution Layer"] BuildPrompt["buildPrompt()"] ModelCall["Model Invocation"] RenderJSX["Ink Render"] RunLocal["Direct Execution"] end Result[" Result Display"] User --> findCmd findCmd --> Validate Validate --> Prompt Validate --> JSX Validate --> Local Prompt --> BuildPrompt BuildPrompt --> ModelCall JSX --> RenderJSX Local --> RunLocal ModelCall --> Result RenderJSX --> Result RunLocal --> Result Categories -.-> Types
Data Flow — /commit Command
sequenceDiagram
participant U as User
participant P as Parser
participant R as Registry
participant A as Auth Gate
participant C as CommitCommand
participant B as PromptBuilder
participant M as Model (Claude)
participant T as Tool Executor
participant G as Git CLI
participant D as Display
U->>P: /commit --all "feat: add search"
P->>R: findCommand("commit")
R->>A: checkPermissions(user, "commit")
A-->>R: Authorized
R->>C: execute(args, context)
C->>B: buildPrompt(diffContext, message)
B-->>C: SystemPrompt + UserPrompt
C->>M: streamChat(prompt)
M->>T: tool_call: bash("git add -A")
T->>G: exec("git add -A && git commit -m ...")
G-->>T: commit abc1234
T-->>M: tool_result: success
M-->>C: "Committed abc1234"
C->>D: renderSuccess(commitHash)
D-->>U: Committed abc1234
🚶 Step-by-Step: /config Through the Full Lifecycle
Follow a single /config set theme dark invocation as it flows through the entire commands pipeline:
- Input Parsing — The CLI input loop detects the
/prefix and extracts the raw token"config"plus arguments["set", "theme", "dark"]. - Command Lookup —
findCommand("config")searches the command registry. The registry is lazily populated on first access; if theconfigmodule hasn't been loaded yet, its dynamicimport()fires now (~2 ms). - Type Resolution — The registry identifies
/configas aLocalJSXCommand, meaning it renders a React (Ink) component rather than invoking the model. - Auth Gate —
validateAuth()checks whether the current session has the required permissions./configis available to all users—no auth gate blocks it. - Argument Validation — The command's argument schema (sub-command
set, keytheme, valuedark) is validated against its declared options. Invalid keys produce a helpful error message. - State Read — The config command reads the current configuration from
~/.claude/settings.jsonand the project-level.claude/settings.json, merging them with precedence rules. - Mutation — The
setsub-command writestheme: "dark"into the appropriate config file. A file lock prevents concurrent writes from parallel sessions. - JSX Render — The
ConfigViewInk component receives the updated config object and renders a confirmation panel: a diff of old → new values, styled with the new theme colors. - Side Effects — A
configChangedevent is emitted on the global event bus, triggering subscribers (the theme engine, prompt builder, and telemetry collector) to reload their cached values. - Completion — Control returns to the input loop. The user sees
✅ theme → darkand the UI instantly re-renders with the dark palette. Total wall time: ~15 ms.
Key Components
| Command | Type | Category | Description |
|---|---|---|---|
/commit | PromptCommand | Git | Stages changes, generates commit message via model, runs git commit |
/diff | PromptCommand | Git | Summarizes working-tree or branch diffs with AI-generated explanations |
/review | PromptCommand | Git | Code-review of staged changes; produces inline comments and summary |
/session | LocalJSXCommand | Session | Lists, creates, and switches conversation sessions |
/resume | LocalCommand | Session | Restores a previously saved session from disk |
/branch | PromptCommand | Session | Creates a Git branch and a new session simultaneously |
/config | LocalJSXCommand | Config | Gets/sets configuration values; renders current config as table |
/theme | LocalCommand | Config | Quick toggle between light, dark, and system themes |
/model | LocalJSXCommand | Config | Switches the active Claude model (Haiku, Sonnet, Opus) |
/mcp | LocalJSXCommand | MCP | Manages MCP server connections and tool registrations |
/skills | LocalJSXCommand | MCP | Installs, lists, and removes agent skill definitions |
/plugin | LocalCommand | MCP | Loads and configures third-party plugin modules |
/doctor | LocalJSXCommand | Dev | Runs diagnostic checks on environment, auth, and connectivity |
/status | LocalCommand | Dev | Prints current session info: model, tokens used, active tools |
/stats | LocalJSXCommand | Dev | Displays usage statistics, cost breakdown, and latency percentiles |
Configuration & Feature Flags
| Setting | Scope | Default | Description |
|---|---|---|---|
commands.lazyLoad | Global | true | Defer command module imports until first invocation |
commands.authGate | Per-command | false | Require authenticated session to execute |
commands.maxHistory | Session | 100 | Number of recent commands stored for /history |
commands.timeout | Per-command | 30000 | Maximum execution time in milliseconds |
commands.skillsEnabled | Global | true | Allow skill-provided commands to register |
commands.pluginDir | Project | .claude/plugins/ | Directory scanned for plugin command modules |
commands.mcpAutoDiscover | Global | true | Auto-register commands from connected MCP servers |
commands.featureFlags.review | Global | true | Enable the experimental /review command |
Sub-Modules
mcp/
MCP integration commands — server management, tool registration, and protocol bridge.
/mcp— connect/disconnect MCP servers/skills— install & manage agent skills/plugin— third-party plugin loader
config/
Configuration and preference commands — theme, model selection, and settings management.
/config— get/set configuration values/theme— toggle UI theme/model— switch active Claude model
session/
Session lifecycle commands — create, resume, branch, and manage conversation state.
/session— list & switch sessions/resume— restore saved session/branch— new branch + session
Directory Map
Source tree for commands/
commands/
├── index.ts ← Registry entry-point, re-exports findCommand()
├── types.ts ← PromptCommand / LocalJSXCommand / LocalCommand interfaces
├── registry.ts ← Lazy command map, register() / unregister()
├── parser.ts ← Slash-prefix parser, argument tokeniser
├── validator.ts ← Argument schema validation & error messages
├── auth-gate.ts ← Per-command permission checks
│
├── commit/ ← /commit — AI-assisted git commit
│ ├── index.ts ← PromptCommand definition
│ ├── prompt.ts ← System & user prompt templates
│ └── diff-context.ts ← Staged-diff extraction helpers
├── diff/ ← /diff — AI diff summaries
│ └── index.ts
├── review/ ← /review — Code review command
│ ├── index.ts
│ └── review-prompt.ts
│
├── session/ ← /session, /resume, /branch
│ ├── index.ts ← LocalJSXCommand for session list
│ ├── resume.ts ← LocalCommand for session restore
│ └── branch.ts ← PromptCommand for branch+session
├── config/ ← /config, /theme, /model
│ ├── index.ts ← LocalJSXCommand for config UI
│ ├── theme.ts ← LocalCommand for theme toggle
│ └── model.ts ← LocalJSXCommand for model picker
│
├── mcp/ ← /mcp, /skills, /plugin
│ ├── index.ts ← MCP server management
│ ├── skills.ts ← Skill install/remove
│ └── plugin.ts ← Plugin loader
├── doctor/ ← /doctor — environment diagnostics
│ └── index.ts
├── status/ ← /status — session info
│ └── index.ts
├── stats/ ← /stats — usage statistics
│ └── index.ts
│
├── help/ ← /help — command listing & docs
│ └── index.ts
├── clear/ ← /clear — clear terminal
│ └── index.ts
├── history/ ← /history — recent command log
│ └── index.ts
└── ... (70+ more command directories)
Code Example — Registering a Command
import { registerCommand, PromptCommand } from "../registry";
const commitCommand: PromptCommand = {
name: "commit",
description: "AI-assisted git commit with generated message",
aliases: ["ci"],
category: "git",
authRequired: false,
async buildPrompt(args, context) {
const diff = await context.git.getStagedDiff();
return {
system: "You are a commit message generator...",
user: `Write a commit message for:\n\n${diff}`,
};
},
async onComplete(result, context) {
await context.git.commit(result.message);
context.display.success(`Committed ${result.hash}`);
},
};
registerCommand(commitCommand);