A sidecar-daemon + MCP bridge designed to give CLI/IDE-based AI agents (Claude Code, Codex, etc.) deep access to a project's filesystem, git state, and source code without paying the per-call fork/exec tax of traditional shell-tool wrappers.
Significant wins across both major agents measured on 2026-04-21 (analysis of openai/codex@rust-v0.122.0).
- −44 % Wall-clock (209s → 117s)
- −66 %
execvecalls (64 → 22) - −64 % Input tokens (1.9M → 0.7M)
- −5 % Wall-clock (even on cold pass)
- −82 %
execvecalls (85 → 15) - −14 % Output tokens
Warm-cache bonus: Re-running tasks on a resident daemon saves an additional 650k–950k tokens per pass via tree-sitter parse and grep result caching.
There is now a matching Claude Code twin benchmark under
bench/claudecode-forkexec/: same
target workload, but three passes (baseline, cold mcp-cli, warm mcp-cli) so the daemon's cross-session cache payoff is visible too.
The Codex run above is still the headline result in the README; the
Claude Code twin broadens the measurement surface beyond a single
agent and is the next place to fold into the top-level story.
+---------------------+ stdio (MCP) +----------------------+
| Claude Code / | <-------------------------> | mcp-cli-bridge |
| Codex / IDE | | (MCP stdio server) |
+---------------------+ +----------+-----------+
|
UDS + length-prefixed JSON-RPC
|
+----------v-----------+
| mcp-cli-daemon |
| - mmap VFS |
| - libgit2 |
| - grep-searcher |
| - (future) tree- |
| sitter, LSP |
+----------------------+
crates/protocol- shared JSON-RPC request/response types between bridge and daemon.crates/daemon- long-livedmcp-cli-daemonprocess that owns the project. Listens on a Unix Domain Socket and exposes in-process tools:fs.read- mmap-backed file read (noread(2)per call).fs.snapshot/fs.changes- incremental sync. The daemon runs an inotify (Linux) / FSEvent (macOS) watcher with a gitignore-aware filter, maintains a monotonic version cursor, and returns coalesced created/modified/removed events since a client-supplied version. If the client falls too far behind, the response setsoverflowed: trueso the client can re-scan instead of silently missing events.git.status- libgit2 status (nogitfork/exec).search.grep- ripgrep'sgrep-searcherlibrary over the project tree.
crates/mcp-bridge- smallmcp-cli-bridgestdio binary that the agent spawns. Translates MCPtools/callrequests into UDS calls. Cheap to spawn, but the heavy state stays in the daemon.
Every traditional shell-wrapped tool call (cat, git status, rg ...) costs
a fork + exec + page-table setup + library loading + syscall stream + tear
down. For an agent that issues hundreds of small reads per task, that's
dominated by kernel overhead, not useful work. By keeping a single hot daemon:
- File reads come from an
mmapalready in the page cache - the kernel only pages in on misses; no per-callreadsyscall stream. - Git, search, and (planned) parse operations stay in-process, so the kernel sees one long-lived process instead of thousands of short-lived ones.
- The bridge stays tiny and the per-call cost is a UDS round-trip on a single pre-warmed socket.
This is the foundation for later layers (incremental inotify diffs, tree-sitter indexing, language-specific backends like clangd / rust-analyzer reuse).
cargo build --releaseArtifacts under target/release/: mcp-cli-daemon, mcp-cli-bridge,
and the mcp-cli installer.
One-command registration for the agents the installer knows about:
# Claude Code + Codex at once (auto-spawns the daemon on first tool
# call; no always-on process needed).
target/release/mcp-cli installFor codex specifically, also pass --prefer-mcp so codex
actually routes through the daemon instead of preferring its own
built-in Bash (this is the configuration the headline numbers were
measured under):
target/release/mcp-cli install --target codex --prefer-mcp--prefer-mcp writes [features] shell_tool = false to
~/.codex/config.toml (so codex stops emitting Bash tool calls for
cat / rg / git / etc.) and sets per-tool
approval_mode = "approve" for every mcp-cli tool (so codex doesn't
prompt for approval in non-interactive codex exec).
Without --prefer-mcp, codex still mounts mcp-cli but keeps
reaching for Bash — see the v1 benchmark writeup for evidence.
The daemon auto-spawns per project root on the bridge's first
connect and idle-exits after 30 min of inactivity; you don't need
to run anything by hand. To always keep one resident, see
doc/services/.
See doc/ROADMAP.md and doc/TODO.md.
- Done (M0–M6 + parts of M7) — Daemon/Bridge skeleton, incremental watch sync, tree-sitter indexing (
rust,python,c,cpp,ts,go), drop-inmcp-cli install, per-cwd auto-spawn, reconnect-on-dead,mimalloc+ buffer pooling, full M5 performance benchmarks, andgit.log/git.diffRPCs. - In Progress (M7) — Token-killer compaction (
?compactongit.status,search.grep,fs.scan;?strip_noiseonfs.read), metrics telemetry, and the generictool.runwrapper. - Open (M8–M10) — Write-path with optimistic concurrency (
fs.apply_patch), advanced structural tools (dependency graphs, dynamic folding), and deep git/process management.