{"_id":"@cara-review/cara","_rev":"2-722cd78977928ce71567badb6415bf90","name":"@cara-review/cara","dist-tags":{"latest":"0.6.1"},"versions":{"0.6.0":{"name":"@cara-review/cara","version":"0.6.0","keywords":["code-review","diff","git","ai-agent","llm","cli","developer-tools","local-first","hexagonal"],"license":"MIT","_id":"@cara-review/cara@0.6.0","maintainers":[{"name":"paul.grimshaw","email":"paul.grimshaw@sennen.tech"}],"homepage":"https://github.com/cara-review/cara#readme","bugs":{"url":"https://github.com/cara-review/cara/issues"},"bin":{"cara":"dist/index.js"},"dist":{"shasum":"8fbb5fd7b31a5c7466b285cef15b185d64841cb2","tarball":"https://registry.npmjs.org/@cara-review/cara/-/cara-0.6.0.tgz","fileCount":12,"integrity":"sha512-F8FGdnFDAdb+Uo8dbUjuaEoz8bO5xqLrxQvlibHuEk6gJFMhj/vmQN6PKi6Oxoi4zbAdQDxPqvQRPHmnqMIAJg==","signatures":[{"sig":"MEQCICQ35DyVHKIXjETvHcLcprYdDe0lZiWCE73MHngYng0ZAiAEANlRFr6lHywnsKFeCOCUZAGuRGljkF9iP0BQ+IHRHQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13633517},"type":"module","engines":{"bun":">=1.3.0"},"gitHead":"d8a181e05d372ea96fdaae1d4fd9758c0697ab21","scripts":{"lint":"eslint .","test":"bun run typecheck && bun test packages apps","build":"bun run --filter='@cara/web' build","test:e2e":"bun run typecheck:e2e && bun run build && bun --bun playwright test -c e2e/playwright.config.ts","typecheck":"bun run --filter='*' typecheck","build:dist":"bun run build && bun scripts/pack-dist.ts","test:e2e:cli":"bun run typecheck:e2e && bun test e2e/cli","typecheck:e2e":"tsc -p e2e/tsconfig.json","prepublishOnly":"bun run build:dist"},"_npmUser":{"name":"paul.grimshaw","email":"paul.grimshaw@sennen.tech"},"repository":{"url":"git+https://github.com/cara-review/cara.git","type":"git"},"workspaces":["packages/*","apps/*"],"_npmVersion":"11.11.1","description":"cara — a local-first, completeness-gated code-review engine an AI agent drives; the LLM stays outside the trust boundary.","directories":{},"_nodeVersion":"25.8.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.17.0","globals":"^15.14.0","@eslint/js":"^9.17.0","@types/bun":"^1.3.14","typescript":"^5.7.2","@types/node":"^22.10.0","@playwright/test":"^1.60.0","typescript-eslint":"^8.18.0"},"_npmOperationalInternal":{"tmp":"tmp/cara_0.6.0_1782310997791_0.20211563147262201","host":"s3://npm-registry-packages-npm-production"}},"0.6.1":{"name":"@cara-review/cara","version":"0.6.1","description":"cara — a local-first, completeness-gated code-review engine an AI agent drives; the LLM stays outside the trust boundary.","keywords":["code-review","diff","git","ai-agent","llm","cli","developer-tools","local-first","hexagonal"],"homepage":"https://github.com/cara-review/cara#readme","repository":{"type":"git","url":"git+https://github.com/cara-review/cara.git"},"bugs":{"url":"https://github.com/cara-review/cara/issues"},"type":"module","workspaces":["packages/*","apps/*"],"bin":{"cara":"dist/index.js"},"publishConfig":{"access":"public"},"engines":{"bun":">=1.3.0"},"scripts":{"typecheck":"bun run --filter='*' typecheck","typecheck:e2e":"tsc -p e2e/tsconfig.json","lint":"eslint .","test":"bun run typecheck && bun test packages apps","build":"bun run --filter='@cara/web' build","build:dist":"bun run build && bun scripts/pack-dist.ts","prepublishOnly":"bun run build:dist","test:e2e:cli":"bun run typecheck:e2e && bun test e2e/cli","test:e2e":"bun run typecheck:e2e && bun run build && bun --bun playwright test -c e2e/playwright.config.ts"},"devDependencies":{"@eslint/js":"^9.17.0","@playwright/test":"^1.60.0","@types/bun":"^1.3.14","@types/node":"^22.10.0","eslint":"^9.17.0","globals":"^15.14.0","typescript":"^5.7.2","typescript-eslint":"^8.18.0"},"license":"MIT","gitHead":"658522c26fb915586fc06cfc50ef31fb0aab0b32","_id":"@cara-review/cara@0.6.1","_nodeVersion":"25.8.2","_npmVersion":"11.11.1","dist":{"integrity":"sha512-o1xpi09DkCCTt6RdsQbNXrMVOOm5F4Xi1TEgPgHciHKPm1o1W8Lo0OO3qJGYKe8ygxo718X4WJwDNmwX1rdtPA==","shasum":"72c3c904e873cc2553dc8d9a5b29577d35172f34","tarball":"https://registry.npmjs.org/@cara-review/cara/-/cara-0.6.1.tgz","fileCount":12,"unpackedSize":13636424,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDd2vgoVPOgGms3wuKDLsRyByM/R8AnwhsNA17PmSo9SAiEAjhL6W3VXZ9KaC3zb3QjOOF47fWJWxXEM1PfwPraX6NA="}]},"_npmUser":{"name":"paul.grimshaw","email":"paul.grimshaw@sennen.tech"},"directories":{},"maintainers":[{"name":"paul.grimshaw","email":"paul.grimshaw@sennen.tech"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cara_0.6.1_1782382752213_0.6702174407933912"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-24T14:23:17.666Z","modified":"2026-06-25T10:19:12.655Z","0.6.0":"2026-06-24T14:23:18.042Z","0.6.1":"2026-06-25T10:19:12.518Z"},"bugs":{"url":"https://github.com/cara-review/cara/issues"},"license":"MIT","homepage":"https://github.com/cara-review/cara#readme","keywords":["code-review","diff","git","ai-agent","llm","cli","developer-tools","local-first","hexagonal"],"repository":{"type":"git","url":"git+https://github.com/cara-review/cara.git"},"description":"cara — a local-first, completeness-gated code-review engine an AI agent drives; the LLM stays outside the trust boundary.","maintainers":[{"name":"paul.grimshaw","email":"paul.grimshaw@sennen.tech"}],"readme":"# cara\n\n**A local-first, completeness-gated code reviewer that an AI agent drives — not one with an LLM inside it.**\n\ncara is a trusted, deterministic engine: it runs git, splits the change into mechanical units, owns identity and review marks, and enforces that every change is accounted for. Your coding agent (Claude Code, Cursor, the session that *made* the change) reads the diff and supplies the structure, driving the engine over a tiny CLI protocol. The agent arranges and describes; it can never define or change what's in the review.\n\nThe result is review that reads like a report — importance at the top, related things together, evidence on demand — and works two ways: a human reviewing in a browser, or an agent reviewing autonomously, over the same engine.\n\n> **Status: pre-release.** The pivoted engine, CLI protocol, and dual-mode web UI are landed and tested. Distribution polish (`npx`) is in progress.\n\n## Why it's different\n\nEvery other AI reviewer puts the LLM **inside** the trust boundary — it both reads the diff and decides what you see, so a hidden or mis-summarised change is undetectable. cara puts the LLM **outside**:\n\n- **Trusted engine.** Counts and completion derive from a master list computed straight from git, with zero agent involvement. A grouping can never make a change look smaller than it is.\n- **Untrusted agent.** Grouping is ids + titles + summaries only. The engine enforces a bijection — every atom appears exactly once — so the agent **cannot add, remove, hide, or edit** a single line ([ADR-0004](docs/adr/0004-agent-untrusted-master-list.md)).\n- **No LLM in the core.** The engine carries no model and no API key. One LLM, outside the boundary, in an optional wrapper.\n\n## Quickstart\n\n```bash\n# Install (the package is scoped; the command is `cara`):\nnpm i -g @cara-review/cara\ncara init                  # one-time: write ~/.cara/config.toml (interactive)\ncara review                # in any git repo with uncommitted changes\n\n# …or one-off without installing:\nnpx @cara-review/cara review\n```\n\n`cara review` calls an LLM to group the diff, then opens the review in a browser. It needs `~/.cara/config.toml` (below) and the configured API key in your environment. Run `cara init` once to create the config.\n\n## Agent setup\n\nThe point of cara is to be driven by *your* agent. Onboarding is one line — paste into `CLAUDE.md`, `AGENTS.md`, or a rule file:\n\n> To review changes with the user, run `cara instructions` and follow it.\n\n`cara instructions` emits the canonical loop and verb reference. The protocol is **self-narrating** — every response carries a `next` hint — so a cold agent that runs any one verb is pulled through the whole review. Nothing else to install; no shipped skill to drift.\n\n## The protocol\n\nThe agent drives the engine with four verbs plus a helper. cara never calls out to the agent — every verb is agent-invoked, which is what makes it portable to any platform that can run a command and read JSON.\n\n```\ncara atoms [--range <base>..<head>]   # engine → agent: context, merged guidance,\n                              #   atoms (hash, path, ranges, diff lines), open items.\ncara present <grouping> # agent → engine: grouping JSON → bijection repair →\n                              #   boots server + browser. --no-open stays headless.\n                              #   Every chapter & section needs a one-line summary.\ncara dispatch [--wait]  # engine → agent: all comments (open|addressed), any\n                              #   reshape request, + progress.\ncara submit <batch>     # agent → engine: dispositions and/or answers, batched.\n                              #   Returns a gap report (\"38/41 accounted; missing: …\").\ncara instructions       # emits the canonical loop + verb reference.\n```\n\n- **Payloads** — `present`/`submit` take their JSON inline (`'{…}'`), as a file path, or from stdin (`-`). The spec defaults to the worktree vs `origin/main`; pass `--range <base>..<head>` for any other range.\n- **Summaries are required** — `present` rejects a grouping where any chapter or section lacks a one-line summary, returning the missing list to complete. The engine repairs *structure*; it makes you author the *semantics* ([ADR-0012](docs/adr/0012-field-test-amendments.md)).\n- **Reshape** — a human can ask, in plain language, for a different *view* of the diff (regroup, filter, or answer-as-a-view). It rides back on `dispatch`; the agent answers by re-presenting, which live-refreshes the one open browser. The comment stream stays code-only.\n- **One server per context** — a re-present hands the new grouping to the running server and live-refreshes in place (marks intact), never spawning a second window.\n- **Engine as agent memory** — every response returns full open state + a gap report; the agent tracks nothing across calls.\n- **Fixes need no verb** — the agent edits code, the atom's hash changes, the engine marks the comment addressed mechanically.\n- **`dispatch --wait`** blocks (zero agent tokens burned) and returns one of three states: `done`, `reviewInProgress` (human still active — re-run), or `reviewIdle` (no activity ~5 min — stop polling, await the user).\n\nFull contract: [ADR-0011](docs/adr/0011-cli-agent-protocol.md).\n\n## Two modes\n\n| | Human-in-loop | Autonomous |\n|---|---|---|\n| Flow | `atoms` → agent groups → `present` → human reviews → \"done\" → agent edits + answers → converge | `atoms` → agent reviews → `submit` marks + comments → gap report → resubmit until clean |\n| Reviewer | human (browser) | the calling agent (CLI), no browser |\n| Mark tier | `human` | `agent` |\n\nHybrid is free: an agent pre-reviews autonomously; a human later opens the same context, sees the pre-marked tree with tiers visible, and adjudicates only the residue.\n\n### Headless multi-reviewer\n\n```bash\ncara review --headless                      # autonomous, no browser\ncara review --headless --reviewer security  # one labelled lens\ncara review --headless --reviewer architecture\ncara review --fake                           # deterministic stub, no LLM/key\n```\n\nEach headless reviewer's marks carry its `--reviewer` label, so several lenses (security, architecture, …) review the same diff and stay distinguishable; `dispatch` and progress can filter per label.\n\n## Config — `~/.cara/config.toml`\n\n`cara init` writes this interactively (grouping mode, provider/model, key env-var name, editor); re-run with `--force` to overwrite. Or hand-write it:\n\n```toml\n[grouping]\nmode = \"llm\"            # \"llm\" (bundled wrapper) | \"git-order\" (floor, no LLM)\n\n[llm]\nprovider = \"anthropic\"\nmodel = \"claude-sonnet-4-6\"\napi_key_env = \"ANTHROPIC_API_KEY\"   # env var NAME — never the key itself\n\n[editor]\ncommand = \"code\"\n```\n\nNo silent fallbacks — behaviour is configured, never inferred:\n\n| State | Bare `cara review` |\n|---|---|\n| No config | Loud error pointing at `cara init` |\n| `llm`, key resolves | Full semantic review |\n| `llm`, key missing | Loud error at the LLM call — never auto-drops to floor |\n| `git-order` | Floor, by choice — no nag |\n| Plumbing verbs | Never read `[grouping]`/`[llm]` |\n\nReview guidance is separate, in plain markdown (like CLAUDE.md): `CARA.md` at the repo root (project, committed) and `~/.cara/CARA.md` (personal). Both are merged and fed to the agent on every `atoms` call to steer chaptering and relevance.\n\n## Security model\n\n- **Master list is canonical.** The atom set is computed from git every run, zero agent involvement; counts and completion derive from it, never from the grouping.\n- **Grouping is untrusted overlay.** ids + titles + summaries only; repaired to a bijection over the master list before anything renders. The agent cannot add, remove, hide, or edit an atom — structural, not policed.\n- **Provenance is structural.** Mark author tier (`human` | `agent`) is inferred from the channel with no override flag; an agent cannot impersonate a human.\n- **Diff lines are shared, not the change.** `atoms` includes diff lines (the caller has the repo anyway), but rendered evidence always comes from git verbatim; the agent never has a write channel to a line.\n- **Summaries and answers are display-only.** Sanitized markdown subset, escaped on render, never drive an action ([ADR-0010](docs/adr/0010-chat-answer-markdown-rendering.md)). The agent guidance (`CARA.md`) reaching the LLM prompt is an accepted, documented trust seam ([TN-26-026 §Security posture](docs/tn/TN-26-026-cli-agent-protocol-pivot.md)).\n\n## Architecture & docs\n\nA hexagonal core: a pure domain + application core surrounded by interchangeable adapters, so the CLI, the local web UI, and the LLM porcelain all sit over one unchanged engine. The agent is a *driving* actor over the CLI, not a port the core calls.\n\n- [`docs/concept.md`](docs/concept.md) — the product model and voice. Source of intent.\n- [`docs/design-brief.md`](docs/design-brief.md) — the UI and interaction surface.\n- [`docs/adr/`](docs/adr/) — ratified architecture decisions; [`docs/tn/`](docs/tn/) — the technical-note timeline. The pivot is [TN-26-026](docs/tn/TN-26-026-cli-agent-protocol-pivot.md) / [ADR-0011](docs/adr/0011-cli-agent-protocol.md).\n\n## Development\n\nBun toolchain ([CDR-0001](docs/cdr/)). Contributions: see [`CONTRIBUTING.md`](CONTRIBUTING.md).\n\n```bash\nbun install\n./scripts/install-git-hooks.sh   # pre-push gate: lint + test + e2e\nbun run test                     # typecheck + unit\nbun index.js atoms               # dev entry (runs the same cli.ts as the bundled bin)\n```\n\n## Licence\n\nMIT — see [`LICENSE`](LICENSE).\n","readmeFilename":"README.md"}