gitlab-code-review
v0.1.0
Published
Installable GitLab MR code-review skill for Cursor, Claude, Codex, Gemini, and Copilot workflows.
Downloads
146
Maintainers
Readme
gitlab-code-review
Installable GitLab merge-request code-review skill for Cursor, Claude, Codex, Gemini, and Copilot workflows.
The repository itself is the skill. From a target repository root, invoke the runner directly with branch parameters:
bash /path/to/gitlab-code-review/gitlab_agent_review.sh --branch your/feature-branchIf the skill is installed or copied into the target repository root:
bash gitlab_agent_review.sh --branch your/feature-branchBy default, the script uses the Cursor Agent CLI (agent) with --model auto to avoid forcing a higher-cost frontier model for code review. Pass --agent-model only when you want to pin a specific Cursor model.
Install From npm or npx
Run the installer directly with npx:
npx gitlab-code-review@latest install --agent cursor --target .
npx gitlab-code-review@latest install --agent all --target .Or install the CLI globally once:
npm install -g gitlab-code-review
gitlab-code-review install --agent cursor --target .
gitlab-code-review install --agent claude
gitlab-code-review install --agent codex
gitlab-code-review install --agent gemini
gitlab-code-review install --agent copilot --target .
gitlab-code-review install --agent all --target .Or install as a project dev dependency and run through npx:
npm install --save-dev gitlab-code-review
npx gitlab-code-review install --agent cursor --target .For local development from this package checkout:
npm link
gitlab-code-review install --agent cursor --target /path/to/target/projectInstall targets:
| Agent | Install location |
|------|------------------|
| Cursor | <target>/.cursor/skills/gitlab-code-review |
| Claude | ~/.claude/skills/code-review |
| Codex | ${CODEX_HOME:-~/.codex}/skills/code-review |
| Gemini | ~/.gemini/skills/code-review |
| Copilot | <target>/.github/instructions/gitlab-code-review.instructions.md |
Use --dry-run to print planned writes without changing files.
Contents
| File | Role |
|------|------|
| gitlab_agent_review.sh | Updates the base branch, checks out the review branch, builds git diff <base>...HEAD, runs the selected CLI backend, prints the review. |
| code_review_prompt.txt | Static code-review prompt used by gitlab_agent_review.sh; the generated diff is appended at runtime. |
| agent_stream_filter.py | Turns Cursor stream-json output into readable streamed text. |
| reconstruct_assistant_from_ndjson.py | Rebuilds the full assistant reply from raw Cursor NDJSON output for large MRs. |
| gitlab_post_reviews.py | Parses JSON issues from the review and creates GitLab MR inline discussions. |
| gitlab_token.env.example | Template for a local GitLab token file. |
| bin/gitlab-code-review.js | npm installer for agent skill locations. |
Prerequisites
- A Git repository at the repo root when running
gitlab_agent_review.sh. - Cursor Agent CLI:
agentonPATH, authenticated withagent login. - Python 3 for helper scripts.
- Node.js 18+ for the npm installer.
- For GitLab posting: a Personal Access Token with
apiscope, or equivalent project token.
Gradle is not required and is not run by this tool.
Review Only
From the target repository root:
bash /path/to/gitlab-code-review/gitlab_agent_review.sh --branch your/feature-branchOptional base branch, default master:
bash /path/to/gitlab-code-review/gitlab_agent_review.sh --branch your/feature-branch --base origin/masterYou can also pass only the GitLab MR link. The script fetches refs/merge-requests/<iid>/head from origin, checks it out as mr-<iid>, and reviews that branch:
bash /path/to/gitlab-code-review/gitlab_agent_review.sh \
--mr-link 'https://gitlab.com/<namespace>/<project>/-/merge_requests/<iid>'--mr-url is also supported as an alias for --mr-link.
The default backend is Cursor:
bash /path/to/gitlab-code-review/gitlab_agent_review.sh --branch your/feature-branch --llm agentUse another CLI backend when available:
bash /path/to/gitlab-code-review/gitlab_agent_review.sh --branch your/feature-branch --llm geminiGeneric backends are invoked as <tool> -p <review_prompt_path>, so only CLIs with that shape work through --llm other-tool.
Before reviewing, the script checks out the base branch, runs git pull, and updates submodules recursively. It updates submodules recursively again after switching to the review branch or fetched MR branch.
Review From MR Link
After installing the skill in a project, run this from that project root:
bash .cursor/skills/gitlab-code-review/gitlab_agent_review.sh \
--mr-link 'https://gitlab.com/<namespace>/<project>/-/merge_requests/<iid>'What happens:
- Checks out the base branch, pulls latest changes, and updates submodules recursively.
- Fetches the GitLab MR ref from
originand checks it out asmr-<iid>. - Updates submodules recursively again on the MR branch.
- Generates the diff against the base branch.
- Runs Cursor Agent with
--model auto. - Previews parsed review comments.
- Asks whether to post the comments to the MR.
To review without posting comments:
GITLAB_POST_CONFIRM=0 bash .cursor/skills/gitlab-code-review/gitlab_agent_review.sh \
--mr-link 'https://gitlab.com/<namespace>/<project>/-/merge_requests/<iid>'Cursor Model and Streaming
- Default model behavior: Cursor is invoked with
--model auto. - Pin a model with
--agent-modelorAGENT_MODEL. - Cursor runs with
--mode ask --auto-review --trust --workspace <repo-root>. - By default the script streams Cursor
stream-jsonoutput throughagent_stream_filter.py. - Buffered output only:
AGENT_PLAIN_TEXT=1 bash /path/to/gitlab-code-review/gitlab_agent_review.sh --branch your/feature-branchModel override:
bash /path/to/gitlab-code-review/gitlab_agent_review.sh --branch feat/foo --agent-model claude-4.6-sonnet-medium
AGENT_MODEL=claude-4.6-sonnet-medium bash /path/to/gitlab-code-review/gitlab_agent_review.sh --branch feat/fooPost Inline Comments to a GitLab MR
The review prompt asks the model for Markdown issues plus a final fenced json code block containing:
[
{
"file": "app/src/main/java/.../Example.kt",
"line": 42,
"body": "### Example.kt (Line: 42)\n\n**Issue:** ...\n\n..."
}
]Use [] when there are no issues.
Create a local token file next to gitlab_agent_review.sh:
cp /path/to/gitlab-code-review/gitlab_token.env.example /path/to/gitlab-code-review/gitlab_token.envSet:
GITLAB_TOKEN=glpat-your-token-hereRun review and optionally post:
bash /path/to/gitlab-code-review/gitlab_agent_review.sh \
--mr-link 'https://gitlab.com/<namespace>/<project>/-/merge_requests/<iid>'With --mr-link, the script refreshes the base branch, fetches/checks out the MR branch, runs the review, previews parsed comments, and asks before posting parsed inline comments to GitLab. Use GITLAB_POST_CONFIRM=1 to post without a prompt, or GITLAB_POST_CONFIRM=0 to skip posting and keep review_output_capture.txt.
MR posting is implemented for the Cursor backend only.
Manual Post or Dry Run
python3 /path/to/gitlab-code-review/gitlab_post_reviews.py \
--mr-url 'https://gitlab.com/.../merge_requests/123' \
--review-file /path/to/review.txtParse check without calling GitLab:
python3 /path/to/gitlab-code-review/gitlab_post_reviews.py \
--mr-url 'https://gitlab.com/.../merge_requests/123' \
--review-file /path/to/review.txt \
--dry-runEnvironment Variables
| Variable | Purpose |
|----------|---------|
| LLM_TOOL | CLI backend to use, default agent. |
| AGENT_MODEL | Cursor model id, default auto. |
| AGENT_PLAIN_TEXT | Set to 1 for non-streaming Cursor output, ignored with --mr-link unless GITLAB_MR_PLAIN_TEXT=1. |
| GITLAB_MR_PLAIN_TEXT | With --mr-link, force plain text plus tee. |
| GITLAB_MR_FORCE_STREAM | With --mr-link, always use stream-json plus rebuild. |
| REVIEW_AUTO_PLAIN_PROMPT_BYTES | Auto plain-text if prompt exceeds this many bytes, default 350000. |
| REVIEW_AUTO_PLAIN_DIFF_LINES | Auto plain-text if diff line count exceeds this, default 4500. |
| GITLAB_TOKEN / PRIVATE_TOKEN | GitLab API token for posting. |
| GITLAB_POST_CONFIRM | 1 posts without asking, 0 skips posting, unset asks interactively. |
Troubleshooting
- 401 / 403 from GitLab: Token missing, wrong scope, or no access to the project/MR.
- 400 on create discussion: The model picked a line that is not on the MR unified diff. The poster script loads MR changes, snaps to the nearest valid line within
--snap-max, and falls back to a regular MR note if needed. - No JSON parsed: The model must output a valid JSON array in a fenced
jsonblock, or a parseable trailing array. - Empty capture: Re-run with
GITLAB_MR_PLAIN_TEXT=1if stream reconstruction fails. - Re-runs create new threads: Delete old GitLab discussions manually if you need a clean MR.
