Code Review in CI
codeep review is a deterministic reviewer: pattern rules over your changed files, no model involved. It runs in about a second, costs nothing, and gives the same answer twice. That makes it the rare AI-tool feature you can put on a required check without flakiness or a bill.
Everything on this page is offline and needs no API key — with one exception, the optional fix step, which hands the findings to an agent and does need one.
In the terminal
With no arguments it reviews your unstaged changes, falling back to a src/ scan when the tree is clean. Pass files to scope it.
Options
| Flag | What it does |
|---|---|
--json | Print the result as JSON instead of the markdown report |
--fail-on <level> | Exit non-zero at or above error | warning | info | none (default: error) |
--fix | Let an agent fix what was found. Edits the working tree and stops there |
--fix-min-severity <level> | Lowest severity a fix may act on: error | warning (default: warning) |
--rules | List the built-in rule ids and exit |
--ai | Ask your provider for a contextual second opinion (advisory; needs a key) |
0 when nothing at or above --fail-on was found, 1 when something was. --fail-on none never fails, which is how you roll this out to a team without blocking anyone on day one.The GitHub Action
codeep-action wraps the same subcommand. It resolves the pull request's changed files through the GitHub API — so shallow clones are not a problem — runs the review over those, and renders the result three ways: inline annotations on the changed lines, a single self-updating summary comment, and the check's pass/fail status.
Add .github/workflows/codeep-review.yml:
name: Codeep Review
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write # to post the summary comment
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: VladoIvankovic/codeep-action@v1
with:
fail-on: error@v1 is a floating tag that moves with every patch. @v1.0.10 is immutable. The convenience of one is the risk of the other; pick deliberately.Pull requests from forks
GitHub forces the workflow token to read-only on fork pull requests, regardless of what your permissions: block says. The review still runs and you still get annotations and a pass/fail check — only the summary comment is skipped, with a warning in the log. No finding is ever lost.
pull_request_target to get the comment back. That trigger runs with a write token, and checking out and executing an untrusted contributor's code under it hands them your secrets. If you need comments on fork pull requests, use the two-workflow workflow_run pattern instead.Letting it fix what it finds
Off by default. With fix: true the action hands the findings to an agent, lets it edit the code, and opens a second pull request against the branch under review.
permissions:
contents: write # to push the fix branch
pull-requests: write # to open the fix PR and post the comment
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: VladoIvankovic/codeep-action@v1
with:
fix: true
fix-min-severity: warning
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}permissions: block cannot grant this one.The key goes in env, not with. Reviewing needs none; only the fix agent runs a model. Any provider Codeep supports works — set that provider's own variable (ZAI_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY, and so on). With none set, the action says so and skips the fix rather than failing quietly.
What it will not do
| Never | Why |
|---|---|
Pushes to the branch under review | Your pull request is left as you left it; fixes arrive separately, to read or close |
Merges anything | A fix is a proposal, not a decision |
Acts on suggestions | Only error and warning — acting on opinion produces churn and buries what matters |
Runs on fork pull requests | The read-only token there cannot push a branch |
Gets a shell, git, or the network | It has file editing and the test runner, enforced by the same boundary as any custom agent |
That boundary is real rather than a line in a prompt, and the audit record shows it working — a refused tool call is written down alongside the ones that succeeded.
The fix step runs after the review is reported and never changes the check's outcome. A fix that fails, or runs out of its fix-timeout (600 seconds by default), is reported as a warning and leaves the review's result alone.
Rules
Twenty built-in rules across security, performance, bugs, types, style and documentation. List them with their ids:
Add your own, or switch built-ins off, in .codeep/review.yml (or .json). Checked into the repo, so the CLI and the Action enforce the same conventions:
rules:
- id: no-direct-db
pattern: 'db\.query\('
category: best-practice
severity: warning
message: Go through the repository layer
suggestion: Use repo.find() instead
extensions: ['.ts']
disable:
- todo-comment
include: ['src/**']
exclude: ['vendor/**', 'dist/**']Rolling it out
Start at fail-on: none. The comment and annotations appear on every pull request, nothing blocks, and after a week or two you know which rules your codebase actually disagrees with. Disable those, then tighten to error. Turning the gate on first is how a review tool gets switched off.