Skip to content

CLI & npm Package

In addition to the webhook-based GitHub App, ai-review-bot ships as an npm package with a CLI tool for running full-repository audits on demand — no PR, no webhook, no Vercel required.

Local review (ai-review review)

Run the full multi-agent review against your local working copy and write a durable Markdown report into docs/code-reviews/ — no GitHub PR, and it can bill your existing Codex / Claude subscription instead of API credits.

bash
ai-review review [--full | --commit <sha>] [--slug <slug>] [--title <t>] [--out <dir>] [--extra <text>] [--json]
FlagDescription
(default)Review local changes (committed + working-tree, vs the merge-base with the default branch).
--fullReview the entire tracked tree.
--commit <sha>Review exactly the files touched by <sha>, read at that commit.
--slug <slug>Override the filename slug (default: branch / commit subject / full-audit).
--title <t>Override the report H1 / front-matter title.
--out <dir>Output directory (default docs/code-reviews).
--extra <text>Extra instructions passed to every review agent.
--jsonPrint { path, durationSeconds, costUsd, filesReviewed, providers } to stdout.

Reports are named <YYYY-MM-DD>-<slug>-<NN>.md with a per-day, per-slug round number, and carry YAML front-matter (status, scope, remote, duration_seconds, cost_usd, providers, models, skills, findings). Flip status: reviewed → implemented once findings are addressed.

Auth resolution (local, personal use only)

Per provider, the CLI tries in order: API key (OPENAI_API_KEY / ANTHROPIC_API_KEY, or an explicit ANTHROPIC_AUTH_TOKEN / CLAUDE_CODE_OAUTH_TOKEN) → subscription OAuth from your logged-in codex (~/.codex/auth.json) and Claude Code (macOS Keychain). A provider that can't authenticate is skipped.

⚠️ The OAuth fallback is for your own machine only. Anthropic's ToS (eff. 2026-02-20) prohibits using Claude subscription OAuth tokens in third-party tools outside Claude Code / Claude.ai, and refresh tokens are shared with the real CLIs. See docs/code-reviews/README.md. The hosted webhook bot is unaffected — it uses API keys only.

Fix workflow

The /code-review slash command (in .claude/commands/) wraps this CLI with three modes: doc-only (default), --fix (auto-apply findings + run gates + flip status), and --propose (propose fixes, get sign-off, then apply).

What the audit does

The audit mode fetches every code file in a repository at a given ref, batches them into 150 KB chunks, and runs all five review agents on each batch. Findings are merged, deduplicated, and posted as a GitHub issue in the target repo. It runs against the entire codebase, not just a diff.

Supported file extensions: .ts, .tsx, .js, .jsx, .mjs, .cjs, .py, .go, .rs, .rb, .java, .cs, .cpp, .c, .h, .swift, .kt.

Installation

bash
npm install -g ai-review-bot        # global install
npx ai-review-bot@latest owner/repo # one-off, no install

Usage

bash
ai-review OWNER/REPO [--ref <branch-or-sha>] [--dry-run] [--extra <instructions>] [--provider <anthropic|openai>]

Arguments

ArgumentDescription
OWNER/REPORepository to audit (required)
--ref <ref>Branch, tag, or SHA to audit. Defaults to the repo's default branch.
--dry-runPrint the audit report to stdout instead of creating a GitHub issue.
--extra <text>Additional instructions passed to every review agent.
--provider <name>AI provider: anthropic (default) or openai.

Environment variables

VariableRequiredDescription
GITHUB_APP_IDNumeric GitHub App ID
GITHUB_APP_PRIVATE_KEYPKCS#8 private key PEM (\n for newlines)
ANTHROPIC_API_KEY✓ (anthropic)Anthropic API key (required when using --provider anthropic)
OPENAI_API_KEY✓ (openai)OpenAI API key (required when using --provider openai)

Examples

bash
# Audit the default branch, post findings as a GitHub issue
GITHUB_APP_ID=12345 \
GITHUB_APP_PRIVATE_KEY="$(cat key.pem | awk 'NF {printf "%s\\n", $0}')" \
ANTHROPIC_API_KEY=sk-ant-... \
ai-review joeblackwaslike/my-project

# Audit a specific branch without posting (dry run)
ai-review joeblackwaslike/my-project --ref feature/new-api --dry-run

# Audit with extra instructions
ai-review joeblackwaslike/my-project --extra "focus on database query safety"

Output

On success the CLI prints progress as it runs:

Found 142 code files in joeblackwaslike/my-project@main
Fetched 142 files
Running agents over 3 batch(es)...
  Batch 1/3: 20 files
  Batch 2/3: 20 files
  Batch 3/3: 20 files
Audit issue created: https://github.com/joeblackwaslike/my-project/issues/47

With --dry-run, the report is printed to stdout instead of posted as an issue.

GitHub Action

Use the published action to run a full-repo audit inside any CI workflow:

yaml
- uses: joeblackwaslike/ai-review-bot@v0.1.0
  with:
    github-app-id: ${{ secrets.GITHUB_APP_ID }}
    github-app-private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}
    anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}

Action inputs

InputRequiredDefaultDescription
github-app-idGitHub App ID
github-app-private-keyPKCS#8 private key PEM (newlines as \n)
anthropic-api-keyAnthropic API key (required when provider is anthropic)
openai-api-keyOpenAI API key (required when provider is openai)
provideranthropicAI provider: anthropic or openai
repocurrent repositoryRepository to audit (owner/repo)
refrepo default branchBranch, tag, or SHA to audit
dry-runfalseSet to true to print the report without creating an issue
extraAdditional instructions for the review agents
versionlatestnpm version of ai-review-bot to use (e.g. 0.1.0)

Scheduled audit example

Run a full codebase audit every Monday morning and post findings as a GitHub issue:

yaml
name: Weekly audit

on:
  schedule:
    - cron: '0 8 * * 1'   # every Monday at 08:00 UTC
  workflow_dispatch:

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: joeblackwaslike/ai-review-bot@v0.1.0
        with:
          github-app-id: ${{ secrets.GITHUB_APP_ID }}
          github-app-private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}
          anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}

Audit a different repo

yaml
- uses: joeblackwaslike/ai-review-bot@v0.1.0
  with:
    github-app-id: ${{ secrets.GITHUB_APP_ID }}
    github-app-private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}
    anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
    repo: myorg/other-repo
    ref: main
    extra: "This codebase uses strict null checks. Flag any unsafe casts."

Difference from PR reviews

PR Review (webhook bot)Full Audit (CLI / Action)
TriggerPR opened, pushed, or /ai-review commandManual, scheduled, or CI step
InputUnified diff of changed linesAll code files in the repo
OutputGitHub Pull Request Review with inline commentsGitHub Issue with a structured report
ProvidersClaude + Codex in parallelClaude (default) or Codex (--provider openai)
Inline commentsYes — anchored to diff linesNo — whole-file findings only

Private key formatting

Both the CLI and the Action require the private key as a single-line string with \n for newlines:

bash
awk 'NF {printf "%s\\n", $0}' your-private-key.pem

Store the output as a GitHub Actions secret or shell environment variable. The CLI normalizes \n back to real newlines at runtime.

Credentials for ai-review watch outside this repo

The globally npm-linked ai-review binary has no autoload for this repo's .env — if you run ai-review watch from a different repo's directory with no matching environment already exported, it fails with GITHUB_APP_ID environment variable is required. ai-review creds fixes this by storing the credentials in the macOS Keychain, which the CLI checks automatically at startup before falling back to ~/.config/ai-review/.env as a last resort.

Which vars ai-review watch needs

Only the 4 identity vars used to post through the two GitHub App bots:

  • GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY — the Claude bot's identity
  • OPENAI_APP_ID, OPENAI_APP_PRIVATE_KEY — the Codex bot's identity

(Webhook secrets, DATABASE_URL, QSTASH_*, and KV_REST_API_* are server/webhook-only and not needed by the CLI.)

Setting them — primary source: this repo's own .env

The correct values already live in this repo's .env file. creds set <VAR> accepts the value on stdin — it never touches our own argv or shell history:

bash
grep '^GITHUB_APP_ID=' .env | cut -d= -f2- | ai-review creds set GITHUB_APP_ID
grep '^GITHUB_APP_PRIVATE_KEY=' .env | cut -d= -f2- | ai-review creds set GITHUB_APP_PRIVATE_KEY
grep '^OPENAI_APP_ID=' .env | cut -d= -f2- | ai-review creds set OPENAI_APP_ID
grep '^OPENAI_APP_PRIVATE_KEY=' .env | cut -d= -f2- | ai-review creds set OPENAI_APP_PRIVATE_KEY

With no pipe attached, creds set <VAR> prompts interactively (input hidden, not echoed) instead. The private key values in .env are already single-line \n-escaped — no reformatting needed.

creds set <VAR> <value> (value as a third argument) still works for scripted callers that have already accepted the trade-off, but avoid it for anything sensitive: the value additionally lands in your shell history. <VAR> must be one of the 4 vars above — an unrecognized name is rejected rather than silently creating an orphaned Keychain entry.

For the two _PRIVATE_KEY vars specifically, creds set also checks the resolved value looks like a complete PEM (starts with -----BEGIN, contains a matching -----END) before writing it — this catches the one real failure mode of interactive entry: pasting a raw, un-escaped multi-line PEM into the hidden prompt, which reads only one line and would otherwise silently store a truncated key. Pasting the documented single-line \n-escaped form (the only form this CLI ever produces or expects) works fine either way, piped or interactive.

Residual exposure, either way: the stdin/prompt form keeps the value out of ai-review's own argv and your shell history, but the Keychain write itself shells out to macOS's security add-generic-password ... -w <value>, which briefly holds the value in that subprocess's argv (visible via ps//proc for its short lifetime) regardless of how ai-review obtained it. This is a security-CLI limitation, not something this feature can route around: its only non-argv input mode is an interactive double-entry prompt (type it twice, no echo) that reads from the controlling terminal, not stdin — incompatible with the piped/non-interactive flow above, which is the primary intended use. src/auth.ts's existing Keychain writer (the Claude Code OAuth token storage this feature mirrors) has the identical -w <value> pattern for the same reason.

Check what's currently stored (names only, never values) with ai-review creds list, and remove an entry with ai-review creds unset <VAR>.

Recovery path if .env is ever lost

  1. Go to github.com/settings/apps and open the existing app (the Claude bot app for GITHUB_APP_ID, the Codex bot app for OPENAI_APP_ID).

  2. Read the App ID at the top of the settings page.

  3. Under Private keys, click Generate a private key to get a new PEM — the original can't be re-downloaded.

  4. Convert it to the \n-escaped one-liner the CLI expects (same command as Private key formatting above):

    bash
    awk 'NF {printf "%s\\n", $0}' new-private-key.pem
  5. Pipe the result to ai-review creds set GITHUB_APP_PRIVATE_KEY (or OPENAI_APP_PRIVATE_KEY):

    bash
    awk 'NF {printf "%s\\n", $0}' new-private-key.pem | ai-review creds set GITHUB_APP_PRIVATE_KEY

~/.config/ai-review/.env fallback

If the Keychain isn't usable (e.g. a headless/non-interactive context), the CLI falls back to a plain KEY=VALUE file at ~/.config/ai-review/.env — the same format as this repo's own .env.example, so it's literally copyable from there. This file is plaintext on disk; the Keychain is preferred whenever it's available. If you use this fallback, chmod 600 ~/.config/ai-review/.env.

Released under the MIT License.