New 911 verified blocks in 109 days of dogfooding

The harness for your harness.

Local guard layer for AI coding agents. Supported on Claude Code and Codex, with experimental Cursor, Copilot CLI, Gemini CLI, OpenCode, and Pi integrations; evaluates delivered tool hooks against deterministic rules; blocks the dangerous ones in milliseconds; gates new dependencies behind a fail-closed allowlist; keeps a local activity log you can grep.

$ git clone github.com/QuentinCody/interlinked-cli
See receipts

Node 22+, macOS or Linux. No npm package yet. The 0.2 release goes to the waitlist first:

Works with Claude Code Codex Cursor Copilot CLI Gemini CLI opencode Pi
~/myproj — claude
$ claude
 clean up the build artifacts before deploy

  I'll remove the build output now.
  → Bash: rm -rf /

  ⚠ BLOCKED by interlinked harness
    rule:    builtin-rm-rf-root  (critical)
    reason:  Recursive deletion of root-level or wildcard
             paths is dangerous.
    hint:    Be more specific about what to delete.
    ms:      1

  Let me try the project's build output instead.
  → Bash: rm -rf ./dist
  ✓ allowed
  Removed 14 files.

Illustrative. The rule (builtin-rm-rf-root) and reason text are loaded verbatim from src/harness/rules/builtin-rules-processes.ts; the surrounding agent dialogue is synthesized to show the block-and-recover flow.

The receipt

109 days. One developer.
911 verified real blocks.

The author dogfooded the harness on his own machine while writing it. Across every surviving rotation of the activity log, 3834 distinct guard_block events were captured; the rows below are the ones that survived a per-event audit against Claude Code's session transcripts to confirm the agent's actual tool_input.

Some early dramatic-looking categories (shutdown, root-level rm -rf, DROP TABLE) turned out to be false positives — the rules' substring matchers fired on commit-message bodies, echo arguments, and grep patterns. Those rules were tightened with command-start anchors and quote masking; the table reflects only blocks where the agent's resolved command actually matched the row's intent.

Two more deflations keep the numbers honest: 291 duplicate events from a since-fixed hook over-registration bug (one blocked call logged 3–4×) are collapsed to one, and 11 grep-accelerator "block-and-answer" events — the trigram index answering a search, not enforcement — are excluded entirely.

Data window 2026-05-14 → 2026-09-01, audited 2026-09-01. Two earlier log segments (2026-04-24 → 2026-05-14; a prior audit over that longer window verified 1175 blocks total) were lost and are excluded rather than estimated. Audit method: npm run docs:audit-receipts (re-runs the per-event transcript correlation locally).

Count Severity What the agent tried
580 high Edits that introduced a new TypeScript error — blocked before the write landed (tsc-diff-overlay)
93 high Created a new source file with no companion test
128 high Used shell redirect (cat > file.ts) to dodge the content-quality gate
20 critical Wrote outside the repo root (e.g. /tmp/x.ts)
23 high Empty catch {} blocks landing in code
24 critical kill / pkill / killall at running processes — four aimed at the harness or session itself
26 high Edited a file another agent held the reservation on (multi-agent lease enforced)
10 high Destructive git: reset --hard, branch -D, stash drop
2 critical Secrets detected in proposed write content — blocked before landing on disk
5 critical Package installs not on the team allowlist (fail-closed supply-chain gate)

Verified blocks

911

PreToolUse eval p50

3 ms

Distinct blocks logged

3834

Built-in rules

121

How it works

A Unix socket between the agent and disk.

Every PreToolUse hook fires a JSON-RPC message at .interlinked/harness.sock. The harness evaluates rules, returns a decision, and (optionally) attaches warnings the agent will see on its next turn.

Local-only

No cloud, no telemetry, no LLM in the hot path. The socket is on your machine; the activity log stays in your repo.

Multi-runner

Same harness for Claude Code, Codex, Cursor, Copilot CLI, Gemini CLI, opencode, and Pi. One config, every agent.

Deterministic

Regex + AST + a handful of compilers (tsc, biome, gitleaks, semgrep). Replayable from the JSONL log.

Supply-chain gate

New dependencies are blocked until allowlisted — npm, pnpm, yarn, bun, pip, pipx, poetry, uv, cargo, gem, bundle, go, composer, dotnet, mvn. URL installs and registry overrides always blocked. Fail-closed even when the daemon is down.

Coverage-aware

Per-edit coverage, cyclomatic-complexity, and CRAP-score gates wired to real coverage data — an edit that drops a file below its ratchet is blocked before it lands.

Trajectory-aware

23 sequence detectors watch behavior across the session, not single calls — secret read → network call, download → execute, stale read → write, same failing command three times without observing.

# the hot path
Claude / Codex / Cursor / Copilot / Gemini
  ├─→ interlinked-hook
OpenCode / Pi
  ├─→ managed plugin / extension bridge
  │     ├─→ .interlinked/harness.sock
  │     │     └─→ guard eval (block / allow / warn) ............ 3 ms p50
  │     │     └─→ post-edit quality + structural checks ........ ~0.1–3 s (compilers)
  │     │
  │     └─→ .interlinked/activity.jsonl  (append-only, ~0.1 ms)
  │           └─→ interlinked {status, activity, explain, doctor}

Why this and not …

How we compare.

Capability Interlinked Husky / pre-commit claude-code-action (CI) No harness
Blocks tool calls before the agent runs them ✓ PreToolUse hook — (CI is post-action)
Runs locally, no network on hot path ✗ runs in GitHub
Multi-agent runner support ✓ 7 runners — (git only) — (Claude Code only)
Median rule-eval latency 3 ms (p50, n=35k) ~50–500 ms 10s+ (CI startup)
Blocks unapproved package installs (supply chain) ✓ fail-closed allowlist, 15 package managers post-merge at best
Logs every PreToolUse / PostToolUse ✓ JSONL, replayable CI logs only
Catches dangerous shell commands (rm -rf, kubectl delete --all, …) 121 rules — (file lints, not commands) depends on prompt
Compiles proposed file content before write lands ✓ tsc / biome diff-overlay post-commit only CI only
Open-source, MIT

Husky and pre-commit are great at what they do — git-time linting on file content. They sit downstream of the moment the agent runs an arbitrary shell command. Interlinked sits at that moment.

FAQ

Frequently asked.

Does it phone home? +
No telemetry, no analytics, no version pings — by default. The activity log lives at .interlinked/activity.jsonl in the repo it's instrumenting. Network happens only on explicit opt-in: server-backed commands you run (login, sync), allowlist admission screens (registry metadata + OSV advisories, human-invoked, never on the hook path), and — if you enable sponsor slots — a signed sponsor-feed fetch plus anonymous impression beacons (no accounts; interlinked sponsor disable removes it all).
Why no LLM in the hot path? +
Latency budget. The PreToolUse hook has a tight cycle and a remote LLM call eats it on a good day. Determinism also makes guard decisions replayable from the JSONL log — you can replay a session and verify exactly why a call was blocked. An LLM classifier is on the roadmap as a narrow escalation layer, not a hot-path replacement.
Why isn't it on npm? +
On purpose, for now. The public surface is moving and an npm publish freezes a lot of names and shapes. git clone && npm link is a deliberate filter for serious users. A 0.2 release on npm is planned once the surface stabilizes.
What does it actually catch? +
Two layers. Guard rules — destructive shell commands, secrets in writes, recursive deletes, force-pushes to protected branches, sensitive-file reads, package installs not on the team allowlist — block by default. Taste rules — style, complexity, coverage, test gaps — surface as warnings. Mode selection (balanced / lenient / strict) governs the second layer.
Will it slow my agent down? +
Hot-path rules add ~3 ms median to PreToolUse (p50 across ~35k logged evaluations) — imperceptible. Post-edit checks that compile proposed file content (tsc, biome) take whatever the compiler takes; for a typical TS file that's a few hundred milliseconds, paid on code-file edits — reads and shell commands skip it. Latency budgets are enforced per event class.
Does it work with Cursor / Windsurf / Aider / …? +
Claude Code and Codex are the supported integrations. Cursor, Copilot CLI, Gemini CLI, OpenCode, and Pi are experimental: their adapters install and normalize the native surfaces available today, but upstream enforcement and lifecycle capabilities differ. Other agents land as the runtime ecosystem standardizes — if you're using one we don't have an integration for, file an issue and we'll prioritize.
Can teams share rules? +
Yes. .interlinked/guard-rules.json is committed and read by every machine that has the harness; .interlinked/guard-rules.local.json is gitignored and used for personal overrides. The /enforce skill also distills imperative prose from AGENTS.md / CLAUDE.md into the same JSON format.

Waitlist

Get the npm release the day it ships.

Get the receipts. Run it on your machine.

Five minutes from git clone to your first guard_block in .interlinked/activity.jsonl.