Skip to content

Latest commit

 

History

History
1252 lines (988 loc) · 49 KB

File metadata and controls

1252 lines (988 loc) · 49 KB

codereview-cli

cr is the Open CLI Collective code-review CLI. It runs automated pull-request reviews, records review state locally, posts review output back to GitHub, and keeps enough durable metadata to resume, repair, inspect, and prune runs.

Not GitHub Code Review

This project is not affiliated with GitHub and is not a replacement for human review. It is a CLI for orchestrating LLM-backed review agents against GitHub pull requests.

Use cr when you want to:

  • preview review actions before posting anything;
  • run a live PR review with idempotent posting and resume behavior;
  • reuse named LLM sessions across related live reviews;
  • inspect trusted reviewer agents available to a repository;
  • manage local review run data and credentials from the terminal.

Installation

Package-manager installs are available for versions after their package-channel release jobs publish successfully.

Homebrew

brew install --cask open-cli-collective/tap/codereview-cli

Windows Package Managers

winget install OpenCLICollective.codereview-cli
choco install codereview-cli

Linux Packages

cr release builds include .deb and .rpm packages for the open-cli-collective/linux-packages repository.

Binary Download

Download a release archive from the Releases page.

From Source

go install github.com/open-cli-collective/codereview-cli/cmd/cr@latest

Manual Build

git clone https://github.com/open-cli-collective/codereview-cli.git
cd codereview-cli
make build

Platform Support

cr stores secrets in the OS credential store through the shared cli-common/credstore library.

Platform Default credential backend
macOS Keychain
Windows Credential Manager
Linux Secret Service

Supported backend names are keychain, wincred, secret-service, file, pass, and memory. Backend selection precedence is:

  1. --backend <name>
  2. CODEREVIEW_KEYRING_BACKEND=<name>
  3. keyring.backend in config.yml
  4. OS default

Secrets are never written to config.yml. Non-secret config lives in the codereview config directory resolved by the operating system, and durable review data lives under the OS data directory for the cr binary.

Authentication And Setup

cr v1 supports GitHub personal access token authentication for Git-host operations. The credential key for GitHub PATs is git_token.

Quick setup with adapter-managed LLM credentials:

cr init --non-interactive \
  --git-token-from-env GITHUB_TOKEN

Setup with Pi's local RPC runtime. Install Pi's coding agent and make sure the pi binary is available on PATH before running cr review. New installs should use the current npm package (@earendil-works/pi-coding-agent); existing installs from the previous npm scope can also work if their pi binary supports the required --mode rpc and --system-prompt flags.

cr init --non-interactive \
  --llm-provider pi \
  --llm-auth subscription \
  --llm-adapter pi_rpc \
  --git-token-from-env GITHUB_TOKEN

Setup with Codex CLI subscription auth. Install Codex CLI, log in with your subscription, and make sure the codex binary is available on PATH before running cr review. This path is supported for review, but remains best-effort/beta until Codex exposes an explicit all-tools-disabled flag.

cr init --non-interactive \
  --llm-provider openai \
  --llm-auth subscription \
  --llm-adapter codex_cli \
  --git-token-from-env GITHUB_TOKEN

Setup with a direct LLM API key:

cr init --non-interactive \
  --llm-auth api_key \
  --llm-adapter anthropic_api \
  --llm-api-key-from-env ANTHROPIC_API_KEY \
  --git-token-from-env GITHUB_TOKEN

Setup a named profile:

cr --profile work init --non-interactive \
  --git-token-from-env GITHUB_TOKEN \
  --agent-source ~/.config/codereview/agents

Repo-aware profile routing can select a profile from the PR repository when --profile is omitted. Use this when org, personal, or repo-specific reviewer credentials should differ without changing commands:

For scripted installs, use cr init --non-interactive for the core profile and then layer narrow config mutations with the dedicated config commands. A typical sequence looks like:

cr --profile work init --non-interactive \
  --set-default \
  --git-host github.com \
  --git-auth-mode pat \
  --llm-provider anthropic \
  --llm-auth subscription \
  --llm-adapter claude_cli \
  --llm-reviewer-model-tier medium \
  --keyring-backend file

cr --profile work config route set \
  --host github.com \
  --namespace open-cli-collective \
  --repo codereview-cli

cr --profile work config agent-source add ~/.config/codereview/agents
cr --profile work config llm models set medium claude-sonnet-4-6
cr config retention set --max-age-days 30 --enforcement manual_only
printf '%s' "$GITHUB_TOKEN" | cr set-credential \
  --ref codereview/work \
  --key git_token \
  --stdin \
  --overwrite

Use cr config route for repository routing, cr config agent-source for trusted source paths, cr config llm models for llm.model_map, and cr config retention for durable run-data policy. Use cr init --non-interactive --keyring-backend <backend> to persist a keyring backend, --reset-keyring-backend to clear it, --disable-reviewer to remove separate reviewer credentials, --llm-reviewer-model-tier or --clear-llm-reviewer-model-tier for the durable reviewer baseline, and --set-default to make the target profile the default during init. For backward compatibility, init may still persist a runtime --backend when the command writes credentials or configures API-key LLM auth, but the explicit --keyring-backend / --reset-keyring-backend flags are the readable scripted surface to prefer.

default_profile: personal
repository_profiles:
  - profile: personal-reviewer-a
    match:
      host: github.com
      namespace: rianjs
      repos: [bar, baz]
  - profile: personal-reviewer-b
    match:
      host: github.com
      namespace: rianjs
      repos: [qux]
  - profile: work
    match:
      host: github.com
      namespace: open-cli-collective
  - profile: personal
    match:
      host: github.com
      namespace: rianjs
profiles:
  personal: ...
  personal-reviewer-a: ...
  personal-reviewer-b: ...
  work: ...

Route matching is deterministic: host + namespace + repo routes beat host + namespace routes, omitted repos means all repos in that namespace, and no match falls back to default_profile. Host matching is case-insensitive after normalization, while namespace and repo matching are case-sensitive after trimming whitespace. An explicit --profile bypasses repository routing. Route targets still use the profile's configured auth mode. Passing --profile "" also counts as explicit and resolves default_profile without route lookup. For GitHub App auth, cr review can use the PR owner/repo to look up the app installation when github_app_installation_id is not staged.

Add or replace one credential later:

printf '%s' "$GITHUB_TOKEN" | cr set-credential \
  --ref codereview/default \
  --key git_token \
  --stdin \
  --overwrite

Credential refs use the codereview/<profile> service/profile form. cr accepts secrets by --stdin or --from-env during setup and credential writes; it does not read runtime tokens directly from arbitrary environment variables. Reviewer credentials use a separate credential ref that also stores key git_token; keep it distinct from the user Git ref.

Org Deployment / MDM

For managed rollouts, ship non-secret config and pre-stage secrets in the target user's credential store. The staging commands must run as the target OS user who will run cr, not as root, SYSTEM, or an administrator account whose keyring is different from the target user's keyring.

reviewer_credentials may use a PAT or GitHub App auth. A shared reviewer PAT is an access secret even when distributed org-wide. A GitHub App private key is also a deployment secret; cr signs short-lived JWTs locally, mints installation tokens as needed, and never stores those minted tokens in config.yml. Pre-stage reviewer credentials into each target user's credential store, rotate or revoke them with the same set-credential --overwrite flow, and do not store them in config files, agent sources, installers, logs, or shell profiles.

For GitHub App reviewer credentials, grant the app only the repository permissions needed by the enabled review workflow:

GitHub App permission Access Used for
Metadata Read Required by GitHub for repository access and installation lookup.
Contents Read Reading diffs, files, and tree entries during review.
Pull requests Read and write Reading PR metadata/reviews/threads and posting PR reviews or inline comments.
Issues Read and write Reading and posting issue comments on PR conversations.

Thread resolution uses the pull request review-thread GraphQL surface, so keep Pull requests write access when review_policy.resolve_threads is enabled.

Either omit keyring.backend to use the platform default, or set it per-platform and run set-credential with the same backend selection.

Example non-secret config template:

default_profile: work
profiles:
  work:
    git:
      host: github.com
      auth_mode: pat
      credential_ref: codereview/work
    reviewer_credentials:
      auth_mode: github_app
      credential_ref: codereview/work-reviewer-app
    llm:
      provider: anthropic
      auth: api_key
      adapter: anthropic_api
      credential_ref: codereview/work-llm
      model_map:
        medium: claude-sonnet-4-6
    agent_sources:
      - ~/.config/codereview/agents
    review_policy:
      major_event: comment

For adapter-managed LLM credentials, use auth: subscription and omit llm.credential_ref. Codex-backed profiles must set provider: openai, auth: subscription, and adapter: codex_cli together. Pi-backed profiles must set provider: pi, auth: subscription, and adapter: pi_rpc together:

llm:
  provider: openai
  auth: subscription
  adapter: codex_cli
llm:
  provider: pi
  auth: subscription
  adapter: pi_rpc

Agent definitions are non-secret deployment material, not credentials. Ship them separately from keyring pre-staging and point agent_sources at the managed directory. Recommended managed paths:

Platform Example managed agent source
macOS /Library/Application Support/codereview/agents
Windows C:\ProgramData\codereview\agents
Linux /etc/codereview/agents

Use the standard agent layout under that directory:

agents/
  security/
    index.yaml
    secrets/
      index.yaml
      prompt.md

Agent index.yaml files must declare exactly one model selector and an explicit effort:

name: secrets
description: Reviews credential and secret-handling changes.
model_tier: medium
effort: medium
file_globs:
  - "**/*.go"
applies_when:
  - Go files changed
needs_full_file_content: false

Use model_tier: small|medium|large for portable shared catalogs. It means the minimum acceptable reviewer tier for that agent, not a direct model pick. Use model_id: <provider-model-id> only when an agent intentionally requires one provider-specific model. effort is independent and must be one of low, medium, or high.

applies_when is the selector's routing contract. Keep it focused on when the agent should be chosen for a change. Reviewer execution instructions belong in prompt.md and are not sent to the selector.

Legacy agent files that use model: sonnet or another provider-specific model value must be updated. Replace portable intent with model_tier and move provider-specific defaults into profile llm.model_map; use model_id only for intentionally non-portable agents.

cr config show --json reports each configured source by path, presence, status, canonical path, warnings, and SHA-256 fingerprint prefix without inlining index.yaml or prompt.md. Missing or unreadable sources are shown as deployment status in config show; commands that actually load agents, such as cr agents and cr review, fail fast until the source is fixed.

Avoid profile sources under temp directories, relative paths, or Git worktrees. Those locations are warned because they are easy for local scripts or PR authors to mutate. Symlinked sources are accepted, but cr records the canonical path and fingerprints the resolved files.

When deploying a profile without the interactive wizard, run cr init --non-interactive first to write the core non-secret profile shape, then use set-credential only for secrets that you are intentionally staging outside init. Example:

github_app_installation_id is optional for cr review, which can discover the installation from the PR repository. Stage it when you want cr me and other commands without repository context to work.

cr --profile work init --non-interactive \
  --git-host github.com \
  --git-credential-ref codereview/work \
  --reviewer-auth-mode github_app \
  --reviewer-credential-ref codereview/work-reviewer-app \
  --llm-provider anthropic \
  --llm-auth api_key \
  --llm-adapter anthropic_api \
  --llm-credential-ref codereview/work-llm

printf '%s' "$USER_GITHUB_TOKEN" | cr set-credential \
  --ref codereview/work \
  --key git_token \
  --stdin \
  --overwrite

printf '%s' "$GITHUB_APP_ID" | cr set-credential \
  --ref codereview/work-reviewer-app \
  --key github_app_id \
  --stdin \
  --overwrite

printf '%s' "$GITHUB_APP_PRIVATE_KEY" | cr set-credential \
  --ref codereview/work-reviewer-app \
  --key github_app_private_key \
  --stdin \
  --overwrite

# Optional: needed for cr me and other commands without repository context.
printf '%s' "$GITHUB_APP_INSTALLATION_ID" | cr set-credential \
  --ref codereview/work-reviewer-app \
  --key github_app_installation_id \
  --stdin \
  --overwrite

printf '%s' "$ANTHROPIC_API_KEY" | cr set-credential \
  --ref codereview/work-llm \
  --key anthropic_api_key \
  --stdin \
  --overwrite

Then apply any config that intentionally lives outside init flags:

cr --profile work config route set \
  --host github.com \
  --namespace open-cli-collective \
  --repo codereview-cli

cr --profile work config agent-source add ~/.config/codereview/agents
cr --profile work config llm models set medium claude-sonnet-4-6
cr config retention set --max-age-days 30 --enforcement manual_only

Then verify the deployed profile:

cr config show --json
cr me --all --json

Use set-credential only for deferred or multi-key credential bundles that are clearer to manage outside init.

Environment variables in the examples above are setup ingress only. Runtime commands resolve service credentials from config.yml and the configured credential backend.

Configuration

Run cr config show to inspect the active profile and credential status.

default_profile: default
keyring:
  backend: keychain
profiles:
  default:
    git:
      host: github.com
      auth_mode: pat
      credential_ref: codereview/default
    llm:
      provider: anthropic
      auth: subscription
      adapter: claude_cli
      reviewer_model_tier: small
    agent_sources:
      - ~/.config/codereview/agents
    review_policy:
      major_event: comment
      allow_self_approve: false
      resolve_threads: auto
      resolve_after: 24h
data:
  retention:
    max_age_days: 90
    enforcement: at_write

Supported values:

Field Values
git.auth_mode pat and github_app are implemented for GitHub. oauth_device is reserved; config recognizes the mode but validation rejects it in v1.
llm.provider anthropic, openai, pi
llm.auth subscription, api_key
llm.adapter claude_cli, anthropic_api, openai_api, pi_rpc, and codex_cli are usable for review. codex_cli requires provider: openai and auth: subscription, and is currently best-effort/beta because Codex does not yet expose an explicit all-tools-disabled flag.
llm.model_map keys small, medium, large
llm.reviewer_model_tier small, medium, large
review_policy.major_event comment, request_changes
review_policy.resolve_threads auto, never
data.retention.enforcement at_write applies review-time pruning before each cr review; manual_only disables review-time pruning and leaves cr data prune as the explicit maintenance path.

subscription LLM auth means the adapter owns its own credentials, such as a logged-in CLI or local runtime. api_key LLM auth requires llm.credential_ref and stores a provider-specific API key in the credential backend.

Reviewer agents use provider-neutral model_tier values as minimum floors. At runtime, cr combines the profile's llm.reviewer_model_tier baseline with the agent floor and resolves the higher tier through the active profile's llm.model_map plus provider+adapter built-ins. User llm.model_map entries override built-ins, and model IDs are opaque strings so future provider models can be configured without a CLI update.

Effective reviewer tier is:

max(llm.reviewer_model_tier, agent.model_tier)

When llm.reviewer_model_tier is omitted, cr defaults it to small. model_id stays an exact provider-specific selection and does not participate in the tier-floor calculation.

Migration note: older releases treated reviewer model_tier as a direct map lookup. Current releases treat it as a minimum acceptable tier, so profiles can raise the reviewer baseline without editing shared agent catalogs.

Dry-run and no-post runs also record selected reviewer runtime resolution in agent-sources.json for auditability. Each selected agent may include reviewer_runtime with:

Field Meaning
mode tier_floor for portable tier resolution, exact_model for agent model_id passthrough
floor_tier Declared agent model_tier floor when mode=tier_floor
baseline_tier Effective operator baseline tier used for this run
effective_tier Higher of baseline and agent floor
resolved_model Resolved provider model, from the active model map for tier_floor or from agent model_id for exact_model
model_map_source built_in or config for the resolved tier mapping

Built-in model maps:

Provider Adapter small medium large
openai codex_cli gpt-5.4-mini gpt-5.4 gpt-5.5
openai openai_api gpt-5.4-mini gpt-5.4 gpt-5.5
anthropic claude_cli unset claude-sonnet-4-6 claude-opus-4-8
anthropic anthropic_api unset unset unset
pi pi_rpc unset unset unset

anthropic_api, pi_rpc, and claude_cli small-tier usage require explicit llm.model_map entries.

For Anthropic subscription profiles, adapter: claude_cli runs Claude Code background jobs, writes the full review task to cr-prompt.txt in an adapter-owned scratch directory, and starts claude --bg with a compact positional prompt that allows only Read,Write. The adapter reads the review result from cr-result.json in that scratch directory and records the Claude provider session returned by the job state. Background jobs run from a stable cache workdir so Claude Code can resolve resumed sessions consistently; set CR_CLAUDE_BG_WORK_DIR to override that workdir.

For OpenAI subscription profiles, adapter: codex_cli runs codex exec in an adapter-owned scratch directory with --json, --ephemeral, --skip-git-repo-check, --ignore-user-config, --ignore-rules, a read-only sandbox, and a scratch --cd. The adapter rejects unsafe flags and fails the review if Codex emits tool-use events. This remains best-effort/beta because Codex CLI does not yet expose a first-class all-tools-disabled flag.

Credential key matrix:

Profile field Purpose Auth/provider Required keys Optional keys v1 behavior
git.credential_ref User Git host auth pat git_token None Supported
reviewer_credentials.credential_ref Reviewer Git host auth pat git_token None Supported; must use a distinct ref from git.credential_ref in the same profile
git.credential_ref / reviewer_credentials.credential_ref Git host auth github_app github_app_id, github_app_private_key github_app_installation_id Supported for GitHub. cr review can discover the installation from the PR repository when the optional installation ID is omitted; commands without repository context require it
git.credential_ref / reviewer_credentials.credential_ref Git host auth oauth_device None None Reserved; config recognizes the mode but v1 rejects it and does not accept future keys such as git_oauth_access_token or git_oauth_refresh_token
llm.credential_ref Anthropic direct API auth api_key + anthropic anthropic_api_key None Supported
llm.credential_ref OpenAI direct API auth api_key + openai openai_api_key None Supported
Omitted llm.credential_ref Adapter-managed LLM auth subscription + anthropic/openai/pi None None Supported; credentials are owned by the selected adapter. openai + codex_cli is best-effort/beta until Codex exposes an explicit all-tools-disabled flag
llm.credential_ref Pi direct API auth api_key + pi None None Unsupported; use adapter-managed subscription auth with pi_rpc

Upgrade note: pre-matrix versions used the generic llm_api_key key for direct LLM API credentials. Re-provision API-key LLM refs with anthropic_api_key or openai_api_key; llm_api_key is not accepted by v1 set-credential.

Common Workflows

Preview a review without posting:

cr review --dry-run https://github.com/OWNER/REPO/pull/123

Run a live review:

cr review https://github.com/OWNER/REPO/pull/123

Run a live review and fail the command when a major or blocking finding exists:

cr review --fail-on major https://github.com/OWNER/REPO/pull/123

Force a fresh live review instead of using existing approval, override, resume, or marker gates:

cr review --rerun https://github.com/OWNER/REPO/pull/123

Retry missing or failed required posts without rerunning the LLM review:

cr review --retry-posts https://github.com/OWNER/REPO/pull/123

Approve after a prior agentic pass when the PR author explicitly asks to skip a low-value rerun:

# Comment on the PR after the latest codereview marker, for example:
# "These findings are low-value; please approve the pull request."
cr review https://github.com/OWNER/REPO/pull/123

Reuse a named LLM session for a series of related live reviews:

cr review --session release-train https://github.com/OWNER/REPO/pull/123
cr sessions show release-train

Inspect trusted agents for a PR:

cr agents list https://github.com/OWNER/REPO/pull/123
cr agents show harness:reviewer https://github.com/OWNER/REPO/pull/123

Inspect and clean local data:

cr data show
cr data prune --dry-run
cr data prune --keep-last 10
cr data purge --dry-run

Validate and run a benchmark suite:

cr benchmark validate .codereview/benchmarks/reviewer.yml
cr benchmark doctor .codereview/benchmarks/reviewer.yml --json
cr benchmark select .codereview/benchmarks/reviewer.yml \
  --candidate claude-sonnet-medium \
  --case merged-security-pr
cr benchmark run .codereview/benchmarks/reviewer.yml \
  --candidate claude-sonnet-medium \
  --case merged-security-pr

See BENCHMARKING.md for suite schema, terminology, artifact layout, privacy guidance, and metric caveats.

Command Reference

All commands accept the global flags:

Flag Semantics
--profile <name> Select a configured profile and bypass repo-aware routing. When omitted, PR-aware commands may use repository_profiles, then fall back to default_profile; during init, empty means default.
--backend <name> Select the credential backend for this invocation. One of keychain, wincred, secret-service, file, pass, memory.

cr

cr [flags]
cr [command]

With no subcommand, cr prints help. cr --version prints the same version line as cr version. Unknown commands and malformed flags return usage errors.

cr version

cr version

Prints the build version as cr <version-info>. It takes no arguments.

cr init

cr init [flags]

Creates or updates non-secret config. In v1, --non-interactive is required. If the selected profile already exists, pass --replace-profile to replace the profile config.

Flags:

Flag Semantics
--non-interactive Required in v1. Run without prompts.
--git-host <host> Git host, default github.com. The PR host must match this value.
--git-credential-ref <ref> Credential ref for Git auth. Defaults to codereview/<profile>.
--git-token-stdin Read the Git token from stdin and write key git_token.
--git-token-from-env <env> Read the Git token from an environment variable and write key git_token.
--reviewer-credential-ref <ref> Credential ref for reviewer Git auth. Defaults to codereview/<profile>-reviewer when reviewer credentials are requested.
--reviewer-auth-mode <mode> Reviewer Git auth mode, default pat. github_app writes config and prints follow-up credential commands.
--reviewer-token-stdin Read the reviewer Git token from stdin and write key git_token; PAT reviewer auth only.
--reviewer-token-from-env <env> Read the reviewer Git token from an environment variable and write key git_token; PAT reviewer auth only.
--llm-provider <provider> LLM provider, default anthropic; also selects whether API-key ingress writes anthropic_api_key or openai_api_key. pi is adapter-managed and does not accept API-key ingress.
--llm-auth <mode> LLM auth mode, default subscription. Use api_key for keyring-managed direct API keys.
--llm-adapter <adapter> LLM adapter, default claude_cli.
--llm-credential-ref <ref> Credential ref for LLM API-key auth. Defaults to codereview/<profile>-llm when --llm-auth api_key.
--llm-api-key-stdin Read the LLM API key from stdin and write anthropic_api_key or openai_api_key according to --llm-provider.
--llm-api-key-from-env <env> Read the LLM API key from an environment variable and write anthropic_api_key or openai_api_key according to --llm-provider.
--agent-source <path> Add a trusted agent source directory. Repeatable.
--major-event <policy> comment or request_changes. Controls review event for major findings.
--allow-self-approve Store profile policy allowing self approval. Live review can still require --allow-self-approve depending on invocation.
--resolve-threads <policy> auto or never. Empty leaves thread resolution unset.
--resolve-after <duration> Store a validated duration such as 24h for future thread-resolution policy. Current review planning uses resolve_threads/--no-resolve-threads, not this delay.
--overwrite Replace existing keyring entries written by this command.
--replace-profile Replace an existing profile config.

Only one stdin secret ingress flag may be used at a time. PAT reviewer credentials use key git_token under their own credential ref, so --reviewer-credential-ref must differ from --git-credential-ref. GitHub App reviewer credentials use github_app_id and github_app_private_key, plus optional github_app_installation_id; init does not accept reviewer token ingress for --reviewer-auth-mode github_app. LLM API-key ingress requires --llm-auth api_key. --overwrite with API-key auth requires an LLM key ingress flag. --allow-self-review is intentionally runtime-only on cr review; init only stores the profile-level self-approval policy.

cr set-credential

cr set-credential --ref <ref> --key <key> (--stdin | --from-env <env>) [flags]

Writes one secret value to the credential store. Globally allowed keys are git_token, github_app_id, github_app_private_key, github_app_installation_id, anthropic_api_key, and openai_api_key. When config.yml declares the target ref, set-credential narrows that global allowlist to the exact key set expected for that ref. PAT user Git refs and PAT reviewer refs use git_token; GitHub App refs use github_app_id, github_app_private_key, and optional github_app_installation_id; Anthropic LLM API-key refs use anthropic_api_key; OpenAI LLM API-key refs use openai_api_key.

Flags:

Flag Semantics
--ref <ref> Required credential ref, such as codereview/default.
--key <key> Required key name. Git refs accept the keys described in the credential key matrix; LLM API-key refs accept anthropic_api_key or openai_api_key.
--stdin Read the secret from stdin.
--from-env <env> Read the secret from an environment variable.
--overwrite Replace an existing key. Without it, existing keys are not overwritten.
--json Emit a JSON result.

Exactly one of --stdin or --from-env is required.

cr config show

cr config show [--json]

Shows the resolved active profile, selected credential backend and source, credential refs, non-secret profile config, review policy, and data retention. For each declared credential ref, it reports whether expected keys are present and labels optional keys as optional. For each configured agent source, it reports deployment-material status, canonical path, warnings, and SHA-256 fingerprint prefix without inlining agent definition contents.

--json emits the same information as structured JSON.

cr config route

cr config route list [--json]
cr config route set --host <host> --namespace <namespace> [--repo <repo> ...]
cr config route unset --host <host> --namespace <namespace> [--repo <repo> ...]

Inspects and updates repository_profiles routing rules. set and unset apply to the active profile when --profile is supplied; omit --repo to make the route namespace-wide, or repeat --repo for repo-specific routes.

Use this command for scripted route parity instead of trying to encode routing inside cr init --non-interactive.

cr config agent-source

cr config agent-source list [--json]
cr config agent-source add <path>
cr config agent-source remove <path>

Inspects and updates the active profile's agent_sources. add normalizes the path, skips duplicates, and preserves unrelated sources. remove removes only matching normalized paths from the active profile.

cr config retention

cr config retention get [--json]
cr config retention set [--max-age-days <days>] [--enforcement <policy>]
cr config retention reset

Inspects and updates global data.retention. set accepts a non-negative --max-age-days value where 0 means keep forever, and an --enforcement value of at_write or manual_only. reset restores the default 90 day at_write policy.

cr config llm models

cr config llm models list [--json]
cr config llm models resolve <tier> [--json]
cr config llm models set <tier> <model>
cr config llm models unset <tier>
cr config llm models reset [--provider <provider>]

Inspects and updates the active profile's llm.model_map. list shows the effective small/medium/large map, including whether each value came from profile config, built-in defaults, or is unset. resolve prints the concrete provider model ID for one tier under the active profile.

set, unset, and reset mutate only the active profile. reset clears the configured map so built-ins apply again; --provider is a safety guard and must match the active profile provider.

cr config clear

cr config clear [--all] [--dry-run] [--json]

Deletes stored credentials declared by the active profile.

Flags:

Flag Semantics
--all Also remove the active profile from config.yml and clear the disposable cache root. Inactive profiles and durable data are not touched.
--dry-run Report the credential refs, config profile reset, and cache cleanup that would happen without deleting credentials, config, cache, or data.
--json Emit a JSON result.

Without --all, this removes secret keyring entries only and leaves config.yml intact. With --all, --profile <name> selects the profile to reset; otherwise the default profile is reset. If other profiles remain after a profile reset, the default profile is updated deterministically to the first remaining profile name when needed. If the last profile is reset, config.yml is removed.

config clear never touches durable review data. Use cr data purge for the data pillar.

cr me

cr me [--all] [--json]

Resolves the active git-host identity using configured posting credentials and caches the identity in config. With --all, refreshes every configured profile and verifies both user Git and reviewer identity credentials when a profile declares both. --json emits structured output. --all cannot be combined with --profile.

cr agents list

cr agents list [PR] [--agents-dir <path> ...] [--json]

Lists trusted review agents. If a PR URL is supplied, repo-local agents are loaded from the PR base branch under .codereview/agents, not from the PR head. This keeps unreviewed agent changes from affecting their own review. Filesystem profile and flag sources include structured provenance with configured path, canonical path, warnings, and SHA-256 fingerprint prefix so an operator can verify which org-shipped agent version was used.

Agent source precedence is profile sources, repo-local base-branch agents, then --agents-dir sources. Later sources override earlier agents with the same ID.

Flags:

Flag Semantics
--agents-dir <path> Additional trusted agents directory. Repeatable.
--json Emit JSON.

cr agents show

cr agents show <name> [PR] [--agents-dir <path> ...] [--json]

Shows one agent, including category metadata, model_tier or model_id, effort, file globs, applies_when, needs_full_file_content, prompt, provenance, and trust note when repo-local agents are considered.

cr review

cr review <PR> [flags]

Runs the automated review pipeline for a GitHub pull request URL. The PR host must match the active profile's git.host.

Modes:

Flag Semantics
--dry-run Plan review actions, write local artifacts, and print the plan without posting.
--no-post Alias for --dry-run.
--rerun Bypass existing approval, approval-override, resume, and marker gates and start a fresh live review. Mutually exclusive with --retry-posts.
--retry-posts Retry missing or failed required posts for an existing run without rerunning LLM planning or checking approval overrides. Mutually exclusive with --rerun and incompatible with --session.

Review selection and execution flags:

Flag Semantics
--agents-dir <path> Additional trusted agents directory. Repeatable.
--max-agents <n> Limit selected reviewer agents. Omit the flag or pass 0 for the default limit of 5. Negative values are rejected.
--max-concurrency <n> Limit concurrent reviewer agents. Omit the flag or pass 0 for the default limit of 5. Negative values are rejected.
--selection-model <model> Exact provider model ID passthrough for the selection stage only. Bypasses the default medium-tier selection model resolution. Requires --dry-run or --no-post.
--selection-effort <effort> Override selection-stage effort only with low, medium, or high. Requires --dry-run or --no-post.
--selection-prompt <path> Load selection-stage instruction text from a file while preserving the structured JSON selection protocol. Requires --dry-run or --no-post.
--reviewer-model <model> Exact provider model ID passthrough for reviewer stages only. Bypasses reviewer agent model_tier, model_id, and profile model-map resolution. Requires --dry-run or --no-post.
--reviewer-model-tier <tier> Override the reviewer baseline tier only with small, medium, or large. This still respects higher agent model_tier floors. Requires --dry-run or --no-post.
--reviewer-effort <effort> Override reviewer-stage effort only with low, medium, or high. Requires --dry-run or --no-post.
--review-base-sha <sha> Review this base commit SHA instead of the PR's current base SHA. Requires --review-head-sha and --dry-run or --no-post.
--review-head-sha <sha> Review this head commit SHA instead of the PR's current head SHA. Requires --review-base-sha and --dry-run or --no-post.
--session <name> Reuse a named LLM session for live reviews. Not allowed with --dry-run, --no-post, or --retry-posts.
--verbose Include nits in review output and emit additional diagnostics.

Policy and output flags:

Flag Semantics
--fail-on <severity> Exit 1 if any finding is at or above blocking, major, minor, or nits.
--allow-self-review Allow reviewer credentials that resolve to the PR author.
--allow-self-approve Allow approval when the posting identity is the PR author.
--no-resolve-threads Do not plan thread-resolution actions. Also implied by profile resolve_threads: never.
--json Emit JSON.

Live review uses a gate before planning or posting. If the posting identity has already approved the PR, cr review exits immediately in Go code before any LLM classifier or reviewer loop runs; this is true even if newer commits made the approval stale. Use --rerun to force a fresh review anyway.

If there is no existing approval, cr review looks for an explicit PR-author approval override request newer than the latest codereview marker from the posting identity. This check only runs after at least one prior codereview marker exists. Candidate comments are filtered in Go to PR-author issue comments, review bodies, and inline-thread comments newer than that marker; a small-tier LLM classifier only decides whether those comments ask for approval override. A positive classification skips the reviewer loop and posts an approving review through the normal ledger/outbox path. Only ordering relative to the latest codereview marker is enforced; the tool intentionally does not require the request to be newer than a later head update.

If matching complete markers already exist for the current head/base/profile/posting identity, cr review exits early. If a prior compatible partial run exists, it resumes or repairs posting from durable local state. If the PR base moved, live review aborts with an upstream exit. --rerun starts fresh and bypasses the approval/override fast paths. --retry-posts replays required posts that are missing or failed without rerunning the LLM review or checking approval overrides.

Dry-run output contains planned actions and artifact paths. Dry-run action markers are reported as omitted because nothing is posted.

Live text output includes run ID, gate status, decision, outcome, PR, artifacts, and post counts. JSON output includes run, status, decision, message, outbox, artifacts, and fail_on_triggered.

cr benchmark

cr benchmark <command>

Validates, inspects, runs, and compares benchmark suites. See BENCHMARKING.md for the full benchmark guide.

cr benchmark validate

cr benchmark validate <suite.yml>

Validates benchmark suite schema and configured profile compatibility without running reviews. For the current full-pipeline commands, this includes stage-recipe validation and selection prompt file readiness checks.

cr benchmark doctor

cr benchmark doctor <suite.yml> [--candidate <id> ...] [--case <id> ...] [--results-dir <path>] [--cr-bin <path>] [--json]

Inspects benchmark readiness without running reviews. It reports the selected candidates and cases, resolved results directory, selected cr binary, profile availability, selection/reviewer/synthesis stage recipes, reviewer agent directories, and warnings.

cr benchmark run

cr benchmark run <suite.yml> [--candidate <id> ...] [--case <id> ...] [--results-dir <path>] [--cr-bin <path>] [--json]

Runs the selected candidate x case matrix by invoking cr review --dry-run --json for each run. It always uses dry-run review mode, captures stdout and stderr separately, records each child exit code, and writes generated artifacts under .cr-bench/results/<suite-id>/<timestamp>/ unless --results-dir is set.

Use --candidate and --case for benchmark selection. Candidate YAML fields such as stages.selection, stages.reviewers, max_agents, and max_concurrency control review runtime overrides. stages.selection.model and stages.selection.effort map to --selection-model and --selection-effort; optional stages.selection.prompt maps to --selection-prompt. stages.reviewers.model remains the exact-model bypass, while stages.reviewers.model_tier maps to --reviewer-model-tier. stages.reviewers.effort and stages.reviewers.agent_dirs[] map to --reviewer-effort and repeated --agents-dir flags. Case YAML fields review_base_sha and review_head_sha pin the exact base/head commit pair reviewed by the dry-run child command. Optional stages.synthesis metadata is reserved for future benchmark support and does not change benchmark run execution yet.

cr benchmark select

cr benchmark select <suite.yml> [--candidate <id> ...] [--case <id> ...] [--results-dir <path>] [--json]

Runs the selected candidate x case matrix through the extracted in-process selection phase only. It reuses the same profile, provider, adapter, and agent catalog loading semantics as cr review, but stops after selector execution. It does not spawn a child cr review, does not run reviewer agents, and does not run synthesis.

Candidate stages.selection.model and stages.selection.effort map to selection overrides directly. Optional stages.selection.prompt is loaded from disk into selection instructions, and optional stages.reviewers.agent_dirs[] are passed into the selector catalog so candidate reviewer packs still influence routing. Case YAML review_base_sha and review_head_sha still pin the exact base/head commit pair used to build the selector diff view.

Optional stages.synthesis metadata is preserved in summaries and selector recipe.json artifacts, but selector-only benchmarking still stops after selection. Dedicated synthesis benchmarking is future work.

Selector benchmarks write selector-specific per-run artifacts such as selection.json, recipe.json, metrics.json, and selection log metadata. When one selector run fails after partial execution, benchmark select records that run as failed and continues the remaining matrix when it can still write trustworthy suite artifacts.

cr benchmark compare

cr benchmark compare <results-dir> [--json]

Reads an existing benchmark results directory and writes deterministic comparison.json and comparison.md artifacts. Comparison is local-only: it does not invoke models, read live PR state, mutate Git provider state, or require provider credentials. cr benchmark run and cr benchmark select write the same comparison artifacts automatically.

cr sessions list

cr sessions list [--json]

Lists named LLM sessions in name order. Text output shows name, profile, provider, adapter, model, host, and last-used time. JSON output includes the provider session ID plus created and last-used timestamps.

cr sessions show

cr sessions show <name> [--json]

Shows one named LLM session. Missing sessions return an error. Text output includes the provider session ID.

cr sessions delete

cr sessions delete <name> [--json]

Deletes one named LLM session row. It does not delete provider-side session state. Missing sessions return an error.

cr data show

cr data show [--json]

Shows local durable data usage: data root, ledger path, runs root, run counts, live/dry-run counts, outcome counts in JSON, oldest/newest run timestamps, artifact bytes, and orphan artifact counts/bytes.

cr data prune

cr data prune [--older-than <duration> | --keep-last <n>] [--dry-run] [--json]

Prunes selected ledger runs and their artifacts, then removes orphan artifact directories. The default with no selector applies built-in manual retention: live runs older than 90 days and dry-run runs older than 7 days. This manual default is independent from data.retention.* review-time pruning config.

Flags:

Flag Semantics
--older-than <duration> Prune runs older than the given positive duration. Mutually exclusive with --keep-last.
--keep-last <n> Keep the newest non-negative n runs per post mode and prune the rest. Mutually exclusive with --older-than.
--dry-run Report selected runs and orphans without deleting.
--json Emit JSON including selected/deleted runs, orphan removals, and warnings.

Prune deletes the ledger row first, then removes artifact directories best effort. Unsafe artifact paths and remove failures are reported as warnings after the ledger row is deleted.

cr data purge

cr data purge --yes [--json]
cr data purge --dry-run [--json]

Purges the whole local data root. --yes is required unless --dry-run is set. Purge does not open the ledger database, so it can remove a corrupt local data root. --json emits the data root, dry-run status, and removed status.

Flags:

Flag Semantics
--yes Confirm permanent deletion. Required unless --dry-run is set.
--dry-run Report the data root without deleting.
--json Emit JSON.

Operational Semantics

Local State

cr keeps non-secret config in the OS config directory for service codereview. Durable review data lives under the OS data directory for the cr binary and includes:

  • ledger.db: runs, sessions, findings, planned actions, and named sessions;
  • runs/...: per-run artifacts such as diff.patch, findings.json, rollup.md, diff slices, and agent JSONL logs;
  • locks/...: live-review advisory locks.

The HTTP cache is under the OS cache directory for the cr binary.

Releases before this state-layout alignment wrote data/cache below a nested codereview child inside the cr root. Commands that write review state migrate those legacy entries into the cr root without changing config or credential refs.

Posting, Markers, And Idempotency

Live posting records hidden codereview markers on comments/reviews created by the posting identity. Markers let later invocations classify the PR as complete, partial, stale-base, or fresh for the current head/base context. The outbox reconciles markers only from the posting identity, so unrelated comments from other users do not satisfy cr's idempotency checks.

Planned actions can include inline comments, file-level or rollup comments, review submission, thread summary replies, and thread resolution. Thread summary content uses separate summary markers. Model-generated marker-looking text is escaped before posting.

Session Reuse

--session <name> stores and reuses the provider session for live orchestrator turns. A named session is scoped by name, profile, provider, adapter, model, and host. Profile/provider/adapter/model mismatches are errors. Host mismatches warn and continue. If the active adapter does not support resume, cr starts fresh and records the new provider session when available. claude_cli supports resume by launching a new Claude Code background job with the stored provider session.

Retention

cr review applies retention before fetching the PR or allocating the next run when data.retention.enforcement is at_write. data.retention.max_age_days controls live-run retention and defaults to 90 days. A value of 0 keeps live runs forever. Dry-run runs remain throwaway data and use a fixed 7-day review-time retention cap.

Set data.retention.enforcement: manual_only to disable review-time pruning for both live and dry-run invocations. The explicit cr data prune --dry-run command remains the safe preview path for manual maintenance, and no-selector cr data prune uses its built-in live 90-day and dry-run 7-day windows independent from profile config.

Development

make tidy
make lint
make test
make build
make snapshot
make check

The main binary lives in cmd/cr. Command wiring is in internal/cmd, provider boundaries are under internal/gitprovider, and review orchestration is split between internal/pipeline, internal/reviewrun, internal/reviewplan, and internal/outbox.

See docs/development.md for local development notes.