FerryCat: Contract-Driven Cross-Host AI Agent Handoff Bus
English •
中文
[npm version]
[MCP Registry]
[Node.js Version]
[Native Addons]
[Protocol]
[Glama]
[License]
FerryCat (ferrycat) is a lightweight, deterministic cross-host AI agent handoff, code review, and verification harness built on the Model Context Protocol (MCP) and Node.js built-in node:sqlite (WAL mode).
Purpose-built to safely bridge isolated desktop IDE agent hosts (such as Google Antigravity, WorkBuddy, Claude Code, and Cursor) across separate OS processes—enabling Actor-Critic evaluation loops, static analysis gates, and SWE-bench-style patch verification without context drift or blind reviews on stale files.
[FerryCat Architecture and Workflow]
📖 Deep Dive: Why I Started Building FerryCat: When Two AI Coding Hosts Live on the Same Desktop
Quick Glance (See It in 60s)
No IDE setup or config file edits required. Watch the entire deterministic loop execute inside an isolated sandbox in ~2 seconds:
💡 Real benchmark: spins up an isolated child-process sandbox, triggers 1 real lease renewal, and runs a static analysis & verification gate that catches loose equality at src/calc.ts:6. Options (--keep / --json / --no-color) detailed in Quickstart §0.
Core Pain Points & Engineering Solutions
While the official MCP Tasks specification (2025-11 / 2026-07) addresses long-running operations within a single Client ↔ Server connection, it does not solve cross-host collaboration on a developer workstation:
stdio Process Isolation: Desktop IDEs spawn local MCP servers as independent child processes with isolated memory spaces and distinct Node.js runtimes.
- Silent Blind Reviews on Stale Code (
Stale Context): When handing off a task from Host A to Host B, unushed IDE buffers, branch switches, or mid-review edits cause the receiving agent to audit outdated code and produce plausible but invalid conclusions.
- Context Window Bloat: Pasting hundreds of lines of source code across chat windows duplicates token consumption on both ends.
- Unstructured Handoff Outputs: Free-form prose responses lack deterministic schema enforcement, making downstream consumption unreliable and prone to infinite retry loops.
FerryCat resolves these failure modes through a human-scheduled, contract-driven SQLite WAL bus:
Key Architectural Pillars
1. Deterministic 7-State Machine
Every state transition is bound to an explicit SQL transaction with optimistic concurrency control (changes === 1), eliminating phantom or dangling states:
Note on POINTER_STALE vs. SELF_CONTAINED Patch Mode (FC-202): POINTER_STALE is terminal whenever on-disk pointer files mismatch the dispatched SHA-256 baseline, except when a read-only contract (code_review / architecture_audit) attaches a verified unified git_patch (--patch-file) that satisfies all three gates: every declared file block carries at least one @@ hunk with real +/- content (EMPTY_PATCH_HUNKS / EMPTY_PATCH_CONTENT otherwise), and the touched paths cover every pointer file (PATCH_DOES_NOT_COVER_POINTERS otherwise). In that SELF_CONTAINED mode, poll_next_task returns patch_mode: "SELF_CONTAINED" with an explicit workspace_warning instructing the reviewer to inspect git_patch rather than stale on-disk files.
Holder-side lifecycle controls on a CLAIMED contract (all require agent_id === target_agent):
2. Full-File SHA-256 Fingerprinting, Pre-Flight Verify & TOCTOU Soft-Failure Buffering (ADR-0004)
- Dispatch Snapshot:
dispatch_contract reads target files on disk, recording byte size, full-file sha256 (64 hex chars), first_line, and last_line. If a file was modified within the last 3 seconds, a warning is emitted to alert the requester of potential unsaved IDE buffers.
- Claim Verification:
poll_next_task verifies Existence -> Byte Size -> Full-File SHA-256 (never rejecting on mtime_ms alone to tolerate no-op IDE saves). On mismatch, it waits 150ms asynchronously (non-blocking, FC-203) and retries once to rule out transient IDE flushes before marking the contract POINTER_STALE — unless the contract is a read-only review/audit carrying a verified unified git_patch covering all pointer files (SELF_CONTAINED patch mode, FC-202), in which case it claims with an explicit workspace_warning and records __verified_on_disk__: "NO" and __unverified_pointers__ in verified_sha256.
- Pre-Flight Verify (
verify_contract): A strictly read-only check allowing workers or scripts to audit pointer health (valid: true vs valid: false with dirty files list) before submitting.
- TOCTOU Soft-Failure Buffering:
fulfill_contract checks on-disk pointer fingerprints. If dirty pointers are detected:
- Strike 1 returns
RETRY_NEEDED, leaves the contract CLAIMED, renews the execution window, and lists dirty files with recovery instructions (git stash / git checkout -- <file>).
- Strike 2 transitions to terminal
POINTER_STALE and saves the full submitted review payload into salvaged_result_json so review effort is never lost.
- TOCTOU Race Narrowing: While no file-based system can eliminate the microsecond race between reading disk bytes and committing a database row, FerryCat's dual-verification (at
poll and at fulfill) drastically narrows the TOCTOU window from minutes of blind review down to the sub-millisecond atomic SQL transition boundary.
3. Bounded Schema Validation (RETRY_NEEDED $\le 2$)
- Outputs are validated against the contract's JSON Schema via cached Ajv validators, with errors flattened into concise single-line paths (e.g.,
["/passed: must be boolean"]).
- Up to 2 validation failures return
RETRY_NEEDED while keeping the contract CLAIMED for immediate self-correction (each rejection also renews the execution window); a 3rd failure transitions the contract to terminal VALIDATION_FAILED.
4. Dual-Stage TTL & Read-Before-Write Sweeping
- Separates
queue_ttl_sec (default 1800s for SUBMITTED) from exec_ttl_sec (measured from claimed_at), preventing tasks claimed late in the queue window from timing out prematurely during execution.
exec_ttl_sec defaults are tiered by task_type: code_review / architecture_audit → 1800s (deep reasoning or human-in-the-loop), implementation / test_generation → 300s. An explicit exec_ttl_sec always wins.
poll_next_task executes a lock-free SELECT COUNT(*) probe before attempting any UPDATE on expired rows; inspect_mesh_state is strictly read-only.
5. Defense-in-Depth Path Security
- Enforces path containment within
workspace_root and blocks sensitive file patterns (.env*, *.pem, *.key, id_rsa*, *credentials*, *secret*, .npmrc, .git/config) on both dispatch and worker verification paths.
- Path Resolution:
workspace_root is strongly recommended to be passed as an absolute path. If a relative path is provided, it is deterministically resolved against process.cwd() via path.resolve.
6. Threat Model & Security Assumptions (Local Workstation IPC)
- Assumed Trust Environment: FerryCat is intentionally designed as a Trusted Local Workstation Bus bridging isolated IDE hosts operating under the same OS user account. Callers and workers share the local file system (
workspace_root) and SQLite database (~/.ferrycat/mesh.db).
- Defense Scope: Path containment (
assertSafePointerPath) and sensitive file pattern filters prevent unintentional workspace escapes, symlink traversals, or accidental leakage of credentials/secret files during handoffs.
- Daemon Execution Surface: In daemon mode (
ferrycat-cli daemon), handler scripts are invoked directly via execFile. Write permissions to ferrycat.config.json or handler script paths are equivalent to host execution privileges (ADR-0005 §2.2). Keep configurations local and version-controlled.
- Out of Scope (Non-Goals): FerryCat does not provide adversarial sandboxing, multi-tenant isolation, or network authorization against malicious local processes or adversarial agents spoofing
AGENT_NAME.
Applicability Boundaries (When NOT to Use FerryCat)
- Disjoint File Systems: FerryCat offloads context by file reference; both hosts must share access to the same local
workspace_root.
- Trivial Single-Turn Queries: Each cross-host handoff involves 3 explicit human window switches (~15–25s overhead).
- Multi-Step Dynamic DAG Pipelines: FerryCat's background daemon (
ferrycat-cli daemon, ADR-0005) manages single-step contract dispatch and supervised worker lifecycles; for complex multi-step branching DAG orchestrations, use dedicated DAG workflow engines such as PatchCat.
Controlled Daemon & Declarative Handlers (ADR-0005)
FerryCat provides a controlled daemon mode governed by SQLite microsecond CAS leases on daemon_locks and declarative scripts defined in ferrycat.config.json (ideal for binding static analysis gates like tsc / eslint / AST checks or automated test suites like Jest / Vitest / Pytest as deterministic verification workers):
daemon --status reports journal_degraded / last_journal_error / journal_path / journal_entries alongside lease ownership, so a silently unwritable write-ahead journal (which would disarm crash recovery) is visible instead of failing mute.
Example ferrycat.config.json:
Quickstart
0. See what it actually does first (ferrycat demo)
Before configuring any MCP server, watch the whole loop in ~3 seconds:
(or npx -p ferrycat ferrycat-cli demo)
It spins up a fully isolated sandbox under the OS temp dir (dedicated SQLite database,
sample source file, sample handler), runs dispatch → claim → supervised execution → TOCTOU re-verification → COMPLETED, then deletes the sandbox.
Your real workspace and ~/.ferrycat/mesh.db are never read or written.
1. Recommended: Zero-Install MCP Mounting (via npx)
No local clone or manual compilation required. Run npx ferrycat init --yes to auto-detect installed hosts (Antigravity, WorkBuddy, Cursor, VS Code, Windsurf, Claude Desktop, Claude Code) and safely merge the ferrycat server entry (with backup and JSONC protection), or mount manually into your IDE's MCP configuration using npx -y ferrycat:
Antigravity Configuration
Edit %USERPROFILE%\.gemini\antigravity\mcp_config.json (or ~/.gemini/antigravity/mcp_config.json on macOS/Linux):
WorkBuddy / Claude Code / Cursor / Codex Configuration
Configure the target host's MCP settings with its respective AGENT_NAME:
2. Global Installation & Source Build
- Global CLI Installation:
Then simply set
"command": "ferrycat" in your MCP config.
- Local Source Build (For Contributors):
Mount using your local path:
"command": "node", "args": ["--experimental-sqlite", "/path/to/FerryCat/dist/index.js"].
First-Class CLI Experience (ferrycat-cli)
Beyond serving as an in-IDE MCP Server, FerryCat provides a first-class CLI utility (ferrycat-cli). The single ferrycat executable dispatches on its first argument: no argv starts the MCP stdio server, a known subcommand routes to the CLI. So you can run npx ferrycat <command> with zero install (or ferrycat-cli <command> once installed globally). Sharing the same ~/.ferrycat/mesh.db SQLite WAL database and Zod validation contracts, the CLI allows developers to inspect mesh health, verify working tree safety, and hook into automated CI/Git scripts without leaving their terminal:
1. Terminal Visual Inspection (ASCII Status Table)
Inspect all cross-host handoffs and error reasons formatted as an ASCII table:
2. Pre-Flight Verification (Auditing Before Mutation)
Audit on-disk pointer file integrity against the contract's baseline SHA-256 before committing review work (ADR-0004), eliminating false-positive deliveries:
3. Local CI & Headless Worker Execution
Poll the queue, claim tasks, and execute local review/test scripts with automatic failure closure:
4. Zero-Config Sandbox Walkthrough (demo)
Run the self-contained multi-agent lifecycle simulation without configuring an MCP server:
Options (--keep to retain SQLite for manual inspection, --json for CI assertions) detailed in Quickstart §0.
5. Production Controlled Daemon (daemon, ADR-0005)
Run the headless orchestration daemon coordinating background workers via atomic CAS leases and declarative script bindings:
Exposed MCP Tools
💡 Architecture Decision Records & Engineering Verification:
About the Author
Guo Qiang (GuoBug), Product Engineer specializing in platform engineering and growth. Currently focused on AI workflow orchestration, DAG state machines, and deterministic system architectures.
Open Source & Homepage: https://github.com/GuoBug · https://guobug.github.io
Inquiries and discussions on workflow engine architecture, topological scheduling, and developer experience are warmly welcomed.