✨ milady
This commit is contained in:
8
.github/copilot-instructions.md
vendored
8
.github/copilot-instructions.md
vendored
@@ -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`
|
- **Follow the bridge**: IDE integration starts at `src/bridge/bridgeMain.ts`
|
||||||
- **MCP integration**: `src/services/mcp/`
|
- **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
48
.github/workflows/publish-mcp.yml
vendored
Normal 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
72
CONTRIBUTING.md
Normal 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
487
README.md
@@ -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**
|
||||||
|
|
||||||
|
[](#tech-stack)
|
||||||
|
[](#tech-stack)
|
||||||
|
[](#tech-stack)
|
||||||
|
[](#directory-structure)
|
||||||
|
[](#-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
|
## 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!"**
|
> **"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)
|
> — [@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
|
Also see: [CONTRIBUTING.md](CONTRIBUTING.md) · [MCP Server README](mcp-server/README.md)
|
||||||
- **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
|
## <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/
|
src/
|
||||||
├── main.tsx # Entrypoint (Commander.js-based CLI parser)
|
├── main.tsx # Entrypoint — Commander.js CLI parser + React/Ink renderer
|
||||||
├── commands.ts # Command registry
|
├── 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
|
├── tools.ts # Tool registry
|
||||||
├── Tool.ts # Tool type definitions
|
|
||||||
├── QueryEngine.ts # LLM query engine (core Anthropic API caller)
|
|
||||||
├── context.ts # System/user context collection
|
├── context.ts # System/user context collection
|
||||||
├── cost-tracker.ts # Token cost tracking
|
├── cost-tracker.ts # Token cost tracking
|
||||||
│
|
│
|
||||||
├── commands/ # Slash command implementations (~50)
|
|
||||||
├── tools/ # Agent tool implementations (~40)
|
├── tools/ # Agent tool implementations (~40)
|
||||||
|
├── commands/ # Slash command implementations (~50)
|
||||||
├── components/ # Ink UI components (~140)
|
├── components/ # Ink UI components (~140)
|
||||||
├── hooks/ # React hooks
|
|
||||||
├── services/ # External service integrations
|
├── services/ # External service integrations
|
||||||
├── screens/ # Full-screen UIs (Doctor, REPL, Resume)
|
├── hooks/ # React hooks (incl. permission checks)
|
||||||
├── types/ # TypeScript type definitions
|
├── types/ # TypeScript type definitions
|
||||||
├── utils/ # Utility functions
|
├── utils/ # Utility functions
|
||||||
|
├── screens/ # Full-screen UIs (Doctor, REPL, Resume)
|
||||||
│
|
│
|
||||||
├── bridge/ # IDE integration bridge (VS Code, JetBrains)
|
├── bridge/ # IDE integration (VS Code, JetBrains)
|
||||||
├── coordinator/ # Multi-agent coordinator
|
├── coordinator/ # Multi-agent orchestration
|
||||||
├── plugins/ # Plugin system
|
├── plugins/ # Plugin system
|
||||||
├── skills/ # Skill system
|
├── skills/ # Skill system
|
||||||
├── keybindings/ # Keybinding configuration
|
|
||||||
├── vim/ # Vim mode
|
|
||||||
├── voice/ # Voice input
|
|
||||||
├── remote/ # Remote sessions
|
|
||||||
├── server/ # Server mode
|
├── server/ # Server mode
|
||||||
├── memdir/ # Memory directory (persistent memory)
|
├── remote/ # Remote sessions
|
||||||
|
├── memdir/ # Persistent memory directory
|
||||||
├── tasks/ # Task management
|
├── tasks/ # Task management
|
||||||
├── state/ # State management
|
├── state/ # State management
|
||||||
├── migrations/ # Config migrations
|
│
|
||||||
|
├── voice/ # Voice input
|
||||||
|
├── vim/ # Vim mode
|
||||||
|
├── keybindings/ # Keybinding configuration
|
||||||
├── schemas/ # Config schemas (Zod)
|
├── schemas/ # Config schemas (Zod)
|
||||||
|
├── migrations/ # Config migrations
|
||||||
├── entrypoints/ # Initialization logic
|
├── entrypoints/ # Initialization logic
|
||||||
|
├── query/ # Query pipeline
|
||||||
├── ink/ # Ink renderer wrapper
|
├── ink/ # Ink renderer wrapper
|
||||||
├── buddy/ # Companion sprite (Easter egg)
|
├── buddy/ # Companion sprite (Easter egg 🐣)
|
||||||
├── native-ts/ # Native TypeScript utils
|
├── native-ts/ # Native TypeScript utils
|
||||||
├── outputStyles/ # Output styling
|
├── outputStyles/ # Output styling
|
||||||
├── query/ # Query pipeline
|
|
||||||
└── upstreamproxy/ # Proxy configuration
|
└── 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 |
|
| Tool | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `BashTool` | Shell command execution |
|
| **File I/O** | |
|
||||||
| `FileReadTool` | File reading (images, PDFs, notebooks) |
|
| `FileReadTool` | Read files (images, PDFs, notebooks) |
|
||||||
| `FileWriteTool` | File creation / overwrite |
|
| `FileWriteTool` | Create / overwrite files |
|
||||||
| `FileEditTool` | Partial file modification (string replacement) |
|
| `FileEditTool` | Partial modification (string replacement) |
|
||||||
| `GlobTool` | File pattern matching search |
|
| `NotebookEditTool` | Jupyter notebook editing |
|
||||||
|
| **Search** | |
|
||||||
|
| `GlobTool` | File pattern matching |
|
||||||
| `GrepTool` | ripgrep-based content search |
|
| `GrepTool` | ripgrep-based content search |
|
||||||
| `WebFetchTool` | Fetch URL content |
|
|
||||||
| `WebSearchTool` | Web search |
|
| `WebSearchTool` | Web search |
|
||||||
| `AgentTool` | Sub-agent spawning |
|
| `WebFetchTool` | Fetch URL content |
|
||||||
|
| **Execution** | |
|
||||||
|
| `BashTool` | Shell command execution |
|
||||||
| `SkillTool` | Skill execution |
|
| `SkillTool` | Skill execution |
|
||||||
| `MCPTool` | MCP server tool invocation |
|
| `MCPTool` | MCP server tool invocation |
|
||||||
| `LSPTool` | Language Server Protocol integration |
|
| `LSPTool` | Language Server Protocol integration |
|
||||||
| `NotebookEditTool` | Jupyter notebook editing |
|
| **Agents & Teams** | |
|
||||||
| `TaskCreateTool` / `TaskUpdateTool` | Task creation and management |
|
| `AgentTool` | Sub-agent spawning |
|
||||||
| `SendMessageTool` | Inter-agent messaging |
|
| `SendMessageTool` | Inter-agent messaging |
|
||||||
| `TeamCreateTool` / `TeamDeleteTool` | Team agent management |
|
| `TeamCreateTool` / `TeamDeleteTool` | Team management |
|
||||||
|
| `TaskCreateTool` / `TaskUpdateTool` | Task management |
|
||||||
|
| **Mode & State** | |
|
||||||
| `EnterPlanModeTool` / `ExitPlanModeTool` | Plan mode toggle |
|
| `EnterPlanModeTool` / `ExitPlanModeTool` | Plan mode toggle |
|
||||||
| `EnterWorktreeTool` / `ExitWorktreeTool` | Git worktree isolation |
|
| `EnterWorktreeTool` / `ExitWorktreeTool` | Git worktree isolation |
|
||||||
| `ToolSearchTool` | Deferred tool discovery |
|
| `ToolSearchTool` | Deferred tool discovery |
|
||||||
| `CronCreateTool` | Scheduled trigger creation |
|
|
||||||
| `RemoteTriggerTool` | Remote trigger |
|
|
||||||
| `SleepTool` | Proactive mode wait |
|
| `SleepTool` | Proactive mode wait |
|
||||||
|
| `CronCreateTool` | Scheduled triggers |
|
||||||
|
| `RemoteTriggerTool` | Remote trigger |
|
||||||
| `SyntheticOutputTool` | Structured output generation |
|
| `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 |
|
| Command | Description | | Command | Description |
|
||||||
|---|---|
|
|---|---|---|---|---|
|
||||||
| `/commit` | Create a git commit |
|
| `/commit` | Git commit | | `/memory` | Persistent memory |
|
||||||
| `/review` | Code review |
|
| `/review` | Code review | | `/skills` | Skill management |
|
||||||
| `/compact` | Context compression |
|
| `/compact` | Context compression | | `/tasks` | Task management |
|
||||||
| `/mcp` | MCP server management |
|
| `/mcp` | MCP server management | | `/vim` | Vim mode toggle |
|
||||||
| `/config` | Settings management |
|
| `/config` | Settings | | `/diff` | View changes |
|
||||||
| `/doctor` | Environment diagnostics |
|
| `/doctor` | Environment diagnostics | | `/cost` | Check usage cost |
|
||||||
| `/login` / `/logout` | Authentication |
|
| `/login` / `/logout` | Auth | | `/theme` | Change theme |
|
||||||
| `/memory` | Persistent memory management |
|
| `/context` | Context visualization | | `/share` | Share session |
|
||||||
| `/skills` | Skill management |
|
| `/pr_comments` | PR comments | | `/resume` | Restore session |
|
||||||
| `/tasks` | Task management |
|
| `/desktop` | Desktop handoff | | `/mobile` | Mobile handoff |
|
||||||
| `/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 |
|
|
||||||
|
|
||||||
### 3. Service Layer (`src/services/`)
|
### 3. Service Layer
|
||||||
|
|
||||||
|
> `src/services/` — External integrations and core infrastructure.
|
||||||
|
|
||||||
| Service | Description |
|
| Service | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `api/` | Anthropic API client, file API, bootstrap |
|
| `api/` | Anthropic API client, file API, bootstrap |
|
||||||
| `mcp/` | Model Context Protocol server connection and management |
|
| `mcp/` | Model Context Protocol connection & management |
|
||||||
| `oauth/` | OAuth 2.0 authentication flow |
|
| `oauth/` | OAuth 2.0 authentication |
|
||||||
| `lsp/` | Language Server Protocol manager |
|
| `lsp/` | Language Server Protocol manager |
|
||||||
| `analytics/` | GrowthBook-based feature flags and analytics |
|
| `analytics/` | GrowthBook feature flags & analytics |
|
||||||
| `plugins/` | Plugin loader |
|
| `plugins/` | Plugin loader |
|
||||||
| `compact/` | Conversation context compression |
|
| `compact/` | Conversation context compression |
|
||||||
|
| `extractMemories/` | Automatic memory extraction |
|
||||||
|
| `teamMemorySync/` | Team memory synchronization |
|
||||||
|
| `tokenEstimation.ts` | Token count estimation |
|
||||||
| `policyLimits/` | Organization policy limits |
|
| `policyLimits/` | Organization policy limits |
|
||||||
| `remoteManagedSettings/` | Remote managed settings |
|
| `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
|
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)
|
||||||
- `bridgeMessaging.ts` — Message protocol
|
|
||||||
- `bridgePermissionCallbacks.ts` — Permission callbacks
|
|
||||||
- `replBridge.ts` — REPL session bridge
|
|
||||||
- `jwtUtils.ts` — JWT-based authentication
|
|
||||||
- `sessionRunner.ts` — Session execution management
|
|
||||||
|
|
||||||
### 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
|
### 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
|
```typescript
|
||||||
import { feature } from 'bun:bundle'
|
import { feature } from 'bun:bundle'
|
||||||
|
|
||||||
// Inactive code is completely stripped at build time
|
|
||||||
const voiceCommand = feature('VOICE_MODE')
|
const voiceCommand = feature('VOICE_MODE')
|
||||||
? require('./commands/voice/index.js').default
|
? require('./commands/voice/index.js').default
|
||||||
: null
|
: 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)
|
| File | Lines | Purpose |
|
||||||
|
|------|------:|---------|
|
||||||
The core engine for LLM API calls. Handles streaming responses, tool-call loops, thinking mode, retry logic, and token counting.
|
| `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 |
|
||||||
### `Tool.ts` (~29K lines)
|
| `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 |
|
||||||
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.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -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) |
|
| CLI Parsing | [Commander.js](https://github.com/tj/commander.js) (extra-typings) |
|
||||||
| Schema Validation | [Zod v4](https://zod.dev) |
|
| Schema Validation | [Zod v4](https://zod.dev) |
|
||||||
| Code Search | [ripgrep](https://github.com/BurntSushi/ripgrep) (via GrepTool) |
|
| 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) |
|
| API | [Anthropic SDK](https://docs.anthropic.com) |
|
||||||
| Telemetry | OpenTelemetry + gRPC |
|
| Telemetry | OpenTelemetry + gRPC |
|
||||||
| Feature Flags | GrowthBook |
|
| 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
|
```typescript
|
||||||
// main.tsx — fired as side-effects before other imports
|
// main.tsx
|
||||||
startMdmRawRead()
|
startMdmRawRead()
|
||||||
startKeychainPrefetch()
|
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
|
```bash
|
||||||
|
# Apply emoji commits
|
||||||
bash ./gitpretty-apply.sh .
|
bash ./gitpretty-apply.sh .
|
||||||
```
|
|
||||||
|
|
||||||
This will:
|
# Optional: install hooks for future commits
|
||||||
|
|
||||||
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
|
|
||||||
bash ./gitpretty-apply.sh . --hooks
|
bash ./gitpretty-apply.sh . --hooks
|
||||||
```
|
|
||||||
|
|
||||||
After running, push as usual:
|
# Push as usual
|
||||||
|
|
||||||
```bash
|
|
||||||
git push origin main
|
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
|
> **Note:** The `src/` directory is the original leaked source and should not be modified.
|
||||||
|
|
||||||
```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
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Disclaimer
|
## 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
224
docs/architecture.md
Normal 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
211
docs/commands.md
Normal 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
246
docs/exploration-guide.md
Normal 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
346
docs/subsystems.md
Normal 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
173
docs/tools.md
Normal 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
|
||||||
@@ -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 the `explain_tool` prompt with "FileEditTool" to get a full breakdown
|
||||||
- Use `how_does_it_work` with "bridge" to understand IDE integration
|
- 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
|
## Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
1364
mcp-server/package-lock.json
generated
1364
mcp-server/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
24
mcp-server/server.json
Normal file
24
mcp-server/server.json
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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
|
// Try directory first, then .ts / .tsx
|
||||||
const candidates = [
|
const candidates = [
|
||||||
`commands/${commandName}`,
|
`commands/${commandName}`,
|
||||||
|
|||||||
24
mcp-server/src/index.ts.new
Normal file
24
mcp-server/src/index.ts.new
Normal 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
2560
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
prompts/00-overview.md
Normal file
35
prompts/00-overview.md
Normal 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.) | 01–03 |
|
||||||
|
| 08 | `08-command-system.md` | Audit and wire up the 50+ slash commands (/commit, /review, etc.) | 01–03, 07 |
|
||||||
|
| 09 | `09-query-engine.md` | Get the core LLM call loop (QueryEngine) functional — streaming, tool calls, retries | 01–03, 05, 07 |
|
||||||
|
| 10 | `10-context-and-prompts.md` | Wire up system prompt construction, context gathering, memory system | 01–03 |
|
||||||
|
| 11 | `11-mcp-integration.md` | Get MCP client/server integration working — registry, tool discovery | 01–04 |
|
||||||
|
| 12 | `12-services-layer.md` | Wire up analytics, policy limits, remote settings, session memory | 01–03, 05 |
|
||||||
|
| 13 | `13-bridge-ide.md` | Stub out or implement the VS Code / JetBrains bridge layer | 01–03, 09 |
|
||||||
|
| 14 | `14-dev-runner.md` | Create `npm run dev` / `bun run dev` script that launches the CLI in dev mode | 01–03 |
|
||||||
|
| 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 07–13 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
|
||||||
38
prompts/01-install-bun-and-deps.md
Normal file
38
prompts/01-install-bun-and-deps.md
Normal 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
137
prompts/02-runtime-shims.md
Normal 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
165
prompts/03-build-config.md
Normal 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
|
||||||
45
prompts/04-fix-mcp-server.md
Normal file
45
prompts/04-fix-mcp-server.md
Normal 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
100
prompts/05-env-and-auth.md
Normal 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
|
||||||
110
prompts/06-ink-react-terminal-ui.md
Normal file
110
prompts/06-ink-react-terminal-ui.md
Normal 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
104
prompts/07-tool-system.md
Normal 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)
|
||||||
90
prompts/08-command-system.md
Normal file
90
prompts/08-command-system.md
Normal 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
118
prompts/09-query-engine.md
Normal 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
|
||||||
100
prompts/10-context-and-prompts.md
Normal file
100
prompts/10-context-and-prompts.md
Normal 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
|
||||||
113
prompts/11-mcp-integration.md
Normal file
113
prompts/11-mcp-integration.md
Normal 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
|
||||||
123
prompts/12-services-layer.md
Normal file
123
prompts/12-services-layer.md
Normal 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
75
prompts/13-bridge-ide.md
Normal 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
137
prompts/14-dev-runner.md
Normal 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
|
||||||
123
prompts/15-production-bundle.md
Normal file
123
prompts/15-production-bundle.md
Normal 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
125
prompts/16-testing.md
Normal 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
|
||||||
26
server.json
26
server.json
@@ -2,33 +2,11 @@
|
|||||||
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
||||||
"name": "io.github.nirholas/claude-code-explorer-mcp",
|
"name": "io.github.nirholas/claude-code-explorer-mcp",
|
||||||
"title": "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": {
|
"repository": {
|
||||||
"url": "https://github.com/nirholas/claude-code",
|
"url": "https://github.com/nirholas/claude-code",
|
||||||
"source": "github",
|
"source": "github",
|
||||||
"subfolder": "mcp-server"
|
"subfolder": "mcp-server"
|
||||||
},
|
},
|
||||||
"version": "1.1.0",
|
"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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ const usageReport: Command = {
|
|||||||
}
|
}
|
||||||
import oauthRefresh from './commands/oauth-refresh/index.js'
|
import oauthRefresh from './commands/oauth-refresh/index.js'
|
||||||
import debugToolCall from './commands/debug-tool-call/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 { getSettingSourceName } from './utils/settings/constants.js'
|
||||||
import {
|
import {
|
||||||
type Command,
|
type Command,
|
||||||
@@ -317,6 +318,7 @@ const COMMANDS = memoize((): Command[] => [
|
|||||||
usage,
|
usage,
|
||||||
usageReport,
|
usageReport,
|
||||||
vim,
|
vim,
|
||||||
|
x402,
|
||||||
...(webCmd ? [webCmd] : []),
|
...(webCmd ? [webCmd] : []),
|
||||||
...(forkCmd ? [forkCmd] : []),
|
...(forkCmd ? [forkCmd] : []),
|
||||||
...(buddy ? [buddy] : []),
|
...(buddy ? [buddy] : []),
|
||||||
|
|||||||
216
src/commands/x402/x402.ts
Normal file
216
src/commands/x402/x402.ts
Normal 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 }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user