mirror of
https://github.com/codeaashu/claude-code.git
synced 2026-04-08 22:28:48 +03:00
claude-code
This commit is contained in:
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
|
||||
85
prompts/04-fix-mcp-server.md
Normal file
85
prompts/04-fix-mcp-server.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 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
|
||||
|
||||
---
|
||||
|
||||
## Fix: GitHub Push Protection Blocked Push
|
||||
|
||||
`git push origin main` is rejected because commits `5e99ad6` and `7adaa5d` contain a **GitHub OAuth token** in `.mcpregistry_github_token`. The file was deleted from disk but still exists in git history. You must rewrite history to remove it.
|
||||
|
||||
### Step 1: Scrub secrets from history
|
||||
|
||||
```bash
|
||||
git filter-branch --force --index-filter \
|
||||
'git rm --cached --ignore-unmatch .mcpregistry_github_token .mcpregistry_registry_token mcp-server/.mcpregistry_github_token mcp-server/.mcpregistry_registry_token' \
|
||||
--prune-empty HEAD~5..HEAD
|
||||
```
|
||||
|
||||
### Step 2: Push
|
||||
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### Alternative: Interactive rebase
|
||||
|
||||
```bash
|
||||
git rebase -i HEAD~5
|
||||
# Change "pick" to "edit" for commits 5e99ad6 and 7adaa5d
|
||||
# At each stop, run:
|
||||
git rm --cached .mcpregistry_github_token .mcpregistry_registry_token 2>/dev/null
|
||||
git rm --cached mcp-server/.mcpregistry_github_token mcp-server/.mcpregistry_registry_token 2>/dev/null
|
||||
git commit --amend --no-edit
|
||||
git rebase --continue
|
||||
```
|
||||
|
||||
### Step 3: Prevent future leaks
|
||||
|
||||
```bash
|
||||
echo ".mcpregistry_github_token" >> .gitignore
|
||||
echo ".mcpregistry_registry_token" >> .gitignore
|
||||
git add .gitignore && git commit -m "chore: gitignore token files"
|
||||
```
|
||||
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
|
||||
Reference in New Issue
Block a user