AI code review CLI for CI. Runs on GitHub Actions and GitLab CI, comments on the PR/MR, and exports structured reports compatible with
local-review.
Reviews a pull request or merge request with an LLM, posts the result back as a comment, and emits machine-readable artifacts (review.xml, checkstyle.xml) for downstream tooling. The review.xml is round-trip compatible with local-review, so a human can browse the AI review locally and let an agent apply suggestions.
Workflow:
- Trigger — a PR/MR opens or updates and CI runs
remote-review - Review — the CLI fetches the diff, asks the model, and posts a comment
- Export —
review.xmlandcheckstyle.xmlare uploaded as artifacts - Apply (optional) — pull the artifact locally and let
local-review+ an agent apply suggestions to your tree
| Command | Purpose |
|---|---|
remote-review review |
Detailed code review of the PR/MR. Emits review.xml, checkstyle.xml, Markdown, or JSON. |
remote-review check |
Verifies whether the PR/MR meets the requirements of the supplied task definition. With --strict exits non-zero on non-compliance (CI gate). |
remote-review summary |
Concise summary of the changes. |
remote-review init prompts |
Write the bundled prompts to .remote-review/prompts/ for editing. |
# GitHub PR — emit review.xml + checkstyle.xml + comment on the PR
remote-review review --platform github --pr 42 --repo acme/widgets \
--comment --out review-xml --out checkstyle
# GitLab MR — custom output paths
remote-review review --platform gitlab --mr 42 --project group/repo \
--comment --out review-xml:reports/review.xml --out checkstyle:reports/checkstyle.xml
# CI gate against a task definition piped in from any source
cat task.md | remote-review check --platform gitlab --mr 42 --project group/repo \
--task-stdin --strictThe task definition is supplied by the caller — remote-review is forge- and tracker-agnostic. Pass it via --task-text "<inline>", --task-file <path>, or pipe it in with --task-stdin. See CI integration for examples that fetch the task from Redmine, Jira, Linear, or GitHub Issues before invoking the CLI.
| Flag | Description |
|---|---|
--platform <name> |
github or gitlab. Auto-detected from GITHUB_ACTIONS / GITLAB_CI. |
--pr <number> / --repo <owner/repo> |
GitHub identifiers (or GITHUB_REF / GITHUB_REPOSITORY) |
--mr <iid> / --project <id> |
GitLab identifiers (or CI_MERGE_REQUEST_IID / CI_PROJECT_ID) |
--task-file <path> / --task-text <text> / --task-stdin |
Provide the task definition (any tracker — caller's responsibility to fetch) |
--context <text> |
Extra instruction appended to the prompt |
--language <code> |
Language for the agent's response (e.g. en, es, Spanish). Defaults to English. |
--comment |
Post the result back as a PR/MR comment |
--out <fmt[:path]> |
Repeatable. review-xml / checkstyle / markdown / json |
-q, --quiet |
Silence progress |
-m, --model <id> |
Override the model |
--verbose |
Log agent tool calls (skills loaded, files read, submitReview) to stderr for debugging. |
remote-review is designed to be driven by another process (a job runner, a web
backend, etc.) without touching the filesystem. The streams are cleanly split:
- stdout — the review result, and only that.
review --out jsonwrites the structured review as JSON;--out markdownwrites Markdown. Nothing else in thereviewcommand writes to stdout. - stderr — everything else: the progress spinner, phase log, file-write notices, and errors.
--verbose— adds a readable phase log to stderr (→ resolving PR/MR…,✓ loaded github-pr — "…",analyzing diff and generating review…,writing outputs…) plus the agent tool-call detail. Without a TTY the spinner is not drawn at all — only plain text lines.- Exit code —
0on success,1on error (message on stderr).
So the caller captures stdout and stderr separately: stdout is the result to parse, stderr is the live log to surface to the user.
remote-review review --platform github --pr 42 --repo acme/widgets \
--out json --verbose 1>review.json 2>review.logThe JSON on stdout has the shape:
{ "timestamp": "…", "source": { … }, "review": { "summary": "…", "comments": [ … ] } }remote-review is distributed as a self-contained binary on GitHub Releases and as a Docker image on GHCR and Docker Hub. There is no npm package — it's a CI tool, not a library.
# Linux x64 example — replace the asset name for your platform
curl -L -o remote-review \
https://github.com/loureirodev/remote-review/releases/latest/download/remote-review-linux-x64
chmod +x remote-review
sudo mv remote-review /usr/local/bin/Available targets: linux-x64, linux-arm64, darwin-x64, darwin-arm64, windows-x64.
docker pull ghcr.io/loureirodev/remote-review:latest
# or
docker pull loureirodev/remote-review:latestTagged as vX.Y.Z, vX (major), and latest.
- A git repository (when running locally)
- API key for the chosen AI provider (see below)
| Variable | Flag | Purpose |
|---|---|---|
REMOTE_REVIEW_GITLAB_URL |
--gitlab-url |
GitLab base URL |
REMOTE_REVIEW_GITLAB_TOKEN |
--gitlab-token |
GitLab personal access token |
GITHUB_TOKEN (or REMOTE_REVIEW_GITHUB_TOKEN) |
--github-token |
GitHub token (Actions provides it automatically) |
REMOTE_REVIEW_MODEL |
--model |
Model id provider/name (default: openai/gpt-4o) |
REMOTE_REVIEW_MODEL is provider/name. API keys per provider:
| Provider | Example | Env var |
|---|---|---|
| OpenAI | openai/gpt-4o |
OPENAI_API_KEY |
| Anthropic | anthropic/claude-opus-4-5 |
ANTHROPIC_API_KEY |
google/gemini-2.5-pro |
GOOGLE_GENERATIVE_AI_API_KEY |
|
| Mistral | mistral/mistral-large-latest |
MISTRAL_API_KEY |
| Vercel AI Gateway (any other) | — | AI_GATEWAY_API_KEY |
remote-review does not talk to any task tracker. If you want task-aware reviews (the prompt's {{#if task}} block), the caller is responsible for fetching the task from wherever it lives (Redmine, Jira, Linear, GitHub Issues, a Markdown file in the repo…) and handing the text to the CLI via --task-text, --task-file, or --task-stdin. If none of those are supplied, the {{#if task}} block is stripped and the review proceeds without task context.
See CI integration for end-to-end examples (including a Redmine fetcher in GitLab CI).
The default prompts are embedded inside the binary, so remote-review works out of the box. To customize them, scaffold editable copies into your repo:
remote-review init prompts
# → .remote-review/prompts/{review,check,summary}.mdEdit them, commit them, and remote-review will pick them up automatically. Resolution order:
- Env var:
REMOTE_REVIEW_PROMPT_REVIEW,REMOTE_REVIEW_PROMPT_CHECK,REMOTE_REVIEW_PROMPT_SUMMARY→ absolute path to a custom file - Working dir:
.remote-review/prompts/{review,check,summary}.md - Embedded defaults bundled into the binary
Templates use {{task}} and {{#if task}}…{{/if task}} blocks.
Skills let your team define custom review rules — architecture conventions, security checklists, framework-specific guidelines — that the review agent loads on demand depending on what's in the diff.
Create a SKILL.md inside a named subdirectory:
.remote-review/skills/<skill-name>/SKILL.md
SKILL.md must start with a YAML frontmatter block containing name and description:
---
name: drupal
description: Drupal coding standards and hook usage guidelines
---
## Drupal guidelines
- All hook implementations must follow the `MODULE_HOOKNAME()` naming convention.
- Never call `drupal_set_message()` — use `\Drupal::messenger()` instead.
- ...The agent reads the diff, decides which skills are relevant, and loads their full content via the loadSkill tool. Skills can also reference additional files in their directory using relative paths.
Skills are discovered from two locations, with project-level taking precedence:
- Project:
.remote-review/skills/<name>/SKILL.md(relative to working directory) - User-global:
~/.config/remote-review/skills/<name>/SKILL.md
If two skills share the same name field, the project-level one wins.
Detailed setup guides and copy-pasteable example files live under docs/ci/:
- GitHub Actions →
docs/ci/github-actions.md— uses the publishedloureirodev/remote-review@v1action. - GitLab CI →
docs/ci/gitlab-ci.md— uses the GHCR Docker image. - Task-aware reviews (Redmine, Jira, Linear, …) →
docs/ci/task-integration.md.
- uses: loureirodev/remote-review@v1
with:
comment: true
out: review-xml,checkstyle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}remote-review:
image: ghcr.io/loureirodev/remote-review:latest
rules: [{ if: $CI_MERGE_REQUEST_IID }]
script:
- remote-review review --platform gitlab --comment --out review-xml --out checkstyleremote-review is tracker-agnostic — if you want task-aware reviews, fetch the task in a previous step and hand it to the CLI via --task-text, --task-file, or --task-stdin. See docs/ci/task-integration.md for end-to-end examples.
# In CI
remote-review review --platform github --pr 42 --repo acme/widgets --out review-xml
# Locally — pull the artifact and load it
local-review --existing- Two forges: GitHub Actions and GitLab CI auto-detection
- Multiple outputs:
review-xml,checkstyle,markdown,json— combinable - Reviewdog-friendly: Checkstyle output annotates PR diffs natively on GitHub
- Round-trip with local-review: same
review.xmlschema - Multi-provider: OpenAI, Anthropic, Google, Mistral, or any model behind the Vercel AI Gateway
- Tracker-agnostic: task definition is supplied by the caller (Redmine, Jira, Linear, …) — the CLI focuses solely on review
- Customizable prompts: env-var or in-repo Markdown overrides
- Distributed as binary + Docker: no Node/Bun runtime required on the runner
- Bitbucket and Azure DevOps support
- SARIF output for GitHub code scanning
- Caching of unchanged hunks across PR updates
Contributions are welcome! See CONTRIBUTING.md for development setup, architecture, and the release process.
MIT