Development conventions and architecture guide for the Claude Code CLI repository.
Claude Code is Anthropic's CLI tool for interacting with Claude from the terminal. It supports file editing, shell commands, git workflows, code review, multi-agent coordination, IDE integration (VS Code, JetBrains), and Model Context Protocol (MCP).
Codebase: ~1,900 files, 512,000+ lines of TypeScript under src/.
| Component | Technology |
|---|---|
| Language | TypeScript (strict mode, ES modules) |
| Runtime | Bun (JSX support, bun:bundle feature flags) |
| Terminal UI | React + Ink (React for CLI) |
| CLI Parser | Commander.js (@commander-js/extra-typings) |
| API Client | @anthropic-ai/sdk |
| Validation | Zod v4 |
| Linter/Formatter | Biome |
| Analytics | GrowthBook (feature flags & A/B testing) |
| Protocol | Model Context Protocol (MCP) |
src/)| Directory | Purpose |
|---|---|
commands/ | ~50 slash commands (/commit, /review, /config, etc.) |
tools/ | ~40 agent tools (Bash, FileRead, FileWrite, Glob, Grep, etc.) |
components/ | ~140 Ink/React UI components for terminal rendering |
services/ | External integrations (API, OAuth, MCP, LSP, analytics, plugins) |
bridge/ | Bidirectional IDE communication layer |
state/ | React context + custom store (AppState) |
hooks/ | React hooks (permissions, keybindings, commands, settings) |
types/ | TypeScript type definitions |
utils/ | Utilities (shell, file ops, permissions, config, git) |
screens/ | Full-screen UIs (Doctor, REPL, Resume, Compact) |
skills/ | Bundled skills + skill loader system |
plugins/ | Plugin system (marketplace + bundled plugins) |
coordinator/ | Multi-agent coordination & supervisor logic |
tasks/ | Task management (shell tasks, agent tasks, teammates) |
context/ | React context providers (notifications, stats, FPS) |
memdir/ | Persistent memory system (CLAUDE.md, user/project memory) |
entrypoints/ | Initialization logic, Agent SDK, MCP entry |
voice/ | Voice input/output (STT, keyterms) |
vim/ | Vim mode keybinding support |
schemas/ | Zod configuration schemas |
keybindings/ | Keybinding configuration & resolver |
migrations/ | Config migrations between versions |
outputStyles/ | Output formatting & theming |
query/ | Query pipeline & processing |
server/ | Server/daemon mode |
remote/ | Remote session handling |
| File | Role |
|---|---|
src/main.tsx | CLI entry point (Commander parser, startup profiling) |
src/QueryEngine.ts | Core LLM API caller (streaming, tool-call loops) |
src/Tool.ts | Tool type definitions & buildTool factory |
src/tools.ts | Tool registry & presets |
src/commands.ts | Command registry |
src/context.ts | System/user context collection (git status, memory) |
src/cost-tracker.ts | Token cost tracking |
src/main.tsx — Commander CLI parser, startup profilingsrc/entrypoints/init.ts — Config, telemetry, OAuth, MDMsrc/entrypoints/cli.tsx — CLI session orchestrationsrc/entrypoints/mcp.ts — MCP server modesrc/entrypoints/sdk/ — Agent SDK (programmatic API)src/replLauncher.tsx — REPL session launcherStartup performs parallel initialization: MDM policy reads, Keychain prefetch, feature flag checks, then core init.
Each tool lives in src/tools/{ToolName}/ and uses buildTool:
export const MyTool = buildTool({
name: 'MyTool',
aliases: ['my_tool'],
description: 'What this tool does',
inputSchema: z.object({
param: z.string(),
}),
async call(args, context, canUseTool, parentMessage, onProgress) {
// Execute and return { data: result, newMessages?: [...] }
},
async checkPermissions(input, context) { /* Permission checks */ },
isConcurrencySafe(input) { /* Can run in parallel? */ },
isReadOnly(input) { /* Non-destructive? */ },
prompt(options) { /* System prompt injection */ },
renderToolUseMessage(input, options) { /* UI for invocation */ },
renderToolResultMessage(content, progressMessages, options) { /* UI for result */ },
})
Directory structure per tool: {ToolName}.ts or .tsx (main), UI.tsx (rendering), prompt.ts (system prompt), plus utility files.
Commands live in src/commands/ and follow three types:
const command = {
type: 'prompt',
name: 'my-command',
description: 'What this command does',
progressMessage: 'working...',
allowedTools: ['Bash(git *)', 'FileRead(*)'],
source: 'builtin',
async getPromptForCommand(args, context) {
return [{ type: 'text', text: '...' }]
},
} satisfies Command
Commands are registered in src/commands.ts and invoked via /command-name in the REPL.
Box, Text, useInput())src/components/design-system/AppState via React context + custom store (src/state/AppStateStore.ts)src/state/onChangeAppState.tsdefault (prompt per operation), plan (show plan, ask once), bypassPermissions (auto-approve), auto (ML classifier)Bash(git *), FileEdit(/src/*)checkPermissions() returning { granted: boolean, reason?, prompt? }Bun's bun:bundle feature flags enable dead-code elimination at build time:
import { feature } from 'bun:bundle'
if (feature('PROACTIVE')) { /* proactive agent tools */ }
Notable flags: PROACTIVE, KAIROS, BRIDGE_MODE, VOICE_MODE, COORDINATOR_MODE, DAEMON, WORKFLOW_SCRIPTS.
Some features are also gated via process.env.USER_TYPE === 'ant'.
| Element | Convention | Example |
|---|---|---|
| Files | PascalCase (exports) or kebab-case (commands) | BashTool.tsx, commit-push-pr.ts |
| Components | PascalCase | App.tsx, PromptInput.tsx |
| Types | PascalCase, suffix with Props/State/Context | ToolUseContext |
| Hooks | use prefix | useCanUseTool, useSettings |
| Constants | SCREAMING_SNAKE_CASE | MAX_TOKENS, DEFAULT_TIMEOUT_MS |
.js extensions (Bun convention)const getModule = () => require('./heavy.js')process.envbiome-ignore markers for manual import ordering where needed| Service | Path | Purpose |
|---|---|---|
| API | services/api/ | Anthropic SDK client, file uploads |
| MCP | services/mcp/ | MCP client, tool/resource discovery |
| OAuth | services/oauth/ | OAuth 2.0 auth flow |
| LSP | services/lsp/ | Language Server Protocol manager |
| Analytics | services/analytics/ | GrowthBook, telemetry, events |
| Plugins | services/plugins/ | Plugin loader, marketplace |
| Compact | services/compact/ | Context compression |
| Policy Limits | services/policyLimits/ | Org rate limits, quota checking |
| Remote Settings | services/remoteManagedSettings/ | Managed settings sync (Enterprise) |
| Token Estimation | services/tokenEstimation.ts | Token count estimation |
Settings locations:
~/.claude/config.json, ~/.claude/settings.json.claude/config.json, .claude/settings.jsonbun:bundle feature flags or env checks.checkPermissions().