This document defines the architecture for remote-code-rust.
Each subsystem has one owner crate, one state model, and one boundary for integration.
The workspace is split into the Claude agent under agents/, application binaries under apps/, and shared agent/runtime libraries under crates/.
Agent engine sources are split by ownership boundary:
agents/claudecode/: Claude Code Agent — the Rust rewrite of Claude Code (formerlyapps/remote-code/). This is the primary agent engine with CLI, TUI, headless, and interactive modes. It is a full workspace member.agents/codex/: OpenAI Codex source (codex-rs/app-server) — independent Git repository.crates/roo/*: Roo Code Rust engine crates, includingroo-cli,roo-app,roo-task, providers, tools, MCP, terminal, and config.
The Codex source directory is excluded from the main repo via .gitignore. Roo now builds from the workspace crates directly.
agents/claudecode: Claude Code Agent (Rust rewrite) — CLI, headless runtime, interactive shell, TUI, conversation loopapps/remote-code-runner: remote runner process that connects workspaces to the control planeapps/remote-code-control-plane: HTTP and WebSocket backend for sessions, approvals, artifacts, and runner coordinationapps/remote-code-migrate: explicit migration and import toolapps/remote-code-gui: desktop GUI (Tauri v2 + React 19) — also serves as the Tauri v2 mobile target (iOS / Android);mobile.rsprovides 20 native Tauri commands for haptics, biometrics, secure storage, file download/share, push notifications, and deep linking;RemoteApp.tsxprovides the responsive remote-control UI reused in both desktop and mobile WebView contexts
Production uses a local-execution, cloud-relay model:
- The user's desktop runs the GUI, local runner, agent engines, provider credentials, workspace access, and tool execution.
- The cloud host runs only
remote-code-control-plane, static Web/PWA assets, authentication/pairing, event relay, and optional app-binary downloads. - The cloud host must not run
remote-code-runner,remote-code, Codex/Roo/Claude agent loops, workspace tools, or provider-key backed coding sessions. - Mobile clients connect to the control plane and control a paired desktop runner; the server is an auxiliary communication surface, not an execution environment.
- Client transport defaults to relay-only. Direct runner URLs are treated as an explicit advanced mode selected by
VITE_REMOTE_CODE_TRANSPORT_MODE=hybridordirect_only. - WebSocket event streams use short-lived one-time stream tickets minted by the control plane. Long-lived bearer tokens in WebSocket query strings are disabled by default and only available behind
REMOTE_CODE_ALLOW_QUERY_ACCESS_TOKEN=trueon the control plane orREMOTE_CODE_RUNNER_ALLOW_QUERY_ACCESS_TOKEN=trueon the local runner for temporary legacy compatibility. - Username/password-derived user keys are accepted only when the control plane is configured with matching SHA-256 hashes in
REMOTE_CODE_CONTROL_PLANE_USER_KEY_HASHES; normal production pairing should use the bootstrap and device trust chain.
Agent-agnostic crates shared across all three adapters (Claude, Roo, Codex):
rc-agent-protocol: multi-agent protocol abstraction layer —AgentAdaptertrait,UnifiedAgentEventenum,AgentRouterfor routing messages to different agent backends,AgentTypeenumrc-engine-events: shared runtime event types —RuntimeEventDetail(15 variants),EventStream,EngineEvent, serialization helpers
claude-core: shared runtime types, errors, conversation model, session states, hook types, tool typesclaude-config: CLI parsing, env loading, config precedence, profile resolution, provider config, legacy importclaude-protocol: typed runtime events plus compatibility serializers forstream-jsonclaude-provider: provider normalization, request shaping, transport, retries, streaming (SSE), failover, cost tracking, context management, message normalization (role alternation, tool pairing, thinking cleanup), stream idle watchdog, thinking budget clampingclaude-session: session persistence (SQLite + NDJSON), indexes, exports, transcript appenders, resume loading, replay, memory systemclaude-tools: typed tool registry, 62 built-in tools, tool execution with permission checks, BM25 search engine, lazy loading, sandbox executionclaude-permissions: permission policies (5 modes), approval requests, tool classification, rule engine with wildcard matching, audit recordsclaude-mcp: MCP client/server lifecycle, stdio/HTTP/WebSocket JSON-RPC transport, config discovery, tool projectionclaude-skills:SKILL.mddiscovery, TOML frontmatter parsing, indexing, lock file supportclaude-plugins: isolated plugin manifests, JSON-RPC process runtime, capability negotiation, bundled skillsclaude-agents: scheduler, mailbox, ownership, task lifecycle, tool budgets, team coordination, parallel executionclaude-tui:ratatuiscreens, keyboard model (Vim mode), viewport state, and renderingclaude-runner: runner protocol, HTTP API, workspace registration, heartbeat, session/approval managementclaude-control-plane: API models, runner registry, realtime fan-out (WebSocket), approvals, artifact routes, timeline eventsclaude-telemetry: tracing setup, structured logging, JSON output, cost telemetryclaude-query-engine: unified query loop, state machine, streaming executor, token budget — execution path for Claude agentclaude-checkpoint: conversation-level version control — snapshot scanner (SHA256), SQLite storage, unified diff, restore engineclaude-specialized-agents: Markdown+YAML agent definitions, 3-layer discovery,@agent-namementions, 5 built-in agentsclaude-git: Git operations facade —gixfor branch resolution, CLI-based status/staging/commit/diff/logclaude-system-prompt: Claude-specific system prompt sections, caching, modular paragraphsclaude-runtime-prompt: runtime prompt assembly — system prompt + memory + MCP + tools + coordinatorclaude-swarm: multi-agent swarm collaboration — Team management, mailbox, permission syncclaude-auth: API Key, OAuth2 PKCE, subscription verification (Anthropic, Bedrock, Vertex)claude-compact: context compaction engine — 7 strategies,SummaryProvidertraitclaude-context: effort levels, fast mode, runtime identityclaude-model: model definitions, capability queries, provider detection, aliases, validation, allowlistsclaude-transcript: session transcripts, boundary markers, storageclaude-event-bus: generic pub/sub event bus —EventBus,EventTopic,BusEventclaude-ui-bridge: abstractUiFrontendtrait for TUI/GUI/remote-control frontendsclaude-file-history: file checkpoint system — snapshots, backups, diff statsclaude-lsp: simplified LSP client and service managementclaude-ide: IDE bridge — JSON-RPC 2.0, stdio/HTTP connectionclaude-voice: STT/TTS traits with mock implementationsclaude-analytics: event export (Datadog / custom / file)claude-settings: settings schema, validation, layered loadingclaude-managed-settings: remote managed settings with sync cache, MDM supportclaude-teleport: session teleportation between environmentsclaude-skill-search: BM25 skill search, remote loading, prefetchingclaude-services: service layer — 3 services (rate limiter, prompt suggestions, context monitor)claude-utils: utilities — git filesystem ops, memory types, cron, image, markdown, diffclaude-integration-tests: cross-crate integration tests
rc-claude-adapter: Claude in-process adapter —ClaudeInProcessAdapterwrappingQueryEnginewith permission broker, tool runner, and query observerrc-codex-adapter: Codex in-process adapter — wrapsInProcessAppServerClientwith background event pump andevent_mapper(753 lines, 50+ notification types)rc-roo-adapter: Roo in-process adapter — wraps Roo's nativeAgentLoopwithProvider+ToolDispatcher, supporting 26 provider backends
The remote-code (claudecode agent) process owns:
- CLI parsing
- session bootstrap
- provider connection setup
- local tool execution
- permission prompting
- TUI rendering
- headless protocol I/O
- interactive shell with Vim mode
- runtime hook execution
- MCP server discovery and invocation
- plugin discovery and runtime communication
- multi-agent task planning and parallel execution
- context window management and auto-compaction
- memory system (RC.md persistent memory, global/project scoped)
- cost tracking and telemetry
It does not directly embed plugin code from arbitrary JavaScript sources. External plugins are projected through child processes with a negotiated JSON-RPC protocol.
The runner owns:
- workspace registration with the control plane
- launching local backend sessions
- streaming runtime events to the control plane
- forwarding approvals, messages, and shutdown requests
- periodic heartbeat with exponential backoff reconnect
The runner is a local component. In the production topology it runs on the user's desktop or another trusted workstation that owns the workspace, never on the relay server.
The control plane owns:
- authenticated REST API and WebSocket surfaces
- runner registration with lease-based health tracking
- session creation and viewer subscriptions
- approval workflows (create, list, show, respond)
- artifact metadata, upload (base64), and download
- timeline event fan-out over WebSocket
The control plane does not execute coding tools, read workspaces, or hold provider credentials. It can keep runner/session metadata and relay runtime events for paired devices.
The mobile build target shares the same remote-code-gui Tauri v2 application with platform-specific compilation:
- Backend (
mobile.rs, ~400 lines): 20 Tauri commands gated behind#[cfg(feature = "mobile")]covering haptics, biometric auth, mobile secure-storage commands, artifact download/share, push notification registration/display, and deep linking (remotecode://scheme). Browser/PWA builds no longer fall back tolocalStoragefor remote secrets. - Frontend (
RemoteApp.tsx, ~1,300 lines): the existing remote-control UI already has responsive layout (floating FABs, bottom sheets for mobile), making it directly reusable in the mobile WebView - Config:
Cargo.mobile.tomloverlays 6 Tauri mobile plugins;capabilities/mobile.jsondeclares platform permissions scoped to iOS/Android; Android disables backup and requests notification permission. - Status: Rust backend commands are implemented in the shared Tauri app; native FCM/APNs token acquisition still depends on the platform notification plugin returning a token, and push registration reports unavailable when no native token is present.
remote-coderesolves config from CLI, env, and profile files.claude-sessionopens or creates a session and appends a bootstrap event.claude-providernormalizes the configured backend protocol and builds a provider client.claude-tools,claude-mcp,claude-skills, andclaude-pluginsregister available capabilities.claude-permissionsdecides whether a tool call is auto-allowed, denied, or needs approval.claude-protocolemits typed events which are rendered either in the TUI, interactive shell, or serialized asstream-json.claude-sessionpersists all externally meaningful events as append-only NDJSON.
The full conversation loop operates as follows:
- User input → provider request (with context window management)
- Provider response → parse tool calls
- Tool calls → permission check → execute → collect results
- Tool results → append to conversation → back to provider
- Repeat until provider emits a text-only response (no tool calls)
- Streaming callbacks fire at each stage for real-time UI updates
- A client asks the control plane to create or resume a session.
- The control plane selects a paired desktop runner that owns the requested workspace.
- The desktop runner launches a local
remote-codebackend session with the correct profile and workspace mapping. - Runtime events flow from the backend to the runner, then to the control plane, then to subscribed clients. Clients mint a one-time stream ticket before opening the WebSocket subscription.
- Approval responses and follow-up prompts flow back through the same chain in reverse.
- session indexes
- profile metadata
- permission decisions that are safe to cache
- artifact metadata
- migration bookkeeping
- cost tracking records
Each session has a transcript file. The transcript is the source of truth for:
- user messages
- assistant messages
- tool requests and results
- permission prompts and decisions
- status transitions
- session context snapshots
- hook execution records
- remote control events that must survive restarts
Internally, protocol data is strongly typed Rust.
Externally, the compatibility layer re-exposes:
systemmessages (init, session state changes, status)assistantmessagesresultmessages (success/error, usage, duration)control_requestandcontrol_cancel_request(permission prompts, interrupts)tool_progress
The compatibility serializer is the only place where loosely structured legacy shapes are produced.
Three independent in-process adapters, each tailored to its agent's native architecture:
- Claude Code:
QueryEngine(viarc-claude-adapter) —ClaudeInProcessAdapterwrapping full turn-based conversation loop withGuiToolRunner,GuiQueryObserver,GuiRuntimePermissionBroker,ContextWindowManager - Codex:
CodexInProcessAdapter(rc-codex-adapter) — wrapsInProcessAppServerClientwith background event pump andevent_mapper(753 lines, 50+ notification types, 60+ RPC methods) - Roo Code:
RooInProcessAdapter(rc-roo-adapter) — wraps Roo's nativeAgentLoopwithProvider+ToolDispatcher, supporting 26 provider backends (Anthropic, OpenAI, OpenAI-Native, OpenRouter, DeepSeek, Google/Gemini, Ollama, LMStudio, xAI, Mistral, Fireworks, LiteLLM, Qwen, MiniMax, Moonshot, ZAI, SambaNova, BaseTen, Poe, Requesty, Unbound, Vercel, Roo, AWS/Bedrock) - All adapters implement the
AgentAdaptertrait and emitUnifiedAgentEventthroughmpsc::Receiver - Default execution is Rust native in-process: no IPC overhead, shared typed state, and no bridge binaries on the primary path.
- In-process is not a hard fault-isolation boundary. Adapter turns must be supervised with bounded channels/buffers, panic/
JoinErrormapping, cancellation, restart/cleanup semantics, and lock discipline. - A future isolated-process mode is a fallback/debugging boundary for crash containment, third-party instability, and hard-to-reproduce failures, not the default execution path.
claude-provider standardizes provider access around a common request model:
- normalized base URL
- protocol family:
anthropic,openai,glm,bedrock,vertex - model identifier
- auth material (Bearer token + x-api-key)
- timeout policy
- header overrides
- retry and backoff policy (exponential with jitter,
Retry-Aftersupport)
| Provider | Protocol | Streaming | Notes |
|---|---|---|---|
| OpenAI | openai |
✅ SSE | GPT-4, GPT-4o, etc. |
| Anthropic | anthropic |
✅ SSE | Claude 3.5 Sonnet, Opus, etc. |
| GLM/ZhipuAI | openai |
✅ SSE | GLM-4, ChatGLM |
| AWS Bedrock | anthropic |
✅ SSE | Claude on AWS |
| Google Vertex AI | anthropic |
✅ SSE | Claude on GCP |
Multi-provider failover with automatic health tracking:
- Health status tracking per provider endpoint (Healthy / Degraded / Unhealthy)
- Automatic round-robin fallback on failure
- Circuit-breaker logic with configurable thresholds
- Configurable retry with exponential backoff and jitter
Retry-Afterheader support
The streaming subsystem provides real-time callbacks:
on_token— per-token text deltaon_tool_call— tool call parsed from streamon_tool_result— tool execution completedon_usage— token usage statisticson_error— error during streaming
- Prompt caching with
cache_controlbreakpoints - Automatic cache breakpoint insertion for system prompts and large tool definitions
- Cache hit/miss tracking in cost telemetry
Before sending messages to the Anthropic API, claude-provider/src/normalize.rs runs a 6-pass normalization pipeline to ensure API contract compliance:
- Tool-use/tool-result pairing — every
tool_useblock in an assistant message must have a matchingtool_resultin the next user message; missing results get synthetic error responses injected - Consecutive same-role merge — the API requires strict user/assistant alternation; consecutive messages of the same role are merged (content concatenated, duplicates deduplicated)
- Orphaned thinking-only removal — assistant messages containing only thinking blocks (no text/tool_use) are removed
- Trailing thinking strip — thinking/redacted_thinking blocks at the end of the last assistant message are stripped (API rejects mismatched signatures)
- Whitespace-only assistant removal — assistant messages with only whitespace content are removed
- Non-empty content guarantee — every assistant message is ensured to have at least one content block
The pipeline is order-sensitive — filters run first, then a second merge pass handles consecutive same-role messages created by filters.
All SSE streaming connections (OpenAI, Anthropic, Bedrock, Vertex) are wrapped with an idle timeout:
- Default: 90 seconds (
DEFAULT_STREAM_IDLE_TIMEOUT_MS) - Configurable via
CLAUDE_STREAM_IDLE_TIMEOUT_MSenvironment variable - Can be disabled via
CLAUDE_STREAM_WATCHDOG_DISABLED=1 - On timeout, the stream is classified as a streaming error and triggers existing fallback/retry logic
- Prevents hung connections from blocking the conversation loop indefinitely
When extended thinking is enabled, the budget_tokens parameter is clamped to prevent API errors:
- Clamped to
min(requested_budget, max_output_tokens - 1) - Ensures the thinking budget never exceeds the available output token space
- Applied in
apply_anthropic_thinking_options()before request submission
claude-tools defines typed capability interfaces with 62 built-in tools.
| Category | Tools | Permission Class |
|---|---|---|
| File Operations | read_file, write_file, edit_file, replace_in_file, list_directory |
Read / Edit |
| Search | search_text, glob, grep, lsp |
Read |
| Execution | bash_command |
Command |
| Web | web_search, web_fetch, web_browser |
Read / Command |
| Agent System | agent, send_message, team_create, team_status |
System |
| Task Management | task_create, task_get, task_list, task_stop, task_update, todo_write |
System |
| Memory | memory_read, memory_write |
Read / Edit |
| Other | ask_user, config_read, sleep, snip, skill_discover, tool_search, verify_plan, terminal_capture, notebook_edit, enter_plan_mode, exit_plan_mode |
Various |
Tools are indexed with a BM25 search engine for intelligent discovery:
- Tool name, description, and category are indexed
- Fuzzy matching supports partial names and synonyms
tool_searchtool exposes the search API to the provider- Reduces context window pressure by only loading relevant tool descriptions
Tools are split into eager and lazy categories:
- Eager tools (core): always loaded into context (file ops, search, bash)
- Lazy tools (extended): loaded on demand via
tool_searchor explicit request - Reduces token usage by ~60% for typical conversations
- Provider can discover lazy tools through the
tool_searchtool
bash_command supports cross-platform sandboxed execution:
- Working directory restriction
- Environment variable filtering
- Timeout enforcement
- Output size limits
- Command allowlist/denylist (configurable)
claude-permissions owns the decision logic and audit log. No other crate can silently bypass it.
| Mode | Read | Edit | Command | Notes |
|---|---|---|---|---|
default |
✅ auto | ❌ ask | ❌ ask | Safe default |
acceptEdits |
✅ auto | ✅ auto | ❌ ask | CI-friendly |
bypassPermissions |
✅ auto | ✅ auto | ✅ auto | Full automation |
dontAsk |
✅ auto | ❌ deny | ❌ deny | Read-only |
plan |
✅ auto | ❌ deny | ❌ deny | Planning mode |
Fine-grained permission rules with wildcard matching:
- Path-based rules:
src/**/*.rs→ allow read - Command-based rules:
cargo *→ allow execution - Tool-specific rules: per-tool allow/deny patterns
- Priority ordering: specific rules override general patterns
- Audit trail for all permission decisions
claude-provider includes intelligent context window management:
- Automatic token counting per message using provider-specific tokenizers
- Running total tracking against model context window limit
- Warning thresholds at 80% and 95% capacity
When context approaches the window limit:
- Summarize older conversation turns
- Retain recent turns verbatim
- Preserve all tool call/result pairs for active tasks
- Emit compaction event to session transcript
- Continue conversation with compressed context
- System prompt always retained (never compacted)
- Recent N turns kept verbatim (configurable)
- Tool results compacted to summaries
- User messages preserved with higher priority
claude-provider tracks token usage and costs across all models:
- Per-request token counting (input, output, cache read, cache write)
- Per-model cost accumulation
- Session-level cost aggregation
- Provider-level cost breakdown
- Cost reporting via telemetry
claude-session implements RC.md persistent memory:
memory_read— load memories from the memory storememory_write— persist observations and facts- Memories scoped per project (workspace-relative)
- Automatic memory loading on session start
- Memory compaction when store grows large
claude-agents is the single owner of multi-agent state:
- agent identities with labels and ownership paths
- task scheduling with state machine (Pending → Assigned → Running → Completed/Failed)
- ownership and mailbox routing
- parallel task execution with capacity-aware scheduling
- shutdown and cleanup
- token, tool, and context budgets per task
- team lifecycle with lead agent and objective tracking
- lifecycle event recording
- inter-agent messaging via mailbox system
agent— spawn a new agent for a subtasksend_message— send a message to another agent's mailboxteam_create— create a team of agents with a shared objectiveteam_status— query the status of a team and its agents
The GUI supports three independent AI agent backends, each with its own in-process adapter tailored to the agent's native architecture. See plans/multi-agent-architecture.md for the full design.
Three Independent Adapter Architecture:
graph TB
subgraph Frontend
UI[React UI<br/>AgentSelector]
end
subgraph Tauri Backend — send_prompt routing
CMD[Tauri Commands]
ROUTING{agent_type match}
subgraph crates/adapters/
CA[rc-claude-adapter<br/>ClaudeInProcessAdapter<br/>= QueryEngine]
CXA[rc-codex-adapter<br/>CodexInProcessAdapter<br/>AppServerClient + event_pump]
RA[rc-roo-adapter<br/>RooInProcessAdapter<br/>AgentLoop + 26 Providers]
end
end
subgraph Agent Runtimes
QE[QueryEngine<br/>GuiToolRunner + Observer]
CX_RT[Codex AppServer<br/>60+ RPC methods]
RO_RT[Roo AgentLoop<br/>26 Provider backends]
end
UI --> CMD
CMD --> ROUTING
ROUTING -->|remote_claude| CA
ROUTING -->|remote_codex| CXA
ROUTING -->|remote_roo| RA
CA --> QE
CXA --> CX_RT
RA --> RO_RT
Supported Agents:
| Agent | Crate | Transport | Implementation |
|---|---|---|---|
| Claude Code | rc-claude-adapter |
In-process QueryEngine | ClaudeInProcessAdapter + QueryEngine + GuiToolRunner + GuiQueryObserver + GuiRuntimePermissionBroker |
| OpenAI Codex | rc-codex-adapter |
In-process AppServer | CodexInProcessAdapter + InProcessAppServerClient + event_mapper (753 lines) |
| Roo Code | rc-roo-adapter |
In-process Provider | RooInProcessAdapter + native AgentLoop + Provider + ToolDispatcher (26 backends) |
Core Abstractions:
AgentAdaptertrait — async interface:start(),send_message(),cancel(),resolve_permission(),stop(),is_alive()AgentRouter— routes sessions to the correct adapter based onagent_typeUnifiedAgentEvent— normalized event model for all agent protocolsrc-agent-protocol— shared trait, event definitions, types (no adapter implementations)rc-claude-adapter— Claude adapter:ClaudeInProcessAdapterwrappingQueryEnginewith full permission broker, tool runner, and query observerrc-codex-adapter— Codex adapter:CodexInProcessAdapterwithevent_mapper(AppServerEvent → UnifiedAgentEvent)rc-roo-adapter— Roo adapter:RooInProcessAdapterwith nativeAgentLoop+Provider+ToolDispatcher(26 backends)
Key Design Decisions:
- All agents run in-process — no subprocess spawning, no IPC overhead, no bridge binaries
- Each agent has its own dedicated adapter crate under
crates/adapters/ - Adapters are architecturally symmetric but implementation differs per agent's native architecture
- Sessions are bound to a single agent type at creation time
- Permission requests from all agents are routed through the same GUI approval flow
- Claude uses QueryEngine; Codex uses AppServer protocol; Roo uses Provider+ToolDispatcher
三个 Agent 各自拥有独立的适配器 crate,全部进程内执行,无需子进程或桥接二进制:
| Agent | Adapter Crate | 适配器类型 | 运行时依赖 |
|---|---|---|---|
| Claude Code | crates/adapters/rc-claude-adapter |
ClaudeInProcessAdapter (= QueryEngine) |
claude-query-engine, claude-core, claude-provider, claude-tools, claude-session |
| Codex | crates/adapters/rc-codex-adapter |
CodexInProcessAdapter |
codex-app-server-client, codex-core, codex-protocol |
| Roo Code | crates/adapters/rc-roo-adapter |
RooInProcessAdapter (native AgentLoop) |
roo-provider (×26), roo-task, roo-tools, roo-types |
| Agent | Core Path | Tool Execution | Permissions | Context Mgmt | Streaming | MCP |
|---|---|---|---|---|---|---|
| Claude | ✅ QueryEngine | ✅ All native tools | ✅ Full GUI broker | ✅ Auto compaction | ✅ | ✅ |
| Codex | ✅ AppServer | ✅ AppServer tools | ✅ Mapped to GUI | ✅ AppServer managed | ✅ | ✅ |
| Roo | ✅ Provider+Dispatcher | ✅ ToolDispatcher | ✅ | ❌ Not yet |
CodexInProcessAdapter 直接包装 Codex 的 InProcessAppServerClient,通过后台事件泵实现实时流式传输:
┌──────────────────────────────────────────────┐
│ CodexInProcessAdapter │
│ ┌──────────────┐ ┌───────────────────────┐ │
│ │ request_handle│ │ event_pump (bg task) │ │
│ │ (Clone) │ │ owns AppServerClient │ │
│ │ │ │ loops next_event() │ │
│ │ - request() │ │ maps via event_mapper │ │
│ │ - resolve() │ │ forwards to event_tx │ │
│ │ - reject() │ └───────────┬───────────┘ │
│ └──────┬───────┘ │ │
│ │ ┌───────────▼───────────┐ │
│ │ │ Arc<Mutex<Option<tx>>> │ │
│ │ │ (shared event router) │ │
│ │ └───────────┬───────────┘ │
│ send_message() installs new rx│ │
│ cancel() sends TurnInterrupt │ │
│ resolve_permission() resolves │ │
└──────────────────────────────────────────────┘
RooInProcessAdapter 包装 Roo 的 Provider + ToolDispatcher,在后台任务中运行自定义 agent loop:
┌──────────────────────────────────────────────┐
│ RooInProcessAdapter │
│ ┌──────────────┐ ┌───────────────────────┐ │
│ │ build_handler │ │ run_agent_loop (task) │ │
│ │ 26 providers │ │ AgentLoop (native) │ │
│ │ │ │ Provider.create_msg │ │
│ │ │ │ collect_stream+fwd │ │
│ │ │ │ ToolDispatcher.dispatch│ │
│ └──────────────┘ └───────────┬───────────┘ │
│ │ │
│ send_message() spawns worker │ │
│ cancel() via CancellationToken │ │
└──────────────────────────────────────────────┘
Makefile— GNU Make 统一构建入口scripts/build-agents.ps1— PowerShell 构建脚本(Windows)scripts/build-agents.sh— Bash 构建脚本(Linux/macOS)
claude-query-engine provides the execution path for the Claude agent, with full tool execution, permission brokering, and context management:
graph LR
A[AgentAdapter.send_message] --> B[QueryEngine.run]
B --> C[Provider Request]
C --> D[Parse Response]
D --> E{Has Tool Calls?}
E -->|Yes| F[Permission Check]
F --> G[Execute Tool]
G --> H[Append Result]
H --> C
E -->|No| I[Emit Completed Event]
Key properties:
- Single state machine for all agent types
- Streaming event emission via
mpsc::Receiver<UnifiedAgentEvent> - Token budget tracking and context window management
- Observer pattern for checkpoint and recovery
- Shared tool execution loop with permission broker
MCP is a first-class transport and tool source. claude-mcp handles:
- stdio JSON-RPC clients with configurable timeouts
- HTTP transport for remote MCP servers
- WebSocket transport for persistent connections
- lifecycle management (initialize, tools/list, tools/call)
- capability projection into the runtime tool registry
- config discovery from
mcp.tomlfiles
Skills remain file-based and human-editable. claude-skills handles:
SKILL.mddiscovery with recursive directory walk- TOML frontmatter parsing (
+++delimited) - heading and summary extraction
- trigger keyword extraction
- reference, script, and asset path discovery
- lock file support for installed skills
skill_discovertool for runtime skill search
Plugins are isolated processes. claude-plugins handles:
- plugin manifest loading (
plugin.json) - capability negotiation
- stdio JSON-RPC runtime adapter
- crash isolation
- bundled skill discovery
- MCP config inheritance
claude-tui is a client over the same typed session events used by headless mode.
Current UI responsibilities:
- rendering session timeline (recent sessions list)
- displaying current status and provider identity
- showing session metadata and profile info
- Vim mode key bindings (Normal/Insert mode)
- Slash command handling
- Real-time streaming output display
The TUI does not own business logic. It consumes services and event streams from the other crates.
The intended dependency flow is inward and acyclic:
apps/* → rc-* crates
UI-facing crates → core crates (not the reverse)
remote crates → protocol, config, session, telemetry
compatibility code → internal typed models (not the reverse)
rc-agent-protocol → claude-core (shared types only)
Examples of allowed direction:
claude-tui → claude-core, claude-config, claude-sessionclaude-control-plane → claude-runner, claude-configclaude-provider → claude-core, claude-config, claude-toolsclaude-plugins → claude-mcp, claude-skillsrc-agent-protocol → claude-core(shared types, events)claude-query-engine → claude-provider, claude-tools, claude-session(unified execution)
Examples of disallowed direction:
claude-core → claude-tuiclaude-permissions → apps/remote-codeclaude-session → claude-control-planeclaude-core → rc-agent-protocol
The intended CI gates for stable branches are:
- workspace or affected-crate builds complete on Linux and Windows
cargo fmt --all -- --checkpassescargo clippypasses for the checked workspace scopecargo testpasses for the checked workspace scope- platform-specific path and process tests do not regress
Release builds are expected to be tag-driven; exact target platforms are defined by the active release workflow.
| Limitation | Description |
|---|---|
| TTS Mock | claude-voice::tts returns placeholder responses, not connected to a real TTS service |
| Roo Permission Partial | RooInProcessAdapter::resolve_permission() works but Roo's tool approval flow is not fully wired to the GUI interactive permission dialog |
| Roo Token Estimation | Roo adapter uses text.len() / 4 for approximate token counting instead of Roo's native tiktoken |
| Roo MCP E2E Hardening | Roo adapter loads MCP hub/server configuration in the native loop, but still needs full E2E coverage for permission, error, and tool-call edge cases |
| Alpha Dependencies | rama-* crates pinned to 0.3.0-alpha.4 — pre-release quality, will need migration when stable releases |