Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,15 @@ One engine, three ways in — the headless loop is the front door:
- **Ambient** (after onboarding): say what you're working on; the injected frame classifies it —
actionable requests become goals driven through `knitbrain_run_loop` until the verify gate
passes; questions get answered directly.
- **`/goal <done-means>`** — loop until met. **`/loop <same> --for 2h --iters N`** — same engine
plus a wall-clock and iteration budget. Every iteration runs as a full goal cycle.
- **Two slash front doors, on every host that has a slash surface** (Claude Code, Codex, Gemini,
VS Code Copilot, Windsurf — Cursor via terminal):
- **`/goal <done-means>`** drives the gate **with you, in this session** — `knitbrain_run`
orchestrates a skill + agents, then `knitbrain_run_loop` runs your verify command each cycle
until it exits 0. Single context, interactive.
- **`/loop goal.md --for 2h`** hands off to the **external runner** (`knitbrain loop`): it
*launches detached*, spawns a fresh agent per checkbox, and owns the loop itself — surviving
your context window, not depending on any model choosing to continue. A slash command can't
*be* an hour-long loop, so it launches the runner and hands back a watch handle.

**Self-healing:** each failed cycle's verify output is persisted (`failures[]`, last 3) and
injected into the next directive — "previous failures — iter 1: …. Address the ROOT CAUSE" — so
Expand Down Expand Up @@ -189,18 +196,21 @@ The optimizer is identical everywhere; what differs is reach:

| Platform | MCP tools | Hook enforcement | Auto-compression | Slash commands |
|---|---|---|---|---|
| Claude Code | ✅ | ✅ full (deny · stop-block · inject · rewrite) | ✅ hooks | `/goal` `/loop` `/meter` `/handoff` `/terse` |
| Codex CLI | ✅ | ✅ full (`.codex/hooks.json`) | hooks + `knitbrain_read` | |
| Cursor | ✅ | ✅ deny + follow-up loop (`.cursor/hooks.json`) | hooks + `knitbrain_read` | — |
| Gemini CLI | ✅ | ✅ deny + AfterAgent loop (`.gemini/settings.json`) | hooks + `knitbrain_read` | |
| VS Code Copilot | ✅ | ✅ full (reads `.claude/settings.json` natively) | hooks + `knitbrain_read` | |
| Windsurf | ✅ | ✅ deny-only (exit-2) (`.windsurf/hooks.json`) | hooks + `knitbrain_read` | |
| Cline · any other MCP client | ✅ | — (advisory; hooks planned where APIs allow) | via `knitbrain_read` | — |
| Claude Code | ✅ | ✅ full (deny · stop-block · inject · rewrite) | ✅ hooks | `/goal` `/loop` `/meter` `/handoff` `/terse` (`.claude/commands`) |
| Codex CLI | ✅ | ✅ full (`.codex/hooks.json`) | hooks + `knitbrain_read` | `/goal` `/loop` (`~/.codex/prompts`) |
| Cursor | ✅ | ✅ deny + follow-up loop (`.cursor/hooks.json`) | hooks + `knitbrain_read` | — (no slash API; documented in rules) |
| Gemini CLI | ✅ | ✅ deny + AfterAgent loop (`.gemini/settings.json`) | hooks + `knitbrain_read` | `/goal` `/loop` (`.gemini/commands/*.toml`) |
| VS Code Copilot | ✅ | ✅ full (reads `.claude/settings.json` natively) | hooks + `knitbrain_read` | `/goal` `/loop` (`.github/prompts/*.prompt.md`) |
| Windsurf | ✅ | ✅ deny-only (exit-2) (`.windsurf/hooks.json`) | hooks + `knitbrain_read` | `/goal` `/loop` (`.windsurf/workflows`) |
| Cline · any other MCP client | ✅ | — (advisory; hooks planned where APIs allow) | via `knitbrain_read` | — (runner works from any terminal) |
| Any agent, API key | ✅ | — | ✅ proxy (full wire) | — |

One hook binary serves every row: it detects the calling platform from the payload and answers in
that host's schema. Where a host's API can't do something (Cursor can't block stop; Gemini can't
rewrite output), knitbrain degrades to the nearest honest mechanism instead of claiming otherwise.
`/goal` and `/loop` ship for every host with a slash-command surface — each in that host's native
format — so both front doors are the same everywhere. Cursor has no such surface; there the runner
is a terminal command (`knitbrain loop`), documented in its always-on rules.

## Commands

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "knitbrain",
"version": "0.19.0",
"version": "0.20.0",
"description": "Loop engineering substrate for coding agents — state, lossless optimization, and hook enforcement: verify-gated loops that can't lie, run away, or go broke. For Claude Code, Codex, Cursor, Gemini CLI, VS Code Copilot, and any MCP client.",
"type": "module",
"main": "dist/lib.js",
Expand Down
4 changes: 2 additions & 2 deletions src/mcp/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1089,12 +1089,12 @@ export const TOOLS: readonly ToolDef[] = [
"",
...tasks,
"",
"Drive: knitbrain_run_loop(goal, verify_cmd) per cycle, or `knitbrain loop goal.md`.",
"Drive hands-off: `/loop goal.md --for 1h` (autonomous external runner) or `/goal` in this session. CLI: `knitbrain loop goal.md`.",
].join("\n"),
"utf8",
);
const checkboxCount = tasks.filter((t) => t.startsWith("- [ ]")).length;
goalNote = ` goal.md written (${checkboxCount} checkbox${checkboxCount === 1 ? "" : "es"}, VERIFY honored by the loop) — start with \`knitbrain loop goal.md\` or knitbrain_run_loop.`;
goalNote = ` goal.md written (${checkboxCount} checkbox${checkboxCount === 1 ? "" : "es"}, VERIFY honored by the loop) — start with \`/loop goal.md --for 1h\` (autonomous runner) or \`/goal\` in-session.`;
}
return `Onboarding complete — Project Charter ("${r.page}") + constraints skill ("${r.skill}") + workflow written (ROUTING covers: ${domains.join(", ") || "none"}). knitbrain_load_session now surfaces your intent + workflow every session.${gapHint}${goalNote}`;
}
Expand Down
Loading
Loading