Clew Code v0.2.7 — Complete Architecture

18 interconnected systems powering a multi-provider AI coding agent CLI with terminal UI, P2P mesh, preference learning, and autonomous operation. Fork of Anthropic's Claude Code.

Bun + React 19 + Ink 32 AI Providers 78 Tool Dirs P2P LAN Mesh MCP Client Autonomous Agent
18Systems
32AI Providers
78Tool Dirs
461Components
411Command Files
27Hook Events
6Transports
6475main.tsx Lines

All 18 Systems

1

Entry Point main.tsx (6475 lin)

Core Bootstrap • CLI • Lifecycle Key files:main.tsxsetup.ts (423)commands.ts (740)

Startup Sequence (5 Phases)

Phase 0 → Pre-import: TTY force, version check, MDM raw read, keychain prefetch, MACRO injection Phase 1 → Module evaluation (~135ms imports resolve) Phase 2 → main() + run(): PATH security, signal handlers (SIGINT/SIGCONT/SIGTSTP), argv preprocess (`--`, `cc://` URLs, SSH), mode detection, Commander setup Phase 3 → preAction hook: MDM + keychain await, init() (memoized), taste init, sinks, plugin dir, migrations, remote managed settings, policy limits Phase 4 → Action handler: prompt parse, peer auto-start, MCP config, system prompt assembly, agent selection, model resolution Phase 5 → Interactive REPL (Ink-based TUI) or headless --print path

CLI Argument Parsing

Uses Commander.js with ~70+ options. Custom sorted help config. run() creates the program with preAction hook for init and .action() for main dispatch. Mode detection branches interactive vs headless vs init-only.

Command Dispatching

COMMANDS — memoized lazy loader returning 150+ built-in commands. getCommands(cwd) merges bundled skills, built-in plugin skills, skill directory commands, workflow commands, plugin commands, plugin skills, and core COMMANDS(). Resolution: exact match → prefix match → colon-separated fallback.

Key Init Steps (setup.ts, 423 lines)

  • Node version check (≥ 18), custom session ID, UDS messaging
  • FileChanged watcher — initializeFileChangedWatcher(cwd)
  • Worktree — git worktree + tmux session if --worktree
  • Session memory — initSessionMemory(), context collapse (gated)
  • Plugin prefetch — getCommands() + loadPluginHooks() as void promises
  • Teammate snapshot — captures agent swarm configuration
  • Bootstrap state — global STATE singleton with ~100+ accessor functions exported
2

AI Providers 32 providers · 9 dedicated + 23 compatible

High ProviderManager singleton • 10 provider files • 2197-line providers.json

Provider Categories

TypeCountProviders
Dedicated Provider classes10AnthropicProvider, OpenAIProvider, GoogleProvider, CohereProvider, OpenRouterProvider, KiloCodeProvider, OllamaProvider, ClewGatewayProvider, OpenAICompatibleProvider, ProviderInterface
OpenAI-compatible (driven by providers.json)23deepseek, opencode, opencode-go, groq, xai, mistral, together, fireworks, nvidia, deepinfra, perplexity, cerebras, siliconflow, moonshot, zhipu, huggingface, poe, digitalocean, cline, and custom

ProviderManager Singleton (369 lines)

Selection priority chain (getActiveProviderName):

Session override → AI_PROVIDER env → provider.json (persisted) → Legacy env vars (BEDROCK/VERTEX/FOUNDRY) → 'openai' (fallback)

Config persistence: User-level ~/.claude/provider.json, project-level .claude/provider.json (takes priority). Auth resolved via getApiKeyForProvider() — checks session keys → OAuth tokens → persisted config → environment variables.

Common Interface

interface ProviderInterface {
  readonly providerId: ProviderId;
  readonly label: string;
  getProviderId(): ProviderId;
  getProviderLabel(): string;
  getProviderApiKeyEnvVar(): string;
  createClient(options: ProviderInitOptions): Promise<ProviderClient>;
  listModels(options: ProviderInitOptions): Promise<{ id: string; label: string }[]>;
}

Streaming — Two-Layer Architecture

Layer 1 — Provider SDK: chat.completions.create({ stream: true }) returns SSE AsyncGenerator.

Layer 2 — AnthropicAdapter: Wraps any provider into Anthropic-compatible BetaRawMessageStreamEvent types via wrapStream(). Converts OpenAI delta chunks → Anthropic events (message_start, content_block_start, content_block_delta, etc.). Supports thinking/reasoning_content blocks.

Stream watchdog: 45s (OpenAI-compatible), 60s (Google), 30s (default). Throws stall error if no chunk arrives.

Additional Services

The src/services/ai/ module also includes: ModelDiscoveryService, BrowserAgent, contentBlockUtils, errorNormalizer, providerMetadata, providerModels, toolCallParser, usageNormalizer, usageTypes (130 lines).

3

Query Engine QueryEngine.ts (1219) · query.ts (1623)

High Conversation orchestrator • Core 10-step AI loop • Dependency injection

QueryEngine (1219 lines)

One instance per conversation. Manages mutableMessages, abortController, totalUsage, readFileState (file cache), discoveredSkillNames, loadedNestedMemoryPaths.

Key method: submitMessage() — AsyncGenerator that orchestrates user input → system init → AI loop → post-processing → result.

Core AI Loop (query() → queryLoop())

1. Snip compact → Remove zombie messages, GC stale markers 2. Microcompact → Compress individual tool results 3. Context collapse → Read-time projection (gated) 4. Auto-compact → Summarize old context when token budget tight 5. API call → Streaming model request with fallback 6. Tool execution → runTools() or StreamingToolExecutor 7. Post-sampling hooks 8. Stop hooks → Goal evaluator, memory extraction, job classification 9. Token budget check → Auto-continue if within budget 10. Max turns / goal check → Continue loop or return completed

System Prompt Construction

  1. fetchSystemPromptParts() — default + user context + system context (tools, model, MCP clients, working dirs)
  2. Custom system prompt (SDK-provided) replaces default if present
  3. Memory mechanics prompt — when CLAUDE_COWORK_MEMORY_PATH_OVERRIDE is set
  4. Taste/Rules injection — getTasteInjectionBlock() + evaluated rules with confidence ≥ 55%
  5. appendSystemPrompt — additional prompt appended

Loop Continuation Signals

State.transition controls loop iteration: max_output_tokens_escalate, max_output_tokens_recovery, reactive_compact_retry, collapse_drain_retry, stop_hook_blocking, goal_continuation, token_budget_continuation, brief_mode_retry, completed.

Key Features

  • Dependency injection via QueryDeps — tests can inject fakes for callModel, microcompact, autocompact
  • Streaming tool execution — gated by Statsig flag, tools execute concurrently while model streams
  • Ultracode bridge — tryAutoRunDynamicWorkflow() classifies task complexity, spawns parallel coordinator workflows
  • Query config (query/config.ts) — snapshots immutable values at query entry
4

Tool System 78 dirs · 353 files · Tool.ts (782 lin)

Very High Structural type system • 17 categories • Permission framework • Execution pipeline

Base Tool Type

Structural type (Tool<Input, Output, P>), not a class. Created via buildTool(def) which fills safe defaults. ~30+ lifecycle/UI/safety methods per tool.

Tool Categories

CategoryTools
FilesystemFileRead, FileEdit, FileWrite, Glob, Grep, NotebookEdit
ExecutionBash, PowerShell, REPL, ComputerUse
WebWebSearch, WebFetch, MultiSearch, Browser, BrowserAgent
Planning/ModeEnterPlanMode, ExitPlanMode, EnterWorktree, ExitWorktree, Brief
Peer Collaboration (17)PeerDiscover, PeerSendMessage, PeerSpawn, PeerShare, PeerInfo, PeerRun, PeerJoin, PeerSetName, PeerSetRole, PeerListRoles, PeerPing, PeerDisconnect, PeerBroadcast, PeerListMessages, PeerHelp, ProcessPeer, ListPeers
MCPMCPTool, McpAuthTool, ListMcpResourcesTool, ReadMcpResourceTool
Task ManagementTaskCreate, TaskGet, TaskUpdate, TaskList, TaskOutput, TaskStop
Skill & TasteSkill, TasteLearn, TasteForget, TasteProfile, TasteSuggest
Code/DevLSP, PR, PrSubscription, JsonPath, Tungsten, Research
TeamTeamCreate, TeamDelete
Automation (10)ScheduleCron, Sleep, RemoteTrigger, Workflow, Monitor, PushNotification, SubscribePR, SuggestBackgroundPR, VerifyPlanExecution, SendUserFile
Meta/SearchToolSearch, SessionSearch, TodoWrite, SyntheticOutput
CommunicationSendMessage, AskUserQuestion, Config, RequestShutdown
AgentAgentTool

Tool Execution Pipeline

LLM returns tool_use block → [1] Parse via Zod schema → [2] Validate via tool.validateInput?.() → [3] Run PreToolUse hooks → [4] Check permissions (classifier + rules + prompts) → [5] Call tool.call() with ToolUseContext (~30+ fields) → [6] Run PostToolUse hooks → [7] Map result to API format → [8] Return MessageUpdateLazy

Registration (tools.ts)

Core tools statically imported. Feature-gated tools (REPLTool, ComputerUseTool, LSPTool, worktree, team, PowerShell, ToolSearchTool) lazy-loaded via helper getters.

Pipeline: getAllBaseTools() → getTools(permissionContext) (filter by SIMPLE mode, isEnabled, deny rules) → assembleToolPool(permCtx, mcpTools) (merge + dedup).

5

Peer-to-Peer 6 files · UDP multicast + file registry

High PeerServer • PeerDiscovery • PeerStore • ProcessPeerProvider • 17 peer tools

4 Core Modules

ModuleRole
PeerServerLightweight HTTP server on 127.0.0.1 (random OS port). Endpoints: GET /peer-info, GET /peer-events (SSE), POST /peer-msg, POST /peer-todo, POST /peer-exec, WebSocket upgrade /peer-chat (currently destroyed)
PeerDiscoveryTwo-layer: file registry (~/.claude/peers/{pid}.json, 30s heartbeat, 90s stale timeout) + UDP multicast (239.255.37.37:42069, currently disabled for localhost safety)
PeerStoreIn-memory peer registry with auto-eviction, message queuing (chunked reassembly), liveness pings (60s interval)
ProcessPeerProviderRuns AI tasks as subprocesses — exec mode (spawn with stdin) or PTY mode (node-pty for interactive). Default command: codex

Peer Tools (17)

PeerDiscover, PeerSendMessage, PeerSpawn, PeerShare, PeerInfo, PeerRun, PeerJoin, PeerSetName, PeerSetRole, PeerListRoles, PeerPing, PeerDisconnect, PeerBroadcast, PeerListMessages, PeerHelp, ProcessPeer, ListPeers.

Connection Lifecycle

DISCOVERED → File registry or UDP beacon detected JOINED → Explicit connection, liveness pings every 60s (5s timeout) ACTIVE → Messages + todos + exec via HTTP, SSE for real-time push OFFLINE → No heartbeat >90s or HTTP ping fails DESTROY → stopAdvertising() removes file, clears timers
6

Taste (Preferences) 8 core files · 5 subdirs

High Epsilon-greedy bandit • Lexical neural scorer • Half-life decay • 3-tiers

System Layout

src/services/taste/ — TasteIntegration.ts + 7 subdirectories:

SubdirFilesContents
core/9TasteBandit, TasteDecay, TasteMemory, TasteNeuralScorer, TastePolicy, TasteRewardModel, TasteRuntime, TasteSymbolicEngine, TasteTypes
auto-learn/4AutoLearnEngine, PatternDetector, TasteCodebaseAnalyzer
signals/4AcceptRejectTracker, DiffSignalExtractor, EditDistanceReward, TasteSignalCollector
prompt/2TasteConstraintCompiler, TastePromptInjector
storage/—Profile store, event log
eval/—Evaluation utilities

Epsilon-Greedy Bandit

6 arms: minimal, strict_style, architecture_first, test_first, safety_first, refactor_heavy. Exploit (80%): pick highest averageReward. Explore (ε=0.2): pick random arm weighted by inverse pulls. Epsilon decays by 0.99×/update, floor 0.05. Supports future BanditContext extension (file ext, command type, model provider).

Neural Scorer

Provider-agnostic — uses Jaccard similarity + TF-IDF tokenization. Tokenization: strip punctuation, lowercase, remove 100+ stop words, filter <2 chars. Scoring: Jaccard|tokens∩|/|tokens∪| + tag bonus (0.05/tag). Combined: finalScore = (avgSimilarity × 0.5) + (outputScore × 0.5).

Tiers & Persistence

Project ({cwd}/.clew/taste/profile.json), Global (~/.clew/taste/profile.json), Session (RAM ring buffer: 200 events, 100 rules). Load order: Project → Global → new project-level created.

Auto-Learn: PatternDetector — min 5 events, min 3 occurrences to suggest, auto-accept at confidence ≥ 0.7, 30-min cooldown. Decay: half-life 30 days, decayedExcess = excess × 0.5^(daysSinceUse/30), floor at 0.5.

Model Influence

  1. Prompt injection: <clew_taste> block (max 8 rules, min confidence 0.55)
  2. Edit validation: TastePolicy.evaluate() — symbolic + neural scorer, scores ≥ 0.85 can block edits
  3. Bandit strategy: Selected arm queries via getCurrentArm()
7

Autonomous Agent 8 files · daemon · supervisor IPC

Medium 24/7 agent loop • File-backed task queue • Cron scheduler • 17 agentRuntime files

Core Files

Services: agentLoop.ts, daemonMode.ts, supervisorIntegration.ts, taskQueue.ts. Supervisor: supervisor.ts, ipcClient.ts. Agent Runtime: 17 files at src/agentRuntime/ — including ultracode.ts, ultracodeBridge.ts, orchestrator.ts, dynamicWorkflow.ts, transcriptClassifier.ts, verifierAgent.ts, workflowRegistry.ts, toolGateway.ts.

Agent Loop

startLoop() → Load queue → Expire stale leases → Start heartbeat (60s) → Cron scheduler → Peer sharing → File watcher Main polling: getNextTask() → if task AND workers < 3: processTask() → acquire lease → IPC spawn worker → monitor → complete else: sleep(15s)

Worker spawns child Bun process via Supervisor IPC (main.tsx -p). Max 3 concurrent workers. Task timeout 30 min.

Task Queue Data Model

File-backed at ~/.claude/daemon/tasks.json. Key fields: id, priority (critical/high/normal/low), status (pending→in_progress→completed/failed/cancelled/dead_letter), scheduledAt, dependsOn, retryCount/maxRetries (default 3), leaseOwner/leaseExpiresAt (5-min default), projectRoot, tags, errorLog (last 20 lines).

Supervisor IPC

One per user, auto-started. Transport: Windows named pipe or Unix socket. Commands: spawn, attach, stop, respawn, rm, list, logs, shutdown, ping, autonomous_start/stop/status. Auto-exits after 1hr idle. Detects binary upgrades (inode/mtime check every 5min).

Safety

  • Lease/lock — prevents duplicate execution across restarts
  • Prompt injection boundary — XML-wrapped task data with explicit system policy, CDATA sanitization, max 4000 chars
  • Dead-letter — stops infinite retries after maxRetries
  • Exponential backoff — base × factor^retryCount (capped at 1h)
8

MCP (Model Context Protocol) 23 files · 6 transports · OAuth 2207 lin

Very High MCP SDK client • 6 transport types • OAuth + XAA • Server lifecycle

23 Files at src/services/mcp/

Key files: client.ts (connection management + tool/resource fetching), auth.ts (2207 lines — OAuth + XAA), config.ts (multi-source config), types.ts (state enums + types), useManageMCPConnections.ts (React lifecycle), MCPConnectionManager.tsx (React context), InProcessTransport.ts, SdkControlTransport.ts, claudeai.ts, xaa.ts, xaaIdpLogin.ts, elicitationHandler.ts, mcpStringUtils.ts, channelAllowlist.ts, oauthPort.ts, officialRegistry.ts.

6 Transport Types

TransportMechanismReconnection
StdioChild process spawnNo (process exited)
HTTP (StreamableHTTP)MCP Streamable HTTP specExponential backoff, 5 attempts
SSELong-lived SSE + POST messagesSame as HTTP
WebSocketCustom transport (Bun + ws package)—
SDKIn-process CLI↔SDK bridge—
In-ProcessLinked transport pair (queueMicrotask)—

OAuth (2207 lines)

Standard flow: RFC 8414 discovery → localhost callback server (127.0.0.1:random) → browser popup → CSRF state validation → code exchange → OS keychain storage (keyed by serverName|sha256(configHash)[:16]). Token refresh with lockfile-based cross-process coordination, exponential backoff (1s, 2s, 4s).

XAA (SEP-990): Single IdP login across all XAA servers. OIDC + PKCE browser popup → RFC 8693/7523 token exchange (no browser). Silent refresh reuses cached id_token for zero-interaction re-auth.

Step-Up Auth: Detects 403 insufficient_scope, forces PKCE re-auth.

Tool & Resource Exposure

fetchToolsForClient() (memoized) → client.listTools() → wraps each in MCPTool. Tools named mcp__<server>__<toolName>. Dynamic updates via tools.listChanged capability. Resources fetched via fetchResourcesForClient(), with subscription support and skills integration.

Config Sources

Precedence: enterprise > local (.claude/settings.local.json) > project (.mcp.json) > user > dynamic (--mcp-config) > claudeai > managed. Each server validated independently. Supports env var expansion (${VAR_NAME}). Enterprise policy: allowedMcpServers, deniedMcpServers, allowManagedMcpServersOnly.

9

Bridge 31 files · 2651 lin bridgeMain + 2166 lin replBridge

Very High v1 env-based + v2 env-less • Remote WebSocket server • JWT refresh • Relay NAT

31 Files at src/bridge/

Key files: bridgeMain.ts (2651 lines — v1 env-based daemon), replBridge.ts (2166 lines — v1 REPL bridge), remoteBridgeCore.ts (861 lines — v2 env-less), initReplBridge.ts, jwtUtils.ts, replBridgeTransport.ts, bridgeApi.ts, bridgeConfig.ts, bridgeMessaging.ts, sessionRunner.ts, inboundMessages.ts, inboundAttachments.ts, createSession.ts, trustedDevice.ts, flushGate.ts, capacityWake.ts, workSecret.ts, types.ts.

Two Bridge Paths

v1 (Environment-based): Registers on claude.ai via POST /v1/environments. Poll loop: pollForWork() → WorkSecret (session_ingress_token + api_base_url). Spawns child processes via Session-Ingress WebSocket → HybridTransport. Lifecycle: register → poll → ack → spawn → heartbeat → stop → deregister.

v2 (Env-less, newer): Skips Environments API. Connects via POST /v1/code/sessions (OAuth) → POST /v1/code/sessions/{id}/bridge → worker_jwt. Uses SSETransport (reads) + CCRClient (writes via /worker/*). Token refresh bumps epoch. Gated by tengu_bridge_repl_v2.

JWT Token Refresh

createTokenRefreshScheduler — reads JWT exp, sets timer for exp - 5min_buffer. Generation counter per session prevents stale refreshes. Retry: up to 3 failures, 60s delay. Fallback every 30min for long-running sessions.

Remote Control (Self-Hosted)

RemoteServer — HTTP+WS server: GET /health, POST /v1/sessions, GET /ws. Token store: one-time tokens clew-rt-<24-hex>, SHA-256 hashed, 24h expiry. Relay Server (NAT traversal): JSON over WebSocket, pairs listener + connector, forwards data bidirectionally.

10

Plugins 3 ops files · 27 hook events · builtin + marketplace

Medium pluginOperations • PluginInstallationManager • 10+ builtin plugins

Core Plugin Files

Service layer: src/services/plugins/ — pluginOperations.ts, PluginInstallationManager.ts, pluginCliCommands.ts. Builtin: src/plugins/builtinPlugins.ts, src/plugins/bundled/. External: plugins/ directory.

Lifecycle

Declaration (settings) → Materialization (marketplace clone/fetch) → Loading (validate + cache) → Enablement (settings + transitive deps force-enabled) → Execution (commands + hooks + agents + MCP servers) → Disable/Uninstall

27 Hook Events

Hook types: command (shell exec), prompt (LLM eval), agent (verifier), http (POST), callback (internal). Events include: Setup, SessionStart, UserPromptSubmit, PreToolUse/PostToolUse/PostToolUseFailure, PermissionRequest/PermissionDenied, Stop/StopFailure, SessionEnd, SubagentStart/Stop, PreCompact/PostCompact, Elicitation, ConfigChange, WorktreeCreate/Remove, FileChanged, CwdChanged, TeammateIdle, TaskCreated/Completed, InstructionsLoaded, MessageDisplay.

Exit codes: 0 = stdout to Claude, 2 = stderr to model (blocking). Supports async: true (background), once: true (auto-remove), if conditions (permission rule syntax).

Manifest & Marketplace

plugin.json fields: name, version, dependencies, commands, agents, skills, hooks, mcpServers, lspServers, userConfig, settings, strict. Marketplace sources: github, git, url, npm, file, directory. Dependency resolution: DFS with cycle detection. Cross-marketplace deps blocked by default.

Builtin Plugins

commit-commands, code-review, feature-dev, frontend-design, security-guidance, agent-sdk-dev, hookify, plugin-dev, pr-review-toolkit, plus output styles and migrations.

11

AppState 6 files · monolithic store ~80 fields

Medium createStore factory • useSyncExternalStore • Immutable updates

6 Files

store.ts — generic createStore<T>() returning { getState, setState, subscribe }. Uses Object.is for no-op skip.

AppStateStore.ts — AppState type (~80 fields): settings, MCP connections, plugins, tasks, tool permissions, bridge, speculation, voice, tmux/tungsten, agent definitions, file history, notifications.

AppState.tsx — React glue: AppStateProvider creates store, provides via context. useAppState(selector) uses useSyncExternalStore. useSetAppState() stable updater ref.

onChangeAppState.ts — side-effect orchestrator: syncs permission mode to CCR/SDK, persists model/settings.

selectors.ts — getViewedTeammateTask(), getActiveAgentForInput().

teammateViewHelpers.ts — agent view utilities.

12

Ink UI 97 files · custom React renderer

Medium Custom fiber reconciler • Yoga flexbox layout • Full ANSI event system • 461 component files

Custom Renderer (src/ink/, 97 files)

A reimplementation of the ink library:

  • Reconciler (reconciler.ts) — custom React fiber reconciler using react-reconciler
  • Render pipeline — renderer.ts, render-to-screen.ts, render-node-to-output.ts (virtual tree → ANSI escape sequences)
  • Layout — Yoga (Facebook flexbox) engine for terminal positioning
  • Event system — keyboard, mouse, terminal resize, focus dispatcher
  • Terminal I/O — ANSI/SGR/CSI/DEC parsing, OSC commands, tokenizer
  • Components — Box, Text, Button, Spacer, Newline, Link, ScrollBox, AlternateScreen
  • Hooks — use-input, use-app, use-stdin, use-interval, use-animation-frame, use-terminal-viewport, use-selection, use-search-highlight, use-tab-status, use-terminal-focus

UI Components (src/components/, 461 files)

  • Shell: App.tsx (top-level with AppStateProvider, stats, FPS, Sentry), Messages.tsx, Message.tsx, MessageRow.tsx
  • Prompt input: PromptInput/ directory — input, footer, voice indicator, history search, suggestions
  • Messages: UserPromptMessage, AssistantTextMessage, AssistantThinkingMessage, AssistantToolUseMessage, UserBashInputMessage, UserToolResultMessage, SystemTextMessage + many more
  • Permissions: Dialogs for bash, file write, file edit, PowerShell, sandbox, web fetch, skills, notebook edit, plan mode, computer use
  • Design system: ThemedText, ThemedBox, Dialog, Pane, Tabs, Divider, ListItem, ProgressBar, StatusIcon
  • Management: MCP servers, plugins, agents (create wizard with 10+ steps), skills, hooks

Screens (src/screens/, 3 files)

REPL.tsx — main read-eval-print loop. Doctor.tsx — diagnostics screen. ResumeConversation.tsx — session picker with progressive loading.

13

Slash Commands 120+ dirs · 411 files

Medium Organized in subdirectories, each exports call() + index.ts

Command Categories

CategoryCommands
Core session/clear, /compact, /exit, /resume, /session, /status, /version
Configuration/config, /model, /provider-select, /theme, /color, /output-style, /effort, /fast, /thinking, /keybindings, /scroll-speed
Collaboration/buddy, /peer, /bridge, /remote, /teleport, /session
Code review/review, /pr, /diff, /commit, /commit-push-pr, /branch, /autofix-pr
Agent management/agent, /agents, /skill, /skills, /task, /tasks, /daemon
Utilities/help, /doctor, /cost, /usage, /stats, /export, /install, /upgrade, /feedback, /recap
MCP/Plugin/plugin, /mcp, /reload-plugins, /searxng, /tools
Voice/UI/voice, /vim, /desktop, /mobile, /sandbox-toggle
Advanced/ultraplan, /ultracode, /goal, /plan, /research, /workflow, /thinkback, /thinkback-play, /bg, /explorer
Auth/login, /logout, /oauth-refresh

Also includes: /taste, /taste1, /memory, /context, /rename, /tag, /insights, /guardian, /approve, /brief, /copy, /onboarding, /powerup, /looplock, /passes, /privacy-settings, /permissions, /env, /files, advisory commands, and many more.

14

Cost & History cost-tracker.ts (350) · history.ts (451)

Medium Token accounting per model • JSONL persistence • Paste store

Cost Tracker (350 lines)

addToTotalSessionCost(cost, usage, model) — accepts both Anthropic (snake_case) and generic (camelCase) usage. Accumulates input/output/cache tokens per model. Tracks advisor usage costs. Sends OpenTelemetry metrics.

Session persistence: restoreCostStateForSession(sessionId) reads from project config; saveCurrentSessionCosts() writes back with FPS metrics and per-model usage. Re-exports from bootstrap/state: getTotalCost, getTotalInputTokens, getTotalOutputTokens, getTotalDuration, getTotalAPIDuration, getModelUsage.

History System (451 lines)

Prompt history persists to ~/.claude/history.jsonl:

  • addToHistory(entry) — deduplicates consecutive identical entries. Large paste contents hashed to pasteStore.
  • getHistory() — async generator: current-session first (newest-first), then cross-session. Max 1000 items.
  • getTimestampedHistory() — for ctrl+R picker: deduplicated by display text, lazy resolve() for paste contents.
  • removeLastFromHistory() — undo last entry (Esc-rewind): fast path pops pending buffer.
  • File I/O: JSONL with pid-based file locking, retry logic, batch flushing.
15

Context & Permissions context.ts (195 lines)

Medium System context • Git status • CLAUDE.md • Tool permissions in AppState

System Context (getSystemContext())

  • gitStatus — Git branch, short status, recent commits (memoized, capped 2000 chars, async exec)
  • capabilities — detected system tools available
  • computerUseHint — prompt injection when computer use enabled
  • cacheBreaker — ephemeral injection (ant-only, cache breaking)

User Context (getUserContext())

  • claudeMd — parsed CLAUDE.md / memory files from .claude/memory/
  • currentDate — today's date string

Permissions

toolPermissionContext lives in AppState (not context.ts). This module provides the context window content for the LLM's workspace understanding. Tool permissions use classifier + rules + prompt approval in the tool execution pipeline. initializeToolPermissionContext() is called with allowed/disallowed tool lists.

16

Voice voiceModeEnabled.ts (58 lines)

Medium Gateway checks • OAuth auth • Alternative STT backends

Gateway Checks

  • isVoiceGrowthBookEnabled() — always true in OSS build
  • hasVoiceAuth() — requires valid Anthropic OAuth tokens (voice_stream endpoint)
  • hasAlternativeSttKey() — true if OPENAI_API_KEY, GROQ_API_KEY, or WHISPER_API_KEY + WHISPER_API_URL set
  • isVoiceModeEnabled() — full check: hasVoiceAuth() || hasAlternativeSttKey() AND GrowthBook gate

Wider Implementation

Spans into src/commands/voice/ (/voice command), src/services/voice.ts, voiceStreamSTT.ts, voiceKeyterms.ts, and UI components VoiceIndicator, VoiceModeNotice. Supports Anthropic voice streaming + alternative STT (OpenAI, Groq, Whisper).

17

Memory 14 files · SQLite FTS5

Medium No embeddings • Full-text search • Chunk-based indexing

14 Files at src/memory/

FilePurpose
db.tsSQLite bootstrap: sources, chunks, chunks_fts (FTS5). WAL mode. DB at .claude/index/chunks.db
store.tsCRUD: getSource, upsertSource, deleteSource, insertChunks (FTS transaction), searchChunksFTS (sanitized prefix search)
search.tssearchMemories(cwd, query, limit) — FTS + scoring: priority (0-1) × recency (0-0.15 for <24h) × lexical. Returns sorted MemorySearchResult[]
ingest.tsingestMemoryWorkspace(cwd, config) — full re-scan, content hash compare, re-chunk changed files, delete removed
chunker.tschunkMarkdown() — splits by word boundary, default 3000 tokens/chunk
redact.tsredactSecrets() — strips API keys, tokens before indexing
types.tsMemoryType: user, project, feedback, agent, pending, wiki, run, index
runs/runWriter.tsWrites conversation summaries to memory

Scoring & Config

Truth priority: user=80, feedback=70, project=60, default=50. Content hashing: quick stat-based (relPath + size + mtime) avoids re-indexing. Config: memory dir, wiki dir, index dir, max chunk tokens (3000), auto-capture, auto-sync, exclude globs.

18

Architecture Flow end-to-end system map

Medium Data flow • Component relationships • Execution paths

End-to-End Data Flow

CLI (bin/clew.cjs) → main.tsx (bootstrap + init, 6475 lines) → setup.ts (env, git, worktree, plugins, memory, 423 lines) → AppStateProvider + Ink renderer → REPL screen → User types prompt (or slash command /) → QueryEngine.submitMessage() → Process user input (slash commands, attachments) → Build system init (tools, MCP, model, agents, skills) → query() → queryLoop() (1623 lines) → Compact history (snip → micro → collapse → auto) → ProviderAdapter → AI Provider (streaming) → Tool Execution (runTools or StreamingToolExecutor) → Post-sampling hooks + Stop hooks → Token budget check → continue or complete → Yield result (success/error/budget-exceeded) → Update AppState → Ink re-renders UI → Taste learns from accept/reject/edit → Cost tracker accumulates → History appended to history.jsonl

Execution Paths

Interactive: main.tsx → showSetupScreens() → LaunchRepl() → Ink TUI → QueryEngine → AI loop → Tool execution → Response

Headless (--print): main.tsx → runHeadless() → headlessStore → QueryEngine → StructuredIO → stdout

Autonomous: Supervisor IPC → daemonMode.ts → agentLoop.ts → taskQueue → spawn workers via IPC → monitor → complete/fail

Peer-to-Peer: /peer share → PeerDiscovery → PeerServer on random port → file registry → HTTP POST/SSE → peers communicate

Bridge: /bridge → initReplBridge() → v1 (env poll loop) or v2 (env-less) → JWT refresh → bidir message relay

System Dependencies

#SystemDepends OnUsed By
1Entry Point—All
2AI Providers—QueryEngine, Tools
3Query EngineProviders, Tools, Taste, ContextREPL, Headless, Workers
4Tool SystemAppState, MCPQueryEngine
5Peer-to-PeerAppStateCommands, Autonomous
6TasteStorageQueryEngine
7AutonomousSupervisor, QueueDaemon, Cron
8MCPAuthTools, QueryEngine
9BridgeProviders, AuthRemote sessions
10PluginsSettingsCommands, Hooks, Agents
11AppState—All
12Ink UIAppStateREPL, Interactive
13CommandsAppState, PluginsREPL
14Cost & HistoryBootstrap stateReporting, Resume
15ContextGit, FSQueryEngine
16VoiceOAuthREPL
17MemorySQLiteQueryEngine

Key File Metrics

FileLinesRole
main.tsx6,475Entry — full bootstrap + CLI + lifecycle
query.ts1,623Core AI loop
QueryEngine.ts1,219Conversation orchestrator
Tool.ts782Base tool type + buildTool()
commands.ts740Command registrations
ProviderManager.ts369Provider selection singleton
setup.ts423Init/setup sequence
context.ts195System + user context
history.ts451Prompt history persistence
cost-tracker.ts350Token/cost accounting
bridgeMain.ts2,651v1 bridge daemon
replBridge.ts2,166v1 REPL bridge
mcp/auth.ts2,207MCP OAuth + XAA
providers.json2,197AI provider definitions
remoteBridgeCore.ts861v2 env-less bridge