Skip to content

Repository files navigation

CodeFerret 🦑

Autonomous code review and bug-hunting plugin, model-agnostic across the frontier AI stack: Claude Code and Claude Desktop, OpenAI Codex, Gemini CLI, and any other MCP client. Diff-scoped semantic review across five detection vectors β€” logic, security, concurrency, performance, and API contracts β€” with confidence scoring, linter deduplication, a false-positive suppression cache, interactive triage, and a pre-commit secret guard.

CodeFerret runs entirely on your machine. There is no CodeFerret service, account, or API key: the review is performed by a coding agent you already have installed, and your code never leaves your computer through anything CodeFerret does. That is the deliberate difference from hosted reviewers like CodeRabbit. The one setting that can make a network call β€” dependency auditing β€” is off by default and documented below.

Install

Claude Code (plugin)

# From a local clone
/plugin marketplace add ~/projects/code-ferret
/plugin install code-ferret@code-ferret-marketplace

# Or from GitHub
/plugin marketplace add musicofthings/code-ferret
/plugin install code-ferret

Claude Desktop (MCP Bundle)

bash mcp-server/build-mcpb.sh   # produces dist/code-ferret.mcpb

Double-click the bundle (or drag it into Claude Desktop) to install. See packaging/claude-desktop/README.md.

OpenAI Codex

Register the MCP server in ~/.codex/config.toml and copy the /ferret-review, /ferret-precommit, /ferret-triage custom prompts. See packaging/codex/README.md.

Gemini CLI (extension)

gemini extensions install https://github.com/musicofthings/code-ferret
cd ~/.gemini/extensions/code-ferret/mcp-server && npm install

The repo root is a Gemini CLI extension (gemini-extension.json): it wires up the MCP server, GEMINI.md context, and /ferret:review, /ferret:precommit, /ferret:triage commands.

Any other MCP client (Cursor, Grok desktop, ...)

Run npm install in mcp-server/, then point the client at node mcp-server/server/index.js (stdio). The host's model does the semantic analysis, so CodeFerret works with whichever frontier model the client runs.

Model compatibility

CodeFerret never calls a model API itself. The semantic analysis is done by whatever model your host application already runs β€” Claude Code, Claude Desktop, Codex, Gemini CLI, or any other MCP client β€” so it is model-agnostic by construction, with no provider registry, no key to configure, and no model for CodeFerret to keep up to date.

The standalone CLI works the same way: it shells out to an installed claude, codex, or gemini and reads back the findings file. See CLI.

Commands

Command What it does
/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.
/code-ferret:triage Steps through findings one by one: Accept & apply patch, Ignore pattern (suppresses it in future runs), Discuss, or Skip.
/code-ferret:precommit Fast staged-only check. Reports only CRITICAL + HIGH-confidence blockers and secrets. First line is FERRET: PASS or FERRET: BLOCK.

CLI

CodeFerret also ships a standalone CLI that runs reviews from any terminal by delegating to a coding agent you already have installed (claude, codex, or gemini) β€” no API key and no CodeFerret account.

cd cli && npm link      # or, from the repo root: npm install -g ./cli
ferret doctor           # verify the setup first
ferret                  # review committed + staged + unstaged changes
Command What it does
ferret [review] Review the current diff; plain-text report
ferret review --agent Structured JSONL for coding agents and automation
ferret review --light Fast policy: no analyzers, -U10 context, LOGIC + SECURITY only
ferret review findings Replay the last review without re-analyzing
ferret review --show-prompts Print the prompts from the last review
ferret doctor Verify setup and connectivity; exit 1 on failure
ferret stats [--rebuild] Review statistics from .ferret/history.jsonl

Scope flags: --committed, --uncommitted, --include-untracked, --base <branch>, --base-commit <sha>, --dir <path>, -c/--config <file>. Contradictory combinations are rejected before a review starts, as is a base ref that does not resolve β€” a review that cannot run always exits non-zero, never "no changes found".

Agent output (--agent)

One JSON object per line on stdout, and nothing else β€” anything a human would read goes to stderr.

type When
review_context Once, first: target, branch, base ref, file count, agent, light
status Phase change: collecting_context, reviewing, or review_skipped
heartbeat Every 15s while the agent is running
finding One per finding; severity on the wire is critical/major/minor
prompts --show-prompts only: the saved prompts from the last review
complete Once, last, on success β€” including the empty-diff case
error Once, last, on any failure

Every failure path emits an error event, including ones that occur before a review starts (bad flags, unresolvable base ref, no agent, a blocked lock), so a consumer never has to distinguish "failed" from "produced nothing".

Concurrent reviews

Reviews are serialized per repository through a .ferret/review.lock. A second ferret review against the same repo fails immediately, naming the process that holds the lock, rather than queueing or letting two agents overwrite each other's results. A lock left behind by a killed process is reclaimed automatically β€” either its process is gone, or it has aged out.

The MCP review prompt takes the same lock through the ferret_review_lock tool, so a prompt-driven review and a terminal ferret review cannot run against one repository at once. That path holds a 30-minute lease rather than a process-lifetime lock: the MCP server stays alive between tool calls, so its process being up says nothing about whether a review is still going, and only an expiry can free one that was abandoned mid-conversation. Use ferret_review_lock with status to see the holder, or release with force to clear an abandoned lock without waiting out the lease.

Because the agent writes .ferret/last-review.json with its own file tools rather than through the server, this lock is cooperative β€” it is honored by the shipped review prompt, not enforced against an agent that ignores it.

Every ferret review spawns a real agent session against your existing subscription. Use --light for the cheap path, and keep the git pre-commit hook on the pure-bash secret scan rather than a full review.

What gets reviewed

Only the diff plus its surrounding lexical scope, never the whole repo. Each hunk is shown with its complete enclosing function (git -W), not a fixed number of context lines β€” a small edit deep inside a 600-line function still arrives with the whole function attached, which a fixed -U window cannot do. Standard .gitignore rules apply automatically; add a .ferretignore (gitignore syntax) at the repo root to also skip generated files, schemas, minified assets, etc.

Lockfile hunks (package-lock.json, Cargo.lock, go.sum, and nine others) are omitted by default β€” thousands of machine-generated lines no semantic vector can find a bug in. Their names still appear in the changed-file and dependency-manifest lists, so version-bump analysis is unaffected. Set FERRET_INCLUDE_LOCKFILES=1 to include them.

Detection vectors:

  • LOGIC β€” off-by-one, boundary conditions, null/undefined flow, unhandled promises, resource leaks, infinite loops
  • SECURITY β€” hardcoded secrets, SQL injection, XSS, unsafe deserialization, OWASP Top 10
  • CONCURRENCY β€” races, deadlocks, non-atomic read-modify-write, unsynchronized shared state
  • PERFORMANCE β€” O(NΒ²) on unbounded data, N+1 queries, redundant allocations
  • API β€” breaking public contract changes, type-safety violations, SDK misuse

Style and lint issues are explicitly out of scope β€” findings matching an existing linter rule are deduplicated away.

Before semantic analysis, full reviews run known analyzers that are already installed: ESLint, Ruff, ShellCheck, TypeScript, Semgrep with a checked-in configuration, and the CodeFerret secret scanner. Tools are never installed automatically or invoked through arbitrary package scripts. Normalized, secret-scrubbed results are saved to .ferret/tool-results.json. Analyzers run in the current environment and may load repository-owned configuration or plugins, so run them only in a checkout you trust.

Dependency auditing (npm audit, pip-audit) is off by default: it is the only analyzer group that contacts the network, sending your dependency tree to the npm registry or the advisory API. Your source is never sent, but the call happens, so enabling it is a deliberate choice β€” set tools.dependencies: true in .codeferret.yaml. Everything else runs offline.

Configuration

Copy .codeferret.example.yaml to .codeferret.yaml to configure review behavior. Supported controls include:

  • reviews.profile: chill, balanced, or assertive
  • reviews.minimum_severity: critical, warning, or suggestion
  • reviews.ignore: repository-relative glob patterns
  • reviews.path_instructions: focused review policy for matching paths
  • guidelines: automatic discovery of AGENTS.md, CLAUDE.md, .cursorrules, or additional repository policy files
  • reports: PR summary, walkthrough, risk assessment, and linked-issue validation controls
  • tools: installed linter, type-checker, security, dependency, and CI-context controls with bounded execution time

/code-ferret:review runs use the working tree configuration and root-level guideline context from collect-context.sh.

Collector environment variables

collect-context.sh is tuned through the environment. Defaults are chosen so a review is cheap without losing the context needed to trace a failure.

Variable Default Effect
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.
FERRET_CONTEXT_LINES 12 (6 light) Fixed context lines when function context is off.
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.
FERRET_FILES unset Colon- or newline-separated file subset. Scopes a batch when working a large diff in sequence.
FERRET_SKIP_GUIDELINES 0 Omit AGENTS.md/CLAUDE.md/.cursorrules bodies when the host agent already has them.
FERRET_INCLUDE_LOCKFILES 0 Include lockfile hunks in the diff.
FERRET_LIGHT 0 Speed over depth: fixed -U6, no per-file history.
FERRET_DIR_PATHSPEC . Restrict everything to one subtree.
FERRET_BASE_REF main Base ref for all mode.
FERRET_INCLUDE_UNTRACKED mode-dependent Force untracked files in.
FERRET_MAX_TOOL_OUTPUT 8000 Per-analyzer output cap, head+tail truncated so summary lines survive.

Sharding a large review

scripts/plan-shards.sh <target> <n> prints n colon-joined file lists, balanced by diff size rather than file count, ready to pass as FERRET_FILES:

bash scripts/plan-shards.sh main 5

Collect once with FERRET_OUT, then give each reviewer one shard and the shared context file. Collecting per-agent instead multiplies a review's cost by the number of agents.

Noise control

  • Every finding carries a confidence rating (HIGH/MEDIUM/LOW) based on structural proof, independent of severity (CRITICAL/WARNING/SUGGESTION).

  • Choosing Ignore pattern during triage records a structural hash in .ferret/review-cache.json; matching findings are silently suppressed in future reviews. Manage the cache with:

    python3 scripts/fp_cache.py list
    python3 scripts/fp_cache.py add <file> <vector> "<message>" "<reason>"

    Commit .ferret/review-cache.json to share suppressions with your team.

Pre-commit guard (hook)

The plugin ships a PreToolUse hook: whenever Claude Code runs git commit, staged changes are regex-scanned for credentials (GitHub/AWS/Anthropic/Slack tokens, private keys, generic high-entropy assignments) and the commit is blocked if any are found. It is fast (pure bash/grep, no LLM call).

For commits made outside Claude Code, install the native git hook:

cp examples/git-pre-commit-hook .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
git config codeferret.root "$(pwd)"

If the target repository is not the CodeFerret checkout, set codeferret.root to CodeFerret's absolute installation path instead.

Privacy guardrails

  • Reviews run on your machine, through a coding agent you already installed. There is no CodeFerret service or account, and no telemetry.
  • Code payloads are regex-scrubbed for credentials ([REDACTED_SECRET]) before reaching the model.
  • Secret locations are reported, never secret values.
  • Nothing CodeFerret runs contacts the network, with one opt-in exception: dependency auditing (tools.dependencies, off by default) calls the npm registry / advisory API. Your source is never transmitted.
  • .ferret/ state stays in your working tree; only the shareable false-positive cache (review-cache.json) is intended to be committed.

Tests

# Shell collectors, secret scanner, commit guards, and the analyzer runner
bash tests/run.sh

# Analyzer runner and model checks
python3 -m pytest tests/ -v

# CLI unit tests
cd cli && npm test

tests/run.sh covers the context-collection controls that determine what a reviewer actually sees: FERRET_OUT indexing, FERRET_FILES sharding (both ends of the list), guideline omission, lockfile suppression and opt-in, function context on/off/light, and shard partitioning.

Layout

code-ferret/
β”œβ”€β”€ .claude-plugin/plugin.json      # Claude Code plugin manifest (+ marketplace.json)
β”œβ”€β”€ gemini-extension.json           # Gemini CLI extension manifest (+ GEMINI.md)
β”œβ”€β”€ commands/                       # /code-ferret:* (Claude Code .md) + ferret/*.toml (Gemini CLI)
β”œβ”€β”€ skills/code-ferret/             # review methodology + vector checklists + schema
β”œβ”€β”€ hooks/hooks.json                # PreToolUse git-commit secret guard
β”œβ”€β”€ scripts/                        # collectors, shard planner, analyzers, fp cache
β”œβ”€β”€ cli/                            # standalone `ferret` CLI (delegates to your agent)
β”œβ”€β”€ mcp-server/                     # MCP server + MCPB bundle build (Claude Desktop et al.)
β”œβ”€β”€ packaging/                      # Codex prompts/config, Claude Desktop install guide
└── examples/                       # native git pre-commit hook

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages