From 3a932bd81162dc9b74a5dabcba05f6342eb2eccc Mon Sep 17 00:00:00 2001 From: morluto Date: Wed, 1 Apr 2026 02:33:04 +0800 Subject: [PATCH 1/2] docs: add CLAUDE.md and ARCHITECTURE.md for agent guidance Co-Authored-By: Claude Opus 4.6 --- ARCHITECTURE.md | 287 ++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 126 +++++++++++++++++++++ 2 files changed, 413 insertions(+) create mode 100644 ARCHITECTURE.md create mode 100644 CLAUDE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000..64be8545 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,287 @@ +# Architecture + +Deep dive into how free-code (Claude Code) works internally. + +## Overview + +``` +User Input → QueryEngine → AI Model API → Tool Execution → Response + ↑__________________________________| + (loop until task complete) +``` + +The app runs a conversation loop with an AI model, which can call tools (Bash, Read, Edit, etc.) to interact with the filesystem and system. Context is compacted when it grows too large. + +--- + +## Entry Points + +### cli.tsx - Bootstrap +- Handles fast-path flags with zero/dynamic imports for speed: + - `--version` / `-v` - print version, exit + - `--dump-system-prompt` - output rendered system prompt, exit + - `--claude-in-chrome-mcp` / `--chrome-native-host` - Chrome integration + - `--computer-use-mcp` - computer use mode + - `--daemon-worker` - internal supervisor spawning + - `remote`, `bridge`, `daemon`, `ps`, `logs`, `attach`, `kill` - daemon modes + - `templates`, `environment-runner`, `self-hosted-runner` - template modes + - `--tmux` - tmux integration +- All other paths fall through to main.tsx + +### main.tsx - Full Init +1. Parallel prefetch: MDM settings, keychain reads +2. Feature flags gate COORDINATOR_MODE and KAIROS imports +3. Load all major systems: analytics, auth, API, MCP, tools +4. Call init() then setup() then context.ts +5. Launch REPL or commander-based CLI + +--- + +## Core Loop - QueryEngine + +Located in `src/query.ts` and `src/QueryEngine.ts`. + +**QueryEngine** is an async generator that owns the query lifecycle per conversation. + +### Query Flow Per Turn + +``` +submitMessage(userInput) + 1. processUserInput() → slash commands, permissions + 2. fetchSystemPromptParts() → build system prompt + 3. callModel() → call AI model API + 4. runTools() → StreamingToolExecutor handles tool calls + 5. handleResponse() → process model response + 6. compactContext() → if needed, reduce context size + 7. yield stream events, messages, tool summaries +``` + +### State Maintained + +- `mutableMessages[]` - conversation history +- `readFileState` - LRU cache of file contents +- `permissionDenials[]` - track denied permissions +- `totalUsage` - cost tracking + +--- + +## Tool System + +### Tool Interface (src/Tool.ts) + +Every tool implements the `Tool` type with ~30 methods: +- `call()` - actual execution +- `description()` - human-readable description +- `prompt()` - how the model sees this tool +- `renderToolUseMessage()` / `renderToolResultMessage()` - UI rendering +- Input/output validated via Zod schemas + +### Tool Builder (src/tools.ts) + +```typescript +getAllBaseTools() // ~40 built-in tools +getTools() // + permission filtering, mode filtering +assembleToolPool() // + MCP tools +``` + +Tools are conditionally loaded via `feature('FLAG_NAME')` from `bun:bundle`. + +### Tool Structure + +Each tool lives in `src/tools//`: +- `Tool.ts` - main implementation +- `UI.tsx` - React component for rendering +- `prompt.ts` - prompt instructions for the model + +### Tool Execution (services/tools/toolOrchestration.js) + +`runTools()` handles execution. `StreamingToolExecutor` streams results back to the model. + +### Built-in Tools + +Key tools include: Bash, Read, Edit, Write, Grep, Glob, NotebookRead, NotebookEdit, TaskCreate, TaskComplete, WebSearch, WebFetch, etc. + +--- + +## Command System + +Commands are prefixed with `/` and executed locally (not by the model). + +### Command Types + +- **prompt** - model can invoke them (`/plan`, `/review`, `/commit`) +- **local** - local execution only (`/help`, `/clear`, `/exit`) +- **local-jsx** - render Ink UI (`/connect`, `/mcp`) + +### Registration (src/commands.ts) + +```typescript +COMMANDS() // ~80 built-in commands +loadAllCommands() // memoized loading +getCommands() // filter by availability + isCommandEnabled() +getSlashCommandToolSkills() // prompt-type for model invocation +``` + +### Sources + +1. Built-in commands (src/commands/) +2. Skill dir commands +3. Plugin skills +4. Bundled skills +5. Workflow commands +6. MCP skills + +--- + +## Task System + +Background work that runs orthogonal to the query loop. + +### Task Types (src/Task.ts) + +- `local_bash` - spawned bash process +- `local_agent` - local sub-agent +- `remote_agent` - remote sub-agent +- `in_process_teammate` - in-process teammate +- `local_workflow` - workflow runner +- `monitor_mcp` - MCP connection monitor +- `dream` - dream mode + +### Task Lifecycle + +1. Created via `AgentTool` during query execution +2. Registered in `AppState.tasks` map +3. Runs independently of query loop +4. Can communicate results back to parent agent + +--- + +## State Management + +### Store (src/state/store.ts) + +Custom Zustand-like store: +```typescript +createStore({ + getState(), + setState(), + subscribe() +}) +``` + +### React Integration + +`AppStateProvider` wraps React Context + `useSyncExternalStore`. + +Access via `useAppState(selector)` - selectors return stable references to avoid re-renders. + +--- + +## Coordinator Mode + +Multi-agent orchestration via `COORDINATOR_MODE` feature flag. + +When enabled, provides internal worker tools: +- `TEAM_CREATE` - create a team +- `TEAM_DELETE` - delete a team +- `SEND_MESSAGE` - message a teammate +- `SEND_MESSAGE_TO_WORKTEAM` - message a work team +- `GET_TEAM_MEMBERS` - list team members + +Environment variable: `CLAUDE_CODE_COORDINATOR_MODE` + +--- + +## Services + +### analytics/ +- Datadog integration +- GrowthBook feature flags (local eval only, no reporting) +- First-party event logging + +### api/ +- bootstrap - bootstrap API +- claude - main Claude API client +- files - file operations +- grove - internal service +- logging - event logging +- usage - usage tracking +- metrics - metrics collection + +### compact/ +Session context compaction: +- autoCompact - automatic compaction +- microCompact - lightweight compaction +- snipCompact - snippet-based compaction + +### lsp/ +Language Server Protocol client/manager for code intelligence. + +### mcp/ +Model Context Protocol: +- MCP connections management +- OAuth handling +- Channel permissions + +### oauth/ +- Auth code listeners +- Portable auth flows + +--- + +## Initialization Sequence + +``` +cli.tsx (fast-path flags) + ↓ +main.tsx + ├── Parallel prefetch (MDM, keychain) + ├── Feature flag gates + └── init() [entrypoints/init.ts] + └── setup() [setup.ts] + ├── Session init (cwd, git root) + ├── Hooks setup + ├── Memory init + └── context() [context.ts] + ├── System context + └── User context + ↓ + launchRepl() or CLI handler +``` + +--- + +## Feature Flags + +All flags use `feature('FLAG_NAME')` from `bun:bundle` - compile-time dead code elimination. + +Key flags: +- `ULTRAPLAN` - Remote multi-agent planning +- `ULTRATHINK` - Deep thinking mode +- `VOICE_MODE` - Voice input +- `AGENT_TRIGGERS` - Cron/trigger tools +- `BRIDGE_MODE` - IDE bridge +- `COORDINATOR_MODE` - Multi-agent teams +- `TOKEN_BUDGET` - Usage tracking +- `VERIFICATION_AGENT` - Task validation + +See `FEATURES.md` for full audit of all 88 flags. + +--- + +## Key Files + +| File | Purpose | +|------|---------| +| `src/query.ts` | Query generator (async) | +| `src/QueryEngine.ts` | Query lifecycle class | +| `src/Tool.ts` | Tool interface definition | +| `src/tools.ts` | Tool registration | +| `src/commands.ts` | Command registration | +| `src/Task.ts` | Task types and creation | +| `src/state/store.ts` | State management | +| `src/context.ts` | System/user context | +| `src/setup.ts` | Session setup | +| `src/main.tsx` | Main entrypoint | +| `src/entrypoints/cli.tsx` | CLI bootstrap | +| `src/services/tools/toolOrchestration.js` | Tool execution | diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..643160ca --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,126 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is a fork of Anthropic's Claude Code CLI. The fork removes telemetry, strips security-prompt guardrails, and enables 45+ experimental feature flags (see `FEATURES.md` for full audit). + +## Build Commands + +```bash +bun run build # Production build +bun run build:dev # Dev build +bun run dev # Run CLI directly (src/entrypoints/cli.tsx) +``` + +Uses Bun (v1.3.11) with TypeScript (strict: false, skipLibCheck: true). No test runner, linter, or formatter configured. + +## Architecture Overview + +### Entry Points + +- **CLI** (`src/entrypoints/cli.tsx`): Bootstrap with fast-path flags (--version, --dump-system-prompt, --daemon-worker, remote modes). Falls through to main.tsx. +- **Desktop** (`src/main.tsx`): Loads analytics, auth, API, MCP, tools; launches REPL or CLI handler. + +### Initialization Flow + +1. `cli.tsx` handles fast-path flags with zero/dynamic imports +2. `main.tsx` runs parallel prefetch (MDM settings, keychain reads) +3. `init()` from `entrypoints/init.ts` - telemetry/trust +4. `setup()` from `setup.ts` - session init (cwd, git root, hooks, memory) +5. `context.ts` - system/user prompt context +6. `launchRepl()` or commander-based CLI + +### Layers + +``` +CLI entrypoint → main.tsx → bootstrap/state, setup, context, services + → bridge (desktop/REPL comms) → commands, tools, coordinator → QueryEngine +``` + +### Coordinator + +Multi-agent orchestration via `COORDINATOR_MODE` feature flag + `CLAUDE_CODE_COORDINATOR_MODE` env var. Provides internal worker tools (TEAM_CREATE, TEAM_DELETE, SEND_MESSAGE, etc.). + +### Feature Flags + +All feature flags use `feature('FLAG_NAME')` from `bun:bundle`. Key flags: +- `ULTRAPLAN` - Remote multi-agent planning +- `ULTRATHINK` - Deep thinking mode ("ultrathink" command) +- `VOICE_MODE` - Push-to-talk voice input +- `AGENT_TRIGGERS` - Local cron/trigger tools +- `BRIDGE_MODE` - IDE remote-control bridge (VS Code, JetBrains) +- `TOKEN_BUDGET` - Token budget tracking +- `BUILTIN_EXPLORE_PLAN_AGENTS` - Built-in explore/plan agent presets +- `VERIFICATION_AGENT` - Task validation agent +- `BASH_CLASSIFIER` - Classifier-assisted bash permissions +- `EXTRACT_MEMORIES` - Post-query memory extraction +- `HISTORY_PICKER` - Interactive prompt history + +## Core Domains + +### QueryEngine (`src/query.ts`, `src/QueryEngine.ts`) + +Async generator orchestrating the main query loop. Each `submitMessage()` starts a new turn with: +1. Process user input (slash commands, permissions) +2. Build system prompt from `fetchSystemPromptParts` +3. Call AI model API +4. Handle tool calls via `runTools`/`StreamingToolExecutor` +5. Compact context when needed + +State: `mutableMessages` (conversation history), `readFileState` (LRU file cache), `permissionDenials`, `totalUsage` (cost tracking). + +### Tool System + +- Every tool implements `Tool` type (~30 methods) from `src/Tool.ts` +- Built via `buildTool()` helper with Zod schema validation +- `getAllBaseTools()` returns ~40 built-in tools, conditionally loaded via `feature()` flags +- `assembleToolPool()` merges built-in + MCP tools +- Tool structure: `src/tools//Tool.ts`, `UI.tsx`, `prompt.ts` + +### Command System + +- `src/commands.ts`: `COMMANDS()` returns ~80 built-in commands +- Command types: `prompt` (model-invocable), `local` (local exec), `local-jsx` (Ink UI) +- Sources: built-in, skill dir, plugins, bundled skills, workflow commands, MCP skills +- `getSlashCommandToolSkills()` returns prompt-type commands for model invocation + +### Task System (`src/Task.ts`) + +Task types: `local_bash`, `local_agent`, `remote_agent`, `in_process_teammate`, `local_workflow`, `monitor_mcp`, `dream` + +- `QueryEngine` handles main conversation loop +- Tasks manage background work spawned during tool execution (via `AgentTool`, `TaskStopTool`) +- Tasks registered in `AppState.tasks` map, run orthogonal to query loop + +## State Management + +Custom store (similar to Zustand) in `src/state/store.ts`: `createStore` with `getState`, `setState`, `subscribe` interface. + +`AppStateProvider` wraps React Context + `useSyncExternalStore`. Single `AppState` object accessed via `useAppState(selector)` hook. + +## Key Services (`src/services/`) + +- **analytics/** - Datadog, GrowthBook, event logging +- **api/** - API clients: bootstrap, claude, files, grove, logging, usage, metrics +- **compact/** - Session compaction (autoCompact, microCompact, snipCompact) +- **lsp/** - Language Server Protocol client/manager +- **mcp/** - Model Context Protocol connections, OAuth, channel permissions +- **oauth/** - Auth code listeners, portable auth +- **AgentSummary, MagicDocs, PromptSuggestion, SessionMemory** - Feature services + +## Utilities (`src/utils/`) + +Notable subdirectories: +- **bash/** - Parser, shell commands, treeSitter analysis +- **computer_use/** - App names, executor, locks, drainRunLoop +- **background/remote/** - Remote session utilities + +## Components (`src/components/`) + +~100+ small, focused components in flat structure. Notable: `CustomSelect/`, `FeedbackSurvey/`, `HelpV2/`, `MCPServerDialog/`, `ManagedSettingsSecurityDialog/`. + +## Hooks (`src/hooks/`) + +Key patterns: `useSettings`, `useIdeConnectionStatus`, `useMCPConnections`, `useMergedClients`, `useCommandQueue`. Permission handlers in `toolPermission/` with coordinator/interactive/swarm handlers. From 37a70a518390fdbf435ad550c005cef9c114d1c4 Mon Sep 17 00:00:00 2001 From: morluto Date: Wed, 1 Apr 2026 10:56:36 +0800 Subject: [PATCH 2/2] security: vendor modifiers-napi locally The npm package 'modifiers-napi' was squatting (published 11h ago by disposable email). This removes the runtime dependency on the malicious package by using a local vendored stub instead. Co-Authored-By: Claude Opus 4.6 --- scripts/build.ts | 2 +- src/utils/modifiers.ts | 3 ++- src/vendor/modifiers-napi.ts | 11 +++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/vendor/modifiers-napi.ts diff --git a/scripts/build.ts b/scripts/build.ts index 262a6e9d..935ea4d2 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -125,7 +125,7 @@ const externals = [ '@ant/*', 'audio-capture-napi', 'image-processor-napi', - 'modifiers-napi', + // modifiers-napi - vendored locally (was npm squatting target) 'url-handler-napi', ] diff --git a/src/utils/modifiers.ts b/src/utils/modifiers.ts index f8ec9dcd..e64ba235 100644 --- a/src/utils/modifiers.ts +++ b/src/utils/modifiers.ts @@ -18,9 +18,10 @@ function loadNativeModifiersModule(): NativeModifiersModule | null { } try { + // Use local vendored stub instead of npm package (original was squatting target) nativeModifiersModule = // eslint-disable-next-line @typescript-eslint/no-require-imports - (require('modifiers-napi') as NativeModifiersModule) ?? null + (require('../vendor/modifiers-napi') as NativeModifiersModule) ?? null } catch { nativeModifiersModule = null } diff --git a/src/vendor/modifiers-napi.ts b/src/vendor/modifiers-napi.ts new file mode 100644 index 00000000..78ae04bf --- /dev/null +++ b/src/vendor/modifiers-napi.ts @@ -0,0 +1,11 @@ +// Vendored stub for modifiers-napi (malicious package squatted on npm) +// Original was a native macOS module for keyboard modifier detection. +// This stub provides no-op implementations for safety. + +export function prewarm(): void { + // no-op +} + +export function isModifierPressed(_modifier: string): boolean { + return false +}