gitlab

$npx mdskill add vm0-ai/vm0-skills/gitlab

Execute GitLab API calls for repo management and CI/CD automation.

  • Retrieves project data, manages repositories, and runs CI/CD pipelines.
  • Depends on GitLab API v4 and requires valid authentication tokens.
  • Processes project IDs or paths to fetch specific repository details.
  • Returns structured JSON responses containing project metadata and status.

SKILL.md

.github/skills/gitlabView on GitHub ↗
---
name: gitlab
description: GitLab API for repos and CI/CD. Use when user mentions "GitLab", "gitlab.com",
  shares a GitLab link, "GitLab repo", or asks about GitLab projects.
---

## Troubleshooting

If requests fail, run `zero doctor check-connector --env-name GITLAB_TOKEN` or `zero doctor check-connector --url https://gitlab.com/api/v4/user --method GET`

## How to Use

All examples below assume `GITLAB_HOST` and `GITLAB_TOKEN` are set.

Base URL: `https://${GITLAB_HOST}/api/v4`

> Note: Project IDs can be numeric (e.g., `123`) or URL-encoded paths (e.g., `mygroup%2Fmyproject`).

### 1. Get Current User

Verify your authentication:

```bash
curl -s "https://$GITLAB_HOST/api/v4/user" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '{id, username, name, email, state}'
```

### 2. List Projects

Get projects accessible to you:

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects?membership=true&per_page=20" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '.[] | {id, path_with_namespace, visibility, default_branch}'
```

Filter options:
- `membership=true` - Only projects you're a member of
- `owned=true` - Only projects you own
- `search=keyword` - Search by name
- `visibility=public|internal|private` - Filter by visibility

### 3. Get Project Details

Get details for a specific project. Replace `<project-id>` with the numeric project ID or URL-encoded path (e.g., `mygroup%2Fmyproject`):

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects/<project-id>" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '{id, name, path_with_namespace, default_branch, visibility, web_url}
```

### 4. List Project Issues

Get issues for a project. Replace `<project-id>` with the numeric project ID or URL-encoded path:

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects/<project-id>/issues?state=opened&per_page=20" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '.[] | {iid, title, state, author: .author.username, labels, web_url}'
```

Filter options:
- `state=opened|closed|all` - Filter by state
- `labels=bug,urgent` - Filter by labels
- `assignee_id=123` - Filter by assignee
- `search=keyword` - Search in title/description

### 5. Get Issue Details

Get a specific issue. Replace `<project-id>` and `<issue-iid>` with actual values:

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects/<project-id>/issues/<issue-iid>" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '{iid, title, description, state, author: .author.username, assignees: [.assignees[].username], labels, created_at, web_url}'
```

### 6. Create Issue

Create a new issue in a project. Replace `<project-id>` with the actual project ID:

Write to `/tmp/gitlab_request.json`:

```json
{
  "title": "Bug: Login page not loading",
  "description": "The login page shows a blank screen on mobile devices.",
  "labels": "bug,frontend"
}
```

Then run:

```bash
curl -s -X POST "https://$GITLAB_HOST/api/v4/projects/<project-id>/issues" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" -d @/tmp/gitlab_request.json | jq '{iid, title, web_url}'
```

### 7. Create Issue with Assignee and Milestone

Create issue with additional fields. Replace `<project-id>`, `<assignee-id>`, and `<milestone-id>` with actual IDs:

Write to `/tmp/gitlab_request.json`:

```json
{
  "title": "Implement user profile page",
  "description": "Create a user profile page with avatar and bio.",
  "assignee_ids": [<assignee-id>],
  "milestone_id": <milestone-id>,
  "labels": "feature,frontend"
}
```

Then run:

```bash
curl -s -X POST "https://$GITLAB_HOST/api/v4/projects/<project-id>/issues" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" -d @/tmp/gitlab_request.json | jq '{iid, title, web_url}'
```

### 8. Update Issue

Update an existing issue. Replace `<project-id>` and `<issue-iid>` with actual values:

Write to `/tmp/gitlab_request.json`:

```json
{
  "title": "Updated: Bug fix for login page",
  "labels": "bug,frontend,in-progress"
}
```

Then run:

```bash
curl -s -X PUT "https://$GITLAB_HOST/api/v4/projects/<project-id>/issues/<issue-iid>" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" -d @/tmp/gitlab_request.json | jq '{iid, title, labels, updated_at}'
```

### 9. Close Issue

Close an issue. Replace `<project-id>` and `<issue-iid>` with actual values:

Write to `/tmp/gitlab_request.json`:

```json
{
  "state_event": "close"
}
```

Then run:

```bash
curl -s -X PUT "https://$GITLAB_HOST/api/v4/projects/<project-id>/issues/<issue-iid>" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" -d @/tmp/gitlab_request.json | jq '{iid, title, state}'
```

Use `"state_event": "reopen"` to reopen a closed issue.

### 10. Add Comment to Issue

Add a note/comment to an issue. Replace `<project-id>` and `<issue-iid>` with actual values:

Write to `/tmp/gitlab_request.json`:

```json
{
  "body": "Investigating this issue. Will update soon."
}
```

Then run:

```bash
curl -s -X POST "https://$GITLAB_HOST/api/v4/projects/<project-id>/issues/<issue-iid>/notes" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" -d @/tmp/gitlab_request.json | jq '{id, body, author: .author.username, created_at}'
```

### 11. List Merge Requests

Get merge requests for a project. Replace `<project-id>` with the actual project ID:

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects/<project-id>/merge_requests?state=opened&per_page=20" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '.[] | {iid, title, state, source_branch, target_branch, author: .author.username, web_url}'
```

Filter options:
- `state=opened|closed|merged|all` - Filter by state
- `scope=created_by_me|assigned_to_me|all` - Filter by involvement
- `labels=review-needed` - Filter by labels

### 12. Get Merge Request Details

Get a specific merge request. Replace `<project-id>` and `<mr-iid>` with actual values:

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects/<project-id>/merge_requests/<mr-iid>" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '{iid, title, state, source_branch, target_branch, author: .author.username, merge_status, has_conflicts, web_url}'
```

### 13. Create Merge Request

Create a new merge request. Replace `<project-id>` with the actual project ID:

Write to `/tmp/gitlab_request.json`:

```json
{
  "source_branch": "feature/user-profile",
  "target_branch": "main",
  "title": "Add user profile page",
  "description": "This MR adds a new user profile page with avatar support."
}
```

Then run:

```bash
curl -s -X POST "https://$GITLAB_HOST/api/v4/projects/<project-id>/merge_requests" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" -d @/tmp/gitlab_request.json | jq '{iid, title, web_url}'
```

### 14. Merge a Merge Request

Merge an MR (if it's ready). Replace `<project-id>` and `<mr-iid>` with actual values:

Write to `/tmp/gitlab_request.json`:

```json
{
  "merge_when_pipeline_succeeds": true
}
```

Then run:

```bash
curl -s -X PUT "https://$GITLAB_HOST/api/v4/projects/<project-id>/merge_requests/<mr-iid>/merge" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" -d @/tmp/gitlab_request.json | jq '{iid, title, state, merged_by: .merged_by.username}'
```

Options:
- `merge_when_pipeline_succeeds=true` - Auto-merge when pipeline passes
- `squash=true` - Squash commits before merging
- `should_remove_source_branch=true` - Delete source branch after merge

### 15. List Pipelines

Get pipelines for a project. Replace `<project-id>` with the actual project ID:

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects/<project-id>/pipelines?per_page=10" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '.[] | {id, status, ref, sha: .sha[0:8], created_at, web_url}'
```

### 16. Get Pipeline Details

Get details of a specific pipeline. Replace `<project-id>` and `<pipeline-id>` with actual values:

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects/<project-id>/pipelines/<pipeline-id>" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '{id, status, ref, duration, finished_at, web_url}'
```

### 17. List Pipeline Jobs

Get jobs in a pipeline. Replace `<project-id>` and `<pipeline-id>` with actual values:

```bash
curl -s "https://$GITLAB_HOST/api/v4/projects/<project-id>/pipelines/<pipeline-id>/jobs" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" | jq '.[] | {id, name, stage, status, duration}'
```

### 18. Search Users

Search for users:

Write to `/tmp/gitlab_search.txt`:

```
john
```

```bash
curl -s -G "https://$GITLAB_HOST/api/v4/users" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --data-urlencode "search@/tmp/gitlab_search.txt" | jq '.[] | {id, username, name, state}'
```

### 19. Create Project

Create a new project:

Write to `/tmp/gitlab_request.json`:

```json
{
  "name": "my-new-project",
  "visibility": "private",
  "initialize_with_readme": true
}
```

Then run:

```bash
curl -s -X POST "https://$GITLAB_HOST/api/v4/projects" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header "Content-Type: application/json" -d @/tmp/gitlab_request.json | jq '{id, path_with_namespace, web_url}'
```

### 20. Delete Issue

Delete an issue (requires admin or owner permissions). Replace `<project-id>` and `<issue-iid>` with actual values:

```bash
curl -s -X DELETE "https://$GITLAB_HOST/api/v4/projects/<project-id>/issues/<issue-iid>" --header "PRIVATE-TOKEN: $GITLAB_TOKEN" -w "\nHTTP Status: %{http_code}"
```

Returns 204 No Content on success.

## Project ID Encoding

When using project paths instead of numeric IDs, URL-encode the path:

- `mygroup/myproject` → `mygroup%2Fmyproject`
- `mygroup/subgroup/myproject` → `mygroup%2Fsubgroup%2Fmyproject`

```bash
# Using numeric ID
PROJECT_ID="123"

# Using encoded path
PROJECT_ID="mygroup%2Fmyproject"
```

## Guidelines

1. **Use IID for issues/MRs**: Within a project, use `iid` (internal ID like #1, #2) not the global `id`
2. **URL-encode project paths**: If using paths instead of numeric IDs, encode slashes as `%2F`
3. **Handle pagination**: Use `per_page` and `page` params for large result sets
4. **Check merge status**: Before merging, verify `merge_status` is `can_be_merged`
5. **Rate limiting**: Implement backoff if you receive 429 responses
6. **Self-hosted GitLab**: Set `GITLAB_HOST` to your instance domain (without https://)

More from vm0-ai/vm0-skills

SkillDescription
account-reconciliationPerform account reconciliations comparing general ledger balances against subledgers, bank statements, or external records. Use for bank reconciliation, GL-to-subledger reconciliation, intercompany reconciliation, balance sheet reconciliation, reconciling item analysis, outstanding item aging, or clearing open items.
agentphoneBuild AI phone agents with AgentPhone API. Use when the user wants to make phone calls, send/receive SMS, manage phone numbers, create voice agents, set up webhooks, or check usage — anything related to telephony, phone numbers, or voice AI.
ahrefsAhrefs SEO API for backlink and keyword analysis. Use when user mentions
amplitudeAmplitude product analytics API. Use when user mentions "Amplitude",
analysis-qaQuality-check a data analysis before sharing — verify joins, aggregations, denominators, time ranges, and metric definitions. Detect pitfalls like survivorship bias, average-of-averages, join explosion, timezone mismatches, incomplete periods, and selection bias. Includes documentation templates for reproducible analyses.
anthropic-managed-agentsAnthropic Managed Agents API for programmatically creating, running, and streaming AI agents on Anthropic's cloud infrastructure. Use when the user mentions "Managed Agents", "Anthropic agent sessions", or needs to create/run/stream an Anthropic agent with tool use (bash, git, web), attach GitHub repositories, or inject secrets via Vault. Do NOT use for standard Claude Messages API — use the Claude API skill instead.
apifyApify web scraping platform. Use when user mentions "scrape website",
asanaAsana API for tasks and projects. Use when user mentions "Asana", "asana.com",
atlassianAtlassian API for Confluence and Jira. Use when user mentions "Confluence
attioAttio REST API for AI-native CRM operations — manage companies, people, deals, and custom objects, plus notes, tasks, lists, and comments. Use when the user mentions "Attio", "CRM record", "create company", "add person", "list entry", "CRM note", or "CRM task".