milady

This commit is contained in:
nirholas
2026-03-31 10:38:23 +00:00
parent 8ba939ba68
commit cf9b405372
35 changed files with 7380 additions and 793 deletions

View File

@@ -64,4 +64,12 @@ Bun strips inactive code at build time via `import { feature } from 'bun:bundle'
- **Follow the bridge**: IDE integration starts at `src/bridge/bridgeMain.ts`
- **MCP integration**: `src/services/mcp/`
## Terminal Management
- **Always use background terminals** (`isBackground: true`) for every command so a terminal ID is returned
- **Always kill the terminal** after the command completes, whether it succeeds or fails — never leave terminals open
- Do not reuse foreground shell sessions — stale sessions block future terminal operations in Codespaces
- In GitHub Codespaces, agent-spawned terminals may be hidden — they still work. Do not assume a terminal is broken if you cannot see it
- If a terminal appears unresponsive, kill it and create a new one rather than retrying in the same terminal

48
.github/workflows/publish-mcp.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: Publish to MCP Registry
on:
push:
tags: ["v*"]
jobs:
publish:
name: Publish MCP Server
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
defaults:
run:
working-directory: mcp-server
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
registry-url: "https://registry.npmjs.org"
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Publish to npm
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Install MCP Publisher CLI
run: |
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
working-directory: ${{ github.workspace }}
- name: Login to MCP Registry
run: ../mcp-publisher login github-oidc
working-directory: ${{ github.workspace }}/mcp-server
- name: Publish to MCP Registry
run: ../mcp-publisher publish
working-directory: ${{ github.workspace }}/mcp-server

72
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,72 @@
# Contributing
Thanks for your interest in contributing to this repository!
## What This Is
This repo archives the **leaked source code** of Anthropic's Claude Code CLI. Contributions here are about **documentation, tooling, and exploration aids** — not modifying the original Claude Code source.
## What You Can Contribute
- **Documentation** — Improve or expand the [docs/](docs/) directory
- **MCP Server** — Enhance the exploration MCP server in [mcp-server/](mcp-server/)
- **Analysis** — Write-ups, architecture diagrams, or annotated walkthroughs
- **Tooling** — Scripts or tools that aid in studying the source code
- **Bug fixes** — Fix issues in the MCP server or supporting infrastructure
## What Not to Change
- **`src/` directory** — This is the original leaked source, preserved as-is. Don't modify it.
- The [`backup` branch](https://github.com/nirholas/claude-code/tree/backup) contains the unmodified original.
## Getting Started
### Prerequisites
- **Node.js** 18+ (for the MCP server)
- **Git**
### Setup
```bash
git clone https://github.com/nirholas/claude-code.git
cd claude-code
```
### MCP Server Development
```bash
cd mcp-server
npm install
npm run dev # Run with tsx (no build step)
npm run build # Compile to dist/
```
### Linting & Type Checking
```bash
# From the repo root — checks the leaked src/
npm run lint # Biome lint
npm run typecheck # TypeScript type check
```
## Code Style
For any new code (MCP server, tooling, scripts):
- TypeScript with strict mode
- ES modules
- 2-space indentation (tabs for `src/` to match Biome config)
- Descriptive variable names, minimal comments
## Submitting Changes
1. Fork the repository
2. Create a feature branch (`git checkout -b my-feature`)
3. Make your changes
4. Commit with a clear message
5. Push and open a pull request
## Questions?
Open an issue or reach out to [nichxbt](https://www.x.com/nichxbt).

487
README.md
View File

@@ -1,34 +1,182 @@
> **Note:** The original unmodified leaked source is preserved in the [`backup` branch](https://github.com/nirholas/claude-code/tree/backup).
<div align="center">
# Claude Code — Leaked Source (2026-03-31)
# Claude Code — Leaked Source
> **On March 31, 2026, the full source code of Anthropic's Claude Code CLI was leaked** via a `.map` file exposed in their npm registry.
**The full source code of Anthropic's Claude Code CLI, leaked on March 31, 2026**
[![TypeScript](https://img.shields.io/badge/TypeScript-512K%2B_lines-3178C6?logo=typescript&logoColor=white)](#tech-stack)
[![Bun](https://img.shields.io/badge/Runtime-Bun-f472b6?logo=bun&logoColor=white)](#tech-stack)
[![React + Ink](https://img.shields.io/badge/UI-React_%2B_Ink-61DAFB?logo=react&logoColor=black)](#tech-stack)
[![Files](https://img.shields.io/badge/~1,900_files-source_only-grey)](#directory-structure)
[![MCP Server](https://img.shields.io/badge/MCP-Explorer_Server-blueviolet)](#-explore-with-mcp-server)
> The original unmodified leaked source is preserved in the [`backup` branch](https://github.com/nirholas/claude-code/tree/backup).
</div>
---
## Table of Contents
- [How It Leaked](#how-it-leaked)
- [What Is Claude Code?](#what-is-claude-code)
- [Documentation](#-documentation)
- [Explore with MCP Server](#-explore-with-mcp-server)
- [Directory Structure](#directory-structure)
- [Architecture](#architecture)
- [Tool System](#1-tool-system)
- [Command System](#2-command-system)
- [Service Layer](#3-service-layer)
- [Bridge System](#4-bridge-system)
- [Permission System](#5-permission-system)
- [Feature Flags](#6-feature-flags)
- [Key Files](#key-files)
- [Tech Stack](#tech-stack)
- [Design Patterns](#design-patterns)
- [GitPretty Setup](#gitpretty-setup)
- [Contributing](#contributing)
- [Disclaimer](#disclaimer)
---
## How It Leaked
[Chaofan Shou (@Fried_rice)](https://x.com/Fried_rice) discovered the leak and posted it publicly:
[Chaofan Shou (@Fried_rice)](https://x.com/Fried_rice) discovered that the published npm package for Claude Code included a `.map` file referencing the full, unobfuscated TypeScript source — downloadable as a zip from Anthropic's R2 storage bucket.
> **"Claude code source code has been leaked via a map file in their npm registry!"**
>
> — [@Fried_rice, March 31, 2026](https://x.com/Fried_rice/status/2038894956459290963)
The source map file in the published npm package contained a reference to the full, unobfuscated TypeScript source, which was downloadable as a zip archive from Anthropic's R2 storage bucket.
---
## What Is Claude Code?
Claude Code is Anthropic's official CLI tool for interacting with Claude directly from the terminal — editing files, running commands, searching codebases, managing git workflows, and more. This repository contains the leaked `src/` directory.
| | |
|---|---|
| **Leaked** | 2026-03-31 |
| **Language** | TypeScript (strict) |
| **Runtime** | [Bun](https://bun.sh) |
| **Terminal UI** | [React](https://react.dev) + [Ink](https://github.com/vadimdemedes/ink) |
| **Scale** | ~1,900 files · 512,000+ lines of code |
---
## Overview
## <EFBFBD> Documentation
Claude Code is Anthropic's official CLI tool that lets you interact with Claude directly from the terminal to perform software engineering tasks — editing files, running commands, searching codebases, managing git workflows, and more.
For in-depth guides, see the [`docs/`](docs/) directory:
This repository contains the leaked `src/` directory.
| Guide | Description |
|-------|-------------|
| **[Architecture](docs/architecture.md)** | Core pipeline, startup sequence, state management, rendering, data flow |
| **[Tools Reference](docs/tools.md)** | Complete catalog of all ~40 agent tools with categories and permission model |
| **[Commands Reference](docs/commands.md)** | All ~85 slash commands organized by category |
| **[Subsystems Guide](docs/subsystems.md)** | Deep dives into Bridge, MCP, Permissions, Plugins, Skills, Tasks, Memory, Voice |
| **[Exploration Guide](docs/exploration-guide.md)** | How to navigate the codebase — study paths, grep patterns, key files |
- **Leaked on**: 2026-03-31
- **Language**: TypeScript
- **Runtime**: Bun
- **Terminal UI**: React + [Ink](https://github.com/vadimdemedes/ink) (React for CLI)
- **Scale**: ~1,900 files, 512,000+ lines of code
Also see: [CONTRIBUTING.md](CONTRIBUTING.md) · [MCP Server README](mcp-server/README.md)
---
## <20>🔍 Explore with MCP Server
This repo ships an [MCP server](https://modelcontextprotocol.io/) that lets any MCP-compatible client (Claude Code, Claude Desktop, VS Code Copilot, Cursor) explore the full source interactively.
### One-liner setup
```bash
git clone https://github.com/nirholas/claude-code.git ~/claude-code \
&& cd ~/claude-code/mcp-server \
&& npm install && npm run build \
&& claude mcp add claude-code-explorer -- node ~/claude-code/mcp-server/dist/index.js
```
<details>
<summary><strong>Step-by-step setup</strong></summary>
```bash
# 1. Clone the repo
git clone https://github.com/nirholas/claude-code.git
cd claude-code/mcp-server
# 2. Install & build
npm install && npm run build
# 3. Register with Claude Code
claude mcp add claude-code-explorer -- node /absolute/path/to/claude-code/mcp-server/dist/index.js
```
Replace `/absolute/path/to/claude-code` with your actual clone path.
</details>
<details>
<summary><strong>VS Code / Cursor / Claude Desktop config</strong></summary>
**VS Code** — add to `.vscode/mcp.json`:
```json
{
"servers": {
"claude-code-explorer": {
"type": "stdio",
"command": "node",
"args": ["${workspaceFolder}/mcp-server/dist/index.js"],
"env": { "CLAUDE_CODE_SRC_ROOT": "${workspaceFolder}/src" }
}
}
}
```
**Claude Desktop** — add to your config file:
```json
{
"mcpServers": {
"claude-code-explorer": {
"command": "node",
"args": ["/absolute/path/to/claude-code/mcp-server/dist/index.js"],
"env": { "CLAUDE_CODE_SRC_ROOT": "/absolute/path/to/claude-code/src" }
}
}
}
```
**Cursor** — add to `~/.cursor/mcp.json` (same format as Claude Desktop).
</details>
### Available tools & prompts
| Tool | Description |
|------|-------------|
| `list_tools` | List all ~40 agent tools with source files |
| `list_commands` | List all ~50 slash commands with source files |
| `get_tool_source` | Read full source of any tool (e.g. BashTool, FileEditTool) |
| `get_command_source` | Read source of any slash command (e.g. review, mcp) |
| `read_source_file` | Read any file from `src/` by path |
| `search_source` | Grep across the entire source tree |
| `list_directory` | Browse `src/` directories |
| `get_architecture` | High-level architecture overview |
| Prompt | Description |
|--------|-------------|
| `explain_tool` | Deep-dive into how a specific tool works |
| `explain_command` | Understand a slash command's implementation |
| `architecture_overview` | Guided tour of the full architecture |
| `how_does_it_work` | Explain any subsystem (permissions, MCP, bridge, etc.) |
| `compare_tools` | Side-by-side comparison of two tools |
**Try asking:** *"How does the BashTool work?"* · *"Search for where permissions are checked"* · *"Show me the /review command source"*
### Custom source path / Remove
```bash
# Custom source location
claude mcp add claude-code-explorer -e CLAUDE_CODE_SRC_ROOT=/path/to/src -- node /path/to/mcp-server/dist/index.js
# Remove
claude mcp remove claude-code-explorer
```
---
@@ -36,173 +184,158 @@ This repository contains the leaked `src/` directory.
```
src/
├── main.tsx # Entrypoint (Commander.js-based CLI parser)
├── commands.ts # Command registry
├── main.tsx # Entrypoint Commander.js CLI parser + React/Ink renderer
├── QueryEngine.ts # Core LLM API caller (~46K lines)
├── Tool.ts # Tool type definitions (~29K lines)
├── commands.ts # Command registry (~25K lines)
├── tools.ts # Tool registry
├── Tool.ts # Tool type definitions
├── QueryEngine.ts # LLM query engine (core Anthropic API caller)
├── context.ts # System/user context collection
├── cost-tracker.ts # Token cost tracking
├── commands/ # Slash command implementations (~50)
├── tools/ # Agent tool implementations (~40)
├── commands/ # Slash command implementations (~50)
├── components/ # Ink UI components (~140)
├── hooks/ # React hooks
├── services/ # External service integrations
├── screens/ # Full-screen UIs (Doctor, REPL, Resume)
├── hooks/ # React hooks (incl. permission checks)
├── types/ # TypeScript type definitions
├── utils/ # Utility functions
├── screens/ # Full-screen UIs (Doctor, REPL, Resume)
├── bridge/ # IDE integration bridge (VS Code, JetBrains)
├── coordinator/ # Multi-agent coordinator
├── bridge/ # IDE integration (VS Code, JetBrains)
├── coordinator/ # Multi-agent orchestration
├── plugins/ # Plugin system
├── skills/ # Skill system
├── keybindings/ # Keybinding configuration
├── vim/ # Vim mode
├── voice/ # Voice input
├── remote/ # Remote sessions
├── server/ # Server mode
├── memdir/ # Memory directory (persistent memory)
├── remote/ # Remote sessions
├── memdir/ # Persistent memory directory
├── tasks/ # Task management
├── state/ # State management
├── migrations/ # Config migrations
├── voice/ # Voice input
├── vim/ # Vim mode
├── keybindings/ # Keybinding configuration
├── schemas/ # Config schemas (Zod)
├── migrations/ # Config migrations
├── entrypoints/ # Initialization logic
├── query/ # Query pipeline
├── ink/ # Ink renderer wrapper
├── buddy/ # Companion sprite (Easter egg)
├── buddy/ # Companion sprite (Easter egg 🐣)
├── native-ts/ # Native TypeScript utils
├── outputStyles/ # Output styling
├── query/ # Query pipeline
└── upstreamproxy/ # Proxy configuration
```
---
## Core Architecture
## Architecture
### 1. Tool System (`src/tools/`)
### 1. Tool System
Every tool Claude Code can invoke is implemented as a self-contained module. Each tool defines its input schema, permission model, and execution logic.
> `src/tools/` — Every tool Claude can invoke is a self-contained module with its own input schema, permission model, and execution logic.
| Tool | Description |
|---|---|
| `BashTool` | Shell command execution |
| `FileReadTool` | File reading (images, PDFs, notebooks) |
| `FileWriteTool` | File creation / overwrite |
| `FileEditTool` | Partial file modification (string replacement) |
| `GlobTool` | File pattern matching search |
| **File I/O** | |
| `FileReadTool` | Read files (images, PDFs, notebooks) |
| `FileWriteTool` | Create / overwrite files |
| `FileEditTool` | Partial modification (string replacement) |
| `NotebookEditTool` | Jupyter notebook editing |
| **Search** | |
| `GlobTool` | File pattern matching |
| `GrepTool` | ripgrep-based content search |
| `WebFetchTool` | Fetch URL content |
| `WebSearchTool` | Web search |
| `AgentTool` | Sub-agent spawning |
| `WebFetchTool` | Fetch URL content |
| **Execution** | |
| `BashTool` | Shell command execution |
| `SkillTool` | Skill execution |
| `MCPTool` | MCP server tool invocation |
| `LSPTool` | Language Server Protocol integration |
| `NotebookEditTool` | Jupyter notebook editing |
| `TaskCreateTool` / `TaskUpdateTool` | Task creation and management |
| **Agents & Teams** | |
| `AgentTool` | Sub-agent spawning |
| `SendMessageTool` | Inter-agent messaging |
| `TeamCreateTool` / `TeamDeleteTool` | Team agent management |
| `TeamCreateTool` / `TeamDeleteTool` | Team management |
| `TaskCreateTool` / `TaskUpdateTool` | Task management |
| **Mode & State** | |
| `EnterPlanModeTool` / `ExitPlanModeTool` | Plan mode toggle |
| `EnterWorktreeTool` / `ExitWorktreeTool` | Git worktree isolation |
| `ToolSearchTool` | Deferred tool discovery |
| `CronCreateTool` | Scheduled trigger creation |
| `RemoteTriggerTool` | Remote trigger |
| `SleepTool` | Proactive mode wait |
| `CronCreateTool` | Scheduled triggers |
| `RemoteTriggerTool` | Remote trigger |
| `SyntheticOutputTool` | Structured output generation |
### 2. Command System (`src/commands/`)
### 2. Command System
User-facing slash commands invoked with `/` prefix.
> `src/commands/` — User-facing slash commands invoked with `/` in the REPL.
| Command | Description |
|---|---|
| `/commit` | Create a git commit |
| `/review` | Code review |
| `/compact` | Context compression |
| `/mcp` | MCP server management |
| `/config` | Settings management |
| `/doctor` | Environment diagnostics |
| `/login` / `/logout` | Authentication |
| `/memory` | Persistent memory management |
| `/skills` | Skill management |
| `/tasks` | Task management |
| `/vim` | Vim mode toggle |
| `/diff` | View changes |
| `/cost` | Check usage cost |
| `/theme` | Change theme |
| `/context` | Context visualization |
| `/pr_comments` | View PR comments |
| `/resume` | Restore previous session |
| `/share` | Share session |
| `/desktop` | Desktop app handoff |
| `/mobile` | Mobile app handoff |
| Command | Description | | Command | Description |
|---|---|---|---|---|
| `/commit` | Git commit | | `/memory` | Persistent memory |
| `/review` | Code review | | `/skills` | Skill management |
| `/compact` | Context compression | | `/tasks` | Task management |
| `/mcp` | MCP server management | | `/vim` | Vim mode toggle |
| `/config` | Settings | | `/diff` | View changes |
| `/doctor` | Environment diagnostics | | `/cost` | Check usage cost |
| `/login` / `/logout` | Auth | | `/theme` | Change theme |
| `/context` | Context visualization | | `/share` | Share session |
| `/pr_comments` | PR comments | | `/resume` | Restore session |
| `/desktop` | Desktop handoff | | `/mobile` | Mobile handoff |
### 3. Service Layer (`src/services/`)
### 3. Service Layer
> `src/services/` — External integrations and core infrastructure.
| Service | Description |
|---|---|
| `api/` | Anthropic API client, file API, bootstrap |
| `mcp/` | Model Context Protocol server connection and management |
| `oauth/` | OAuth 2.0 authentication flow |
| `mcp/` | Model Context Protocol connection & management |
| `oauth/` | OAuth 2.0 authentication |
| `lsp/` | Language Server Protocol manager |
| `analytics/` | GrowthBook-based feature flags and analytics |
| `analytics/` | GrowthBook feature flags & analytics |
| `plugins/` | Plugin loader |
| `compact/` | Conversation context compression |
| `extractMemories/` | Automatic memory extraction |
| `teamMemorySync/` | Team memory synchronization |
| `tokenEstimation.ts` | Token count estimation |
| `policyLimits/` | Organization policy limits |
| `remoteManagedSettings/` | Remote managed settings |
| `extractMemories/` | Automatic memory extraction |
| `tokenEstimation.ts` | Token count estimation |
| `teamMemorySync/` | Team memory synchronization |
### 4. Bridge System (`src/bridge/`)
### 4. Bridge System
A bidirectional communication layer connecting IDE extensions (VS Code, JetBrains) with the Claude Code CLI.
> `src/bridge/` — Bidirectional communication layer connecting IDE extensions (VS Code, JetBrains) with the CLI.
- `bridgeMain.ts` — Bridge main loop
- `bridgeMessaging.ts` — Message protocol
- `bridgePermissionCallbacks.ts` — Permission callbacks
- `replBridge.ts` — REPL session bridge
- `jwtUtils.ts` — JWT-based authentication
- `sessionRunner.ts` — Session execution management
Key files: `bridgeMain.ts` (main loop) · `bridgeMessaging.ts` (protocol) · `bridgePermissionCallbacks.ts` (permission callbacks) · `replBridge.ts` (REPL session) · `jwtUtils.ts` (JWT auth) · `sessionRunner.ts` (session execution)
### 5. Permission System (`src/hooks/toolPermission/`)
### 5. Permission System
Checks permissions on every tool invocation. Either prompts the user for approval/denial or automatically resolves based on the configured permission mode (`default`, `plan`, `bypassPermissions`, `auto`, etc.).
> `src/hooks/toolPermission/` — Checks permissions on every tool invocation.
Prompts the user for approval/denial or auto-resolves based on the configured permission mode: `default`, `plan`, `bypassPermissions`, `auto`, etc.
### 6. Feature Flags
Dead code elimination via Bun's `bun:bundle` feature flags:
Dead code elimination at build time via Bun's `bun:bundle`:
```typescript
import { feature } from 'bun:bundle'
// Inactive code is completely stripped at build time
const voiceCommand = feature('VOICE_MODE')
? require('./commands/voice/index.js').default
: null
```
Notable flags: `PROACTIVE`, `KAIROS`, `BRIDGE_MODE`, `DAEMON`, `VOICE_MODE`, `AGENT_TRIGGERS`, `MONITOR_TOOL`
Notable flags: `PROACTIVE` · `KAIROS` · `BRIDGE_MODE` · `DAEMON` · `VOICE_MODE` · `AGENT_TRIGGERS` · `MONITOR_TOOL`
---
## Key Files in Detail
## Key Files
### `QueryEngine.ts` (~46K lines)
The core engine for LLM API calls. Handles streaming responses, tool-call loops, thinking mode, retry logic, and token counting.
### `Tool.ts` (~29K lines)
Defines base types and interfaces for all tools — input schemas, permission models, and progress state types.
### `commands.ts` (~25K lines)
Manages registration and execution of all slash commands. Uses conditional imports to load different command sets per environment.
### `main.tsx`
Commander.js-based CLI parser + React/Ink renderer initialization. At startup, parallelizes MDM settings, keychain prefetch, and GrowthBook initialization for faster boot.
| File | Lines | Purpose |
|------|------:|---------|
| `QueryEngine.ts` | ~46K | Core LLM API engine — streaming, tool loops, thinking mode, retries, token counting |
| `Tool.ts` | ~29K | Base types/interfaces for all tools — input schemas, permissions, progress state |
| `commands.ts` | ~25K | Command registration & execution with conditional per-environment imports |
| `main.tsx` | — | CLI parser + React/Ink renderer; parallelizes MDM, keychain, and GrowthBook on startup |
---
@@ -216,151 +349,89 @@ Commander.js-based CLI parser + React/Ink renderer initialization. At startup, p
| CLI Parsing | [Commander.js](https://github.com/tj/commander.js) (extra-typings) |
| Schema Validation | [Zod v4](https://zod.dev) |
| Code Search | [ripgrep](https://github.com/BurntSushi/ripgrep) (via GrepTool) |
| Protocols | [MCP SDK](https://modelcontextprotocol.io), LSP |
| Protocols | [MCP SDK](https://modelcontextprotocol.io) · LSP |
| API | [Anthropic SDK](https://docs.anthropic.com) |
| Telemetry | OpenTelemetry + gRPC |
| Feature Flags | GrowthBook |
| Auth | OAuth 2.0, JWT, macOS Keychain |
| Auth | OAuth 2.0 · JWT · macOS Keychain |
---
## Notable Design Patterns
## Design Patterns
### Parallel Prefetch
<details>
<summary><strong>Parallel Prefetch</strong> — Startup optimization</summary>
Startup time is optimized by prefetching MDM settings, keychain reads, and API preconnect in parallel before heavy module evaluation begins.
MDM settings, keychain reads, and API preconnect fire in parallel as side-effects before heavy module evaluation:
```typescript
// main.tsx — fired as side-effects before other imports
// main.tsx
startMdmRawRead()
startKeychainPrefetch()
```
### Lazy Loading
</details>
Heavy modules (OpenTelemetry ~400KB, gRPC ~700KB) are deferred via dynamic `import()` until actually needed.
<details>
<summary><strong>Lazy Loading</strong> — Deferred heavy modules</summary>
### Agent Swarms
OpenTelemetry (~400KB) and gRPC (~700KB) are loaded via dynamic `import()` only when needed.
Sub-agents are spawned via `AgentTool`, with `coordinator/` handling multi-agent orchestration. `TeamCreateTool` enables team-level parallel work.
</details>
### Skill System
<details>
<summary><strong>Agent Swarms</strong> — Multi-agent orchestration</summary>
Reusable workflows defined in `skills/` and executed through `SkillTool`. Users can add custom skills.
Sub-agents spawn via `AgentTool`, with `coordinator/` handling orchestration. `TeamCreateTool` enables team-level parallel work.
### Plugin Architecture
</details>
Built-in and third-party plugins are loaded through the `plugins/` subsystem.
<details>
<summary><strong>Skill System</strong> — Reusable workflows</summary>
Defined in `skills/` and executed through `SkillTool`. Users can add custom skills.
</details>
<details>
<summary><strong>Plugin Architecture</strong> — Extensibility</summary>
Built-in and third-party plugins loaded through the `plugins/` subsystem.
</details>
---
## GitPretty Setup (Per-File Pretty Commits)
## GitPretty Setup
If you want GitHub's file UI to show visually distinct commit messages per file, use the helper script in this repo:
<details>
<summary>Show per-file emoji commit messages in GitHub's file UI</summary>
```bash
# Apply emoji commits
bash ./gitpretty-apply.sh .
```
This will:
1. Clone `gitpretty` into `~/.gitpretty` (first run only)
2. Make scripts executable
3. Run `emoji-file-commits.sh` against this repo
Optional: install auto-emoji hooks for future commits:
```bash
# Optional: install hooks for future commits
bash ./gitpretty-apply.sh . --hooks
```
After running, push as usual:
```bash
# Push as usual
git push origin main
```
</details>
---
## Use It in Claude Code (MCP Server)
## Contributing
This repo includes an MCP server that lets you explore the Claude Code source directly from any Claude session. One command to set it up:
Contributions to documentation, the MCP server, and exploration tooling are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
### Quick Start
```bash
# Clone the repo (if you haven't already)
git clone https://github.com/nirholas/claude-code.git
cd claude-code/mcp-server
# Install dependencies and build
npm install && npm run build
# Add to Claude Code (run from the repo root)
claude mcp add claude-code-explorer -- node /absolute/path/to/claude-code/mcp-server/dist/index.js
```
Replace `/absolute/path/to/claude-code` with the actual path where you cloned the repo.
**Or as a single copy-paste block** (clones, builds, and registers in one go):
```bash
git clone https://github.com/nirholas/claude-code.git ~/claude-code \
&& cd ~/claude-code/mcp-server \
&& npm install && npm run build \
&& claude mcp add claude-code-explorer -- node ~/claude-code/mcp-server/dist/index.js
```
### What You Get
Once added, Claude has access to these tools for exploring the codebase:
| Tool | Description |
|------|-------------|
| `list_tools` | List all ~40 agent tools with source files |
| `list_commands` | List all ~50 slash commands with source files |
| `get_tool_source` | Read full source of any tool (e.g. `BashTool`, `FileEditTool`) |
| `get_command_source` | Read source of any slash command (e.g. `review`, `mcp`) |
| `read_source_file` | Read any file from `src/` by path |
| `search_source` | Grep across the entire source tree |
| `list_directory` | Browse `src/` directories |
| `get_architecture` | High-level architecture overview |
Plus **prompts** for guided exploration:
- `explain_tool` — Deep-dive into how a specific tool works
- `explain_command` — Understand a slash command's implementation
- `architecture_overview` — Guided tour of the full architecture
- `how_does_it_work` — Explain any subsystem (permissions, MCP, bridge, etc.)
- `compare_tools` — Side-by-side comparison of two tools
### Example Usage
After adding the MCP server, just ask Claude naturally:
> "How does the BashTool work?"
> "Search for where permissions are checked"
> "Show me the /review command source"
> "Explain the MCP client integration"
### Custom Source Path
If your `src/` directory is in a non-standard location, set the environment variable:
```bash
claude mcp add claude-code-explorer -e CLAUDE_CODE_SRC_ROOT=/path/to/src -- node /path/to/mcp-server/dist/index.js
```
### Remove It
```bash
claude mcp remove claude-code-explorer
```
> **Note:** The `src/` directory is the original leaked source and should not be modified.
---
## Disclaimer
This repository archives source code that was leaked from Anthropic's npm registry on **2026-03-31**. All original source code is the property of [Anthropic](https://www.anthropic.com). Contact [nichxbt](https://www.x.com/nichxbt) for any comments.
This repository archives source code leaked from Anthropic's npm registry on **2026-03-31**. All original source code is the property of [Anthropic](https://www.anthropic.com). This is not an official release and is not licensed for redistribution. Contact [nichxbt](https://www.x.com/nichxbt) for any comments.

224
docs/architecture.md Normal file
View File

@@ -0,0 +1,224 @@
# Architecture
> Deep-dive into how Claude Code is structured internally.
---
## High-Level Overview
Claude Code is a terminal-native AI coding assistant built as a single-binary CLI. The architecture follows a pipeline model:
```
User Input → CLI Parser → Query Engine → LLM API → Tool Execution Loop → Terminal UI
```
The entire UI layer is built with **React + Ink** (React for the terminal), making it a fully reactive CLI application with components, hooks, state management, and all the patterns you'd expect in a React web app — just rendered to the terminal.
---
## Core Pipeline
### 1. Entrypoint (`src/main.tsx`)
The CLI parser is built with [Commander.js](https://github.com/tj/commander.js) (`@commander-js/extra-typings`). On startup, it:
- Fires parallel prefetch side-effects (MDM settings, Keychain, API preconnect) before heavy module imports
- Parses CLI arguments and flags
- Initializes the React/Ink renderer
- Hands off to the REPL launcher (`src/replLauncher.tsx`)
### 2. Initialization (`src/entrypoints/`)
| File | Role |
|------|------|
| `cli.tsx` | CLI session orchestration — the main path from launch to REPL |
| `init.ts` | Config, telemetry, OAuth, MDM policy initialization |
| `mcp.ts` | MCP server mode entrypoint (Claude Code as an MCP server) |
| `sdk/` | Agent SDK — programmatic API for embedding Claude Code |
Startup performs parallel initialization: MDM policy reads, Keychain prefetch, feature flag checks, then core init.
### 3. Query Engine (`src/QueryEngine.ts`, ~46K lines)
The heart of Claude Code. Handles:
- **Streaming responses** from the Anthropic API
- **Tool-call loops** — when the LLM requests a tool, execute it and feed the result back
- **Thinking mode** — extended thinking with budget management
- **Retry logic** — automatic retries with backoff for transient failures
- **Token counting** — tracks input/output tokens and cost per turn
- **Context management** — manages conversation history and context windows
### 4. Tool System (`src/Tool.ts` + `src/tools/`)
Every capability Claude can invoke is a **tool**. Each tool is self-contained with:
- **Input schema** (Zod validation)
- **Permission model** (what needs user approval)
- **Execution logic** (the actual implementation)
- **UI components** (how invocation/results render in the terminal)
Tools are registered in `src/tools.ts` and discovered by the Query Engine during tool-call loops.
See [Tools Reference](tools.md) for the complete catalog.
### 5. Command System (`src/commands.ts` + `src/commands/`)
User-facing slash commands (`/commit`, `/review`, `/mcp`, etc.) that can be typed in the REPL. Three types:
| Type | Description | Example |
|------|-------------|---------|
| **PromptCommand** | Sends a formatted prompt to the LLM with injected tools | `/review`, `/commit` |
| **LocalCommand** | Runs in-process, returns plain text | `/cost`, `/version` |
| **LocalJSXCommand** | Runs in-process, returns React JSX | `/doctor`, `/install` |
Commands are registered in `src/commands.ts` and invoked via `/command-name` in the REPL.
See [Commands Reference](commands.md) for the complete catalog.
---
## State Management
Claude Code uses a **React context + custom store** pattern:
| Component | Location | Purpose |
|-----------|----------|---------|
| `AppState` | `src/state/AppStateStore.ts` | Global mutable state object |
| Context Providers | `src/context/` | React context for notifications, stats, FPS |
| Selectors | `src/state/` | Derived state functions |
| Change Observers | `src/state/onChangeAppState.ts` | Side-effects on state changes |
The `AppState` object is passed into tool contexts, giving tools access to conversation history, settings, and runtime state.
---
## UI Layer
### Components (`src/components/`, ~140 components)
- Functional React components using Ink primitives (`Box`, `Text`, `useInput()`)
- Styled with [Chalk](https://github.com/chalk/chalk) for terminal colors
- React Compiler enabled for optimized re-renders
- Design system primitives in `src/components/design-system/`
### Screens (`src/screens/`)
Full-screen UI modes:
| Screen | Purpose |
|--------|---------|
| `REPL.tsx` | Main interactive REPL (the default screen) |
| `Doctor.tsx` | Environment diagnostics (`/doctor`) |
| `ResumeConversation.tsx` | Session restore (`/resume`) |
### Hooks (`src/hooks/`, ~80 hooks)
Standard React hooks pattern. Notable categories:
- **Permission hooks** — `useCanUseTool`, `src/hooks/toolPermission/`
- **IDE integration** — `useIDEIntegration`, `useIdeConnectionStatus`, `useDiffInIDE`
- **Input handling** — `useTextInput`, `useVimInput`, `usePasteHandler`, `useInputBuffer`
- **Session management** — `useSessionBackgrounding`, `useRemoteSession`, `useAssistantHistory`
- **Plugin/skill hooks** — `useManagePlugins`, `useSkillsChange`
- **Notification hooks** — `src/hooks/notifs/` (rate limits, deprecation warnings, etc.)
---
## Configuration & Schemas
### Config Schemas (`src/schemas/`)
Zod v4-based schemas for all configuration:
- User settings
- Project-level settings
- Organization/enterprise policies
- Permission rules
### Migrations (`src/migrations/`)
Handles config format changes between versions — reads old configs and transforms them to the current schema.
---
## Build System
### Bun Runtime
Claude Code runs on [Bun](https://bun.sh) (not Node.js). Key implications:
- Native JSX/TSX support without a transpilation step
- `bun:bundle` feature flags for dead-code elimination
- ES modules with `.js` extensions (Bun convention)
### Feature Flags (Dead Code Elimination)
```typescript
import { feature } from 'bun:bundle'
// Code inside inactive feature flags is completely stripped at build time
if (feature('VOICE_MODE')) {
const voiceCommand = require('./commands/voice/index.js').default
}
```
Notable flags:
| Flag | Feature |
|------|---------|
| `PROACTIVE` | Proactive agent mode (autonomous actions) |
| `KAIROS` | Kairos subsystem |
| `BRIDGE_MODE` | IDE bridge integration |
| `DAEMON` | Background daemon mode |
| `VOICE_MODE` | Voice input/output |
| `AGENT_TRIGGERS` | Triggered agent actions |
| `MONITOR_TOOL` | Monitoring tool |
| `COORDINATOR_MODE` | Multi-agent coordinator |
| `WORKFLOW_SCRIPTS` | Workflow automation scripts |
### Lazy Loading
Heavy modules are deferred via dynamic `import()` until first use:
- OpenTelemetry (~400KB)
- gRPC (~700KB)
- Other optional dependencies
---
## Error Handling & Telemetry
### Telemetry (`src/services/analytics/`)
- [GrowthBook](https://www.growthbook.io/) for feature flags and A/B testing
- [OpenTelemetry](https://opentelemetry.io/) for distributed tracing and metrics
- Custom event tracking for usage analytics
### Cost Tracking (`src/cost-tracker.ts`)
Tracks token usage and estimated cost per conversation turn. Accessible via the `/cost` command.
### Diagnostics (`/doctor` command)
The `Doctor.tsx` screen runs environment checks: API connectivity, authentication, tool availability, MCP server status, and more.
---
## Concurrency Model
Claude Code uses a **single-threaded event loop** (Bun/Node.js model) with:
- Async/await for I/O operations
- React's concurrent rendering for UI updates
- Web Workers or child processes for CPU-intensive tasks (gRPC, etc.)
- Tool concurrency safety — each tool declares `isConcurrencySafe()` to indicate if it can run in parallel with other tools
---
## See Also
- [Tools Reference](tools.md) — Complete catalog of all 40 agent tools
- [Commands Reference](commands.md) — Complete catalog of all slash commands
- [Subsystems Guide](subsystems.md) — Bridge, MCP, permissions, skills, plugins, and more
- [Exploration Guide](exploration-guide.md) — How to navigate this codebase

211
docs/commands.md Normal file
View File

@@ -0,0 +1,211 @@
# Commands Reference
> Complete catalog of all slash commands in Claude Code.
---
## Overview
Commands are user-facing actions invoked with a `/` prefix in the REPL (e.g., `/commit`, `/review`). They live in `src/commands/` and are registered in `src/commands.ts`.
### Command Types
| Type | Description | Example |
|------|-------------|---------|
| **PromptCommand** | Sends a formatted prompt to the LLM with injected tools | `/review`, `/commit` |
| **LocalCommand** | Runs in-process, returns plain text | `/cost`, `/version` |
| **LocalJSXCommand** | Runs in-process, returns React JSX | `/install`, `/doctor` |
### Command Definition Pattern
```typescript
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
```
---
## Git & Version Control
| Command | Source | Description |
|---------|--------|-------------|
| `/commit` | `commit.ts` | Create a git commit with an AI-generated message |
| `/commit-push-pr` | `commit-push-pr.ts` | Commit, push, and create a PR in one step |
| `/branch` | `branch/` | Create or switch git branches |
| `/diff` | `diff/` | View file changes (staged, unstaged, or against a ref) |
| `/pr_comments` | `pr_comments/` | View and address PR review comments |
| `/rewind` | `rewind/` | Revert to a previous state |
## Code Quality
| Command | Source | Description |
|---------|--------|-------------|
| `/review` | `review.ts` | AI-powered code review of staged/unstaged changes |
| `/security-review` | `security-review.ts` | Security-focused code review |
| `/advisor` | `advisor.ts` | Get architectural or design advice |
| `/bughunter` | `bughunter/` | Find potential bugs in the codebase |
## Session & Context
| Command | Source | Description |
|---------|--------|-------------|
| `/compact` | `compact/` | Compress conversation context to fit more history |
| `/context` | `context/` | Visualize current context (files, memory, etc.) |
| `/resume` | `resume/` | Restore a previous conversation session |
| `/session` | `session/` | Manage sessions (list, switch, delete) |
| `/share` | `share/` | Share a session via link |
| `/export` | `export/` | Export conversation to a file |
| `/summary` | `summary/` | Generate a summary of the current session |
| `/clear` | `clear/` | Clear the conversation history |
## Configuration & Settings
| Command | Source | Description |
|---------|--------|-------------|
| `/config` | `config/` | View or modify Claude Code settings |
| `/permissions` | `permissions/` | Manage tool permission rules |
| `/theme` | `theme/` | Change the terminal color theme |
| `/output-style` | `output-style/` | Change output formatting style |
| `/color` | `color/` | Toggle color output |
| `/keybindings` | `keybindings/` | View or customize keybindings |
| `/vim` | `vim/` | Toggle vim mode for input |
| `/effort` | `effort/` | Adjust response effort level |
| `/model` | `model/` | Switch the active model |
| `/privacy-settings` | `privacy-settings/` | Manage privacy/data settings |
| `/fast` | `fast/` | Toggle fast mode (shorter responses) |
| `/brief` | `brief.ts` | Toggle brief output mode |
## Memory & Knowledge
| Command | Source | Description |
|---------|--------|-------------|
| `/memory` | `memory/` | Manage persistent memory (CLAUDE.md files) |
| `/add-dir` | `add-dir/` | Add a directory to the project context |
| `/files` | `files/` | List files in the current context |
## MCP & Plugins
| Command | Source | Description |
|---------|--------|-------------|
| `/mcp` | `mcp/` | Manage MCP server connections |
| `/plugin` | `plugin/` | Install, remove, or manage plugins |
| `/reload-plugins` | `reload-plugins/` | Reload all installed plugins |
| `/skills` | `skills/` | View and manage skills |
## Authentication
| Command | Source | Description |
|---------|--------|-------------|
| `/login` | `login/` | Authenticate with Anthropic |
| `/logout` | `logout/` | Sign out |
| `/oauth-refresh` | `oauth-refresh/` | Refresh OAuth tokens |
## Tasks & Agents
| Command | Source | Description |
|---------|--------|-------------|
| `/tasks` | `tasks/` | Manage background tasks |
| `/agents` | `agents/` | Manage sub-agents |
| `/ultraplan` | `ultraplan.tsx` | Generate a detailed execution plan |
| `/plan` | `plan/` | Enter planning mode |
## Diagnostics & Status
| Command | Source | Description |
|---------|--------|-------------|
| `/doctor` | `doctor/` | Run environment diagnostics |
| `/status` | `status/` | Show system and session status |
| `/stats` | `stats/` | Show session statistics |
| `/cost` | `cost/` | Display token usage and estimated cost |
| `/version` | `version.ts` | Show Claude Code version |
| `/usage` | `usage/` | Show detailed API usage |
| `/extra-usage` | `extra-usage/` | Show extended usage details |
| `/rate-limit-options` | `rate-limit-options/` | View rate limit configuration |
## Installation & Setup
| Command | Source | Description |
|---------|--------|-------------|
| `/install` | `install.tsx` | Install or update Claude Code |
| `/upgrade` | `upgrade/` | Upgrade to the latest version |
| `/init` | `init.ts` | Initialize a project (create CLAUDE.md) |
| `/init-verifiers` | `init-verifiers.ts` | Set up verifier hooks |
| `/onboarding` | `onboarding/` | Run the first-time setup wizard |
| `/terminalSetup` | `terminalSetup/` | Configure terminal integration |
## IDE & Desktop Integration
| Command | Source | Description |
|---------|--------|-------------|
| `/bridge` | `bridge/` | Manage IDE bridge connections |
| `/bridge-kick` | `bridge-kick.ts` | Force-restart the IDE bridge |
| `/ide` | `ide/` | Open in IDE |
| `/desktop` | `desktop/` | Hand off to the desktop app |
| `/mobile` | `mobile/` | Hand off to the mobile app |
| `/teleport` | `teleport/` | Transfer session to another device |
## Remote & Environment
| Command | Source | Description |
|---------|--------|-------------|
| `/remote-env` | `remote-env/` | Configure remote environment |
| `/remote-setup` | `remote-setup/` | Set up remote session |
| `/env` | `env/` | View environment variables |
| `/sandbox-toggle` | `sandbox-toggle/` | Toggle sandbox mode |
## Misc
| Command | Source | Description |
|---------|--------|-------------|
| `/help` | `help/` | Show help and available commands |
| `/exit` | `exit/` | Exit Claude Code |
| `/copy` | `copy/` | Copy content to clipboard |
| `/feedback` | `feedback/` | Send feedback to Anthropic |
| `/release-notes` | `release-notes/` | View release notes |
| `/rename` | `rename/` | Rename the current session |
| `/tag` | `tag/` | Tag the current session |
| `/insights` | `insights.ts` | Show codebase insights |
| `/stickers` | `stickers/` | Easter egg — stickers |
| `/good-claude` | `good-claude/` | Easter egg — praise Claude |
| `/voice` | `voice/` | Toggle voice input mode |
| `/chrome` | `chrome/` | Chrome extension integration |
| `/issue` | `issue/` | File a GitHub issue |
| `/statusline` | `statusline.tsx` | Customize the status line |
| `/thinkback` | `thinkback/` | Replay Claude's thinking process |
| `/thinkback-play` | `thinkback-play/` | Animated thinking replay |
| `/passes` | `passes/` | Multi-pass execution |
| `/x402` | `x402/` | x402 payment protocol integration |
## Internal / Debug Commands
| Command | Source | Description |
|---------|--------|-------------|
| `/ant-trace` | `ant-trace/` | Anthropic-internal tracing |
| `/autofix-pr` | `autofix-pr/` | Auto-fix PR issues |
| `/backfill-sessions` | `backfill-sessions/` | Backfill session data |
| `/break-cache` | `break-cache/` | Invalidate caches |
| `/btw` | `btw/` | "By the way" interjection |
| `/ctx_viz` | `ctx_viz/` | Context visualization (debug) |
| `/debug-tool-call` | `debug-tool-call/` | Debug a specific tool call |
| `/heapdump` | `heapdump/` | Dump heap for memory analysis |
| `/hooks` | `hooks/` | Manage hook scripts |
| `/mock-limits` | `mock-limits/` | Mock rate limits for testing |
| `/perf-issue` | `perf-issue/` | Report performance issues |
| `/reset-limits` | `reset-limits/` | Reset rate limit counters |
---
## See Also
- [Architecture](architecture.md) — How the command system fits into the pipeline
- [Tools Reference](tools.md) — Agent tools (different from slash commands)
- [Exploration Guide](exploration-guide.md) — Finding command source code

246
docs/exploration-guide.md Normal file
View File

@@ -0,0 +1,246 @@
# Exploration Guide
> How to navigate and study the Claude Code source code.
---
## Quick Start
This is a **read-only reference codebase** — there's no build system or test suite. The goal is to understand how a production AI coding assistant is built.
### Orientation
| What | Where |
|------|-------|
| CLI entrypoint | `src/main.tsx` |
| Core LLM engine | `src/QueryEngine.ts` (~46K lines) |
| Tool definitions | `src/Tool.ts` (~29K lines) |
| Command registry | `src/commands.ts` (~25K lines) |
| Tool registry | `src/tools.ts` |
| Context collection | `src/context.ts` |
| All tool implementations | `src/tools/` (40 subdirectories) |
| All command implementations | `src/commands/` (~85 subdirectories + 15 files) |
---
## Finding Things
### "How does tool X work?"
1. Go to `src/tools/{ToolName}/`
2. Main implementation is `{ToolName}.ts` or `.tsx`
3. UI rendering is in `UI.tsx`
4. System prompt contribution is in `prompt.ts`
Example — understanding BashTool:
```
src/tools/BashTool/
├── BashTool.ts ← Core execution logic
├── UI.tsx ← How bash output renders in terminal
├── prompt.ts ← What the system prompt says about bash
└── ...
```
### "How does command X work?"
1. Check `src/commands/{command-name}/` (directory) or `src/commands/{command-name}.ts` (file)
2. Look for the `getPromptForCommand()` function (PromptCommands) or direct implementation (LocalCommands)
### "How does feature X work?"
| Feature | Start Here |
|---------|-----------|
| Permissions | `src/hooks/toolPermission/` |
| IDE bridge | `src/bridge/bridgeMain.ts` |
| MCP client | `src/services/mcp/` |
| Plugin system | `src/plugins/` + `src/services/plugins/` |
| Skills | `src/skills/` |
| Voice input | `src/voice/` + `src/services/voice.ts` |
| Multi-agent | `src/coordinator/` |
| Memory | `src/memdir/` |
| Authentication | `src/services/oauth/` |
| Config schemas | `src/schemas/` |
| State management | `src/state/` |
### "How does an API call flow?"
Trace from user input to API response:
```
src/main.tsx ← CLI parsing
→ src/replLauncher.tsx ← REPL session start
→ src/QueryEngine.ts ← Core engine
→ src/services/api/ ← Anthropic SDK client
→ (Anthropic API) ← HTTP/streaming
← Tool use response
→ src/tools/{ToolName}/ ← Tool execution
← Tool result
→ (feed back to API) ← Continue the loop
```
---
## Code Patterns to Recognize
### `buildTool()` — Tool Factory
Every tool uses this pattern:
```typescript
export const MyTool = buildTool({
name: 'MyTool',
inputSchema: z.object({ ... }),
async call(args, context) { ... },
async checkPermissions(input, context) { ... },
})
```
### Feature Flag Gates
```typescript
import { feature } from 'bun:bundle'
if (feature('VOICE_MODE')) {
// This code is stripped at build time if VOICE_MODE is off
}
```
### Anthropic-Internal Gates
```typescript
if (process.env.USER_TYPE === 'ant') {
// Anthropic employee-only features
}
```
### Index Re-exports
Most directories have an `index.ts` that re-exports the public API:
```typescript
// src/tools/BashTool/index.ts
export { BashTool } from './BashTool.js'
```
### Lazy Dynamic Imports
Heavy modules are loaded only when needed:
```typescript
const { OpenTelemetry } = await import('./heavy-module.js')
```
### ESM with `.js` Extensions
Bun convention — all imports use `.js` extensions even for `.ts` files:
```typescript
import { something } from './utils.js' // Actually imports utils.ts
```
---
## Key Files by Size
The largest files contain the most logic and are worth studying:
| File | Lines | What's Inside |
|------|-------|---------------|
| `QueryEngine.ts` | ~46K | Streaming, tool loops, retries, token counting |
| `Tool.ts` | ~29K | Tool types, `buildTool`, permission models |
| `commands.ts` | ~25K | Command registry, conditional loading |
| `main.tsx` | — | CLI parser, startup optimization |
| `context.ts` | — | OS, shell, git, user context assembly |
---
## Study Paths
### Path 1: "How does a tool work end-to-end?"
1. Read `src/Tool.ts` — understand the `buildTool` interface
2. Pick a simple tool like `FileReadTool` in `src/tools/FileReadTool/`
3. Trace how `QueryEngine.ts` calls tools during the tool loop
4. See how permissions are checked in `src/hooks/toolPermission/`
### Path 2: "How does the UI work?"
1. Read `src/screens/REPL.tsx` — the main screen
2. Explore `src/components/` — pick a few components
3. See `src/hooks/useTextInput.ts` — how user input is captured
4. Check `src/ink/` — the Ink renderer wrapper
### Path 3: "How does the IDE integration work?"
1. Start at `src/bridge/bridgeMain.ts`
2. Follow `bridgeMessaging.ts` for the message protocol
3. See `bridgePermissionCallbacks.ts` for how permissions route to the IDE
4. Check `replBridge.ts` for REPL session bridging
### Path 4: "How do plugins extend Claude Code?"
1. Read `src/types/plugin.ts` — the plugin API surface
2. See `src/services/plugins/` — how plugins are loaded
3. Check `src/plugins/builtinPlugins.ts` — built-in examples
4. Look at `src/plugins/bundled/` — bundled plugin code
### Path 5: "How does MCP work?"
1. Read `src/services/mcp/` — the MCP client
2. See `src/tools/MCPTool/` — how MCP tools are invoked
3. Check `src/entrypoints/mcp.ts` — Claude Code as an MCP server
4. Look at `src/skills/mcpSkillBuilders.ts` — skills from MCP
---
## Using the MCP Server for Exploration
This repo includes a standalone MCP server (`mcp-server/`) that lets any MCP-compatible client explore the source code. See the [MCP Server README](../mcp-server/README.md) for setup.
Once connected, you can ask an AI assistant to explore the source:
- "How does the BashTool work?"
- "Search for where permissions are checked"
- "List all files in the bridge directory"
- "Read QueryEngine.ts lines 1-100"
---
## Grep Patterns
Useful grep/ripgrep patterns for finding things:
```bash
# Find all tool definitions
rg "buildTool\(" src/tools/
# Find all command definitions
rg "satisfies Command" src/commands/
# Find feature flag usage
rg "feature\(" src/
# Find Anthropic-internal gates
rg "USER_TYPE.*ant" src/
# Find all React hooks
rg "^export function use" src/hooks/
# Find all Zod schemas
rg "z\.object\(" src/schemas/
# Find all system prompt contributions
rg "prompt\(" src/tools/*/prompt.ts
# Find permission rule patterns
rg "checkPermissions" src/tools/
```
---
## See Also
- [Architecture](architecture.md) — Overall system design
- [Tools Reference](tools.md) — Complete tool catalog
- [Commands Reference](commands.md) — All slash commands
- [Subsystems Guide](subsystems.md) — Deep dives into Bridge, MCP, Permissions, etc.

346
docs/subsystems.md Normal file
View File

@@ -0,0 +1,346 @@
# Subsystems Guide
> Detailed documentation of Claude Code's major subsystems.
---
## Table of Contents
- [Bridge (IDE Integration)](#bridge-ide-integration)
- [MCP (Model Context Protocol)](#mcp-model-context-protocol)
- [Permission System](#permission-system)
- [Plugin System](#plugin-system)
- [Skill System](#skill-system)
- [Task System](#task-system)
- [Memory System](#memory-system)
- [Coordinator (Multi-Agent)](#coordinator-multi-agent)
- [Voice System](#voice-system)
- [Service Layer](#service-layer)
---
## Bridge (IDE Integration)
**Location:** `src/bridge/`
The bridge is a bidirectional communication layer connecting Claude Code's CLI with IDE extensions (VS Code, JetBrains). It allows the CLI to run as a backend for IDE-based interfaces.
### Architecture
```
┌──────────────────┐ ┌──────────────────────┐
│ IDE Extension │◄───────►│ Bridge Layer │
│ (VS Code, JB) │ JWT │ (src/bridge/) │
│ │ Auth │ │
│ - UI rendering │ │ - Session mgmt │
│ - File watching │ │ - Message routing │
│ - Diff display │ │ - Permission proxy │
└──────────────────┘ └──────────┬───────────┘
┌──────────────────────┐
│ Claude Code Core │
│ (QueryEngine, Tools) │
└──────────────────────┘
```
### Key Files
| File | Purpose |
|------|---------|
| `bridgeMain.ts` | Main bridge loop — starts the bidirectional channel |
| `bridgeMessaging.ts` | Message protocol (serialize/deserialize) |
| `bridgePermissionCallbacks.ts` | Routes permission prompts to the IDE |
| `bridgeApi.ts` | API surface exposed to the IDE |
| `bridgeConfig.ts` | Bridge configuration |
| `replBridge.ts` | Connects the REPL session to the bridge |
| `jwtUtils.ts` | JWT-based authentication between CLI and IDE |
| `sessionRunner.ts` | Manages bridge session execution |
| `createSession.ts` | Creates new bridge sessions |
| `trustedDevice.ts` | Device trust verification |
| `workSecret.ts` | Workspace-scoped secrets |
| `inboundMessages.ts` | Handles messages coming from the IDE |
| `inboundAttachments.ts` | Handles file attachments from the IDE |
| `types.ts` | TypeScript types for the bridge protocol |
### Feature Flag
The bridge is gated behind the `BRIDGE_MODE` feature flag and is stripped from non-IDE builds.
---
## MCP (Model Context Protocol)
**Location:** `src/services/mcp/`
Claude Code acts as both an **MCP client** (consuming tools/resources from MCP servers) and can run as an **MCP server** (exposing its own tools via `src/entrypoints/mcp.ts`).
### Client Features
- **Tool discovery** — Enumerates tools from connected MCP servers
- **Resource browsing** — Lists and reads MCP-exposed resources
- **Dynamic tool loading** — `ToolSearchTool` discovers tools at runtime
- **Authentication** — `McpAuthTool` handles MCP server auth flows
- **Connectivity monitoring** — `useMcpConnectivityStatus` hook tracks connection health
### Server Mode
When launched via `src/entrypoints/mcp.ts`, Claude Code exposes its own tools and resources via the MCP protocol, allowing other AI agents to use Claude Code as a tool server.
### Related Tools
| Tool | Purpose |
|------|---------|
| `MCPTool` | Invoke tools on connected MCP servers |
| `ListMcpResourcesTool` | List available MCP resources |
| `ReadMcpResourceTool` | Read a specific MCP resource |
| `McpAuthTool` | Authenticate with an MCP server |
| `ToolSearchTool` | Discover deferred tools from MCP servers |
### Configuration
MCP servers are configured via `/mcp` command or settings files. The server approval flow lives in `src/services/mcpServerApproval.tsx`.
---
## Permission System
**Location:** `src/hooks/toolPermission/`
Every tool invocation passes through a centralized permission check before execution.
### Permission Modes
| Mode | Behavior |
|------|----------|
| `default` | Prompts the user for each potentially destructive operation |
| `plan` | Shows the full execution plan, asks once for batch approval |
| `bypassPermissions` | Auto-approves all operations (dangerous — for trusted environments) |
| `auto` | ML-based classifier automatically decides (experimental) |
### How It Works
1. Tool is invoked by the Query Engine
2. `checkPermissions(input, context)` is called on the tool
3. Permission handler checks against configured rules
4. If not auto-approved, user is prompted via terminal or IDE
### Permission Rules
Rules use wildcard patterns to match tool invocations:
```
Bash(git *) # Allow all git commands without prompt
Bash(npm test) # Allow 'npm test' specifically
FileEdit(/src/*) # Allow edits to anything under src/
FileRead(*) # Allow reading any file
```
### Key Files
| File | Path |
|------|------|
| Permission context | `src/hooks/toolPermission/PermissionContext.ts` |
| Permission handlers | `src/hooks/toolPermission/handlers/` |
| Permission logging | `src/hooks/toolPermission/permissionLogging.ts` |
| Permission types | `src/types/permissions.ts` |
---
## Plugin System
**Location:** `src/plugins/`, `src/services/plugins/`
Claude Code supports installable plugins that can extend its capabilities.
### Structure
| Component | Location | Purpose |
|-----------|----------|---------|
| Plugin loader | `src/services/plugins/` | Discovers and loads plugins |
| Built-in plugins | `src/plugins/builtinPlugins.ts` | Plugins that ship with Claude Code |
| Bundled plugins | `src/plugins/bundled/` | Plugin code bundled into the binary |
| Plugin types | `src/types/plugin.ts` | TypeScript types for plugin API |
### Plugin Lifecycle
1. **Discovery** — Scans plugin directories and marketplace
2. **Installation** — Downloaded and registered (`/plugin` command)
3. **Loading** — Initialized at startup or on-demand
4. **Execution** — Plugins can contribute tools, commands, and prompts
5. **Auto-update**`usePluginAutoupdateNotification` handles updates
### Related Commands
| Command | Purpose |
|---------|---------|
| `/plugin` | Install, remove, or manage plugins |
| `/reload-plugins` | Reload all installed plugins |
---
## Skill System
**Location:** `src/skills/`
Skills are reusable, named workflows that bundle prompts and tool configurations for specific tasks.
### Structure
| Component | Location | Purpose |
|-----------|----------|---------|
| Bundled skills | `src/skills/bundled/` | Skills that ship with Claude Code |
| Skill loader | `src/skills/loadSkillsDir.ts` | Loads skills from disk |
| MCP skill builders | `src/skills/mcpSkillBuilders.ts` | Creates skills from MCP resources |
| Skill registry | `src/skills/bundledSkills.ts` | Registration of all bundled skills |
### Bundled Skills (16)
| Skill | Purpose |
|-------|---------|
| `batch` | Batch operations across multiple files |
| `claudeApi` | Direct Anthropic API interaction |
| `claudeInChrome` | Chrome extension integration |
| `debug` | Debugging workflows |
| `keybindings` | Keybinding configuration |
| `loop` | Iterative refinement loops |
| `loremIpsum` | Generate placeholder text |
| `remember` | Persist information to memory |
| `scheduleRemoteAgents` | Schedule agents for remote execution |
| `simplify` | Simplify complex code |
| `skillify` | Create new skills from workflows |
| `stuck` | Get unstuck when blocked |
| `updateConfig` | Modify configuration programmatically |
| `verify` / `verifyContent` | Verify code correctness |
### Execution
Skills are invoked via the `SkillTool` or the `/skills` command. Users can also create custom skills.
---
## Task System
**Location:** `src/tasks/`
Manages background and parallel work items — shell tasks, agent tasks, and teammate agents.
### Task Types
| Type | Location | Purpose |
|------|----------|---------|
| `LocalShellTask` | `LocalShellTask/` | Background shell command execution |
| `LocalAgentTask` | `LocalAgentTask/` | Sub-agent running locally |
| `RemoteAgentTask` | `RemoteAgentTask/` | Agent running on a remote machine |
| `InProcessTeammateTask` | `InProcessTeammateTask/` | Parallel teammate agent |
| `DreamTask` | `DreamTask/` | Background "dreaming" process |
| `LocalMainSessionTask` | `LocalMainSessionTask.ts` | Main session as a task |
### Task Tools
| Tool | Purpose |
|------|---------|
| `TaskCreateTool` | Create a new background task |
| `TaskUpdateTool` | Update task status |
| `TaskGetTool` | Retrieve task details |
| `TaskListTool` | List all tasks |
| `TaskOutputTool` | Get task output |
| `TaskStopTool` | Stop a running task |
---
## Memory System
**Location:** `src/memdir/`
Claude Code's persistent memory system, based on `CLAUDE.md` files.
### Memory Hierarchy
| Scope | Location | Purpose |
|-------|----------|---------|
| Project memory | `CLAUDE.md` in project root | Project-specific facts, conventions |
| User memory | `~/.claude/CLAUDE.md` | User preferences, cross-project |
| Extracted memories | `src/services/extractMemories/` | Auto-extracted from conversations |
| Team memory sync | `src/services/teamMemorySync/` | Shared team knowledge |
### Related
- `/memory` command for managing memories
- `remember` skill for persisting information
- `useMemoryUsage` hook for tracking memory size
---
## Coordinator (Multi-Agent)
**Location:** `src/coordinator/`
Orchestrates multiple agents working in parallel on different aspects of a task.
### How It Works
- `coordinatorMode.ts` manages the coordinator lifecycle
- `TeamCreateTool` and `TeamDeleteTool` manage agent teams
- `SendMessageTool` enables inter-agent communication
- `AgentTool` spawns sub-agents
Gated behind the `COORDINATOR_MODE` feature flag.
---
## Voice System
**Location:** `src/voice/`
Voice input/output support for hands-free interaction.
### Components
| File | Location | Purpose |
|------|----------|---------|
| Voice service | `src/services/voice.ts` | Core voice processing |
| STT streaming | `src/services/voiceStreamSTT.ts` | Speech-to-text streaming |
| Key terms | `src/services/voiceKeyterms.ts` | Domain-specific vocabulary |
| Voice hooks | `src/hooks/useVoice.ts`, `useVoiceEnabled.ts`, `useVoiceIntegration.tsx` | React hooks |
| Voice command | `src/commands/voice/` | `/voice` slash command |
Gated behind the `VOICE_MODE` feature flag.
---
## Service Layer
**Location:** `src/services/`
External integrations and shared services.
| Service | Path | Purpose |
|---------|------|---------|
| **API** | `api/` | Anthropic SDK client, file uploads, bootstrap |
| **MCP** | `mcp/` | MCP client connections and tool discovery |
| **OAuth** | `oauth/` | OAuth 2.0 authentication flow |
| **LSP** | `lsp/` | Language Server Protocol manager |
| **Analytics** | `analytics/` | GrowthBook feature flags, telemetry |
| **Plugins** | `plugins/` | Plugin loader and marketplace |
| **Compact** | `compact/` | Conversation context compression |
| **Policy Limits** | `policyLimits/` | Organization rate limits/quota |
| **Remote Settings** | `remoteManagedSettings/` | Enterprise managed settings sync |
| **Token Estimation** | `tokenEstimation.ts` | Token count estimation |
| **Team Memory** | `teamMemorySync/` | Team knowledge synchronization |
| **Tips** | `tips/` | Contextual usage tips |
| **Agent Summary** | `AgentSummary/` | Agent work summaries |
| **Prompt Suggestion** | `PromptSuggestion/` | Suggested follow-up prompts |
| **Session Memory** | `SessionMemory/` | Session-level memory |
| **Magic Docs** | `MagicDocs/` | Documentation generation |
| **Auto Dream** | `autoDream/` | Background ideation |
| **x402** | `x402/` | x402 payment protocol |
---
## See Also
- [Architecture](architecture.md) — How subsystems connect in the core pipeline
- [Tools Reference](tools.md) — Tools related to each subsystem
- [Commands Reference](commands.md) — Commands for managing subsystems
- [Exploration Guide](exploration-guide.md) — Finding subsystem source code

173
docs/tools.md Normal file
View File

@@ -0,0 +1,173 @@
# Tools Reference
> Complete catalog of all ~40 agent tools in Claude Code.
---
## Overview
Every tool lives in `src/tools/<ToolName>/` as a self-contained module. Each tool defines:
- **Input schema** — Zod-validated parameters
- **Permission model** — What requires user approval
- **Execution logic** — The tool's implementation
- **UI components** — Terminal rendering for invocation and results
- **Concurrency safety** — Whether it can run in parallel
Tools are registered in `src/tools.ts` and invoked by the Query Engine during LLM tool-call loops.
### Tool Definition Pattern
```typescript
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:**
```
src/tools/MyTool/
├── MyTool.ts # Main implementation
├── UI.tsx # Terminal rendering
├── prompt.ts # System prompt contribution
└── utils.ts # Tool-specific helpers
```
---
## File System Tools
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **FileReadTool** | Read file contents (text, images, PDFs, notebooks). Supports line ranges | Yes |
| **FileWriteTool** | Create or overwrite files | No |
| **FileEditTool** | Partial file modification via string replacement | No |
| **GlobTool** | Find files matching glob patterns (e.g. `**/*.ts`) | Yes |
| **GrepTool** | Content search using ripgrep (regex-capable) | Yes |
| **NotebookEditTool** | Edit Jupyter notebook cells | No |
| **TodoWriteTool** | Write to a structured todo/task file | No |
## Shell & Execution Tools
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **BashTool** | Execute shell commands in bash | No |
| **PowerShellTool** | Execute PowerShell commands (Windows) | No |
| **REPLTool** | Run code in a REPL session (Python, Node, etc.) | No |
## Agent & Orchestration Tools
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **AgentTool** | Spawn a sub-agent for complex tasks | No |
| **SendMessageTool** | Send messages between agents | No |
| **TeamCreateTool** | Create a team of parallel agents | No |
| **TeamDeleteTool** | Remove a team agent | No |
| **EnterPlanModeTool** | Switch to planning mode (no execution) | No |
| **ExitPlanModeTool** | Exit planning mode, resume execution | No |
| **EnterWorktreeTool** | Isolate work in a git worktree | No |
| **ExitWorktreeTool** | Exit worktree isolation | No |
| **SleepTool** | Pause execution (proactive mode) | Yes |
| **SyntheticOutputTool** | Generate structured output | Yes |
## Task Management Tools
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **TaskCreateTool** | Create a new background task | No |
| **TaskUpdateTool** | Update a task's status or details | No |
| **TaskGetTool** | Get details of a specific task | Yes |
| **TaskListTool** | List all tasks | Yes |
| **TaskOutputTool** | Get output from a completed task | Yes |
| **TaskStopTool** | Stop a running task | No |
## Web Tools
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **WebFetchTool** | Fetch content from a URL | Yes |
| **WebSearchTool** | Search the web | Yes |
## MCP (Model Context Protocol) Tools
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **MCPTool** | Invoke tools on connected MCP servers | Varies |
| **ListMcpResourcesTool** | List resources exposed by MCP servers | Yes |
| **ReadMcpResourceTool** | Read a specific MCP resource | Yes |
| **McpAuthTool** | Handle MCP server authentication | No |
| **ToolSearchTool** | Discover deferred/dynamic tools from MCP servers | Yes |
## Integration Tools
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **LSPTool** | Language Server Protocol operations (go-to-definition, find references, etc.) | Yes |
| **SkillTool** | Execute a registered skill | Varies |
## Scheduling & Triggers
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **ScheduleCronTool** | Create a scheduled cron trigger | No |
| **RemoteTriggerTool** | Fire a remote trigger | No |
## Utility Tools
| Tool | Description | Read-Only |
|------|-------------|-----------|
| **AskUserQuestionTool** | Prompt the user for input during execution | Yes |
| **BriefTool** | Generate a brief/summary | Yes |
| **ConfigTool** | Read or modify Claude Code configuration | No |
---
## Permission Model
Every tool invocation passes through the permission system (`src/hooks/toolPermission/`). Permission modes:
| Mode | Behavior |
|------|----------|
| `default` | Prompt the user for each potentially destructive operation |
| `plan` | Show the full plan, ask once |
| `bypassPermissions` | Auto-approve everything (dangerous) |
| `auto` | ML-based classifier decides |
Permission rules use wildcard patterns:
```
Bash(git *) # Allow all git commands
FileEdit(/src/*) # Allow edits to anything in src/
FileRead(*) # Allow reading any file
```
Each tool implements `checkPermissions()` returning `{ granted: boolean, reason?, prompt? }`.
---
## Tool Presets
Tools are grouped into presets in `src/tools.ts` for different contexts (e.g. read-only tools for code review, full toolset for development).
---
## See Also
- [Architecture](architecture.md) — How tools fit into the overall pipeline
- [Subsystems Guide](subsystems.md) — MCP, permissions, and other tool-related subsystems
- [Exploration Guide](exploration-guide.md) — How to read tool source code

View File

@@ -134,6 +134,30 @@ Once connected, you can ask your AI assistant things like:
- Use the `explain_tool` prompt with "FileEditTool" to get a full breakdown
- Use `how_does_it_work` with "bridge" to understand IDE integration
## Publishing to MCP Registry
This server is published to the [MCP Registry](https://registry.modelcontextprotocol.io) via GitHub Actions. On a tagged release (`v*`), the workflow:
1. Publishes the npm package to npmjs.org
2. Authenticates with the MCP Registry using GitHub OIDC
3. Publishes the `server.json` metadata to the registry
To publish manually:
```bash
# Install the MCP Publisher CLI
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
# Authenticate (GitHub OAuth)
./mcp-publisher login github
# Publish
cd mcp-server
../mcp-publisher publish
```
Registry name: `io.github.nirholas/claude-code-explorer-mcp`
## Development
```bash

File diff suppressed because it is too large Load Diff

24
mcp-server/server.json Normal file
View File

@@ -0,0 +1,24 @@
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.nirholas/claude-code-explorer-mcp",
"title": "Claude Code Explorer MCP",
"description": "MCP server for exploring the Claude Code CLI source code — browse 40+ tools, 50+ commands, search the full 512K-line codebase, and get architecture overviews.",
"repository": {
"url": "https://github.com/nirholas/claude-code",
"source": "github",
"subfolder": "mcp-server"
},
"version": "1.1.0",
"packages": [
{
"registryType": "npm",
"registryBaseUrl": "https://registry.npmjs.org",
"identifier": "claude-code-explorer-mcp",
"version": "1.1.0",
"transport": {
"type": "stdio"
},
"runtimeHint": "node"
}
]
}

View File

@@ -24,386 +24,6 @@ main().catch((err) => {
});
/** Recursively collect all file paths under `root` (relative to root). */
async function walkFiles(root: string, rel = ""): Promise<string[]> {
const results: string[] = [];
let entries;
try {
entries = await fs.readdir(path.join(root, rel), { withFileTypes: true });
} catch {
return results;
}
for (const e of entries) {
const child = rel ? `${rel}/${e.name}` : e.name;
if (e.isDirectory()) {
results.push(...(await walkFiles(root, child)));
} else {
results.push(child);
}
}
return results;
}
/** Safely resolve a user-supplied relative path under SRC_ROOT. */
function safePath(relPath: string): string | null {
const resolved = path.resolve(SRC_ROOT, relPath);
if (!resolved.startsWith(SRC_ROOT)) return null; // path traversal blocked
return resolved;
}
// ---------------------------------------------------------------------------
// Tool & Command Metadata
// ---------------------------------------------------------------------------
interface ToolInfo {
name: string;
directory: string;
files: string[];
}
interface CommandInfo {
name: string;
path: string;
isDirectory: boolean;
files?: string[];
}
async function getToolList(): Promise<ToolInfo[]> {
const toolsDir = path.join(SRC_ROOT, "tools");
const entries = await fs.readdir(toolsDir, { withFileTypes: true });
const tools: ToolInfo[] = [];
for (const e of entries) {
if (!e.isDirectory() || e.name === "shared" || e.name === "testing")
continue;
const files = await listDir(path.join(toolsDir, e.name));
tools.push({ name: e.name, directory: `tools/${e.name}`, files });
}
return tools.sort((a, b) => a.name.localeCompare(b.name));
}
async function getCommandList(): Promise<CommandInfo[]> {
const cmdsDir = path.join(SRC_ROOT, "commands");
const entries = await fs.readdir(cmdsDir, { withFileTypes: true });
const commands: CommandInfo[] = [];
for (const e of entries) {
if (e.isDirectory()) {
const files = await listDir(path.join(cmdsDir, e.name));
commands.push({
name: e.name,
path: `commands/${e.name}`,
isDirectory: true,
files,
});
} else {
commands.push({
name: e.name.replace(/\.(ts|tsx)$/, ""),
path: `commands/${e.name}`,
isDirectory: false,
});
}
}
return commands.sort((a, b) => a.name.localeCompare(b.name));
}
// ---------------------------------------------------------------------------
// Server
// ---------------------------------------------------------------------------
const server = new Server(
{ name: "claude-code-explorer", version: "1.0.0" },
{
capabilities: {
tools: {},
resources: {},
prompts: {},
},
}
);
// ---- Resources -----------------------------------------------------------
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
resources: [
{
uri: "claude-code://architecture",
name: "Architecture Overview",
description: "High-level overview of the Claude Code source architecture",
mimeType: "text/markdown",
},
{
uri: "claude-code://tools",
name: "Tool Registry",
description: "List of all agent tools with their files",
mimeType: "application/json",
},
{
uri: "claude-code://commands",
name: "Command Registry",
description: "List of all slash commands",
mimeType: "application/json",
},
],
}));
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
resourceTemplates: [
{
uriTemplate: "claude-code://source/{path}",
name: "Source file",
description: "Read a source file from the Claude Code src/ directory",
mimeType: "text/plain",
},
],
}));
server.setRequestHandler(ReadResourceRequestSchema, async (request: { params: { uri: string } }) => {
const { uri } = request.params;
if (uri === "claude-code://architecture") {
const readmePath = path.resolve(SRC_ROOT, "..", "README.md");
let text: string;
try {
text = await fs.readFile(readmePath, "utf-8");
} catch {
text = "README.md not found.";
}
return { contents: [{ uri, mimeType: "text/markdown", text }] };
}
if (uri === "claude-code://tools") {
const tools = await getToolList();
return {
contents: [
{
uri,
mimeType: "application/json",
text: JSON.stringify(tools, null, 2),
},
],
};
}
if (uri === "claude-code://commands") {
const commands = await getCommandList();
return {
contents: [
{
uri,
mimeType: "application/json",
text: JSON.stringify(commands, null, 2),
},
],
};
}
// Source file template
if (uri.startsWith("claude-code://source/")) {
const relPath = uri.slice("claude-code://source/".length);
const abs = safePath(relPath);
if (!abs) throw new Error("Invalid path");
const text = await fs.readFile(abs, "utf-8");
return { contents: [{ uri, mimeType: "text/plain", text }] };
}
throw new Error(`Unknown resource: ${uri}`);
});
// ---- Tools ---------------------------------------------------------------
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "list_tools",
description:
"List all Claude Code agent tools (BashTool, FileReadTool, etc.) with their source files.",
inputSchema: { type: "object" as const, properties: {} },
},
{
name: "list_commands",
description:
"List all Claude Code slash commands (/commit, /review, /mcp, etc.) with their source files.",
inputSchema: { type: "object" as const, properties: {} },
},
{
name: "get_tool_source",
description:
"Read the full source code of a specific Claude Code tool implementation. Provide the tool directory name (e.g. 'BashTool', 'FileEditTool').",
inputSchema: {
type: "object" as const,
properties: {
toolName: {
type: "string",
description:
"Tool directory name, e.g. 'BashTool', 'FileReadTool'",
},
fileName: {
type: "string",
description:
"Optional: specific file within the tool directory. If omitted, returns the main implementation file.",
},
},
required: ["toolName"],
},
},
{
name: "get_command_source",
description:
"Read the source code of a specific Claude Code slash command. Provide the command name (e.g. 'commit', 'review', 'mcp').",
inputSchema: {
type: "object" as const,
properties: {
commandName: {
type: "string",
description: "Command name, e.g. 'commit', 'review', 'mcp'",
},
fileName: {
type: "string",
description:
"Optional: specific file within the command directory.",
},
},
required: ["commandName"],
},
},
{
name: "read_source_file",
description:
"Read any source file from the Claude Code src/ directory by relative path.",
inputSchema: {
type: "object" as const,
properties: {
path: {
type: "string",
description:
"Relative path from src/, e.g. 'QueryEngine.ts', 'services/mcp/types.ts'",
},
startLine: {
type: "number",
description: "Optional 1-based start line to read from.",
},
endLine: {
type: "number",
description: "Optional 1-based end line to read to.",
},
},
required: ["path"],
},
},
{
name: "search_source",
description:
"Search for a pattern (regex or plain text) across the Claude Code source code. Returns matching lines with file paths and line numbers.",
inputSchema: {
type: "object" as const,
properties: {
pattern: {
type: "string",
description: "Search pattern (regex supported).",
},
filePattern: {
type: "string",
description:
"Optional glob-like filter for file extensions, e.g. '.ts', '.tsx'.",
},
maxResults: {
type: "number",
description: "Maximum number of matches to return (default: 50).",
},
},
required: ["pattern"],
},
},
{
name: "list_directory",
description:
"List files and subdirectories within a directory under src/.",
inputSchema: {
type: "object" as const,
properties: {
path: {
type: "string",
description:
"Relative path from src/, e.g. 'services', 'tools/BashTool'. Use '' for the root.",
},
},
required: ["path"],
},
},
{
name: "get_architecture",
description:
"Get a high-level architecture overview of Claude Code including directory structure, core systems, and key files.",
inputSchema: { type: "object" as const, properties: {} },
},
],
}));
server.setRequestHandler(CallToolRequestSchema, async (request: { params: { name: string; arguments?: Record<string, unknown> } }) => {
const { name, arguments: args } = request.params;
switch (name) {
// ---- list_tools ----
case "list_tools": {
const tools = await getToolList();
return {
content: [{ type: "text" as const, text: JSON.stringify(tools, null, 2) }],
};
}
// ---- list_commands ----
case "list_commands": {
const commands = await getCommandList();
return {
content: [
{ type: "text" as const, text: JSON.stringify(commands, null, 2) },
],
};
}
// ---- get_tool_source ----
case "get_tool_source": {
const toolName = (args as Record<string, unknown>)?.toolName as string;
if (!toolName) throw new Error("toolName is required");
const toolDir = safePath(`tools/${toolName}`);
if (!toolDir || !(await dirExists(toolDir)))
throw new Error(`Tool not found: ${toolName}`);
let fileName = (args as Record<string, unknown>)?.fileName as
| string
| undefined;
if (!fileName) {
// Find the main implementation file
const files = await listDir(toolDir);
const main =
files.find(
(f) => f === `${toolName}.ts` || f === `${toolName}.tsx`
) ?? files.find((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
if (!main) throw new Error(`No source files in ${toolName}`);
fileName = main;
}
const filePath = safePath(`tools/${toolName}/${fileName}`);
if (!filePath || !(await fileExists(filePath)))
throw new Error(`File not found: tools/${toolName}/${fileName}`);
const content = await fs.readFile(filePath, "utf-8");
return {
content: [
{
type: "text" as const,
text: `// tools/${toolName}/${fileName}\n// ${content.split("\n").length} lines\n\n${content}`,
},
],
};
}
// ---- get_command_source ----
case "get_command_source": {
const commandName = (args as Record<string, unknown>)
?.commandName as string;
if (!commandName) throw new Error("commandName is required");
// Try directory first, then .ts / .tsx
const candidates = [
`commands/${commandName}`,

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env node
/**
* STDIO entrypoint — for local use with Claude Desktop, Claude Code, etc.
*
* Usage:
* node dist/index.js
* CLAUDE_CODE_SRC_ROOT=/path/to/src node dist/index.js
*/
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { createServer, validateSrcRoot, SRC_ROOT } from "./server.js";
async function main() {
await validateSrcRoot();
const server = createServer();
const transport = new StdioServerTransport();
await server.connect(transport);
console.error(`Claude Code Explorer MCP (stdio) started — src: ${SRC_ROOT}`);
}
main().catch((err) => {
console.error("Fatal error:", err);
process.exit(1);
});

2560
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

35
prompts/00-overview.md Normal file
View File

@@ -0,0 +1,35 @@
# Build-Out Prompt Index
Run these prompts **in order** in separate chat sessions. Each one is self-contained.
| # | File | What It Does | Depends On |
|---|------|-------------|------------|
| 01 | `01-install-bun-and-deps.md` | Install Bun runtime, install all dependencies | — |
| 02 | `02-runtime-shims.md` | Create `bun:bundle` runtime shim + `MACRO` globals so code runs without Bun's bundler | 01 |
| 03 | `03-build-config.md` | Create esbuild-based build system that bundles the CLI to a single runnable file | 01, 02 |
| 04 | `04-fix-mcp-server.md` | Fix TypeScript errors in `mcp-server/` and make it build | 01 |
| 05 | `05-env-and-auth.md` | Set up `.env` file, API key config, OAuth stubs | 01 |
| 06 | `06-ink-react-terminal-ui.md` | Verify and fix the Ink/React terminal rendering pipeline | 01, 02, 03 |
| 07 | `07-tool-system.md` | Audit and wire up the 40+ tool implementations (BashTool, FileEditTool, etc.) | 0103 |
| 08 | `08-command-system.md` | Audit and wire up the 50+ slash commands (/commit, /review, etc.) | 0103, 07 |
| 09 | `09-query-engine.md` | Get the core LLM call loop (QueryEngine) functional — streaming, tool calls, retries | 0103, 05, 07 |
| 10 | `10-context-and-prompts.md` | Wire up system prompt construction, context gathering, memory system | 0103 |
| 11 | `11-mcp-integration.md` | Get MCP client/server integration working — registry, tool discovery | 0104 |
| 12 | `12-services-layer.md` | Wire up analytics, policy limits, remote settings, session memory | 0103, 05 |
| 13 | `13-bridge-ide.md` | Stub out or implement the VS Code / JetBrains bridge layer | 0103, 09 |
| 14 | `14-dev-runner.md` | Create `npm run dev` / `bun run dev` script that launches the CLI in dev mode | 0103 |
| 15 | `15-production-bundle.md` | Create production build: minified bundle, platform-specific packaging | 03 |
| 16 | `16-testing.md` | Add test infrastructure (vitest), write smoke tests for core subsystems | All |
## Quick Start
1. Open a new Copilot chat
2. Paste the contents of `01-install-bun-and-deps.md`
3. Follow the instructions / let the agent run
4. Repeat for `02`, `03`, etc.
## Notes
- Prompts 0713 can be run somewhat in **parallel** (they touch different subsystems)
- If a prompt fails, fix the issue before moving to the next one
- Each prompt is designed to be **independently verifiable** — it tells you how to confirm it worked

View File

@@ -0,0 +1,38 @@
# Prompt 01: Install Bun Runtime & Dependencies
## Context
You are working in `/workspaces/claude-code`, which contains the leaked source code of Anthropic's Claude Code CLI. It's a TypeScript/TSX project that uses **Bun** as its runtime (not Node.js). The `package.json` specifies `"engines": { "bun": ">=1.1.0" }`.
There is no `bun.lockb` lockfile — it was not included in the leak.
## Task
1. **Install Bun** (if not already installed):
```
curl -fsSL https://bun.sh/install | bash
```
Then ensure `bun` is on the PATH.
2. **Run `bun install`** in the project root (`/workspaces/claude-code`) to install all dependencies. This will generate a `bun.lockb` lockfile.
3. **Verify the install** — confirm that:
- `node_modules/` exists and has the major packages: `@anthropic-ai/sdk`, `react`, `chalk`, `@commander-js/extra-typings`, `ink` (may not exist separately — check `@anthropic-ai/sdk`, `zod`, `@modelcontextprotocol/sdk`)
- `bun --version` returns 1.1.0+
4. **Run the typecheck** to see current state:
```
bun run typecheck
```
Report any errors — don't fix them yet, just capture the output.
5. **Also install deps for the mcp-server sub-project**:
```
cd mcp-server && npm install && cd ..
```
## Verification
- `bun --version` outputs >= 1.1.0
- `ls node_modules/@anthropic-ai/sdk` succeeds
- `bun run typecheck` runs (errors are expected at this stage, just report them)

137
prompts/02-runtime-shims.md Normal file
View File

@@ -0,0 +1,137 @@
# Prompt 02: Runtime Shims for `bun:bundle` Feature Flags & `MACRO` Globals
## Context
You are working in `/workspaces/claude-code`. This is the Claude Code CLI source. It was built to run under **Bun's bundler** which provides two build-time features that don't exist at runtime:
### 1. `bun:bundle` feature flags
Throughout the code you'll find:
```ts
import { feature } from 'bun:bundle'
if (feature('BRIDGE_MODE')) { ... }
```
Bun's bundler replaces `feature('X')` with `true`/`false` at build time for dead-code elimination. Without the bundler, this import fails at runtime.
**Current state**: There's a type stub at `src/types/bun-bundle.d.ts` that satisfies TypeScript, but there's no runtime module. We need a real module.
### 2. `MACRO` global object
The code references a global `MACRO` object with these properties:
- `MACRO.VERSION` — package version string (e.g., `"1.0.53"`)
- `MACRO.PACKAGE_URL` — npm package name (e.g., `"@anthropic-ai/claude-code"`)
- `MACRO.ISSUES_EXPLAINER` — feedback URL/instructions string
These are normally inlined by the bundler. Some files already guard with `typeof MACRO !== 'undefined'`, but most don't.
## Task
### Part A: Create `bun:bundle` runtime module
Create a file at `src/shims/bun-bundle.ts` that exports a `feature()` function. Feature flags should be configurable via environment variables so we can toggle them:
```ts
// src/shims/bun-bundle.ts
// Map of feature flags to their enabled state.
// In production Bun builds, these are compile-time constants.
// For our dev build, we read from env vars with sensible defaults.
const FEATURE_FLAGS: Record<string, boolean> = {
PROACTIVE: envBool('CLAUDE_CODE_PROACTIVE', false),
KAIROS: envBool('CLAUDE_CODE_KAIROS', false),
BRIDGE_MODE: envBool('CLAUDE_CODE_BRIDGE_MODE', false),
DAEMON: envBool('CLAUDE_CODE_DAEMON', false),
VOICE_MODE: envBool('CLAUDE_CODE_VOICE_MODE', false),
AGENT_TRIGGERS: envBool('CLAUDE_CODE_AGENT_TRIGGERS', false),
MONITOR_TOOL: envBool('CLAUDE_CODE_MONITOR_TOOL', false),
COORDINATOR_MODE: envBool('CLAUDE_CODE_COORDINATOR_MODE', false),
ABLATION_BASELINE: false, // always off for external builds
DUMP_SYSTEM_PROMPT: envBool('CLAUDE_CODE_DUMP_SYSTEM_PROMPT', false),
BG_SESSIONS: envBool('CLAUDE_CODE_BG_SESSIONS', false),
}
function envBool(key: string, fallback: boolean): boolean {
const v = process.env[key]
if (v === undefined) return fallback
return v === '1' || v === 'true'
}
export function feature(name: string): boolean {
return FEATURE_FLAGS[name] ?? false
}
```
### Part B: Create `MACRO` global definition
Create a file at `src/shims/macro.ts` that defines and installs the global `MACRO` object:
```ts
// src/shims/macro.ts
// Read version from package.json at startup
import { readFileSync } from 'fs'
import { resolve, dirname } from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const pkgPath = resolve(dirname(__filename), '..', '..', 'package.json')
let version = '0.0.0-dev'
try {
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
version = pkg.version || version
} catch {}
const MACRO_OBJ = {
VERSION: version,
PACKAGE_URL: '@anthropic-ai/claude-code',
ISSUES_EXPLAINER: 'report issues at https://github.com/anthropics/claude-code/issues',
}
// Install as global
;(globalThis as any).MACRO = MACRO_OBJ
export default MACRO_OBJ
```
### Part C: Create a preload/bootstrap file
Create `src/shims/preload.ts` that imports both shims so they're available before any app code runs:
```ts
// src/shims/preload.ts
// Must be loaded before any application code.
// Provides runtime equivalents of Bun bundler build-time features.
import './macro.js'
// bun:bundle is resolved via the build alias, not imported here
```
### Part D: Update tsconfig.json `paths`
The current tsconfig.json has:
```json
"paths": {
"bun:bundle": ["./src/types/bun-bundle.d.ts"]
}
```
This handles type-checking. For runtime, we'll need the build system (Prompt 03) to alias `bun:bundle``src/shims/bun-bundle.ts`. **Don't change tsconfig.json** — the type stub is correct for `tsc`. Just note this for the next prompt.
### Part E: Add global MACRO type declaration
Check if there's already a global type declaration for `MACRO`. If not, add one to `src/types/bun-bundle.d.ts` or a new `src/types/macro.d.ts`:
```ts
declare const MACRO: {
VERSION: string
PACKAGE_URL: string
ISSUES_EXPLAINER: string
}
```
Make sure `tsc --noEmit` still passes after your changes.
## Verification
1. `bun run typecheck` should pass (or have the same errors as before — no new errors)
2. The files `src/shims/bun-bundle.ts`, `src/shims/macro.ts`, `src/shims/preload.ts` exist
3. Running `bun -e "import { feature } from './src/shims/bun-bundle.ts'; console.log(feature('BRIDGE_MODE'))"` should print `false`
4. Running `bun -e "import './src/shims/macro.ts'; console.log(MACRO.VERSION)"` should print the version

165
prompts/03-build-config.md Normal file
View File

@@ -0,0 +1,165 @@
# Prompt 03: Create esbuild-Based Build System
## Context
You are working in `/workspaces/claude-code`. This is the Claude Code CLI — a TypeScript/TSX terminal app using React + Ink. It was originally built using **Bun's bundler** with feature flags, but that build config wasn't included in the leak.
We need to create a build system that:
1. Bundles the entire `src/` tree into a runnable output
2. Aliases `bun:bundle` → our shim at `src/shims/bun-bundle.ts`
3. Injects the `MACRO` global (via `src/shims/macro.ts` preload)
4. Handles TSX/JSX (React)
5. Handles ESM `.js` extension imports (the code uses `import from './foo.js'` which maps to `./foo.ts`)
6. Produces output that can run under **Bun** (primary) or **Node.js 20+** (secondary)
## Existing Files
- `src/shims/bun-bundle.ts` — runtime `feature()` function (created in Prompt 02)
- `src/shims/macro.ts` — global `MACRO` object (created in Prompt 02)
- `src/shims/preload.ts` — preload bootstrap (created in Prompt 02)
- `src/entrypoints/cli.tsx` — main entrypoint
- `tsconfig.json` — has `"jsx": "react-jsx"`, `"module": "ESNext"`, `"moduleResolution": "bundler"`
## Task
### Part A: Install esbuild
```bash
bun add -d esbuild
```
### Part B: Create build script
Create `scripts/build-bundle.ts` (a Bun-runnable build script):
```ts
// scripts/build-bundle.ts
// Usage: bun scripts/build-bundle.ts [--watch] [--minify]
import * as esbuild from 'esbuild'
import { resolve } from 'path'
const ROOT = resolve(import.meta.dir, '..')
const watch = process.argv.includes('--watch')
const minify = process.argv.includes('--minify')
const buildOptions: esbuild.BuildOptions = {
entryPoints: [resolve(ROOT, 'src/entrypoints/cli.tsx')],
bundle: true,
platform: 'node',
target: 'node20',
format: 'esm',
outdir: resolve(ROOT, 'dist'),
outExtension: { '.js': '.mjs' },
// Inject the MACRO global before all other code
inject: [resolve(ROOT, 'src/shims/macro.ts')],
// Alias bun:bundle to our runtime shim
alias: {
'bun:bundle': resolve(ROOT, 'src/shims/bun-bundle.ts'),
},
// Don't bundle node built-ins or native packages
external: [
// Node built-ins
'fs', 'path', 'os', 'crypto', 'child_process', 'http', 'https',
'net', 'tls', 'url', 'util', 'stream', 'events', 'buffer',
'querystring', 'readline', 'zlib', 'assert', 'tty', 'worker_threads',
'perf_hooks', 'async_hooks', 'dns', 'dgram', 'cluster',
'node:*',
// Native addons that can't be bundled
'fsevents',
],
jsx: 'automatic',
// Source maps for debugging
sourcemap: true,
minify,
// Banner: shebang for CLI + preload the MACRO global
banner: {
js: '#!/usr/bin/env node\n',
},
// Handle the .js → .ts resolution that the codebase uses
resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
logLevel: 'info',
}
async function main() {
if (watch) {
const ctx = await esbuild.context(buildOptions)
await ctx.watch()
console.log('Watching for changes...')
} else {
const result = await esbuild.build(buildOptions)
if (result.errors.length > 0) {
console.error('Build failed')
process.exit(1)
}
console.log('Build complete → dist/')
}
}
main().catch(err => {
console.error(err)
process.exit(1)
})
```
**Important**: This is a starting point. You will likely need to iterate on the externals list and alias configuration. The codebase has ~1,900 files — some imports may need special handling. When you run the build:
1. Run it: `bun scripts/build-bundle.ts`
2. Look at the errors
3. Fix them (add externals, fix aliases, etc.)
4. Repeat until it bundles successfully
Common issues you'll hit:
- **npm packages that use native modules** → add to `external`
- **Dynamic `require()` calls** behind `process.env.USER_TYPE === 'ant'` → these are Anthropic-internal, wrap them or stub them
- **Circular dependencies** → esbuild handles these but may warn
- **Re-exports from barrel files** → should work but watch for issues
### Part C: Add npm scripts
Add these to `package.json` `"scripts"`:
```json
{
"build": "bun scripts/build-bundle.ts",
"build:watch": "bun scripts/build-bundle.ts --watch",
"build:prod": "bun scripts/build-bundle.ts --minify"
}
```
### Part D: Create dist output directory
Add `dist/` to `.gitignore` (create one if it doesn't exist).
### Part E: Iterate on build errors
Run the build and fix whatever comes up. The goal is a clean `bun scripts/build-bundle.ts` that produces `dist/cli.mjs`.
**Strategy for unresolvable modules**: If modules reference Anthropic-internal packages or Bun-specific APIs (like `Bun.hash`, `Bun.file`), create minimal stubs in `src/shims/` that provide compatible fallbacks.
### Part F: Test the output
After a successful build:
```bash
node dist/cli.mjs --version
# or
bun dist/cli.mjs --version
```
This should print the version. It will likely crash after that because no API key is configured — that's fine for now.
## Verification
1. `bun scripts/build-bundle.ts` completes without errors
2. `dist/cli.mjs` exists
3. `bun dist/cli.mjs --version` or `node dist/cli.mjs --version` prints a version string
4. `package.json` has `build`, `build:watch`, `build:prod` scripts

View File

@@ -0,0 +1,45 @@
# Prompt 04: Fix MCP Server Build
## Context
You are working in `/workspaces/claude-code/mcp-server/`. This is a separate sub-project that provides an MCP (Model Context Protocol) server for exploring the Claude Code source. It's a simpler, self-contained TypeScript project.
Currently `npm run build` (which runs `tsc`) fails with TypeScript errors.
## Task
1. **Run the build and capture errors**:
```bash
cd /workspaces/claude-code/mcp-server
npm run build 2>&1
```
2. **Fix all TypeScript errors** in `mcp-server/src/server.ts` and `mcp-server/src/index.ts`. Common issues include:
- Duplicate function implementations
- Missing imports
- Type mismatches with the MCP SDK types
3. **Verify the fix**:
```bash
npm run build
```
Should complete with zero errors and produce output in `mcp-server/dist/`.
4. **Test the MCP server runs**:
```bash
node dist/index.js --help 2>&1 || node dist/index.js 2>&1 | head -5
```
It may hang waiting for stdio input (that's normal for an MCP server) — just verify it starts without crashing.
## Key Files
- `mcp-server/package.json` — build script and dependencies
- `mcp-server/tsconfig.json` — TypeScript config
- `mcp-server/src/server.ts` — Main server logic (tools, resources, prompts)
- `mcp-server/src/index.ts` — Entrypoint (stdio transport)
## Verification
1. `cd mcp-server && npm run build` succeeds with zero errors
2. `ls mcp-server/dist/` shows compiled `.js` files
3. `node mcp-server/dist/index.js` starts without immediate crash

100
prompts/05-env-and-auth.md Normal file
View File

@@ -0,0 +1,100 @@
# Prompt 05: Environment Configuration & API Authentication
## Context
You are working in `/workspaces/claude-code`. The CLI needs an Anthropic API key to function. The auth system supports multiple backends:
- **Direct API** (`ANTHROPIC_API_KEY`) — simplest
- **OAuth** (Claude.ai subscription) — complex browser flow
- **AWS Bedrock** — `AWS_*` env vars
- **Google Vertex AI** — GCP credentials
- **Azure Foundry** — `ANTHROPIC_FOUNDRY_API_KEY`
## Task
### Part A: Create `.env` file from the existing code
Search the codebase for all environment variables used. Key files to check:
- `src/entrypoints/cli.tsx` (reads env vars at top level)
- `src/services/api/client.ts` (API client construction)
- `src/utils/auth.ts` (authentication)
- `src/utils/config.ts` (config loading)
- `src/constants/` (any hardcoded config)
- `src/entrypoints/init.ts` (initialization reads)
Create a `.env.example` file (or update the existing one if it exists) with ALL discoverable env vars, organized by category, with documentation comments. At minimum include:
```env
# ─── Authentication ───
ANTHROPIC_API_KEY= # Required: Your Anthropic API key (sk-ant-...)
# ─── API Configuration ───
ANTHROPIC_BASE_URL= # Custom API endpoint (default: https://api.anthropic.com)
ANTHROPIC_MODEL= # Override default model (e.g., claude-sonnet-4-20250514)
ANTHROPIC_SMALL_FAST_MODEL= # Model for fast/cheap operations (e.g., claude-haiku)
# ─── Feature Flags (used by bun:bundle shim) ───
CLAUDE_CODE_PROACTIVE=false
CLAUDE_CODE_BRIDGE_MODE=false
CLAUDE_CODE_COORDINATOR_MODE=false
CLAUDE_CODE_VOICE_MODE=false
# ─── Debug ───
CLAUDE_CODE_DEBUG_LOG_LEVEL= # debug, info, warn, error
DEBUG=false
```
### Part B: Trace the API client setup
Read `src/services/api/client.ts` to understand how the Anthropic SDK is initialized. Document:
1. What env vars it reads
2. How it selects between API backends (direct, Bedrock, Vertex, etc.)
3. Where the API key comes from (env var? keychain? OAuth token?)
Create a comment block at the top of `.env.example` explaining how auth works.
### Part C: Create a minimal auth test
Create `scripts/test-auth.ts`:
```ts
// scripts/test-auth.ts
// Quick test that the API key is configured and can reach Anthropic
// Usage: bun scripts/test-auth.ts
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
})
async function main() {
try {
const msg = await client.messages.create({
model: process.env.ANTHROPIC_MODEL || 'claude-sonnet-4-20250514',
max_tokens: 50,
messages: [{ role: 'user', content: 'Say "hello" and nothing else.' }],
})
console.log('✅ API connection successful!')
console.log('Response:', msg.content[0].type === 'text' ? msg.content[0].text : msg.content[0])
} catch (err: any) {
console.error('❌ API connection failed:', err.message)
process.exit(1)
}
}
main()
```
### Part D: Stub OAuth for development
The OAuth flow (`src/services/oauth/`) requires browser interaction and Anthropic's OAuth endpoints. For development, we want to bypass it.
Search for where the auth decision is made (likely in `src/utils/auth.ts` or `src/entrypoints/init.ts`). Document what would need to be stubbed to skip OAuth and use only `ANTHROPIC_API_KEY`.
Don't modify source files yet — just document findings in a comment at the bottom of `.env.example`.
## Verification
1. `.env.example` exists with comprehensive env var documentation
2. `scripts/test-auth.ts` exists
3. With a valid `ANTHROPIC_API_KEY` set: `bun scripts/test-auth.ts` prints success
4. Without an API key: `bun scripts/test-auth.ts` prints a clear error

View File

@@ -0,0 +1,110 @@
# Prompt 06: Verify and Fix the Ink/React Terminal UI Pipeline
## Context
You are working in `/workspaces/claude-code`. The CLI renders its UI using **React + Ink** — a framework that renders React components to the terminal (not a browser). This project includes a **custom fork of Ink** embedded directly in `src/ink/`.
Key files:
- `src/ink.ts` — Public API (re-exports `render()` and `createRoot()`, wraps with `ThemeProvider`)
- `src/ink/root.ts` — Ink's root renderer
- `src/ink/ink.tsx` — Core Ink component
- `src/ink/reconciler.ts` — React reconciler for terminal output
- `src/ink/dom.ts` — Terminal DOM implementation
- `src/ink/renderer.ts` — Renders virtual DOM to terminal strings
- `src/ink/components/` — Built-in Ink components (Box, Text, etc.)
- `src/components/` — Claude Code's ~140 custom components
## Task
### Part A: Trace the render pipeline
Read these files in order and document the rendering flow:
1. `src/ink.ts` → how `render()` and `createRoot()` work
2. `src/ink/root.ts` → how Ink creates a root and mounts React
3. `src/ink/reconciler.ts` → what React reconciler is used
4. `src/ink/renderer.ts` → how the virtual DOM becomes terminal output
5. `src/ink/dom.ts` → what the "DOM nodes" look like
Create a brief architecture doc in a comment block or README section.
### Part B: Verify Ink components compile
Check that the core Ink components are self-contained:
```
src/ink/components/
```
List them all and verify they don't have missing imports.
### Part C: Check the ThemeProvider
Read `src/components/design-system/ThemeProvider.tsx` (or wherever it lives). Verify it:
1. Exists
2. Exports a `ThemeProvider` component
3. The theme system doesn't depend on external resources
### Part D: Create a minimal render test
Create `scripts/test-ink.tsx`:
```tsx
// scripts/test-ink.tsx
// Minimal test that the Ink terminal UI renders
// Usage: bun scripts/test-ink.tsx
import React from 'react'
// We need the shims loaded first
import './src/shims/preload.js'
// Now try to use Ink
import { render } from './src/ink.js'
// Minimal component
function Hello() {
return <Text>Hello from Claude Code Ink UI!</Text>
}
// Need to import Text from Ink
import { Text } from './src/ink/components/Text.js'
async function main() {
const instance = await render(<Hello />)
// Give it a moment to render
setTimeout(() => {
instance.unmount()
process.exit(0)
}, 500)
}
main().catch(err => {
console.error('Ink render test failed:', err)
process.exit(1)
})
```
Adjust the imports based on what you find — the Text component path may differ.
### Part E: Fix any issues
If Ink rendering fails, the common issues are:
1. **Missing `yoga-wasm-web` or `yoga-layout`** — Ink uses Yoga for flexbox layout. Check if there's a Yoga dependency or if it's embedded.
2. **React version mismatch** — The code uses React 19. Verify the reconciler is compatible.
3. **Terminal detection** — Ink checks if stdout is a TTY. In some environments this may need to be forced.
4. **Missing chalk/ansi dependency** — Terminal colors.
Fix whatever you find to make the test render successfully.
### Part F: Verify component imports
Check that `src/components/` components can import from the Ink system without errors. Pick 3-5 key components:
- `src/components/MessageResponse.tsx` (or similar — the main chat message renderer)
- `src/components/ToolUseResult.tsx` (or similar — tool output display)
- `src/components/PermissionRequest.tsx` (or similar — permission modal)
Read their imports and verify nothing is missing.
## Verification
1. `scripts/test-ink.tsx` renders "Hello from Claude Code Ink UI!" to the terminal
2. No new TypeScript errors introduced
3. You've documented the render pipeline flow

104
prompts/07-tool-system.md Normal file
View File

@@ -0,0 +1,104 @@
# Prompt 07: Audit and Wire Up the Tool System
## Context
You are working in `/workspaces/claude-code`. The Claude Code CLI has ~40 tools that the LLM can invoke during conversations. Each tool is in `src/tools/<ToolName>/` and follows a consistent pattern.
Key files:
- `src/Tool.ts` (~29K lines) — Tool type definitions, `ToolUseContext`, `PermissionResult`, etc.
- `src/tools.ts` — Tool registry (`getTools()` function that returns all available tools)
- `src/tools/` — Individual tool directories
## Task
### Part A: Understand the Tool interface
Read `src/Tool.ts` and document the `Tool` interface. Key questions:
1. What fields does a `Tool` have? (name, description, inputSchema, execute, etc.)
2. What is `ToolUseContext`? What does it provide to tool execution?
3. How do tool permissions work? (`PermissionResult`, `needsPermission`)
4. How do tools declare their input schema? (JSON Schema / Zod)
### Part B: Audit the tool registry
Read `src/tools.ts` fully. It dynamically imports tools behind feature flags and env checks:
```ts
const REPLTool = process.env.USER_TYPE === 'ant' ? ... : null
const SleepTool = feature('PROACTIVE') || feature('KAIROS') ? ... : null
```
Create a complete inventory of:
1. **Always-available tools** — imported unconditionally
2. **Feature-gated tools** — which feature flag enables them
3. **Ant-only tools** — gated behind `USER_TYPE === 'ant'` (Anthropic internal)
4. **Broken/missing tools** — any tools referenced but not found
### Part C: Verify each tool compiles
For each tool directory in `src/tools/`, check:
1. Does it have an `index.ts` or main file?
2. Does it export a tool definition matching the `Tool` interface?
3. Are its imports resolvable?
Focus on the **core 10 tools** that are essential for basic operation:
- `BashTool` — shell command execution
- `FileReadTool` — read files
- `FileWriteTool` — write files
- `FileEditTool` — edit files (search & replace)
- `GlobTool` — find files by pattern
- `GrepTool` — search file contents
- `AgentTool` — spawn sub-agent
- `WebFetchTool` — HTTP requests
- `AskUserQuestionTool` — ask the user for input
- `TodoWriteTool` — todo list management
### Part D: Fix import issues
The tool registry (`src/tools.ts`) uses dynamic imports with `bun:bundle` feature flags. With our runtime shim, these should work — but verify:
1. Feature-gated imports resolve when the flag is `false` (should be skipped)
2. Feature-gated imports resolve when the flag is `true` (should load)
3. Ant-only tools gracefully handle `process.env.USER_TYPE !== 'ant'`
Fix any import resolution errors.
### Part E: Create a tool smoke test
Create `scripts/test-tools.ts`:
```ts
// scripts/test-tools.ts
// Verify all tools load without errors
// Usage: bun scripts/test-tools.ts
import './src/shims/preload.js'
async function main() {
const { getTools } = await import('./src/tools.js')
// getTools() may need arguments — check its signature
const tools = getTools(/* ... */)
console.log(`Loaded ${tools.length} tools:\n`)
for (const tool of tools) {
console.log(`${tool.name}`)
}
}
main().catch(err => {
console.error('Tool loading failed:', err)
process.exit(1)
})
```
Adapt the script to match the actual `getTools()` signature.
### Part F: Stub Anthropic-internal tools
Any tools gated behind `USER_TYPE === 'ant'` should be cleanly excluded. Verify the null checks work and don't cause runtime errors when these tools are missing from the registry.
## Verification
1. `scripts/test-tools.ts` runs and lists all available tools without errors
2. The core 10 tools listed above are all present
3. No TypeScript errors in `src/tools/` or `src/tools.ts`
4. Ant-only tools are cleanly excluded (no crashes)

View File

@@ -0,0 +1,90 @@
# Prompt 08: Audit and Wire Up the Command System
## Context
You are working in `/workspaces/claude-code`. The CLI has ~50 slash commands (e.g., `/commit`, `/review`, `/init`, `/config`). These are registered in `src/commands.ts` and implemented in `src/commands/`.
Key files:
- `src/commands.ts` (~25K lines) — Command registry (`getCommands()`)
- `src/commands/` — Individual command implementations
- `src/types/command.ts` — Command type definition
## Task
### Part A: Understand the Command interface
Read `src/types/command.ts` and the top of `src/commands.ts`. Document:
1. The `Command` type (name, description, execute, args, etc.)
2. How commands are registered
3. How command execution is triggered (from the REPL? from CLI args?)
### Part B: Audit the command registry
Read `src/commands.ts` fully. Create a complete inventory of all commands, organized by category:
**Essential commands** (needed for basic operation):
- `/help` — show help
- `/config` — view/edit configuration
- `/init` — initialize a project
- `/commit` — git commit
- `/review` — code review
**Feature-gated commands** (behind feature flags or USER_TYPE):
- List which flag enables each
**Potentially broken commands** (reference missing imports or services):
- List any that can't resolve their imports
### Part C: Verify core commands compile
For the essential commands listed above, read their implementations and check:
1. All imports resolve
2. They don't depend on unavailable services
3. The function signatures match the Command type
### Part D: Fix import issues
Similar to the tool system, commands may have:
- Feature-gated imports that need the `bun:bundle` shim
- Ant-only code paths
- Dynamic imports that need correct paths
Fix whatever is broken.
### Part E: Handle "moved to plugin" commands
There's a file `src/commands/createMovedToPluginCommand.ts`. Read it — some commands have been migrated to the plugin system. These should gracefully tell the user the command has moved, not crash.
### Part F: Create a command smoke test
Create `scripts/test-commands.ts`:
```ts
// scripts/test-commands.ts
// Verify all commands load without errors
// Usage: bun scripts/test-commands.ts
import './src/shims/preload.js'
async function main() {
const { getCommands } = await import('./src/commands.js')
const commands = getCommands(/* check signature */)
console.log(`Loaded ${commands.length} commands:\n`)
for (const cmd of commands) {
console.log(` /${cmd.name}${cmd.description || '(no description)'}`)
}
}
main().catch(err => {
console.error('Command loading failed:', err)
process.exit(1)
})
```
## Verification
1. `scripts/test-commands.ts` lists all available commands
2. Core commands (`/help`, `/config`, `/init`, `/commit`) are present
3. No runtime crashes from missing imports
4. Moved-to-plugin commands show a friendly message instead of crashing

118
prompts/09-query-engine.md Normal file
View File

@@ -0,0 +1,118 @@
# Prompt 09: Get the QueryEngine (Core LLM Loop) Functional
## Context
You are working in `/workspaces/claude-code`. The `QueryEngine` (`src/QueryEngine.ts`, ~46K lines) is the heart of the CLI — it:
1. Sends messages to the Anthropic API (streaming)
2. Processes streaming responses (text, thinking, tool_use blocks)
3. Executes tools when the LLM requests them (tool loop)
4. Handles retries, rate limits, and errors
5. Tracks token usage and costs
6. Manages conversation context (message history)
This is the most complex single file. The goal is to get it functional enough for a basic conversation loop.
## Key Dependencies
The QueryEngine depends on:
- `src/services/api/client.ts` — Anthropic SDK client
- `src/services/api/claude.ts` — Message API wrapper
- `src/Tool.ts` — Tool definitions
- `src/tools.ts` — Tool registry
- `src/context.ts` — System context
- `src/constants/prompts.ts` — System prompt
- Token counting utilities
- Streaming event handlers
## Task
### Part A: Map the QueryEngine architecture
Read `src/QueryEngine.ts` and create a structural map:
1. **Class structure** — What classes/interfaces are defined?
2. **Public API** — What method starts a query? What does it return?
3. **Message flow** — How does a user message become an API call?
4. **Tool loop** — How are tool calls detected, executed, and fed back?
5. **Streaming** — How are streaming events processed?
6. **Retry logic** — How are API errors handled?
### Part B: Trace the API call path
Follow the chain from QueryEngine → API client:
1. Read `src/services/api/client.ts` — how is the Anthropic SDK client created?
2. Read `src/services/api/claude.ts` — what's the message creation wrapper?
3. What parameters are passed? (model, max_tokens, system prompt, tools, messages)
4. How is streaming handled? (SSE? SDK streaming?)
### Part C: Identify and fix blockers
The QueryEngine will have dependencies on many subsystems. For each dependency:
- **If it's essential** (API client, tool execution) → make sure it works
- **If it's optional** (analytics, telemetry, policy limits) → stub or skip it
Common blockers:
1. **Missing API configuration** → needs `ANTHROPIC_API_KEY` (Prompt 05)
2. **Policy limits service** → may block execution, needs stubbing
3. **GrowthBook/analytics** → needs stubbing or graceful failure
4. **Remote managed settings** → needs stubbing
5. **Bootstrap data fetch** → may need to be optional
### Part D: Create a minimal conversation test
Create `scripts/test-query.ts` that exercises the QueryEngine directly:
```ts
// scripts/test-query.ts
// Minimal test of the QueryEngine — single query, no REPL
// Usage: ANTHROPIC_API_KEY=sk-ant-... bun scripts/test-query.ts "What is 2+2?"
import './src/shims/preload.js'
async function main() {
const query = process.argv[2] || 'What is 2+2?'
// Import and set up minimal dependencies
// You'll need to figure out the exact imports and initialization
// by reading src/QueryEngine.ts, src/query.ts, and src/replLauncher.tsx
// The basic flow should be:
// 1. Create API client
// 2. Build system prompt
// 3. Create QueryEngine instance
// 4. Send a query
// 5. Print the response
console.log(`Query: ${query}`)
console.log('---')
// TODO: Wire up the actual QueryEngine call
// This is the hardest part — document what you need to do
}
main().catch(err => {
console.error('Query test failed:', err)
process.exit(1)
})
```
### Part E: Handle the streaming response
The QueryEngine likely uses the Anthropic SDK's streaming interface. Make sure:
1. Text content is printed to stdout as it streams
2. Thinking blocks are handled (displayed or hidden based on config)
3. Tool use blocks trigger tool execution
4. The tool loop feeds results back and continues
### Part F: Document what's still broken
After getting a basic query working, document:
1. Which features work
2. Which features are stubbed
3. What would need to happen for full functionality
## Verification
1. `ANTHROPIC_API_KEY=sk-ant-... bun scripts/test-query.ts "What is 2+2?"` gets a response
2. Streaming output appears in real-time
3. No unhandled crashes (graceful error messages are fine)
4. Architecture is documented

View File

@@ -0,0 +1,100 @@
# Prompt 10: Wire Up System Prompt, Context Gathering & Memory System
## Context
You are working in `/workspaces/claude-code`. The CLI constructs a detailed system prompt before each conversation. This prompt includes:
1. **Static instructions** — core behavior rules (from `src/constants/prompts.ts`)
2. **Dynamic context** — OS, shell, git status, working directory (from `src/context.ts`)
3. **Tool descriptions** — auto-generated from tool schemas
4. **Memory** — persistent `.claude.md` files (from `src/memdir/`)
5. **User context** — config, preferences, project settings
## Key Files
- `src/constants/prompts.ts` — System prompt construction
- `src/constants/system.ts` — System identity strings
- `src/context.ts` — OS/shell/git context collection
- `src/context/` — Additional context modules
- `src/memdir/` — Memory directory system (reads `.claude.md`, `CLAUDE.md` files)
- `src/utils/messages.ts` — Message construction helpers
## Task
### Part A: Trace the system prompt construction
Read `src/constants/prompts.ts` and map:
1. What is `getSystemPrompt()`'s signature and return type?
2. What sections does the system prompt contain?
3. How are tools described in the prompt?
4. What model-specific variations exist?
5. Where does the `MACRO.ISSUES_EXPLAINER` reference resolve to?
### Part B: Fix the context gathering
Read `src/context.ts` and:
1. Understand `getSystemContext()` and `getUserContext()`
2. These collect OS info, shell version, git status, etc.
3. Verify they work on Linux (this codebase was likely developed on macOS, so some paths may be macOS-specific)
4. Fix any platform-specific issues
### Part C: Wire up the memory system
Read `src/memdir/` directory:
1. How does it find `.claude.md` / `CLAUDE.md` files?
2. How is memory content injected into the system prompt?
3. Does it support project-level, user-level, and session-level memory?
Verify it works by:
1. Creating a test `CLAUDE.md` in the project root
2. Running the system prompt builder
3. Checking the memory appears in the output
### Part D: Create a prompt inspection script
Create `scripts/test-prompt.ts`:
```ts
// scripts/test-prompt.ts
// Dump the full system prompt that would be sent to the API
// Usage: bun scripts/test-prompt.ts
import './src/shims/preload.js'
async function main() {
// Import the prompt builder
const { getSystemPrompt } = await import('./src/constants/prompts.js')
// May need to pass tools list and model name
// Check the function signature
const prompt = await getSystemPrompt([], 'claude-sonnet-4-20250514')
console.log('=== SYSTEM PROMPT ===')
console.log(prompt.join('\n'))
console.log('=== END ===')
console.log(`\nTotal length: ${prompt.join('\n').length} characters`)
}
main().catch(err => {
console.error('Prompt test failed:', err)
process.exit(1)
})
```
### Part E: Fix MACRO references in prompts
The prompt system references `MACRO.ISSUES_EXPLAINER`. Make sure our `MACRO` global (from `src/shims/macro.ts`) provides this value. If the prompt references other `MACRO` fields, add them too.
### Part F: Context module audit
Check `src/context/` for additional context modules:
- Project detection (language, framework)
- Git integration (branch, status, recent commits)
- Environment detection (CI, container, SSH)
Verify these work in our dev environment.
## Verification
1. `bun scripts/test-prompt.ts` dumps a complete system prompt
2. The prompt includes: tool descriptions, OS context, memory content
3. No `undefined` or `MACRO.` references in the output
4. Memory system reads `.claude.md` from the project root

View File

@@ -0,0 +1,113 @@
# Prompt 11: MCP Client/Server Integration
## Context
You are working in `/workspaces/claude-code`. The CLI has built-in MCP (Model Context Protocol) support:
- **MCP Client** — connects to external MCP servers (tools, resources)
- **MCP Server** — exposes Claude Code itself as an MCP server
MCP lets the CLI use tools provided by external servers and lets other clients use Claude Code as a tool provider.
## Key Files
- `src/services/mcp/` — MCP client implementation
- `src/services/mcp/types.ts` — MCP config types
- `src/entrypoints/mcp.ts` — MCP server mode entrypoint
- `src/tools/MCPTool/` — Tool that calls MCP servers
- `src/tools/ListMcpResourcesTool/` — Lists MCP resources
- `src/tools/ReadMcpResourceTool/` — Reads MCP resources
- `src/tools/McpAuthTool/` — MCP server authentication
- `mcp-server/` — Standalone MCP server sub-project (from Prompt 04)
## Task
### Part A: Understand MCP client architecture
Read `src/services/mcp/` directory:
1. How are MCP servers discovered? (`.mcp.json` config file?)
2. How are MCP server connections established? (stdio, HTTP, SSE?)
3. How are MCP tools registered and made available?
4. What is the `ScopedMcpServerConfig` type?
### Part B: Understand MCP config format
Search for `.mcp.json` or MCP config loading code. Document:
1. Where does the config file live? (`~/.claude/.mcp.json`? project root?)
2. What's the config schema? (server name, command, args, env?)
3. How are multiple servers configured?
Example config you might find:
```json
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["path/to/server.js"],
"env": {}
}
}
}
```
### Part C: Verify MCP SDK integration
The project uses `@modelcontextprotocol/sdk` (^1.12.1). Check:
1. Is it installed in `node_modules/`?
2. Does the import work: `import { Client } from '@modelcontextprotocol/sdk/client/index.js'`
3. Are there version compatibility issues?
### Part D: Test MCP client with our own server
Create a test that:
1. Starts the `mcp-server/` we fixed in Prompt 04 as a child process
2. Connects to it via stdio using the MCP client from `src/services/mcp/`
3. Lists available tools
4. Calls one tool (e.g., `list_files` or `search_code`)
Create `scripts/test-mcp.ts`:
```ts
// scripts/test-mcp.ts
// Test MCP client/server roundtrip
// Usage: bun scripts/test-mcp.ts
import './src/shims/preload.js'
// TODO:
// 1. Spawn mcp-server as a child process (stdio transport)
// 2. Create MCP client from src/services/mcp/
// 3. Connect client to server
// 4. List tools
// 5. Call a tool
// 6. Print results
```
### Part E: Test MCP server mode
The CLI can run as an MCP server itself (`src/entrypoints/mcp.ts`). Read this file and verify:
1. What tools does it expose?
2. What resources does it provide?
3. Can it be started with `bun src/entrypoints/mcp.ts`?
### Part F: Create sample MCP config
Create a `.mcp.json` in the project root (or wherever the app looks for it) that configures the local MCP server:
```json
{
"mcpServers": {
"claude-code-explorer": {
"command": "node",
"args": ["mcp-server/dist/index.js"],
"env": {
"CLAUDE_CODE_SRC_ROOT": "./src"
}
}
}
}
```
## Verification
1. MCP client code in `src/services/mcp/` loads without errors
2. MCP server mode (`src/entrypoints/mcp.ts`) starts without crashing
3. A roundtrip test (client → server → response) works
4. `.mcp.json` config file is created and parseable

View File

@@ -0,0 +1,123 @@
# Prompt 12: Wire Up Services Layer (Analytics, Policy, Settings, Sessions)
## Context
You are working in `/workspaces/claude-code`. The CLI has several background services that run during operation:
- **Analytics/Telemetry** — GrowthBook feature flags, OpenTelemetry traces
- **Policy Limits** — rate limiting, quota enforcement from Anthropic backend
- **Remote Managed Settings** — server-pushed configuration
- **Session Memory** — persistent conversation history across invocations
- **Bootstrap Data** — initial config fetched from API on startup
Most of these talk to Anthropic's backend servers and will fail in our dev build. The goal is to make them fail gracefully (not crash the app) or provide stubs.
## Key Files
- `src/services/analytics/growthbook.ts` — GrowthBook feature flag client
- `src/services/analytics/` — Telemetry, event logging
- `src/services/policyLimits/` — Rate limit enforcement
- `src/services/remoteManagedSettings/` — Server-pushed settings
- `src/services/SessionMemory/` — Conversation persistence
- `src/services/api/bootstrap.ts` — Initial data fetch
- `src/entrypoints/init.ts` — Where most services are initialized
- `src/cost-tracker.ts` — Token usage and cost tracking
## Task
### Part A: Map the initialization sequence
Read `src/entrypoints/init.ts` carefully. Document:
1. What services are initialized, in what order?
2. Which are blocking (must complete before app starts)?
3. Which are fire-and-forget (async, can fail silently)?
4. What happens if each one fails?
### Part B: Make GrowthBook optional
Read `src/services/analytics/growthbook.ts`:
1. How is GrowthBook initialized?
2. Where is it called from? (feature flag checks throughout the codebase)
3. What happens if initialization fails?
**Goal**: Make GrowthBook fail silently — all feature flag checks should return `false` (default) if GrowthBook is unavailable. This may already be handled, but verify it.
### Part C: Stub policy limits
Read `src/services/policyLimits/`:
1. What limits does it enforce? (messages per minute, tokens per day, etc.)
2. What happens when a limit is hit?
3. Where is `loadPolicyLimits()` called?
**Goal**: Make the app work without policy limits. Either:
- Stub the service to return "no limits" (allow everything)
- Or catch and ignore errors from the API call
### Part D: Make remote settings optional
Read `src/services/remoteManagedSettings/`:
1. What settings does it manage?
2. What's the fallback when the server is unreachable?
**Goal**: Ensure the app works with default settings when the remote endpoint fails.
### Part E: Handle bootstrap data
Read `src/services/api/bootstrap.ts`:
1. What data does it fetch?
2. What uses this data?
3. What happens if the fetch fails?
**Goal**: Provide sensible defaults when bootstrap fails (no API key = no bootstrap).
### Part F: Verify session memory
Read `src/services/SessionMemory/`:
1. Where is session data stored? (filesystem path)
2. How are sessions identified?
3. Does it work with the local filesystem?
**Goal**: Session memory should work out of the box since it's local filesystem.
### Part G: Wire up cost tracking
Read `src/cost-tracker.ts`:
1. How are costs calculated?
2. Where is usage reported?
3. Does it persist across sessions?
**Goal**: Cost tracking should work locally (just display, no remote reporting needed).
### Part H: Create a services smoke test
Create `scripts/test-services.ts`:
```ts
// scripts/test-services.ts
// Test that all services initialize without crashing
// Usage: bun scripts/test-services.ts
import './src/shims/preload.js'
async function main() {
console.log('Testing service initialization...')
// Try to run the init sequence
try {
const { init } = await import('./src/entrypoints/init.js')
await init()
console.log('✅ Services initialized')
} catch (err: any) {
console.error('❌ Init failed:', err.message)
// Document which service failed and why
}
}
main()
```
## Verification
1. `bun scripts/test-services.ts` completes without crashing (warnings are fine)
2. Missing remote services log warnings, not crashes
3. Session memory reads/writes to the local filesystem
4. Cost tracking displays locally
5. The app can start even when Anthropic's backend is unreachable (with just an API key)

75
prompts/13-bridge-ide.md Normal file
View File

@@ -0,0 +1,75 @@
# Prompt 13: Bridge Layer (VS Code / JetBrains IDE Integration)
## Context
You are working in `/workspaces/claude-code`. The "Bridge" is the subsystem that connects Claude Code to IDE extensions (VS Code, JetBrains). It enables:
- Remote control of Claude Code from an IDE
- Sharing file context between IDE and CLI
- Permission approvals from the IDE UI
- Session management across IDE and terminal
The Bridge is **gated behind `feature('BRIDGE_MODE')`** and is the most complex optional subsystem (~30 files in `src/bridge/`).
## Key Files
- `src/bridge/bridgeMain.ts` — Main bridge orchestration
- `src/bridge/bridgeApi.ts` — Bridge API endpoints
- `src/bridge/bridgeMessaging.ts` — WebSocket/HTTP messaging
- `src/bridge/bridgeConfig.ts` — Bridge configuration
- `src/bridge/bridgeUI.ts` — Bridge UI rendering
- `src/bridge/jwtUtils.ts` — JWT authentication for bridge connections
- `src/bridge/types.ts` — Bridge types
- `src/bridge/initReplBridge.ts` — REPL integration
- `src/bridge/replBridge.ts` — REPL bridge handle
## Task
### Part A: Understand the bridge architecture
Read `src/bridge/types.ts` and `src/bridge/bridgeMain.ts` (first 100 lines). Document:
1. What protocols does the bridge use? (WebSocket, HTTP polling, etc.)
2. How does authentication work? (JWT)
3. What messages flow between IDE and CLI?
4. How is the bridge lifecycle managed?
### Part B: Assess what's needed vs. what can be deferred
The bridge is a **nice-to-have** for initial build-out. Categorize:
1. **Must work**: Feature flag gate (`feature('BRIDGE_MODE')` returns `false` → bridge code is skipped)
2. **Can defer**: Full bridge functionality
3. **Might break**: Code paths that assume bridge is available even when disabled
### Part C: Verify the feature gate works
Ensure that when `CLAUDE_CODE_BRIDGE_MODE=false` (or unset):
1. Bridge code is not imported
2. Bridge initialization is skipped
3. No bridge-related errors appear
4. The CLI works normally in terminal-only mode
### Part D: Stub the bridge for safety
If any code paths reference bridge functionality outside the feature gate:
1. Create `src/bridge/stub.ts` with no-op implementations
2. Make sure imports from `src/bridge/` resolve without crashing
3. Ensure the REPL works without bridge
### Part E: Document bridge activation
For future work, document what would be needed to enable the bridge:
1. Set `CLAUDE_CODE_BRIDGE_MODE=true`
2. What IDE extension is needed?
3. What authentication setup is required?
4. What ports/sockets does it use?
### Part F: Check the Chrome extension bridge
There's a `--claude-in-chrome-mcp` and `--chrome-native-host` mode referenced in `src/entrypoints/cli.tsx`. Read these paths and document what they do. These can be deferred — just make sure they don't crash when not in use.
## Verification
1. CLI works normally with bridge disabled (default)
2. No bridge-related errors in stdout/stderr
3. `feature('BRIDGE_MODE')` correctly returns `false`
4. Bridge architecture is documented for future enablement
5. No dangling imports that crash when bridge is off

137
prompts/14-dev-runner.md Normal file
View File

@@ -0,0 +1,137 @@
# Prompt 14: Create Development Runner
## Context
You are working in `/workspaces/claude-code`. By now you should have:
- Bun installed (Prompt 01)
- Runtime shims for `bun:bundle` and `MACRO` (Prompt 02)
- A build system (Prompt 03)
- Environment config (Prompt 05)
Now we need a way to **run the CLI in development mode** — quickly launching it without a full production build.
## Task
### Part A: Create `bun run dev` script
Bun can run TypeScript directly without compilation. Create a development launcher.
**Option 1: Direct Bun execution** (preferred)
Create `scripts/dev.ts`:
```ts
// scripts/dev.ts
// Development launcher — runs the CLI directly via Bun
// Usage: bun scripts/dev.ts [args...]
// Or: bun run dev [args...]
// Load shims first
import '../src/shims/preload.js'
// Register bun:bundle module resolver
// Since Bun natively supports the module, we may need to
// register our shim. Check if this is needed.
// Launch the CLI
await import('../src/entrypoints/cli.js')
```
**Option 2: Bun with preload**
Use Bun's `--preload` flag:
```bash
bun --preload ./src/shims/preload.ts src/entrypoints/cli.tsx
```
**Investigate which approach works** with the `bun:bundle` import. The tricky part is that `bun:bundle` is a special Bun module name — at runtime (without the bundler), Bun may not recognize it. You'll need to either:
1. Use Bun's `bunfig.toml` to create a module alias
2. Use a loader/plugin to intercept the import
3. Use a pre-transform step to rewrite imports
### Part B: Handle the `bun:bundle` import at runtime
This is the critical challenge. Options to investigate:
**Option A: `bunfig.toml` alias**
```toml
[resolve]
alias = { "bun:bundle" = "./src/shims/bun-bundle.ts" }
```
**Option B: Bun plugin**
Create a Bun plugin that intercepts `bun:bundle`:
```ts
// scripts/bun-plugin-shims.ts
import { plugin } from 'bun'
plugin({
name: 'bun-bundle-shim',
setup(build) {
build.onResolve({ filter: /^bun:bundle$/ }, () => ({
path: resolve(import.meta.dir, '../src/shims/bun-bundle.ts'),
}))
},
})
```
Then reference it in `bunfig.toml`:
```toml
preload = ["./scripts/bun-plugin-shims.ts"]
```
**Option C: Patch at build time**
If runtime aliasing doesn't work, use a quick pre-build transform that replaces `from 'bun:bundle'` with `from '../shims/bun-bundle.js'` across all files, outputting to a temp directory.
**Try the options in order** and go with whichever works.
### Part C: Add npm scripts
Add to `package.json`:
```json
{
"scripts": {
"dev": "bun scripts/dev.ts",
"dev:repl": "bun scripts/dev.ts --repl",
"start": "bun scripts/dev.ts"
}
}
```
### Part D: Create a `.env` loader
If the dev script doesn't automatically load `.env`, add dotenv support:
```bash
bun add -d dotenv-cli
```
Then wrap the dev command:
```json
"dev": "dotenv -e .env -- bun scripts/dev.ts"
```
Or use Bun's built-in `.env` loading (Bun automatically reads `.env` files).
### Part E: Test the development runner
1. Set `ANTHROPIC_API_KEY` in `.env`
2. Run `bun run dev --version` → should print version
3. Run `bun run dev --help` → should print help text
4. Run `bun run dev` → should start the interactive REPL (will need working Ink UI)
5. Run `ANTHROPIC_API_KEY=sk-ant-... bun run dev -p "say hello"` → should make one API call and print response
### Part F: Add debug mode
Add a debug script that enables verbose logging:
```json
{
"scripts": {
"dev:debug": "CLAUDE_CODE_DEBUG_LOG_LEVEL=debug bun scripts/dev.ts"
}
}
```
## Verification
1. `bun run dev --version` prints the version
2. `bun run dev --help` prints help without errors
3. The `bun:bundle` import resolves correctly at runtime
4. `.env` variables are loaded
5. No module resolution errors on startup

View File

@@ -0,0 +1,123 @@
# Prompt 15: Production Bundle & Packaging
## Context
You are working in `/workspaces/claude-code`. By now you should have a working development runner (Prompt 14) and build system (Prompt 03). This prompt focuses on creating a production-quality bundle.
## Task
### Part A: Optimize the esbuild configuration
Update `scripts/build-bundle.ts` for production:
1. **Tree shaking** — esbuild does this by default, but verify:
- Feature-gated code with `if (feature('X'))` where X is `false` should be eliminated
- `process.env.USER_TYPE === 'ant'` branches should be eliminated (set `define` to replace with `false`)
2. **Define replacements** — Inline constants at build time:
```ts
define: {
'process.env.USER_TYPE': '"external"', // Not 'ant' (Anthropic internal)
'process.env.NODE_ENV': '"production"',
}
```
3. **Minification** — Enable for production (`--minify` flag)
4. **Source maps** — External source maps for production debugging
5. **Target** — Ensure compatibility with both Bun 1.1+ and Node.js 20+
### Part B: Handle chunking/splitting
The full bundle will be large (~2-5 MB minified). Consider:
1. **Single file** — Simplest, works everywhere (recommended for CLI tools)
2. **Code splitting** — Multiple chunks, only useful if we want lazy loading
Go with single file unless it causes issues.
### Part C: Create the executable
After bundling to `dist/cli.mjs`:
1. **Add shebang** — `#!/usr/bin/env node` (already in banner)
2. **Make executable** — `chmod +x dist/cli.mjs`
3. **Test it runs** — `./dist/cli.mjs --version`
### Part D: Platform packaging
Create packaging scripts for distribution:
**npm package** (`scripts/package-npm.ts`):
```ts
// Generate a publishable npm package in dist/npm/
// - package.json with bin, main, version
// - The bundled CLI file
// - README.md
```
**Standalone binary** (optional, via Bun):
```bash
bun build --compile src/entrypoints/cli.tsx --outfile dist/claude
```
This creates a single binary with Bun runtime embedded. Not all features will work, but it's worth testing.
### Part E: Docker build
Update the existing `Dockerfile` to produce a runnable container:
```dockerfile
FROM oven/bun:1-alpine AS builder
WORKDIR /app
COPY package.json bun.lockb* ./
RUN bun install --frozen-lockfile || bun install
COPY . .
RUN bun run build:prod
FROM oven/bun:1-alpine
WORKDIR /app
COPY --from=builder /app/dist/cli.mjs /app/
RUN apk add --no-cache git ripgrep
ENTRYPOINT ["bun", "/app/cli.mjs"]
```
### Part F: Verify production build
1. `bun run build:prod` succeeds
2. `ls -lh dist/cli.mjs` — check file size
3. `node dist/cli.mjs --version` — works with Node.js
4. `bun dist/cli.mjs --version` — works with Bun
5. `ANTHROPIC_API_KEY=... node dist/cli.mjs -p "hello"` — end-to-end works
### Part G: CI build script
Create `scripts/ci-build.sh`:
```bash
#!/bin/bash
set -euo pipefail
echo "=== Installing dependencies ==="
bun install
echo "=== Type checking ==="
bun run typecheck
echo "=== Linting ==="
bun run lint
echo "=== Building ==="
bun run build:prod
echo "=== Verifying build ==="
node dist/cli.mjs --version
echo "=== Done ==="
```
## Verification
1. `bun run build:prod` produces `dist/cli.mjs`
2. The bundle is < 10 MB (ideally < 5 MB)
3. `node dist/cli.mjs --version` works
4. `docker build .` succeeds (if Docker is available)
5. CI script runs end-to-end without errors

125
prompts/16-testing.md Normal file
View File

@@ -0,0 +1,125 @@
# Prompt 16: Add Test Infrastructure & Smoke Tests
## Context
You are working in `/workspaces/claude-code`. The leaked source does not include any test files or test configuration (they were presumably in a separate directory or repo). We need to add a test framework and write smoke tests for core subsystems.
## Task
### Part A: Set up Vitest
```bash
bun add -d vitest @types/node
```
Create `vitest.config.ts`:
```ts
import { defineConfig } from 'vitest/config'
import { resolve } from 'path'
export default defineConfig({
test: {
globals: true,
environment: 'node',
include: ['tests/**/*.test.ts'],
setupFiles: ['tests/setup.ts'],
testTimeout: 30000,
},
resolve: {
alias: {
'bun:bundle': resolve(__dirname, 'src/shims/bun-bundle.ts'),
},
},
})
```
Create `tests/setup.ts`:
```ts
// Global test setup
import '../src/shims/preload.js'
```
Add to `package.json`:
```json
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest"
}
}
```
### Part B: Write unit tests for shims
`tests/shims/bun-bundle.test.ts`:
- Test `feature()` returns `false` for unknown flags
- Test `feature()` returns `false` for disabled flags
- Test `feature()` returns `true` when env var is set
- Test `feature('ABLATION_BASELINE')` always returns `false`
`tests/shims/macro.test.ts`:
- Test `MACRO.VERSION` is a string
- Test `MACRO.PACKAGE_URL` is set
- Test `MACRO.ISSUES_EXPLAINER` is set
### Part C: Write smoke tests for core modules
`tests/smoke/tools.test.ts`:
- Test that `getTools()` returns an array
- Test that each tool has: name, description, inputSchema
- Test that BashTool, FileReadTool, FileWriteTool are present
`tests/smoke/commands.test.ts`:
- Test that `getCommands()` returns an array
- Test that each command has: name, execute function
- Test that /help and /config commands exist
`tests/smoke/context.test.ts`:
- Test that `getSystemContext()` returns OS info
- Test that git status can be collected
- Test that platform detection works on Linux
`tests/smoke/prompt.test.ts`:
- Test that `getSystemPrompt()` returns a non-empty array
- Test that the prompt includes tool descriptions
- Test that MACRO references are resolved (no `undefined`)
### Part D: Write integration tests (if API key available)
`tests/integration/api.test.ts`:
- Skip if `ANTHROPIC_API_KEY` is not set
- Test API client creation
- Test a simple message (hello world)
- Test streaming works
- Test tool use (calculator-style tool call)
`tests/integration/mcp.test.ts`:
- Test MCP server starts
- Test MCP client connects
- Test tool listing
- Test tool execution roundtrip
### Part E: Write build tests
`tests/build/bundle.test.ts`:
- Test that `dist/cli.mjs` exists after build
- Test that it has a shebang
- Test that it's not empty
- Test that `node dist/cli.mjs --version` exits cleanly
### Part F: Add pre-commit hook (optional)
If the project uses git hooks, add:
```bash
# In package.json or a git hook
bun run typecheck && bun run test
```
## Verification
1. `bun run test` runs all tests
2. Shim tests pass
3. Smoke tests pass (tools, commands, context, prompts load)
4. Integration tests are skipped when no API key is set
5. Integration tests pass when API key is available
6. Test output is clear and readable

View File

@@ -2,33 +2,11 @@
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.nirholas/claude-code-explorer-mcp",
"title": "Claude Code Explorer MCP",
"description": "MCP server for exploring the Claude Code CLI source code — browse 40+ tools, 50+ commands, search the full 512K-line codebase, and get architecture overviews.",
"description": "Explore the Claude Code CLI source — browse tools, commands, search the 512K-line codebase.",
"repository": {
"url": "https://github.com/nirholas/claude-code",
"source": "github",
"subfolder": "mcp-server"
},
"version": "1.1.0",
"packages": [
{
"registryType": "npm",
"registryBaseUrl": "https://registry.npmjs.org",
"identifier": "claude-code-explorer-mcp",
"version": "1.1.0",
"transport": {
"type": "stdio"
},
"runtimeHint": {
"commandLine": {
"args": []
},
"env": {
"CLAUDE_CODE_SRC_ROOT": {
"description": "Path to the Claude Code src/ directory to explore",
"required": false
}
}
}
}
]
"version": "1.1.0"
}

View File

@@ -202,6 +202,7 @@ const usageReport: Command = {
}
import oauthRefresh from './commands/oauth-refresh/index.js'
import debugToolCall from './commands/debug-tool-call/index.js'
import x402 from './commands/x402/index.js'
import { getSettingSourceName } from './utils/settings/constants.js'
import {
type Command,
@@ -317,6 +318,7 @@ const COMMANDS = memoize((): Command[] => [
usage,
usageReport,
vim,
x402,
...(webCmd ? [webCmd] : []),
...(forkCmd ? [forkCmd] : []),
...(buddy ? [buddy] : []),

216
src/commands/x402/x402.ts Normal file
View File

@@ -0,0 +1,216 @@
/**
* /x402 command implementation
*
* Manages x402 wallet configuration for HTTP 402 crypto payments.
*
* Subcommands:
* /x402 setup - Generate a new wallet or import an existing private key
* /x402 status - Show wallet address, balance, and payment history
* /x402 enable - Enable x402 payments
* /x402 disable - Disable x402 payments
* /x402 set-limit - Set per-request or session spend limits
* /x402 network - Switch blockchain network
* /x402 remove - Remove wallet and disable payments
* /x402 - Show help
*/
import type { LocalCommandCall } from '../../types/command.js'
import {
generateX402PrivateKey,
getX402Config,
getX402WalletAddress,
isX402Enabled,
removeX402PrivateKey,
saveX402Config,
saveX402PrivateKey,
setX402MaxPayment,
setX402MaxSessionSpend,
setX402Network,
type PaymentNetwork,
} from '../../services/x402/index.js'
import {
formatX402Cost,
getX402PaymentCount,
getX402SessionSpentUSD,
} from '../../services/x402/tracker.js'
const VALID_NETWORKS: PaymentNetwork[] = [
'base',
'base-sepolia',
'ethereum',
'ethereum-sepolia',
]
function showHelp(): string {
return `x402 — HTTP 402 Crypto Payment Protocol (USDC on Base)
Usage:
/x402 setup Generate a new wallet for x402 payments
/x402 setup <key> Import an existing private key (hex)
/x402 status Show wallet info and session payment history
/x402 enable Enable automatic x402 payments
/x402 disable Disable x402 payments
/x402 set-limit <amt> Set max payment per request (USD)
/x402 set-session <amt> Set max session spend (USD)
/x402 network <name> Switch network (base, base-sepolia, ethereum, ethereum-sepolia)
/x402 remove Remove wallet and disable payments
/x402 Show this help
When enabled, x402 automatically handles HTTP 402 Payment Required responses
by signing USDC payment authorizations within your configured limits.
Environment:
X402_PRIVATE_KEY Override wallet private key (for CI/automation)
Learn more: https://github.com/coinbase/x402`
}
function handleSetup(args: string): string {
const parts = args.trim().split(/\s+/)
const keyArg = parts[1]
if (keyArg) {
// Import existing key
try {
const address = saveX402PrivateKey(keyArg)
saveX402Config({ enabled: true })
return `Wallet imported and enabled.\nAddress: ${address}\n\nFund this address with USDC on ${getX402Config().network} to enable payments.`
} catch (err) {
return `Error importing key: ${err instanceof Error ? err.message : String(err)}`
}
}
// Generate new key
const privateKey = generateX402PrivateKey()
const address = saveX402PrivateKey(privateKey)
saveX402Config({ enabled: true })
return `New wallet generated and enabled.
Address: ${address}
Network: ${getX402Config().network}
IMPORTANT: Fund this address with USDC to enable payments.
Your private key is stored in ~/.claude/config.json
To use on testnet first: /x402 network base-sepolia`
}
function handleStatus(): string {
const config = getX402Config()
const address = getX402WalletAddress()
const enabled = isX402Enabled()
const sessionSpent = getX402SessionSpentUSD()
const paymentCount = getX402PaymentCount()
const lines: string[] = []
lines.push('x402 Payment Status')
lines.push('─'.repeat(40))
lines.push(`Enabled: ${config.enabled ? 'Yes' : 'No'}`)
lines.push(`Wallet: ${address ?? 'Not configured'}`)
lines.push(`Network: ${config.network}`)
lines.push(`Max per request: $${config.maxPaymentPerRequestUSD.toFixed(2)}`)
lines.push(`Max per session: $${config.maxSessionSpendUSD.toFixed(2)}`)
lines.push(`Ready: ${enabled ? 'Yes' : 'No (need wallet + enabled)'}`)
lines.push('')
lines.push('Session:')
lines.push(` Payments: ${paymentCount}`)
lines.push(` Total spent: $${sessionSpent.toFixed(4)}`)
const x402Summary = formatX402Cost()
if (x402Summary) {
lines.push('')
lines.push(x402Summary)
}
return lines.join('\n')
}
function handleSetLimit(args: string): string {
const parts = args.trim().split(/\s+/)
const amount = parseFloat(parts[1] ?? '')
if (isNaN(amount) || amount <= 0) {
return 'Usage: /x402 set-limit <amount>\nAmount must be a positive number (USD).\nExample: /x402 set-limit 0.25'
}
try {
setX402MaxPayment(amount)
return `Max payment per request set to $${amount.toFixed(2)}`
} catch (err) {
return `Error: ${err instanceof Error ? err.message : String(err)}`
}
}
function handleSetSession(args: string): string {
const parts = args.trim().split(/\s+/)
const amount = parseFloat(parts[1] ?? '')
if (isNaN(amount) || amount <= 0) {
return 'Usage: /x402 set-session <amount>\nAmount must be a positive number (USD).\nExample: /x402 set-session 10.00'
}
try {
setX402MaxSessionSpend(amount)
return `Max session spend set to $${amount.toFixed(2)}`
} catch (err) {
return `Error: ${err instanceof Error ? err.message : String(err)}`
}
}
function handleNetwork(args: string): string {
const parts = args.trim().split(/\s+/)
const network = parts[1] as PaymentNetwork | undefined
if (!network || !VALID_NETWORKS.includes(network)) {
return `Usage: /x402 network <name>\nValid networks: ${VALID_NETWORKS.join(', ')}`
}
setX402Network(network)
return `Network switched to ${network}`
}
function handleRemove(): string {
removeX402PrivateKey()
return 'Wallet removed and x402 payments disabled.\nPrivate key has been deleted from config.'
}
export const call: LocalCommandCall = async (_onDone, _context, args) => {
const subcommand = (args ?? '').trim().split(/\s+/)[0]?.toLowerCase()
let value: string
switch (subcommand) {
case 'setup':
value = handleSetup(args ?? '')
break
case 'status':
value = handleStatus()
break
case 'enable':
saveX402Config({ enabled: true })
value = isX402Enabled()
? 'x402 payments enabled.'
: 'x402 enabled but no wallet configured. Run /x402 setup first.'
break
case 'disable':
saveX402Config({ enabled: false })
value = 'x402 payments disabled.'
break
case 'set-limit':
value = handleSetLimit(args ?? '')
break
case 'set-session':
value = handleSetSession(args ?? '')
break
case 'network':
value = handleNetwork(args ?? '')
break
case 'remove':
value = handleRemove()
break
default:
value = showHelp()
}
return { type: 'text', value }
}