Skip to content

Latest commit

 

History

120 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ClutchCode

A model-agnostic, local-first coding-agent runtime. It never phones home, and "done" means your build and tests actually passed — not that the model said so.


License Node TypeScript Tests CI

Stars Forks Issues PRs Welcome

Quick Start · How It Works · Architecture · Security · Roadmap


clutchcode doctor, then a real run to AWAITING_APPROVAL

Real terminal output, recorded from this build — doctor's sandbox/keychain detection, then a run against --provider fake (no API key, no model, exercises the exact same lifecycle a real provider would). Recorded with asciinema + agg; regenerate with bash docs/assets/record-demo.sh after any user-facing CLI change.

$ clutchcode run "fix the failing test" --provider ollama --model qwen2.5-coder:14b
$ clutchcode diff    <runId>      # review what it actually changed
$ clutchcode approve <runId>      # only now does it touch your branch

✨ Why this exists

Every coding agent will tell you it finished. Almost none of them can prove it.

ClutchCode is built around one rule: the model's opinion doesn't count. A run isn't complete until a deterministic gate — your real build, your real tests, your real linter — actually passes. And because a model under pressure will happily delete the assertion that's failing, there's a cheat-detection layer whose only job is catching that.

A model once "fixed" a failing test by deleting its assertion. Verification went green. Cheat detection blocked the run anyway. That scenario is a permanent test in this repo, not an anecdote.


🎯 What it does

Point it at a task and a model. It works in an isolated git worktree, edits code, runs your toolchain, repairs what it broke, and stops. Nothing reaches your branch until you approve a diff.

🔒 Runs sandboxed by default Real OS confinement — bubblewrap namespaces plus a seccomp-BPF filter, verified against the actual kernel. Network is default-deny at the OS level, not just in policy.

🏠 Local-first, provably No account, no telemetry, no cloud. Enforced by a release-gate test that completes a task offline with egress blocked against a local model.

🧩 Model-agnostic A capability probe adapts edit format, context budget and output reservation to whatever you point it at — frontier API or a 14B model on your own GPU.

↩️ Nothing lands without review Every run is a worktree on its own branch, with per-step checkpoints you can roll back to. approve or reject, your call.


🏗️ Architecture

Eleven packages, strict boundaries. apps/* depend only on agent-api — never on runtime internals.

flowchart TB
    subgraph clients["🖥️  Clients"]
        CLI["apps/cli<br/><i>clutchcode</i>"]
        VSC["apps/vscode<br/><i>extension</i>"]
    end

    subgraph boundary["🚪  Public boundary"]
        API["agent-api<br/><i>in-process binding</i>"]
        RPC["agent-rpc<br/><i>JSON-RPC over stdio</i>"]
        ACP["acp<br/><i>Agent Client Protocol</i>"]
    end

    subgraph core["⚙️  Core"]
        RT["runtime<br/><i>the agent loop</i>"]
        CAP["capability<br/><i>model probe + budgets</i>"]
        VER["verification<br/><i>gate + cheat detection</i>"]
        MEM["memory<br/><i>toolchain facts</i>"]
    end

    subgraph found["🧱  Foundation"]
        TOOLS["tools<br/><i>fs · shell · search</i>"]
        SBX["sandbox<br/><i>bwrap · seccomp · policy</i>"]
        GIT["git<br/><i>worktrees · checkpoints</i>"]
        PROV["providers<br/><i>anthropic · openai · ollama</i>"]
    end

    CLI --> API
    CLI --> ACP
    VSC --> RPC
    RPC --> API
    ACP --> API
    API --> RT & CAP & VER & MEM
    RT --> TOOLS & GIT & PROV & SBX
    VER --> TOOLS
    CAP --> PROV
    MEM --> VER
    TOOLS --> SBX

    style boundary fill:#1f6feb22,stroke:#1f6feb
    style found fill:#3fb95022,stroke:#3fb950
    style core fill:#a371f722,stroke:#a371f7
Loading
Why the boundary matters

The CLI, the VS Code extension, and any future editor client all share 100% of the runtime code; only presentation differs. That's why agent-api exists as a hard boundary rather than a convention — and why the same runtime can be driven in-process or over stdio JSON-RPC without a second implementation.


🧠 How it works

sequenceDiagram
    autonumber
    participant You
    participant Agent as ClutchCode
    participant Model as LLM
    participant Gate as ✅ Gate

    You->>Agent: run "fix the failing test"
    Agent->>Agent: 🌿 create isolated worktree
    Agent->>Model: task + probed context budget

    loop until verified or budget spent
        Model-->>Agent: tool calls (read · edit · shell)
        Agent->>Agent: 🔐 policy check + OS sandbox
        Agent->>Gate: build · test · lint
        alt gate red
            Gate-->>Agent: classified failure
            Agent->>Model: targeted repair prompt
        else gate green
            Gate->>Gate: 🕵️ cheat detection
        end
    end

    Agent-->>You: diff + VERIFIED status
    You->>Agent: approve / reject
    Agent->>Agent: 🔀 merge, or discard the worktree entirely
Loading

The interesting step is the one most agents skip: after the gate goes green, it gets audited. Deleted assertions, .skip markers, hardcoded return values, snapshot edits with no source rationale — all block completion even in --yes mode.


⚡ Features

Feature Detail
🔬 Deterministic completion gate Real build + test + lint. No self-reported success.
🕵️ Cheat detection Catches deleted assertions, skip markers, hardcoded outputs, unjustified snapshot edits.
📦 Git worktree isolation Per-run branch, per-step checkpoints, rollback to any of them.
🛡️ Tier-1 OS sandbox bubblewrap + seccomp-BPF (x86_64 Linux, kernel-verified). Seatbelt profile for macOS.
🔑 3-tier credential storage OS keychain → encrypted file store → env. Keys read from stdin, never argv.
🧽 Secret redaction Every boundary scrubbed, proven by a canary test that injects a fake secret.
🎛️ Workflow engine default · quickfix · review-only, plus JSON-Schema-validated custom workflows.
⏸️ Resumable runs Hit a budget? resume --extend-steps N continues from the persisted transcript.
🧪 Replay harness Recorded transcripts re-run the whole loop with zero API calls.
🔌 ACP editor binding clutchcode acp speaks the real Agent Client Protocol — Zed today, any ACP client tomorrow — over a second binding alongside agent-rpc, not a replacement.

🛠️ Tech Stack

TypeScript Node.js pnpm Vitest Linux

Deliberately dependency-light. The seccomp BPF filter is hand-assembled in TypeScript rather than pulling a native module — the entire runtime's external dependencies are commander, ajv, and smol-toml.


🚀 Quick Start

Requirements — Node ≥ 20, pnpm, git. On Linux, bubblewrap for the OS sandbox (without it you get Tier 0 — policy engine only — and doctor will say so).

git clone https://github.com/Derric01/ClutchCode.git
cd ClutchCode && pnpm install && pnpm build
1 · Check what your machine supports
clutchcode doctor      # sandbox backend, seccomp, keychain, toolchain
2 · Run a task

Local model via Ollama — no key needed:

clutchcode run "fix the failing test in src/parser.ts" \
  --provider ollama --model qwen2.5-coder:14b

Hosted provider — key is read from stdin, never argv or shell history:

clutchcode providers set-key anthropic     # paste, then Ctrl-D
clutchcode run "add pagination to /users" --provider anthropic --model claude-sonnet-5

Bound it: --max-steps, --max-tokens, --cost-ceiling-usd.

3 · Review before anything touches your branch
clutchcode status              # all runs and their state
clutchcode diff    <runId>     # what changed
clutchcode approve <runId>     # merge it back
clutchcode reject  <runId>     # discard the worktree entirely

--yes auto-approves only when the gate is green and cheat detection flags nothing.

4 · Try it with no model at all
clutchcode run "" --provider fake

Replays a scripted transcript through the whole loop. It's how the test suite works.


📊 What we're actually sure of

No invented benchmarks here. The eval scoreboard and the §16.4 A/B now exist — but no VTCR number or delta for any real model is published, because none has been measured (this project's CI has neither an API key nor a local GPU). What the scoreboard gives you is the machinery to measure your own, and a methodology you can argue with: docs/EVAL_METHODOLOGY.md.

Claim How it's proven
854 tests, 86 files pnpm test. Real git repos, real shells, real filesystems — FakeProvider stubs only the model.
The suite runs on CI, not just locally GitHub Actions, Node 20 + 22 on every PR: the same suite plus tsc -b and eslint ., with 16 tests skipped there. Those 16 skips are the bwrap confinement/seccomp suites — a hosted runner cannot create those namespaces, so they skip there and run in full locally (774, 0 skipped). CI green therefore does not prove the sandbox confines; only a bwrap-capable host does.
Sandbox actually confines A test writes outside the workspace, then asserts a sandboxed cat of it fails. Network fetch inside the sandbox asserted unreachable. These run for real wherever bwrap can genuinely create namespaces (this project's dev container can); where it can't — a hosted CI runner, an unprivileged container — they skip and ClutchCode falls back to Tier 0 and says so, rather than claiming a confinement it isn't getting.
Seccomp actually blocks Each denied syscall invoked by number inside real bwrap → EPERM, with an unfiltered control run proving the syscall otherwise succeeds.
Secrets don't leak A canary secret injected into a full recorded run, asserted absent from every transcript, event log and artifact.
Cheat detection works A recorded run where the model deletes an assertion — verification goes green, completion is blocked anyway.
The scoreboard can't be fooled by a green gate Every eval task carries a held-out check, copied in only after the run finishes. A scripted run that changes nothing on an already-passing repo reaches DONE with a green gate — and is scored a false completion, not a success.
The eval tasks are real tasks Eight tasks, six categories, three languages (Node, Python, shell). Every one is validated on each test run against real repos: its held-out check must fail on the pristine repo, pass on the reference solution, and leave the repo's own gate green — and each is also run against the plausible wrong solution a model would write, to prove its oracle discriminates. The validity suite has caught two real defects in this project's own fixtures.
Open-weight models can actually call tools Local models mostly emit the Hermes <tool_call> format, not OpenAI-shaped tool_calls — so we used to read a tool call as prose and score the model toolTransport: "none", costing it a weaker edit format and a smaller context budget. There is now a lexical incremental parser for that format, tested over a real HTTP server and the real SSE path with tags split across chunk boundaries, including a message full of bare <, &, unclosed generics and JSX — the exact content that breaks the XML-based extractors this one deliberately is not. Parser verified; not run against a live model (no GPU/weights here) — see the limitations below.
The naked-vs-harness A/B is a real experiment, not a slogan Both arms of §16.4 now run: the same model under ClutchCode, and the same model naked (one call, no tools, no gate, no repair), graded by the same held-out oracle. Every end-to-end naked test asserts the scripted server's own request counter is 1 — "single-shot" is checked, not asserted in a comment. The delta ships with a Wilson interval per arm and a task-clustered bootstrap interval on the delta, and a report whose interval includes 0 says so in its own notes.
Local-first is real A task completed offline with egress blocked at the OS level, against a local model.
🔍 Honest limitations — read this before trusting it
  • Linux is the verified platform. The macOS Seatbelt profile is written against the documented SBPL grammar but has never run on real macOS. Windows Tier 1 is deliberately doc-only; WSL2 is the recommended path.
  • Landlock is not implemented. Seccomp is. The blocker is documented in HANDOFF.md.
  • The Hermes tool-call parser has never met a live open-weight model. It is unit-tested against fixtures modeled on the published chat-template token layout and driven through the real streaming path, and the capability probe now scores such a model native instead of none. But this environment has no Ollama, no GPU and no weights, so the end-to-end claim — a real Hermes-3 / Qwen / vLLM --tool-call-parser hermes deployment drives our tools correctly — is unverified and is flagged as such in packages/providers/src/hermes.ts.
  • No benchmark numbers are published for any model. The eval suite, the VTCR/§16.2 metrics, the held-out grading and now the §16.4 naked-vs-harness A/B all work and are tested — but every scored run so far is a deterministic scripted one, because this project's environment has no API key and no local GPU. So the machinery to measure "makes small local models usable" exists and no VTCR delta for a real model is published or may be quoted from it. Running clutchcode-eval ab against a 14B-class model on a machine that has one is the remaining step, and it needs no code. The SWE-bench-Verified subset is still not built. See docs/EVAL_METHODOLOGY.md §5 and §8.
  • Eight tasks is still a small suite. Enough to detect a large VTCR delta, not enough to resolve a small one — the A/B's confidence intervals reflect that honestly rather than hiding it. The remaining lever is §16.3a's SWE-bench Verified subset, which needs dataset fetching and per-instance container images this offline harness does not take on.
  • Pre-1.0, not yet published to npm.
  • Security reviews have been thorough but single-reviewer. See SECURITY.md for the threat model and how to report an issue.

Anything this project can't verify is flagged in a header comment and here — silence implying completeness is treated as a defect.


🗺️ Roadmap

gantt
    dateFormat YYYY-MM-DD
    axisFormat %b
    title From here to 1.0
    section Shipped
        Agent loop · edit cascade · worktrees   :done, a1, 2026-01-01, 90d
        Sandbox Tier 1 · seccomp · credentials  :done, a2, after a1, 60d
        Workflow engine · VS Code extension      :done, a3, after a2, 45d
        Eval suite · VTCR scoreboard             :done, a4, after a3, 30d
        Naked-vs-harness A/B (the North Star)    :done, a5, after a4, 20d
        ACP editor binding (Zed today)            :done, a6, after a5, 15d
    section Next
        npm release (npx clutchcode)            :active, b1, 2026-08-01, 30d
        Landlock rung                           :b3, after b1, 30d
        MCP client                               :b4, after b1, 30d
    section Later
        SWE-bench Verified subset adapter       :c1, after b4, 60d
        PageRank repo map                       :c2, after c1, 45d
Loading

Live priority order lives in HANDOFF.md — exactly one row is tagged DO FIRST at any time.


🤝 Contributing

PRs welcome. A few things that are load-bearing here:

  1. pnpm build && pnpm test && pnpm lint must be clean before every commit.
  2. Reproduce before fixing. A finding is a hypothesis until you've made the bad thing actually happen.
  3. Prove your test discriminates — stash the fix, watch the test fail, restore it, watch it pass.
  4. Never skip or disable a test to get green. That falsifies the gate this project exists to enforce.
  5. Flag what you couldn't verify. Honesty beats completeness.

Full guide in CONTRIBUTING.md (DCO sign-off required). Design rationale is in PROJECT_SPEC.md; engineering history in docs/PROJECT_LOG.md.


📄 License

Apache-2.0 © ClutchCode contributors.

Reference projects (Aider, Codex, OpenHands, Cline, and others) are study-only — this implementation is clean-room. See LICENSE_AND_REUSE_ANALYSIS.md.


If the idea of an agent that has to prove its work sounds right to you — ⭐ star it, or open an issue.

About

No description, website, or topics provided.

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages