GitLab CLI (glab)
GitLab CLI for merge requests, pipelines, issues, and API access.
Installation
sudo pacman -S glab
pacman -Si glab | grep -E "^(Name|Version|Repository)"
Authentication
glab auth status
If you see 401 Unauthorized — your token is expired. See Token Renewal below.
glab auth login --hostname gitlab.com
Select Token, paste your PAT.
glab auth login --hostname gitlab.com --token "$(yq -r '.hosts["gitlab.com"].token' ~/atelier/_vaults/mounted/credentials/glab/config.yml)"
glab auth login --hostname gitlab.com --token glpat-xxxxxxxxxxxx
Token Renewal
When glab auth status returns 401 Unauthorized, the PAT has expired.
GitLab → Settings → Access Tokens → Add new token Name: glab-cli-2026 Scopes: api, write_repository, read_repository Expiration: set to 1 year or as policy allows
# Edit the config — the token lives under hosts.gitlab.com
vim ~/atelier/_vaults/mounted/credentials/glab/config.yml
The token line MUST be token: glpat-xxxxx — NOT token: !!null glpat-xxxxx. The !!null YAML tag forces the value to null and yq/glab will ignore the actual token string. If you see !!null, remove it.
|
hosts:
gitlab.com:
token: glpat-your-actual-token-here
hosts:
gitlab.com:
token: !!null glpat-your-actual-token-here
yq -r '.hosts["gitlab.com"].token' ~/atelier/_vaults/mounted/credentials/glab/config.yml
Should return glpat-xxxxx. If it returns null, the !!null tag is still there.
glab auth login --hostname gitlab.com --token "$(yq -r '.hosts["gitlab.com"].token' ~/atelier/_vaults/mounted/credentials/glab/config.yml)"
glab auth status
Should show ✓ Logged in to gitlab.com.
# If credentials are age-encrypted, re-encrypt after editing
age -e -R ~/.age/recipients/self.txt -o config.yml.age config.yml
yq Patterns for Credential Files
yq 'keys' ~/atelier/_vaults/mounted/credentials/glab/config.yml
yq '.hosts | keys' ~/atelier/_vaults/mounted/credentials/glab/config.yml
yq '.hosts["gitlab.com"] | keys' ~/atelier/_vaults/mounted/credentials/glab/config.yml
yq -r '.git_protocol' ~/atelier/_vaults/mounted/credentials/glab/config.yml
This should return ssh. If it works, your yq path syntax is correct and you can trust it for the token field.
# WRONG — yq interprets dots as nested keys
yq '.hosts.gitlab.com.token'
# CORRECT — bracket notation for keys with dots
yq '.hosts["gitlab.com"].token'
Repository Management
glab repo create domus-api --private
glab repo clone EvanusModestus/domus-api
glab repo view
glab repo list
Merge Requests (GitLab’s PRs)
glab mr create --title "feat: association graph endpoints" --description "Adds /associations API"
glab mr list
glab mr view 42
glab mr approve 42
glab mr merge 42 --squash --remove-source-branch
glab ci status
Issues
glab issue create --title "Add YAML persistence" --label "enhancement"
glab issue list
glab issue close 15
CI/CD Pipelines
glab ci status
glab ci list
glab ci run
glab ci trace <job-id>
GitLab API — Direct Access
Like gh api, glab api gives raw REST access.
glab api projects/EvanusModestus%2Fdomus-api | jq '{name: .name, visibility: .visibility}'
GitLab API uses %2F for / in project paths (URL encoding).
|
glab api projects/EvanusModestus%2Fdomus-api/pipelines | jq '.[0] | {id, status, ref}'
glab api projects/EvanusModestus%2Fdomus-api/variables | jq '[.[] | {key, protected, masked}]'
Snippets (GitLab’s Gists)
glab snippet create validate.sh --title "domus-api validation script" --visibility private
glab snippet list
gh vs glab — Side by Side
| Action | GitHub (gh) |
GitLab (glab) |
|---|---|---|
Auth |
|
|
Create repo |
|
|
Create PR/MR |
|
|
List PRs/MRs |
|
|
CI status |
|
|
API access |
|
|
Create issue |
|
|
Snippets/Gists |
|
|