gerrit-review

SKILL.md

Gerrit Code Review Skill

This skill enables you to interact with a Gerrit Code Review instance through its REST API. Use it to query open changes, read diffs, post code reviews, and manage change lifecycle (submit, abandon, restore).

Prerequisites

Environment Variables

You must have the following environment variables set:

Variable Description Example
GERRIT_URL Base URL of the Gerrit instance (no trailing slash) https://gerrit.example.com
GERRIT_USERNAME HTTP username from Gerrit → Settings → Profile john.doe
GERRIT_HTTP_PASSWORD HTTP credential token from Gerrit → Settings → HTTP Credentials → Generate Password a1b2c3d4e5...

[!IMPORTANT] The HTTP password is NOT the user's login password. It is a separate token generated in the Gerrit web UI under Settings → HTTP Credentials → Generate Password.

Tools

  • curl — used for all REST API calls
  • jq — used for JSON parsing and pretty-printing
  • base64 — used for decoding file content responses

Quick Start

Use the helper script at scripts/gerrit_api.sh (located relative to this SKILL.md) for common operations:

# Make the script executable (one-time)
chmod +x scripts/gerrit_api.sh

# Query open changes
./scripts/gerrit_api.sh query "status:open+limit:5"

# Get change details
./scripts/gerrit_api.sh get-change 12345

# List files changed in a revision
./scripts/gerrit_api.sh list-files 12345

# Get a file diff
./scripts/gerrit_api.sh get-diff 12345 "src/main/App.java"

# Get raw file content
./scripts/gerrit_api.sh get-content 12345 "src/main/App.java"

# Post a review with a Code-Review +1 label
./scripts/gerrit_api.sh review 12345 current '{"message":"Looks good!","labels":{"Code-Review":1}}'

# Submit a change
./scripts/gerrit_api.sh submit 12345

# Abandon a change
./scripts/gerrit_api.sh abandon 12345

Gerrit Concepts

Changes and Patch Sets

  • A change is a single reviewable unit (corresponds to one commit).
  • Each update to a change creates a new patch set (a new commit with the same Change-Id).
  • Changes live under refs/changes/ refs in the Git repo.

Change-Id

  • A footer line in the commit message (Change-Id: I<hex>) that links commits to Gerrit changes.
  • The commit-msg hook (installed from Gerrit) auto-generates this.

Labels

  • Code-Review: Typically −2 to +2. +2 means approved.
  • Verified: Typically −1 to +1. Usually set by CI.
  • Label ranges and names are project-specific.

Workflow

  1. Push to refs/for/<branch> to create/update a change for review.
  2. Reviewers add comments and vote via labels.
  3. Amend the commit (git commit --amend) and re-push for new patch sets.
  4. Once approvals are met, a committer submits the change.

REST API Reference

Authentication

All authenticated requests use the /a/ prefix and HTTP Basic Auth:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  "$GERRIT_URL/a/changes/?q=status:open+limit:5"

Output Format

Gerrit JSON responses start with an XSSI prevention prefix )]}' on the first line. You must strip it before parsing:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  "$GERRIT_URL/a/changes/?q=status:open" | tail -n +2 | jq .

URL Encoding

Project names, file paths, and branch names in URLs must be URL-encoded. Forward slashes in project/file paths become %2F:

myOrg/myProject  →  myOrg%2FmyProject
src/main/App.java  →  src%2Fmain%2FApp.java

Key Endpoints

1. Query Changes

GET /a/changes/?q=<query>&n=<limit>&o=<option>

Common query operators:

  • status:open / status:merged / status:abandoned
  • owner:self / reviewer:self
  • project:<name> / branch:<name>
  • is:watched / is:starred
  • after:"2025-01-01" / before:"2025-12-31"

Common o (option) parameters to include extra data:

  • CURRENT_REVISION — include current revision info
  • DETAILED_LABELS — include detailed label/vote info
  • DETAILED_ACCOUNTS — include full account info
  • CURRENT_FILES — include file list for current revision
  • MESSAGES — include change messages

Example:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  "$GERRIT_URL/a/changes/?q=status:open+owner:self&n=10&o=CURRENT_REVISION&o=DETAILED_LABELS" \
  | tail -n +2 | jq .

2. Get Change Details

GET /a/changes/<change-id>?o=CURRENT_REVISION&o=DETAILED_LABELS

The <change-id> can be:

  • A numeric change number: 12345
  • The full triplet: project~branch~Change-Id
  • Just the Change-Id: I8473b95934b5732ac55d26311a706c9c2bde9940

Example:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  "$GERRIT_URL/a/changes/12345?o=CURRENT_REVISION&o=DETAILED_LABELS&o=DETAILED_ACCOUNTS" \
  | tail -n +2 | jq .

3. List Files in a Revision

GET /a/changes/<change-id>/revisions/<revision-id>/files/

Use current as <revision-id> for the latest patch set.

Example:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  "$GERRIT_URL/a/changes/12345/revisions/current/files/" \
  | tail -n +2 | jq .

Response is a map of file paths to FileInfo objects:

{
  "/COMMIT_MSG": { "status": "A", "lines_inserted": 7, "size_delta": 551, "size": 551 },
  "src/main/App.java": { "lines_inserted": 5, "lines_deleted": 3, "size_delta": 98, "size": 23348 }
}

4. Get File Diff

GET /a/changes/<change-id>/revisions/<revision-id>/files/<file-id>/diff

The <file-id> must be URL-encoded. Add ?intraline for intraline differences.

Example:

FILE_PATH="src%2Fmain%2FApp.java"
curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  "$GERRIT_URL/a/changes/12345/revisions/current/files/$FILE_PATH/diff" \
  | tail -n +2 | jq .

Response is a DiffInfo entity with content array containing ab (common), a (deleted), and b (added) line arrays.

5. Get File Content

GET /a/changes/<change-id>/revisions/<revision-id>/files/<file-id>/content

Returns base64-encoded file content.

Example:

FILE_PATH="src%2Fmain%2FApp.java"
curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  "$GERRIT_URL/a/changes/12345/revisions/current/files/$FILE_PATH/content" \
  | base64 -d

6. Post a Review (Set Labels, Comments)

POST /a/changes/<change-id>/revisions/<revision-id>/review
Content-Type: application/json

ReviewInput JSON body:

{
  "message": "Overall review comment shown at the top",
  "labels": {
    "Code-Review": 1
  },
  "comments": {
    "src/main/App.java": [
      {
        "line": 23,
        "message": "Consider renaming this variable for clarity."
      },
      {
        "range": {
          "start_line": 50,
          "start_character": 0,
          "end_line": 55,
          "end_character": 20
        },
        "message": "This block should be refactored."
      }
    ]
  }
}

Label values (project-specific, typical):

  • Code-Review: -2 (reject), -1 (looks wrong), 0 (no score), +1 (looks good), +2 (approved)
  • Verified: -1 (fails), 0 (no score), +1 (verified)

Example:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"message":"Looks good to me!","labels":{"Code-Review":1}}' \
  "$GERRIT_URL/a/changes/12345/revisions/current/review" \
  | tail -n +2 | jq .

7. Submit a Change

POST /a/changes/<change-id>/submit

Example:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{}' \
  "$GERRIT_URL/a/changes/12345/submit" \
  | tail -n +2 | jq .

8. Abandon / Restore a Change

POST /a/changes/<change-id>/abandon
POST /a/changes/<change-id>/restore

Both accept an optional JSON body with a message field:

# Abandon
curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"message":"Superseded by change 12346"}' \
  "$GERRIT_URL/a/changes/12345/abandon" \
  | tail -n +2 | jq .

# Restore
curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"message":"Re-opening for further review"}' \
  "$GERRIT_URL/a/changes/12345/restore" \
  | tail -n +2 | jq .

9. Add Reviewer

POST /a/changes/<change-id>/reviewers
Content-Type: application/json
{
  "reviewer": "jane.roe@example.com"
}

To add as CC instead of reviewer, add "state": "CC".

Example:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"reviewer":"jane.roe@example.com"}' \
  "$GERRIT_URL/a/changes/12345/reviewers" \
  | tail -n +2 | jq .

10. Set Topic

PUT /a/changes/<change-id>/topic
Content-Type: application/json
{
  "topic": "my-feature-branch"
}

Example:

curl -s --user "$GERRIT_USERNAME:$GERRIT_HTTP_PASSWORD" \
  -X PUT \
  -H "Content-Type: application/json" \
  -d '{"topic":"my-feature-branch"}' \
  "$GERRIT_URL/a/changes/12345/topic" \
  | tail -n +2 | jq .

Code Review Workflow

Here is a recommended workflow for performing a code review with this skill:

Step 1 — Find changes to review

./scripts/gerrit_api.sh query "status:open+reviewer:self+-owner:self"

Step 2 — Inspect a change

# Get change details with labels and current revision
./scripts/gerrit_api.sh get-change 12345

# List modified files
./scripts/gerrit_api.sh list-files 12345

# Read the diff for each relevant file
./scripts/gerrit_api.sh get-diff 12345 "path/to/file.java"

Step 3 — Post your review

./scripts/gerrit_api.sh review 12345 current '{
  "message": "Overall the approach looks solid. A few suggestions below.",
  "labels": {"Code-Review": 1},
  "comments": {
    "path/to/file.java": [
      {"line": 42, "message": "Consider using a constant here instead of a magic number."}
    ]
  }
}'

The comments field in the JSON body follows the CommentInput entity schema. Additional supported fields include:

  • notify (string) — notification level for email notifications (ALL, OWNER, NONE, etc, suggest using OWNER to avoid spamming everyone)
  • notify_details (object) — fine-grained notification control per account
  • in_reply_to (string) — optional, the URL encoded UUID of the comment to which this comment is a reply.
  • unresolved (boolean) — optional, whether the comment thread should be marked as unresolved. Suggested to set to true for new comments that represent CRITICAL, Bug, or Security issues so they remain open and must be addressed before merging. Use false for purely informational comments or when the issue has already been addressed. The thread can be resolved later by the reviewer or the author when the issue is fixed.
  • fix_suggestions (array) — optional, list of suggested fixes for this comment. Each suggestion includes a description and a replacement patch.

Step 4 — Submit when ready

./scripts/gerrit_api.sh submit 12345

Troubleshooting

Problem Solution
401 Unauthorized Check GERRIT_USERNAME and GERRIT_HTTP_PASSWORD. Re-generate the HTTP password in Gerrit Settings.
404 Not Found Verify the change number exists. Check GERRIT_URL has no trailing slash. Ensure the /a/ prefix is present.
409 Conflict You may be trying to review a change edit, or submit a change that doesn't meet requirements.
JSON parse error Make sure you strip the XSSI prefix )]}'\n from the response before parsing.
URL encoding issues Project paths with / must use %2F. Use the helper script which handles this automatically.

Awareness

  • This skill is designed for interactive use and may not handle all edge cases of the Gerrit API. For complex operations, refer to the official API documentation.
  • GERRIT_URL and GERRIT_USERNAME can be used in the output printed by the skill, but do not print GERRIT_HTTP_PASSWORD or any sensitive information in logs or outputs.
  • Ensure that the HTTP credential token (GERRIT_HTTP_PASSWORD) is kept secure and not exposed in logs, environment dumps, or error messages. It should only be used for authentication in API calls and never printed or logged in plaintext.

References

Weekly Installs
7
GitHub Stars
4
First Seen
11 days ago
Installed on
antigravity6
kiro-cli6
opencode5
github-copilot5
gemini-cli4
codex4