{
  "markdown": "# CodeFerret 🦡\n\nAutonomous code review and bug-hunting plugin, model-agnostic across the\nfrontier AI stack: [Claude Code](https://claude.com/claude-code) and Claude\nDesktop, OpenAI Codex, Gemini CLI, and any other MCP client.\nDiff-scoped semantic review across five detection vectors — logic, security,\nconcurrency, performance, and API contracts — with confidence scoring,\nlinter deduplication, a false-positive suppression cache, interactive triage,\nand a pre-commit secret guard.\n\n**CodeFerret runs entirely on your machine.** There is no CodeFerret service,\naccount, or API key: the review is performed by a coding agent you already have\ninstalled, and your code never leaves your computer through anything CodeFerret\ndoes. That is the deliberate difference from hosted reviewers like CodeRabbit.\nThe one setting that can make a network call — dependency auditing — is off by\ndefault and documented below.\n\n## Install\n\n### Claude Code (plugin)\n\n```bash\n# From a local clone\n/plugin marketplace add ~/projects/code-ferret\n/plugin install code-ferret@code-ferret-marketplace\n\n# Or from GitHub\n/plugin marketplace add musicofthings/code-ferret\n/plugin install code-ferret\n```\n\n### Claude Desktop (MCP Bundle)\n\n```bash\nbash mcp-server/build-mcpb.sh   # produces dist/code-ferret.mcpb\n```\n\nDouble-click the bundle (or drag it into Claude Desktop) to install. See\n`packaging/claude-desktop/README.md`.\n\n### OpenAI Codex\n\nRegister the MCP server in `~/.codex/config.toml` and copy the\n`/ferret-review`, `/ferret-precommit`, `/ferret-triage` custom prompts. See\n`packaging/codex/README.md`.\n\n### Gemini CLI (extension)\n\n```bash\ngemini extensions install https://github.com/musicofthings/code-ferret\ncd ~/.gemini/extensions/code-ferret/mcp-server && npm install\n```\n\nThe repo root is a Gemini CLI extension (`gemini-extension.json`): it wires up\nthe MCP server, `GEMINI.md` context, and `/ferret:review`, `/ferret:precommit`,\n`/ferret:triage` commands.\n\n### Any other MCP client (Cursor, Grok desktop, ...)\n\nRun `npm install` in `mcp-server/`, then point the client at\n`node mcp-server/server/index.js` (stdio). The host's model does the semantic\nanalysis, so CodeFerret works with whichever frontier model the client runs.\n\n## Model compatibility\n\nCodeFerret never calls a model API itself. The semantic analysis is done by\nwhatever model your host application already runs — Claude Code, Claude\nDesktop, Codex, Gemini CLI, or any other MCP client — so it is model-agnostic\nby construction, with no provider registry, no key to configure, and no model\nfor CodeFerret to keep up to date.\n\nThe standalone CLI works the same way: it shells out to an installed `claude`,\n`codex`, or `gemini` and reads back the findings file. See [CLI](#cli).\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `/code-ferret:review [staged\\|head\\|<base>]` | Full semantic review of the diff. Writes findings to `.ferret/last-review.json` and prints a report with clickable `file:line:col` locations, severity tiers, confidence ratings, and ready-to-apply patches. |\n| `/code-ferret:triage` | Steps through findings one by one: **Accept & apply patch**, **Ignore pattern** (suppresses it in future runs), **Discuss**, or **Skip**. |\n| `/code-ferret:precommit` | Fast staged-only check. Reports only CRITICAL + HIGH-confidence blockers and secrets. First line is `FERRET: PASS` or `FERRET: BLOCK`. |\n\n## CLI\n\nCodeFerret also ships a standalone CLI that runs reviews from any terminal by\ndelegating to a coding agent you already have installed (`claude`, `codex`, or\n`gemini`) — no API key and no CodeFerret account.\n\n```bash\ncd cli && npm link      # or, from the repo root: npm install -g ./cli\nferret doctor           # verify the setup first\nferret                  # review committed + staged + unstaged changes\n```\n\n| Command | What it does |\n|---|---|\n| `ferret [review]` | Review the current diff; plain-text report |\n| `ferret review --agent` | Structured JSONL for coding agents and automation |\n| `ferret review --light` | Fast policy: no analyzers, `-U10` context, LOGIC + SECURITY only |\n| `ferret review findings` | Replay the last review without re-analyzing |\n| `ferret review --show-prompts` | Print the prompts from the last review |\n| `ferret doctor` | Verify setup and connectivity; exit 1 on failure |\n| `ferret stats [--rebuild]` | Review statistics from `.ferret/history.jsonl` |\n\nScope flags: `--committed`, `--uncommitted`, `--include-untracked`,\n`--base <branch>`, `--base-commit <sha>`, `--dir <path>`, `-c/--config <file>`.\nContradictory combinations are rejected before a review starts, as is a base\nref that does not resolve — a review that cannot run always exits non-zero,\nnever \"no changes found\".\n\n### Agent output (`--agent`)\n\nOne JSON object per line on stdout, and nothing else — anything a human would\nread goes to stderr.\n\n| `type` | When |\n|---|---|\n| `review_context` | Once, first: target, branch, base ref, file count, agent, light |\n| `status` | Phase change: `collecting_context`, `reviewing`, or `review_skipped` |\n| `heartbeat` | Every 15s while the agent is running |\n| `finding` | One per finding; severity on the wire is `critical`/`major`/`minor` |\n| `prompts` | `--show-prompts` only: the saved prompts from the last review |\n| `complete` | Once, last, on success — including the empty-diff case |\n| `error` | Once, last, on any failure |\n\nEvery failure path emits an `error` event, including ones that occur before a\nreview starts (bad flags, unresolvable base ref, no agent, a blocked lock), so\na consumer never has to distinguish \"failed\" from \"produced nothing\".\n\n### Concurrent reviews\n\nReviews are serialized per repository through a `.ferret/review.lock`. A second\n`ferret review` against the same repo fails immediately, naming the process\nthat holds the lock, rather than queueing or letting two agents overwrite each\nother's results. A lock left behind by a killed process is reclaimed\nautomatically — either its process is gone, or it has aged out.\n\nThe MCP review prompt takes the same lock through the `ferret_review_lock`\ntool, so a prompt-driven review and a terminal `ferret review` cannot run\nagainst one repository at once. That path holds a **30-minute lease** rather\nthan a process-lifetime lock: the MCP server stays alive between tool calls, so\nits process being up says nothing about whether a review is still going, and\nonly an expiry can free one that was abandoned mid-conversation. Use\n`ferret_review_lock` with `status` to see the holder, or `release` with `force`\nto clear an abandoned lock without waiting out the lease.\n\nBecause the agent writes `.ferret/last-review.json` with its own file tools\nrather than through the server, this lock is **cooperative** — it is honored by\nthe shipped review prompt, not enforced against an agent that ignores it.\n\nEvery `ferret review` spawns a real agent session against your existing\nsubscription. Use `--light` for the cheap path, and keep the git pre-commit\nhook on the pure-bash secret scan rather than a full review.\n\n## What gets reviewed\n\nOnly the diff plus its surrounding lexical scope, never the whole repo. Each\nhunk is shown with its **complete enclosing function** (`git -W`), not a fixed\nnumber of context lines — a small edit deep inside a 600-line function still\narrives with the whole function attached, which a fixed `-U` window cannot do.\nStandard `.gitignore` rules apply automatically; add a `.ferretignore`\n(gitignore syntax) at the repo root to also skip generated files, schemas,\nminified assets, etc.\n\nLockfile *hunks* (`package-lock.json`, `Cargo.lock`, `go.sum`, and nine others)\nare omitted by default — thousands of machine-generated lines no semantic\nvector can find a bug in. Their names still appear in the changed-file and\ndependency-manifest lists, so version-bump analysis is unaffected. Set\n`FERRET_INCLUDE_LOCKFILES=1` to include them.\n\nDetection vectors:\n\n- **LOGIC** — off-by-one, boundary conditions, null/undefined flow, unhandled promises, resource leaks, infinite loops\n- **SECURITY** — hardcoded secrets, SQL injection, XSS, unsafe deserialization, OWASP Top 10\n- **CONCURRENCY** — races, deadlocks, non-atomic read-modify-write, unsynchronized shared state\n- **PERFORMANCE** — O(N²) on unbounded data, N+1 queries, redundant allocations\n- **API** — breaking public contract changes, type-safety violations, SDK misuse\n\nStyle and lint issues are explicitly out of scope — findings matching an\nexisting linter rule are deduplicated away.\n\nBefore semantic analysis, full reviews run known analyzers that are already\ninstalled: ESLint, Ruff, ShellCheck, TypeScript, Semgrep with a checked-in\nconfiguration, and the CodeFerret secret scanner. Tools are never installed\nautomatically or invoked through arbitrary package scripts. Normalized,\nsecret-scrubbed results are saved to `.ferret/tool-results.json`. Analyzers run\nin the current environment and may load repository-owned configuration or\nplugins, so run them only in a checkout you trust.\n\nDependency auditing (`npm audit`, `pip-audit`) is **off by default**: it is the\nonly analyzer group that contacts the network, sending your dependency tree to\nthe npm registry or the advisory API. Your source is never sent, but the call\nhappens, so enabling it is a deliberate choice — set `tools.dependencies: true`\nin `.codeferret.yaml`. Everything else runs offline.\n\n## Configuration\n\nCopy `.codeferret.example.yaml` to `.codeferret.yaml` to configure review\nbehavior. Supported controls include:\n\n- `reviews.profile`: `chill`, `balanced`, or `assertive`\n- `reviews.minimum_severity`: `critical`, `warning`, or `suggestion`\n- `reviews.ignore`: repository-relative glob patterns\n- `reviews.path_instructions`: focused review policy for matching paths\n- `guidelines`: automatic discovery of `AGENTS.md`, `CLAUDE.md`,\n  `.cursorrules`, or additional repository policy files\n- `reports`: PR summary, walkthrough, risk assessment, and linked-issue\n  validation controls\n- `tools`: installed linter, type-checker, security, dependency, and CI-context\n  controls with bounded execution time\n\n`/code-ferret:review` runs use the working tree configuration and root-level\nguideline context from `collect-context.sh`.\n\n### Collector environment variables\n\n`collect-context.sh` is tuned through the environment. Defaults are chosen so a\nreview is cheap without losing the context needed to trace a failure.\n\n| Variable | Default | Effect |\n|---|---|---|\n| `FERRET_FUNCTION_CONTEXT` | `1` (`0` in light mode) | Show each hunk's complete enclosing function via `git -W`. `0` falls back to a fixed line count. |\n| `FERRET_CONTEXT_LINES` | `12` (`6` light) | Fixed context lines when function context is off. |\n| `FERRET_OUT` | unset | Write the payload to this path and print only a compact index of section line ranges. Keeps a large diff out of the agent's transcript. |\n| `FERRET_FILES` | unset | Colon- or newline-separated file subset. Scopes a batch when working a large diff in sequence. |\n| `FERRET_SKIP_GUIDELINES` | `0` | Omit `AGENTS.md`/`CLAUDE.md`/`.cursorrules` bodies when the host agent already has them. |\n| `FERRET_INCLUDE_LOCKFILES` | `0` | Include lockfile hunks in the diff. |\n| `FERRET_LIGHT` | `0` | Speed over depth: fixed `-U6`, no per-file history. |\n| `FERRET_DIR_PATHSPEC` | `.` | Restrict everything to one subtree. |\n| `FERRET_BASE_REF` | `main` | Base ref for `all` mode. |\n| `FERRET_INCLUDE_UNTRACKED` | mode-dependent | Force untracked files in. |\n| `FERRET_MAX_TOOL_OUTPUT` | `8000` | Per-analyzer output cap, head+tail truncated so summary lines survive. |\n\n### Sharding a large review\n\n`scripts/plan-shards.sh <target> <n>` prints `n` colon-joined file lists,\nbalanced by diff size rather than file count, ready to pass as `FERRET_FILES`:\n\n```bash\nbash scripts/plan-shards.sh main 5\n```\n\nCollect once with `FERRET_OUT`, then give each reviewer one shard and the\nshared context file. Collecting per-agent instead multiplies a review's cost by\nthe number of agents.\n\n## Noise control\n\n- Every finding carries a **confidence** rating (HIGH/MEDIUM/LOW) based on\n  structural proof, independent of **severity** (CRITICAL/WARNING/SUGGESTION).\n- Choosing **Ignore pattern** during triage records a structural hash in\n  `.ferret/review-cache.json`; matching findings are silently suppressed in\n  future reviews. Manage the cache with:\n\n  ```bash\n  python3 scripts/fp_cache.py list\n  python3 scripts/fp_cache.py add <file> <vector> \"<message>\" \"<reason>\"\n  ```\n\n  Commit `.ferret/review-cache.json` to share suppressions with your team.\n\n## Pre-commit guard (hook)\n\nThe plugin ships a `PreToolUse` hook: whenever Claude Code runs `git commit`,\nstaged changes are regex-scanned for credentials (GitHub/AWS/Anthropic/Slack\ntokens, private keys, generic high-entropy assignments) and the commit is\nblocked if any are found. It is fast (pure bash/grep, no LLM call).\n\nFor commits made outside Claude Code, install the native git hook:\n\n```bash\ncp examples/git-pre-commit-hook .git/hooks/pre-commit\nchmod +x .git/hooks/pre-commit\ngit config codeferret.root \"$(pwd)\"\n```\n\nIf the target repository is not the CodeFerret checkout, set\n`codeferret.root` to CodeFerret's absolute installation path instead.\n\n## Privacy guardrails\n\n- Reviews run on your machine, through a coding agent you already installed.\n  There is no CodeFerret service or account, and no telemetry.\n- Code payloads are regex-scrubbed for credentials (`[REDACTED_SECRET]`) before\n  reaching the model.\n- Secret *locations* are reported, never secret values.\n- Nothing CodeFerret runs contacts the network, with one opt-in exception:\n  dependency auditing (`tools.dependencies`, off by default) calls the npm\n  registry / advisory API. Your source is never transmitted.\n- `.ferret/` state stays in your working tree; only the shareable\n  false-positive cache (`review-cache.json`) is intended to be committed.\n\n## Tests\n\n```bash\n# Shell collectors, secret scanner, commit guards, and the analyzer runner\nbash tests/run.sh\n\n# Analyzer runner and model checks\npython3 -m pytest tests/ -v\n\n# CLI unit tests\ncd cli && npm test\n```\n\n`tests/run.sh` covers the context-collection controls that determine what a\nreviewer actually sees: `FERRET_OUT` indexing, `FERRET_FILES` sharding (both\nends of the list), guideline omission, lockfile suppression and opt-in,\nfunction context on/off/light, and shard partitioning.\n\n## Layout\n\n```\ncode-ferret/\n├── .claude-plugin/plugin.json      # Claude Code plugin manifest (+ marketplace.json)\n├── gemini-extension.json           # Gemini CLI extension manifest (+ GEMINI.md)\n├── commands/                       # /code-ferret:* (Claude Code .md) + ferret/*.toml (Gemini CLI)\n├── skills/code-ferret/             # review methodology + vector checklists + schema\n├── hooks/hooks.json                # PreToolUse git-commit secret guard\n├── scripts/                        # collectors, shard planner, analyzers, fp cache\n├── cli/                            # standalone `ferret` CLI (delegates to your agent)\n├── mcp-server/                     # MCP server + MCPB bundle build (Claude Desktop et al.)\n├── packaging/                      # Codex prompts/config, Claude Desktop install guide\n└── examples/                       # native git pre-commit hook\n```\n",
  "bytes": 15249,
  "sha": "6fd96cab6a69fc70d918d8f70d1177b8ddbbf3f414b29756b17bd0152f167ec0",
  "repo_slug": "musicofthings/code-ferret",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_musicofthings_code_ferret_29e6f334/readme"
}