GitLab Skill
Goal: Eliminate glab CLI errors by design. Scripts handle all quirks internally.
Scripts location: ~/.claude/skills/gitlab/scripts/
Quick Reference
| Script | Purpose | Output |
|---|---|---|
gitlab-mr-create | Create MR | {url, id, project} |
gitlab-mr-update | Update MR | {id, project, updated_fields} |
gitlab-mr-view | Get MR details | Full MR object |
gitlab-mr-close | Close MR | {id, project, status} |
gitlab-mr-branch | Get source branch | "branch-name" |
gitlab-mr-discussions | Get comments/threads | [{discussion}, ...] |
gitlab-mr-discussion-create | Start new thread | {discussion_id, note_id, ...} |
gitlab-mr-discussion-reply | Reply to thread | {note_id, discussion_id, ...} |
gitlab-pipeline-from-mr | Get pipeline ID | 123456 or null |
gitlab-pipeline-jobs | List pipeline jobs | [{id, name, status}, ...] |
gitlab-job-trace | Get job logs | Plain text |
MR Operations
gitlab-mr-create
Create a new merge request.
gitlab-mr-create <org/project> <title> [options]
Options:
| Option | Description | Default |
|---|---|---|
--description <text> | MR description (markdown supported) | none |
--description-file <path> | Read description from file | none |
--target <branch> | Target branch | main |
--source <branch> | Source branch | current branch |
--draft | Create as draft | false |
--labels <l1,l2> | Comma-separated labels | none |
--push | Push branch before creating | false |
Output:
{"url": "https://gitlab.com/.../merge_requests/123", "id": 123, "project": "org/project"}
Example:
gitlab-mr-create publicala/farfalla "Fix: login bug" --description "Fixes #42" --draft
gitlab-mr-update
Update an existing merge request.
gitlab-mr-update <org/project> <mr-id> [options]
Options:
| Option | Description |
|---|---|
--title <text> | New title |
--description <text> | New description |
--description-file <path> | Read description from file |
--draft | Mark as draft |
--ready | Mark as ready (remove draft) |
--labels <l1,l2> | Set labels |
--target <branch> | Change target branch |
Output:
{"id": 123, "project": "org/project", "updated": ["title", "draft"]}
gitlab-mr-view
Get full MR details.
gitlab-mr-view <org/project> <mr-id>
Output:
{
"id": 123,
"title": "Fix: login bug",
"description": "Fixes #42",
"state": "opened",
"draft": false,
"source_branch": "fix/login",
"target_branch": "main",
"author": "username",
"url": "https://gitlab.com/.../merge_requests/123",
"pipeline_status": "success",
"pipeline_id": 456789,
"labels": ["bug", "priority::high"],
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T12:00:00Z"
}
gitlab-mr-close
Close a merge request.
gitlab-mr-close <org/project> <mr-id>
Output:
{"id": 123, "project": "org/project", "status": "closed"}
gitlab-mr-branch
Get the source branch name from an MR.
gitlab-mr-branch <org/project> <mr-id>
Output:
"fix/login-bug"
gitlab-mr-discussions
Get MR discussions (comments and threads). Excludes system notes.
gitlab-mr-discussions <org/project> <mr-id> [filter]
Filters:
| Filter | Description | Default |
|---|---|---|
open | Unresolved discussions only | Yes |
resolved | Resolved discussions only | |
all | All discussions |
Output: Array of GitLab discussion objects:
[
{
"id": "abc123",
"individual_note": false,
"notes": [
{
"body": "Please fix this",
"author": {"username": "reviewer"},
"created_at": "...",
"resolved": false,
"position": {"new_path": "src/file.js", "new_line": 42}
},
{"body": "Fixed!", "author": {"username": "developer"}, ...}
]
}
]
gitlab-mr-discussion-create
Start a new discussion thread on an MR. Supports both general comments and inline (diff) comments.
gitlab-mr-discussion-create <org/project> <mr-id> --body <text> [options]
Options:
| Option | Description |
|---|---|
--body <text> | Comment content (required) |
--body-file <path> | Read content from file |
--file <path> | File path for inline comment |
--line <n> | Line number in new version (added/modified lines) |
--old-line <n> | Line number in old version (removed lines) |
Output:
{
"discussion_id": "abc123...",
"note_id": 12345,
"author": "username",
"created_at": "2025-01-15T10:00:00Z"
}
Examples:
# General comment
gitlab-mr-discussion-create publicala/pla-cli 42 --body "Looks good!"
# Inline comment on added line
gitlab-mr-discussion-create publicala/pla-cli 42 --body "Fix this" --file src/foo.js --line 10
# Inline comment on removed line
gitlab-mr-discussion-create publicala/pla-cli 42 --body "Why removed?" --file src/foo.js --old-line 5
gitlab-mr-discussion-reply
Reply to an existing discussion thread.
gitlab-mr-discussion-reply <org/project> <mr-id> <discussion-id> --body <text>
Options:
| Option | Description |
|---|---|
--body <text> | Reply content (markdown supported) |
--body-file <path> | Read reply content from file |
Output:
{
"note_id": 12345,
"discussion_id": 123,
"author": "username",
"created_at": "2025-01-15T10:00:00Z"
}
Example:
# Get discussion ID from gitlab-mr-discussions
gitlab-mr-discussions publicala/pla-cli 42 | jq '.[0].id'
# Reply to that discussion
gitlab-mr-discussion-reply publicala/pla-cli 42 "abc123def..." --body "Fixed in latest commit"
Pipeline Operations
gitlab-pipeline-from-mr
Get the head pipeline ID from an MR.
gitlab-pipeline-from-mr <org/project> <mr-id>
Output:
- Pipeline ID as number:
2185720401 - Or
nullif no pipeline
gitlab-pipeline-jobs
List jobs in a pipeline.
gitlab-pipeline-jobs <org/project> <pipeline-id> [filter]
Filters:
| Filter | Description | Default |
|---|---|---|
all | All jobs (including skipped, pending) | Yes |
failed | Only failed jobs | |
executed | Jobs that ran (success, failed, canceled) |
Output:
[
{"id": 123, "name": "test:unit", "status": "success"},
{"id": 124, "name": "test:e2e", "status": "failed"},
{"id": 125, "name": "deploy", "status": "skipped"}
]
gitlab-job-trace
Get job log output.
gitlab-job-trace <org/project> <job-id>
Output: Plain text (raw CI log with ANSI codes)
Error Handling
All scripts return JSON errors to stderr with exit code 1:
{"error": "Invalid project format. Use: org/project"}
{"error": "MR ID must be a number"}
{"error": "File not found: /path/to/file"}
{"error": "404 Not found"}
What Scripts Handle Internally
- URL encoding:
org/project→org%2Fproject - Correct flags:
--descriptionnot--body,--yeswhere needed - Input validation: Project format, numeric IDs, file existence
- System note filtering: Discussions exclude "marked as draft" etc.
- Consistent JSON: All operations return parseable output
Reference
- reference.md - Raw API examples and pitfall documentation
- pipelines-guide.md - GitLab CI/CD best practices (rules, cache, artifacts)