Building Custom Commands
Relevant source files
The following files were used as context for generating this wiki page:
Marginalia executes user-defined Claude Code slash commands headless to automate the review and triage of GitLab merge requests (MRs). The bot polls for MR changes, checks out the relevant code in a dedicated worktree, and triggers specific commands defined in the project's .env file, such as REVIEW_COMMAND and TRIAGE_COMMAND. Sources: README.md:1-15, PRODUCT.md:15-22
The Execution Lifecycle
When the poller detects a new commit or a new peer comment, it initiates a headless run. The bot provides specific environment variables like MR_REVIEW_BOT=1 and appends system prompts to guide the command output. Sources: README.md:48-52, README.md:118-125
The diagram shows the sequence from MR detection to the visualization of the report in the local studio. Sources: README.md:48-65
Output Contracts
To ensure the studio displays rich metadata like verdict badges and finding counts, commands must deliver reports in a specific format. The bot looks for results in the following order of preference:
- A file named
.marginalia-report.mdin the worktree root. - A text block in stdout wrapped in
<<<REVIEW_FILE path="...">>>and<<<END_REVIEW_FILE>>>. - The raw final message if it exceeds 200 characters.
Sources: README.md:48-65
Findings Schema (Optional)
While the studio can parse raw Markdown, writing a .marginalia-findings.json file allows for precise anchoring in the diff and stable finding IDs across re-runs. Sources: README.md:67-85, studio/public/openapi.yaml:375-400
| Field | Type | Description |
|---|---|---|
verdict | String | APPROVE or REQUEST_CHANGES. |
summary | String | One or two sentences explaining the overall result. |
findings | Array | List of specific issues found in the code. |
id | String | A stable identifier for the finding (e.g., neg-total). |
severity | String | critical, important, suggestion, or info. |
path | String | Repo-relative file path. |
line | Integer | Line number for anchoring the finding in the diff. |
Sources: README.md:67-75, studio/public/openapi.yaml:405-425
Designing Review Commands
A robust review command assesses risk, verifies correctness without guessing, and produces postable findings. Sources: skills/marginalia-review/SKILL.md:20-60
Risk Assessment Levels
The review command should categorize the MR risk into one of three levels:
- Low: Contained changes, well-covered by tests, non-sensitive areas (e.g., docs).
- Medium: Behavior changes in shared code or meaningful logic with thin tests.
- High: Changes to auth, payments, data migrations, or public contracts.
Sources: skills/marginalia-review/SKILL.md:22-30
Finding Severities
Findings should follow a standardized severity scale to help the reader prioritize fixes. Sources: skills/marginalia-review/SKILL.md:55-70
Citations for severities and their impact on the merge process. Sources: skills/marginalia-review/SKILL.md:58-68
Designing Triage Commands
The triage command handles reviewer comments on MRs authored by the user. It fetches unresolved threads and decides if they are RELEVANT, NOT RELEVANT, or WRONG. Sources: examples/commands/triage.md:1-5
Triage Logic Flow
- Fetch Discussions: Retrieve unresolved GitLab threads for the MR.
- Evaluate: Compare comments against the ticket requirements and the code diff.
- Action:
- If RELEVANT: Apply fixes directly in the worktree and commit locally to the
marginalia/<branch-slug>branch. - If OTHER: Draft a short reply for the user to review.
- If RELEVANT: Apply fixes directly in the worktree and commit locally to the
- Report: Deliver a summary of verdicts and rationales.
Sources: examples/commands/triage.md:1-10, README.md:139-155
Formatting the Markdown Report
The studio parses Markdown reports using specific heading and syntax patterns if a JSON findings file is not provided. Sources: README.md:78-85, studio/src/lib/reviewSections.ts:8-20
- Verdicts: Identified by a
**Verdict:**line. - Sections: Use
## Critical,## Important, and## Suggestions. - Findings: Each bullet point under a severity heading represents one finding.
- Comments: Blockquotes under a finding bullet are treated as the "comment to post" on GitLab.
- Anchoring: The first
path:linestring in a bullet anchors the comment in the studio's diff view.
Sources: README.md:78-85, studio/src/lib/reviewSections.ts:35-50
Standard Section Ranking
The studio organizes sections by importance, regardless of their order in the Markdown file:
- Summary / At a Glance
- Shape of the Change
- Critical Findings
- Important Findings
- Suggestions
- Out of Scope / Supporting Material
Sources: studio/src/lib/reviewSections.ts:8-18
Summary of Guidelines
Custom commands must operate within the bot's sandbox constraints. Bash tools can write to the worktree and the reviews directory, but network access is restricted to the GitLab host. Commands should never attempt to push or post to GitLab directly; they must only generate the report for the user to review in the studio. Sources: README.md:237-255, PRODUCT.md:25-30