Step-by-step guide for building the Claude Code CLI from the alesha-pro/claude-code repository — leaked Anthropic Claude Code source code.
- Linux (Ubuntu 22.04+) or macOS
- 4GB RAM, 4 CPU cores, 30GB disk
- Bun >= 1.3
- Git
curl -fsSL https://bun.sh/install | bash
export PATH=$HOME/.bun/bin:$PATHcd ~
git clone https://github.com/alesha-pro/claude-code.git
cd claude-codeThe repository contains only src/ (~1,900 files, ~512K lines of TypeScript) and README.md. There is no package.json or tsconfig.json — they must be created manually.
cat > package.json << 'EOF'
{
"name": "claude-code",
"version": "1.0.0",
"type": "module",
"private": true,
"dependencies": {
"@alcalzone/ansi-tokenize": "*",
"@anthropic-ai/sdk": "*",
"@anthropic-ai/bedrock-sdk": "*",
"@anthropic-ai/vertex-sdk": "*",
"@aws-sdk/client-bedrock-runtime": "*",
"@aws-sdk/client-bedrock": "*",
"@aws-sdk/client-sts": "*",
"@aws-sdk/credential-provider-node": "*",
"@aws-sdk/credential-providers": "*",
"@azure/identity": "*",
"@commander-js/extra-typings": "12",
"@growthbook/growthbook": "*",
"@modelcontextprotocol/sdk": "*",
"@opentelemetry/api": "*",
"@opentelemetry/api-logs": "*",
"@opentelemetry/core": "*",
"@opentelemetry/exporter-logs-otlp-grpc": "*",
"@opentelemetry/exporter-logs-otlp-http": "*",
"@opentelemetry/exporter-logs-otlp-proto": "*",
"@opentelemetry/exporter-metrics-otlp-grpc": "*",
"@opentelemetry/exporter-metrics-otlp-http": "*",
"@opentelemetry/exporter-metrics-otlp-proto": "*",
"@opentelemetry/exporter-prometheus": "*",
"@opentelemetry/exporter-trace-otlp-grpc": "*",
"@opentelemetry/exporter-trace-otlp-http": "*",
"@opentelemetry/exporter-trace-otlp-proto": "*",
"@opentelemetry/resources": "*",
"@opentelemetry/sdk-logs": "*",
"@opentelemetry/sdk-metrics": "*",
"@opentelemetry/sdk-trace-base": "*",
"@opentelemetry/semantic-conventions": "*",
"@smithy/core": "*",
"@smithy/node-http-handler": "*",
"ajv": "*",
"asciichart": "*",
"auto-bind": "*",
"axios": "*",
"bidi-js": "*",
"cacache": "*",
"chalk": "*",
"chokidar": "*",
"cli-boxes": "*",
"cli-highlight": "*",
"code-excerpt": "*",
"commander": "12",
"diff": "*",
"emoji-regex": "*",
"env-paths": "*",
"execa": "*",
"fflate": "*",
"figures": "*",
"fuse.js": "*",
"get-east-asian-width": "*",
"google-auth-library": "*",
"highlight.js": "*",
"https-proxy-agent": "*",
"ignore": "*",
"indent-string": "*",
"ink": "*",
"jsonc-parser": "*",
"lodash-es": "*",
"lru-cache": "*",
"marked": "*",
"p-map": "*",
"picomatch": "*",
"plist": "*",
"proper-lockfile": "*",
"qrcode": "*",
"react": "*",
"react-reconciler": "*",
"semver": "*",
"sharp": "*",
"shell-quote": "*",
"signal-exit": "*",
"stack-utils": "*",
"strip-ansi": "*",
"supports-hyperlinks": "*",
"tree-kill": "*",
"turndown": "*",
"type-fest": "*",
"undici": "*",
"usehooks-ts": "*",
"vscode-jsonrpc": "*",
"vscode-languageserver-protocol": "*",
"vscode-languageserver-types": "*",
"wrap-ansi": "*",
"ws": "*",
"xss": "*",
"yaml": "*",
"zod": "*"
},
"devDependencies": {
"@types/diff": "*",
"@types/lodash-es": "*",
"@types/node": "*",
"@types/react": "*",
"@types/semver": "*",
"@types/shell-quote": "*",
"@types/ws": "*",
"bun-types": "*",
"typescript": "*"
}
}
EOFImportant: Commander must be version 12. Versions 13+ break the short flag -d2e (used for --debug-to-stderr).
cat > tsconfig.json << 'EOF'
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": false,
"noEmit": true,
"allowImportingTsExtensions": true,
"baseUrl": ".",
"paths": {
"bun:bundle": ["./src/types/bun-bundle.d.ts"],
"src/*": ["./src/*"]
},
"types": ["bun-types"]
},
"include": ["src/**/*.ts", "src/**/*.tsx"]
}
EOFThe key part is "src/*": ["./src/*"] in paths. The source code uses from 'src/utils/...' as absolute imports, and Bun resolves them via tsconfig paths.
Several modules are missing from the leak (Anthropic internal packages, native modules, files behind feature flags). Stubs are required for them.
mkdir -p src/types
cat > src/types/bun-bundle.d.ts << 'EOF'
declare module "bun:bundle" {
export function feature(name: string): boolean;
}
EOFAfter bun install (step 6), create the following:
# @anthropic-ai/sandbox-runtime
mkdir -p node_modules/@anthropic-ai/sandbox-runtime
cat > node_modules/@anthropic-ai/sandbox-runtime/index.js << 'EOF'
class SandboxManager {
static isSupportedPlatform() { return false; }
static isSandboxingEnabled() { return false; }
static isAutoAllowBashIfSandboxedEnabled() { return false; }
static getFsWriteConfig() { return { allowOnly: [], denyWithinAllow: [] }; }
static getFsReadConfig() { return { allowOnly: [], denyWithinAllow: [] }; }
static getNetworkRestrictionConfig() { return { allowOnly: [] }; }
static getIgnoreViolations() { return {}; }
static getProxyPort() { return undefined; }
static getSocksProxyPort() { return undefined; }
static getLinuxHttpSocketPath() { return undefined; }
static getLinuxSocksSocketPath() { return undefined; }
static getAllowUnixSockets() { return false; }
static getAllowLocalBinding() { return false; }
static getEnableWeakerNestedSandbox() { return false; }
static getLinuxGlobPatternWarnings() { return []; }
static getExcludedCommands() { return []; }
static async waitForNetworkInitialization() { return false; }
static async initialize() {}
static updateConfig() {}
static setSandboxSettings() {}
static wrapWithSandbox(cmd) { return cmd; }
static refreshConfig() {}
static reset() {}
static checkDependencies() { return { satisfied: true, missing: [] }; }
static getSandboxViolationStore() { return new SandboxViolationStore(); }
static annotateStderrWithSandboxFailures() {}
static cleanupAfterCommand() {}
}
class SandboxViolationStore {
getViolations() { return []; }
clear() {}
}
const SandboxRuntimeConfigSchema = {
parse: (v) => v,
safeParse: (v) => ({ success: true, data: v }),
};
module.exports = { SandboxManager, SandboxViolationStore, SandboxRuntimeConfigSchema };
EOF
cat > node_modules/@anthropic-ai/sandbox-runtime/package.json << 'EOF'
{"name":"@anthropic-ai/sandbox-runtime","version":"0.0.0","main":"index.js"}
EOF
# @ant/claude-for-chrome-mcp
mkdir -p node_modules/@ant/claude-for-chrome-mcp
cat > node_modules/@ant/claude-for-chrome-mcp/index.js << 'EOF'
const BROWSER_TOOLS = [
{ name: 'tabs_context_mcp' }, { name: 'tabs_create_mcp' },
{ name: 'navigate' }, { name: 'read_page' },
{ name: 'get_page_text' }, { name: 'find' },
{ name: 'computer' }, { name: 'form_input' },
{ name: 'javascript_tool' }, { name: 'read_console_messages' },
{ name: 'read_network_requests' }, { name: 'gif_creator' },
{ name: 'resize_window' }, { name: 'upload_image' },
{ name: 'update_plan' }, { name: 'shortcuts_list' },
{ name: 'shortcuts_execute' }, { name: 'switch_browser' },
];
function createClaudeForChromeMcpServer() { return null; }
module.exports = { BROWSER_TOOLS, createClaudeForChromeMcpServer };
EOF
cat > node_modules/@ant/claude-for-chrome-mcp/package.json << 'EOF'
{"name":"@ant/claude-for-chrome-mcp","version":"0.0.0","main":"index.js"}
EOF
# @anthropic-ai/foundry-sdk
mkdir -p node_modules/@anthropic-ai/foundry-sdk
cat > node_modules/@anthropic-ai/foundry-sdk/index.js << 'EOF'
module.exports = { FoundryClient: class {} };
EOF
cat > node_modules/@anthropic-ai/foundry-sdk/package.json << 'EOF'
{"name":"@anthropic-ai/foundry-sdk","version":"0.0.0","main":"index.js"}
EOF
# @anthropic-ai/mcpb
mkdir -p node_modules/@anthropic-ai/mcpb
cat > node_modules/@anthropic-ai/mcpb/index.js << 'EOF'
module.exports = {};
EOF
cat > node_modules/@anthropic-ai/mcpb/package.json << 'EOF'
{"name":"@anthropic-ai/mcpb","version":"0.0.0","main":"index.js"}
EOF
# color-diff-napi (native C++ module for syntax-highlighted diffs)
mkdir -p node_modules/color-diff-napi
cat > node_modules/color-diff-napi/index.js << 'EOF'
class ColorDiff {
constructor(patch, firstLine, filePath, fileContent) {
this.patch = patch; this.firstLine = firstLine;
this.filePath = filePath; this.fileContent = fileContent;
}
render(theme, width, dim) { return null; }
}
class ColorFile {
constructor(code, filePath) {
this.code = code; this.filePath = filePath;
}
render(theme, width, dim) { return null; }
}
function getSyntaxTheme() { return {}; }
module.exports = { ColorDiff, ColorFile, getSyntaxTheme };
EOF
cat > node_modules/color-diff-napi/index.mjs << 'EOF'
export class ColorDiff {
constructor(patch, firstLine, filePath, fileContent) {
this.patch = patch; this.firstLine = firstLine;
this.filePath = filePath; this.fileContent = fileContent;
}
render(theme, width, dim) { return null; }
}
export class ColorFile {
constructor(code, filePath) {
this.code = code; this.filePath = filePath;
}
render(theme, width, dim) { return null; }
}
export function getSyntaxTheme() { return {}; }
EOF
cat > node_modules/color-diff-napi/package.json << 'EOF'
{"name":"color-diff-napi","version":"0.0.0","main":"index.js","module":"index.mjs","exports":{".":{"import":"./index.mjs","require":"./index.js"}}}
EOF
# modifiers-napi
mkdir -p node_modules/modifiers-napi
cat > node_modules/modifiers-napi/index.js << 'EOF'
module.exports = {};
EOF
cat > node_modules/modifiers-napi/package.json << 'EOF'
{"name":"modifiers-napi","version":"0.0.0","main":"index.js"}
EOF# TungstenTool (Anthropic internal tool)
mkdir -p src/tools/TungstenTool
echo 'export const TungstenTool = null;' > src/tools/TungstenTool/TungstenTool.ts
echo 'export const TungstenLiveMonitor = null;' > src/tools/TungstenTool/TungstenLiveMonitor.ts
# REPLTool
mkdir -p src/tools/REPLTool
echo 'export const REPLTool = null;' > src/tools/REPLTool/REPLTool.ts
# SuggestBackgroundPRTool
mkdir -p src/tools/SuggestBackgroundPRTool
echo 'export const SuggestBackgroundPRTool = null;' > src/tools/SuggestBackgroundPRTool/SuggestBackgroundPRTool.ts
# VerifyPlanExecutionTool
mkdir -p src/tools/VerifyPlanExecutionTool
echo 'export const VerifyPlanExecutionTool = null;' > src/tools/VerifyPlanExecutionTool/VerifyPlanExecutionTool.ts
# WorkflowTool
mkdir -p src/tools/WorkflowTool
echo "export const WORKFLOW_TOOL_NAME = 'WorkflowTool';" > src/tools/WorkflowTool/constants.ts
# SnapshotUpdateDialog
mkdir -p src/components/agents
cat > src/components/agents/SnapshotUpdateDialog.ts << 'EOF'
export const SnapshotUpdateDialog = null;
export const launchSnapshotUpdateDialog = async () => {};
EOF
# AssistantSessionChooser
mkdir -p src/assistant
echo 'export const AssistantSessionChooser = null;' > src/assistant/AssistantSessionChooser.ts
# assistant command
mkdir -p src/commands/assistant
echo 'export default null;' > src/commands/assistant/assistant.ts
# agents-platform command
mkdir -p src/commands/agents-platform
echo 'export default null;' > src/commands/agents-platform/index.ts
# connectorText types
cat > src/types/connectorText.ts << 'EOF'
export type ConnectorText = string;
export type ConnectorTextBlock = { type: 'text'; text: string };
EOF
# contextCollapse service
mkdir -p src/services/contextCollapse
cat > src/services/contextCollapse/index.ts << 'EOF'
export const collapseContext = async () => null;
export const getContextCollapse = () => null;
EOF
# cachedMicrocompact
cat > src/services/compact/cachedMicrocompact.ts << 'EOF'
export type CachedMCState = { cacheEdits: CacheEditsBlock[]; pinnedCacheEdits: PinnedCacheEdits[] };
export type CacheEditsBlock = { type: string; content: any };
export type PinnedCacheEdits = { type: string; content: any };
export const createCachedMCState = (): CachedMCState => ({ cacheEdits: [], pinnedCacheEdits: [] });
export const cachedMicrocompact = async (...args: any[]) => null;
EOF
# protectedNamespace
cat > src/utils/protectedNamespace.ts << 'EOF'
export const protectedNamespaces: string[] = [];
export const isProtectedNamespace = (ns: string) => false;
EOF
# coreTypes.generated
mkdir -p src/entrypoints/sdk
echo 'export type CoreType = any;' > src/entrypoints/sdk/coreTypes.generated.ts
# ink devtools / global.d.ts
echo 'export default {};' > src/ink/devtools.ts
cat > src/ink/global.d.ts << 'EOF'
declare namespace NodeJS {
interface ProcessEnv { DEV?: string; }
}
EOF
# sdk/runtimeTypes and sdk/toolTypes
cat > src/entrypoints/sdk/runtimeTypes.ts << 'EOF'
export type EffortLevel = 'low' | 'medium' | 'high' | 'auto';
export type RuntimeConfig = Record<string, any>;
EOF
cat > src/entrypoints/sdk/toolTypes.ts << 'EOF'
export type ToolType = string;
export type ToolConfig = Record<string, any>;
EOF
# verify skill markdown files
mkdir -p src/skills/bundled/verify/examples
echo '# Verify Skill' > src/skills/bundled/verify/SKILL.md
echo '# CLI Example' > src/skills/bundled/verify/examples/cli.md
echo '# Server Example' > src/skills/bundled/verify/examples/server.md
# ultraplan prompt
mkdir -p src/utils/ultraplan
echo 'You are an expert planner.' > src/utils/ultraplan/prompt.txt
# filePersistence/types (contains constants, not just types)
cat > src/utils/filePersistence/types.ts << 'EOF'
export type TurnStartTime = number;
export type FailedPersistence = { path: string; error: string };
export type FilesPersistedEventData = Record<string, any>;
export type PersistedFile = { path: string; id: string };
export const DEFAULT_UPLOAD_CONCURRENCY = 5;
export const FILE_COUNT_LIMIT = 100;
export const OUTPUTS_SUBDIR = 'outputs';
EOFSeveral directories expect a types.ts file that was not included in the leak. The script below extracts imported names and generates stub files:
generate_types_stub() {
local dir="$1"
local types_file="$dir/types.ts"
[ -f "$types_file" ] && return
echo "// Auto-generated types stub" > "$types_file"
grep -rhP "from './types.js'" "$dir/" --include='*.ts' --include='*.tsx' 2>/dev/null | \
grep -oP '\{\s*[^}]+\}' | tr '{},' '\n' | \
sed 's/^\s*//;s/\s*$//;s/^type //;s/ as .*$//' | \
grep -v '^$' | sort -u | while read imp; do
echo "export type $imp = any;" >> "$types_file"
done
echo "Created: $types_file"
}
for dir in \
src/utils/secureStorage \
src/components/Spinner \
src/components/agents/new-agent-creation \
src/components/wizard \
src/components/mcp \
src/keybindings \
src/services/tips \
src/services/oauth \
src/services/lsp \
src/commands/install-github-app \
src/commands/plugin; do
generate_types_stub "$dir"
donebun installThis installs ~510 packages. After that, run step 5.2 (creating stubs in node_modules).
Claude Code uses ripgrep for file searching. Install it and create a symlink where the CLI expects it:
# Ubuntu/Debian
apt-get install -y ripgrep
# After building (step 8) — create symlink
mkdir -p dist/vendor/ripgrep/x64-linux
ln -sf $(which rg) dist/vendor/ripgrep/x64-linux/rgAll 7 MACRO constants must be defined via --define, otherwise you'll get a runtime error MACRO is not defined:
bun build src/entrypoints/cli.tsx \
--target=bun \
--outdir=dist \
--define 'MACRO.VERSION="1.0.34"' \
--define 'MACRO.BUILD_TIMESTAMP="2026-03-31"' \
--define 'MACRO.BUILD_TIME="2026-03-31T12:00:00Z"' \
--define 'MACRO.FEEDBACK_CHANNEL="#claude-code-feedback"' \
--define 'MACRO.ISSUES_EXPLAINER="https://github.com/anthropics/claude-code/issues"' \
--define 'MACRO.NATIVE_PACKAGE_URL="@anthropic-ai/claude-code"' \
--define 'MACRO.PACKAGE_URL="@anthropic-ai/claude-code"' \
--define 'MACRO.VERSION_CHANGELOG=""'After building, create the ripgrep symlink (step 7).
Output: dist/cli.js (~25MB), ~5,880 modules, builds in ~1 second.
| Parameter | Description |
|---|---|
| Entry point | src/entrypoints/cli.tsx (NOT src/main.tsx!) |
--target=bun |
Target runtime — Bun |
MACRO.VERSION |
Version string. Must be >= current minimum, or CLI will refuse to start |
MACRO.BUILD_TIMESTAMP |
Build date |
MACRO.BUILD_TIME |
ISO timestamp of the build |
MACRO.FEEDBACK_CHANNEL |
Feedback channel (string) |
MACRO.ISSUES_EXPLAINER |
Issues URL |
MACRO.PACKAGE_URL |
npm package name |
MACRO.NATIVE_PACKAGE_URL |
npm native package name |
MACRO.VERSION_CHANGELOG |
Changelog (can be empty) |
export ANTHROPIC_API_KEY="sk-ant-..."
bun run dist/cli.jsZ.AI requires Bearer authentication via ANTHROPIC_AUTH_TOKEN. You must also set ANTHROPIC_API_KEY (required by the SDK constructor):
export ANTHROPIC_API_KEY="your_zai_api_key"
export ANTHROPIC_AUTH_TOKEN="your_zai_api_key"
export ANTHROPIC_BASE_URL="https://api.z.ai/api/anthropic"
export API_TIMEOUT_MS="3000000"
export ANTHROPIC_MODEL="GLM-4.7"
bun run dist/cli.jsOr via ~/.claude/settings.json:
{
"env": {
"ANTHROPIC_API_KEY": "your_zai_api_key",
"ANTHROPIC_AUTH_TOKEN": "your_zai_api_key",
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
"API_TIMEOUT_MS": "3000000",
"ANTHROPIC_MODEL": "GLM-4.7"
}
}bun run dist/cli.js --version # Show version
bun run dist/cli.js --help # Show help
bun run dist/cli.js -p "Hello" # Pipe mode (print response and exit)
bun run dist/cli.js --model sonnet # Specify model
bun run dist/cli.js -d # Debug modeIf the CLI blocks startup due to a minimum version check (remote config from Anthropic), there are two workarounds:
- Rebuild with a higher version:
--define 'MACRO.VERSION="99.0.0"' - Environment variable:
NODE_ENV=test bun run dist/cli.js— disablesassertMinVersion()entirely
cat > /usr/local/bin/claude-dev << 'EOF'
#!/bin/bash
export PATH=$HOME/.bun/bin:$PATH
cd /root/claude-code
exec bun run dist/cli.js "$@"
EOF
chmod +x /usr/local/bin/claude-dev- No syntax-highlighted diffs —
color-diff-napiis a native C++ module by Anthropic, replaced with a stub - Feature flags disabled —
bun:bundlefeature()returnsfalsefor all flags. Voice mode, BRIDGE_MODE, PROACTIVE, and ~80 other features are inactive - Internal tools (TungstenTool, REPLTool, SuggestBackgroundPRTool, VerifyPlanExecutionTool) are replaced with null stubs
- Sandbox disabled —
SandboxManager.isSandboxingEnabled()always returnsfalse - Telemetry — OpenTelemetry initializes, but without real endpoints no data is sent
- Native modules (
modifiers-napi,audio-capture-napi,image-processor-napi,url-handler-napi) are stubs
src/entrypoints/cli.tsx -> Bootstrap: version check, fast paths (--version)
+-- src/main.tsx -> Commander.js CLI, command and option registration
+-- src/QueryEngine.ts -> Core: Anthropic API calls, streaming, tool-call loop
+-- src/tools.ts -> Tool registry (Bash, Edit, Read, Grep, Glob, ...)
+-- src/commands.ts -> Slash command registry (/commit, /review, /compact, ...)
+-- src/services/ -> API, MCP, OAuth, LSP, analytics
+-- src/components/ -> React/Ink UI components (~140)
+-- src/hooks/ -> React hooks (permissions, input, notifications)
+-- src/bridge/ -> IDE integration bridge (VS Code, JetBrains)
+-- src/utils/ -> Utilities (sandbox, settings, shell, model, ...)