GitLab Commands
Overview
The netapi gitlab commands provide CLI access to GitLab’s REST API. All commands support -f json for jq piping.
Prerequisites
# Set GitLab token (personal access token)
export GITLAB_TOKEN="glpat-..."
# Optional: Custom GitLab instance (defaults to gitlab.com)
export GITLAB_URL="https://gitlab.example.com"
Create token at: gitlab.com/-/user_settings/personal_access_tokens
Commands (23 total)
| Command | Description |
|---|---|
|
Get user info |
|
Search users |
|
List user projects |
|
Get project details |
|
Search projects |
|
List branches |
|
List commits |
|
List tags |
|
List releases |
|
Get language breakdown |
|
List issues |
|
Get issue details |
|
List merge requests |
|
Get MR details |
|
List MR files |
|
List groups |
|
Get group details |
|
List group projects |
|
List group members |
|
List pipelines |
|
Get pipeline details |
|
List pipeline jobs |
|
Raw API request |
JSON Output
All commands support -f json:
netapi gitlab projects -f json
netapi gitlab project namespace/project -f json
netapi gitlab mrs namespace/project -f json
jq Patterns
Exploring Structure
# See all keys in first object
netapi gitlab projects -f json | jq '.[0] | keys'
# Keys with types
netapi gitlab projects -f json | jq '.[0] | to_entries | .[] | "\(.key): \(.value | type)"'
# Full first object
netapi gitlab projects -f json | jq '.[0]'
Project Operations
# List all project names
netapi gitlab projects -f json | jq -r '.[].path_with_namespace'
# Filter by visibility
netapi gitlab projects -f json | jq -r '.[] | select(.visibility == "private") | .path_with_namespace'
# Get specific fields
netapi gitlab projects -f json | jq '.[] | {name: .path_with_namespace, stars: .star_count, visibility}'
# Sort by activity
netapi gitlab projects -f json | jq 'sort_by(.last_activity_at) | reverse | .[] | "\(.path_with_namespace): \(.last_activity_at[0:10])"'
# Projects with CI enabled
netapi gitlab projects -f json | jq '.[] | select(.jobs_enabled) | .path_with_namespace'
Single Project
# Full project details
netapi gitlab project mygroup/myproject -f json | jq '.'
# Summary object
netapi gitlab project mygroup/myproject -f json | jq '{
name: .path_with_namespace,
visibility,
stars: .star_count,
forks: .forks_count,
issues: .open_issues_count,
default_branch,
created: .created_at[0:10],
updated: .last_activity_at[0:10],
web_url
}'
# Clone URLs
netapi gitlab project mygroup/myproject -f json | jq '{http: .http_url_to_repo, ssh: .ssh_url_to_repo}'
Language Breakdown
# Languages with percentages
netapi gitlab languages mygroup/myproject -f json | jq 'to_entries | sort_by(-.value) | .[] | "\(.key): \(.value)%"'
Commits
# Recent commits - short format
netapi gitlab commits mygroup/myproject -l 10 -f json | jq -r '.[] | "\(.short_id) \(.author_name): \(.title)"'
# Commits by author
netapi gitlab commits mygroup/myproject -f json | jq -r '.[].author_name' | sort | uniq -c | sort -rn
# Commits with date
netapi gitlab commits mygroup/myproject -f json | jq '.[] | {
sha: .short_id,
author: .author_name,
date: .created_at[0:10],
message: .title
}'
Merge Requests
# Open MRs - titles only
netapi gitlab mrs mygroup/myproject -f json | jq -r '.[] | "!\(.iid): \(.title)"'
# MRs with stats
netapi gitlab mrs mygroup/myproject -f json | jq '.[] | {
iid,
title,
author: .author.username,
source: .source_branch,
target: .target_branch,
created: .created_at[0:10],
state
}'
# Get specific MR
netapi gitlab mr mygroup/myproject 42 -f json | jq '{
title,
state,
author: .author.username,
source_branch,
target_branch,
web_url
}'
# MR changes (files)
netapi gitlab mr-changes mygroup/myproject 42 -f json | jq '.changes[] | {
file: .new_path,
new: .new_file,
deleted: .deleted_file,
renamed: .renamed_file
}'
# Merged MRs
netapi gitlab mrs mygroup/myproject -s merged -f json | jq '.[] | {iid, title, merged: .merged_at[0:10]}'
Issues
# Open issues - titles
netapi gitlab issues mygroup/myproject -f json | jq -r '.[] | "#\(.iid): \(.title)"'
# Issues with labels
netapi gitlab issues mygroup/myproject -f json | jq '.[] | {
iid,
title,
author: .author.username,
labels
}'
# Filter by label
netapi gitlab issues mygroup/myproject -f json | jq '.[] | select(.labels | index("bug"))'
# Issues by state
netapi gitlab issues mygroup/myproject -s closed -f json | jq '.[] | {iid, title, closed: .closed_at[0:10]}'
Pipelines
# Recent pipelines
netapi gitlab pipelines mygroup/myproject -f json | jq '.[] | {id, status, ref, created: .created_at[0:10]}'
# Failed pipelines
netapi gitlab pipelines mygroup/myproject -f json | jq '.[] | select(.status == "failed") | {id, ref}'
# Pipeline details
netapi gitlab pipeline mygroup/myproject 12345 -f json | jq '{id, status, ref, sha: .sha[0:8], web_url}'
# Pipeline jobs
netapi gitlab pipeline-jobs mygroup/myproject 12345 -f json | jq '.[] | {
name,
stage,
status,
duration: (if .duration then "\(.duration | floor)s" else null end)
}'
# Failed jobs only
netapi gitlab pipeline-jobs mygroup/myproject 12345 -f json | jq '.[] | select(.status == "failed") | {name, stage}'
Groups
# List groups
netapi gitlab groups -f json | jq -r '.[].full_path'
# Group details
netapi gitlab group mygroup -f json | jq '{name, full_path, visibility, description, web_url}'
# Group projects sorted by stars
netapi gitlab group-projects mygroup -f json | jq 'sort_by(-.star_count) | .[] | "\(.path): \(.star_count) stars"'
# Group members with access levels
netapi gitlab group-members mygroup -f json | jq '.[] | {
username,
name,
access: (
if .access_level == 50 then "Owner"
elif .access_level == 40 then "Maintainer"
elif .access_level == 30 then "Developer"
elif .access_level == 20 then "Reporter"
else "Guest"
end
)
}'
Raw API Access
# Any GET endpoint
netapi gitlab api /users | jq '.[0]'
# Project variables
netapi gitlab api /projects/mygroup%2Fmyproject/variables | jq '.[] | {key, protected}'
# Project hooks
netapi gitlab api /projects/mygroup%2Fmyproject/hooks | jq '.[] | {url, push_events}'
URL-encode project paths: mygroup/myproject → mygroup%2Fmyproject
|
Environment Variables
| Variable | Description |
|---|---|
|
Personal access token (required) |
|
GitLab instance URL (default: gitlab.com) |
Useful jq Recipes
Export to CSV
netapi gitlab projects -f json | jq -r '.[] | [.path_with_namespace, .visibility, .star_count] | @csv'
Count by Field
# Projects by visibility
netapi gitlab projects -f json | jq 'group_by(.visibility) | map({visibility: .[0].visibility, count: length})'
# MRs by state
netapi gitlab mrs mygroup/myproject -s all -f json | jq 'group_by(.state) | map({state: .[0].state, count: length})'
Pipeline Stats
# Pipeline success rate
netapi gitlab pipelines mygroup/myproject -l 100 -f json | jq '
group_by(.status) |
map({status: .[0].status, count: length}) |
sort_by(-.count)
'
# Average pipeline duration (requires completed pipelines)
netapi gitlab pipelines mygroup/myproject -f json | jq '[.[] | select(.duration) | .duration] | if length > 0 then (add / length | floor) else 0 end'