GitLab CLI Skills Comprehensive GitLab CLI (glab) command reference and workflows. Non-TTY table padding can align cells without a terminal-width cap; an explicit maximum column width can still truncate values. Treat text columns and wrapping as presentation; prefer supported JSON output for machine parsing. Quick start Multi-agent identity note When you want different agents to appear as different GitLab users, give each agent its own GitLab bot/service account. Multiple personal access tokens on the same GitLab user still act as that same visible identity. Use the Actor identity for actor-a…

,\n lambda match: \"%s%s: [REDACTED]\" % (match.group(1), match.group(2)),\n text,\n )\n text = re.sub(r'glpat-[A-Za-z0-9_\\-]+', 'glpat-[REDACTED]', text)\n text = re.sub(r'(?i)(PRIVATE-TOKEN|Authorization|Bearer|token)([=: ]+)(\\S+)', r'\\1\\2[REDACTED]', text)\n if len(text) > limit:\n text = text[:limit] + \"...(truncated)\"\n return text\n\n\ndef parse_included_response(output):\n \"\"\"Parse `glab api --include` output into (JSON body, response headers).\"\"\"\n normalized = output.replace(\"\\r\\n\", \"\\n\")\n status_lines = list(re.finditer(r'(?m)^HTTP/\\S+\\s+\\d{3}(?:\\s+[^\\n]*)?

GitLab CLI Skills Comprehensive GitLab CLI (glab) command reference and workflows. Non-TTY table padding can align cells without a terminal-width cap; an explicit maximum column width can still truncate values. Treat text columns and wrapping as presentation; prefer supported JSON output for machine parsing. Quick start Multi-agent identity note When you want different agents to appear as different GitLab users, give each agent its own GitLab bot/service account. Multiple personal access tokens on the same GitLab user still act as that same visible identity. Use the Actor identity for actor-a…

, normalized))\n if not status_lines:\n raise GlabApiError(\"glab api response did not include an HTTP status line\")\n # Start at the final response's status line, then split at that header block's\n # first blank line. This keeps blank lines in pretty-printed JSON bodies intact.\n final_response = normalized[status_lines[-1].start():]\n header_text, sep, body_text = final_response.partition(\"\\n\\n\")\n if not sep:\n raise GlabApiError(\"glab api response did not include HTTP headers\")\n\n active_headers = header_text.splitlines()\n headers = {}\n for line in active_headers:\n if \":\" not in line:\n continue\n name, value = line.split(\":\", 1)\n headers[name.strip().lower()] = value.strip()\n return json.loads(body_text), headers\n\n\ndef run_glab_api(host, endpoint, method=None, payload=None, include_headers=False):\n \"\"\"Run an authenticated GitLab API call through glab without reading credentials.\"\"\"\n args = [\"glab\", \"api\", \"--hostname\", get_hostname(host)]\n if include_headers:\n args.append(\"--include\")\n if method:\n args.extend([\"--method\", method])\n input_text = None\n if payload is not None:\n args.extend([\"--header\", \"Content-Type: application/json\", \"--input\", \"-\"])\n input_text = json.dumps(payload)\n args.append(endpoint)\n\n try:\n result = subprocess.run(\n args,\n input=input_text,\n stdout=subprocess.PIPE,\n stderr=subprocess.PIPE,\n universal_newlines=True,\n timeout=30,\n )\n except FileNotFoundError:\n raise GlabApiError(\"glab executable not found. Install glab and run: glab auth login\")\n except subprocess.TimeoutExpired:\n raise GlabApiError(\"glab api timed out\")\n\n if result.returncode != 0:\n # glab writes structured API errors to stdout but may also write a generic\n # `glab: HTTP 400` status to stderr. Keep stdout first so callers can\n # inspect validation details such as `line_code` and apply safe retries.\n detail = sanitize_glab_error(\"\\n\".join(\n part for part in (result.stdout, result.stderr) if part\n ))\n if detail:\n raise GlabApiError(\"glab api failed: %s\" % detail)\n raise GlabApiError(\"glab api failed with exit code %s\" % result.returncode)\n\n if include_headers:\n try:\n return parse_included_response(result.stdout)\n except (json.JSONDecodeError, GlabApiError) as e:\n raise GlabApiError(\"Could not parse glab api response: %s\" % e)\n\n try:\n return json.loads(result.stdout)\n except json.JSONDecodeError as e:\n raise GlabApiError(\"Could not parse glab api JSON response: %s\" % e)\n\n\ndef _api_get(host, endpoint):\n \"\"\"Authenticated GET request, returns parsed JSON.\"\"\"\n return run_glab_api(host, endpoint)\n\n\ndef _api_get_with_headers(host, endpoint):\n \"\"\"Authenticated GET request, returns (parsed_json, headers).\"\"\"\n return run_glab_api(host, endpoint, include_headers=True)\n\n\ndef verify_glab_identity(host):\n \"\"\"Verify and display the selected GitLab host/account before write workflow calls.\"\"\"\n user = _api_get(host, \"/user\")\n username = sanitize_terminal(user.get(\"username\")) if isinstance(user, dict) else \"\"\n if not username:\n raise GlabApiError(\"glab /user response did not include a non-empty username\")\n print(f\"GitLab host: {sanitize_terminal(get_hostname(host))}\")\n print(f\"GitLab user: {username}\")\n return username\n\n\ndef get_mr_versions(host, project_id, mr_iid):\n \"\"\"Fetch current HEAD/START/BASE SHAs for an MR.\"\"\"\n endpoint = f\"/projects/{project_id}/merge_requests/{mr_iid}/versions\"\n versions = _api_get(host, endpoint)\n if not versions:\n raise ValueError(f\"No versions found for MR !{mr_iid}\")\n latest = versions[0]\n return {\n \"head_sha\": latest[\"head_commit_sha\"],\n \"start_sha\": latest[\"start_commit_sha\"],\n \"base_sha\": latest[\"base_commit_sha\"],\n }\n\n\ndef get_mr_diffs(host, project_id, mr_iid):\n \"\"\"Fetch all MR diffs so we can compute line_code anchors when GitLab requires them.\"\"\"\n diffs = []\n page = 1\n\n while True:\n endpoint = (\n f\"/projects/{project_id}/merge_requests/{mr_iid}/diffs\"\n f\"?per_page=100&page={page}\"\n )\n page_diffs, headers = _api_get_with_headers(host, endpoint)\n diffs.extend(page_diffs)\n\n next_page = (headers.get(\"x-next-page\") or \"\").strip()\n if not next_page:\n break\n page = int(next_page)\n\n return diffs\n\n\ndef find_file_diff(diffs, file_path):\n \"\"\"Return the diff entry matching file_path on either old or new side.\"\"\"\n for diff in diffs:\n if diff.get(\"new_path\") == file_path or diff.get(\"old_path\") == file_path:\n return diff\n raise ValueError(f\"Could not find diff for file '{file_path}' in this MR.\")\n\n\ndef compute_diff_anchor(diff_text, target_new_line):\n \"\"\"Map a target new-side line number to the diff's old/new anchor pair.\"\"\"\n old_line = None\n new_line = None\n\n for raw_line in diff_text.splitlines():\n hunk = re.match(r'^@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@', raw_line)\n if hunk:\n old_line = int(hunk.group(1))\n new_line = int(hunk.group(2))\n continue\n\n if old_line is None or new_line is None:\n continue\n\n if raw_line.startswith('\\\\'):\n continue\n\n if raw_line.startswith('+'):\n if new_line == target_new_line:\n return {\n \"type\": \"new\",\n \"old_line\": 0,\n \"new_line\": new_line,\n }\n new_line += 1\n continue\n\n if raw_line.startswith('-'):\n old_line += 1\n continue\n\n if new_line == target_new_line:\n return {\n \"type\": \"new\",\n \"old_line\": old_line,\n \"new_line\": new_line,\n }\n old_line += 1\n new_line += 1\n\n raise ValueError(\n f\"Could not map new-side line {target_new_line} to a diff anchor. \"\n \"Make sure the line exists in the MR diff.\"\n )\n\n\ndef compute_line_code(file_path, old_line, new_line):\n \"\"\"GitLab diff line code format: sha1(path)_{old}_{new}.\"\"\"\n file_hash = hashlib.sha1(file_path.encode(\"utf-8\")).hexdigest()\n return f\"{file_hash}_{old_line}_{new_line}\"\n\n\ndef get_position_paths(diff_entry, requested_file_path):\n \"\"\"Return the old/new paths GitLab expects for this diff position.\"\"\"\n return {\n \"old_path\": diff_entry.get(\"old_path\") or requested_file_path,\n \"new_path\": diff_entry.get(\"new_path\") or requested_file_path,\n }\n\n\ndef build_inline_payload(shas, diff_entry, file_path, line_number, body):\n paths = get_position_paths(diff_entry, file_path)\n return {\n \"body\": body,\n \"position\": {\n \"base_sha\": shas[\"base_sha\"],\n \"start_sha\": shas[\"start_sha\"],\n \"head_sha\": shas[\"head_sha\"],\n \"position_type\": \"text\",\n \"new_path\": paths[\"new_path\"],\n \"new_line\": line_number,\n \"old_path\": paths[\"old_path\"],\n \"old_line\": None,\n }\n }\n\n\ndef build_line_range_payload(shas, diff_entry, file_path, body, anchor):\n paths = get_position_paths(diff_entry, file_path)\n line_code_path = paths[\"new_path\"] if anchor[\"type\"] == \"new\" else paths[\"old_path\"]\n point = {\n \"type\": anchor[\"type\"],\n \"line_code\": compute_line_code(line_code_path, anchor[\"old_line\"], anchor[\"new_line\"]),\n }\n if anchor[\"old_line\"] is not None:\n point[\"old_line\"] = anchor[\"old_line\"]\n if anchor[\"new_line\"] is not None:\n point[\"new_line\"] = anchor[\"new_line\"]\n\n return {\n \"body\": body,\n \"position\": {\n \"base_sha\": shas[\"base_sha\"],\n \"start_sha\": shas[\"start_sha\"],\n \"head_sha\": shas[\"head_sha\"],\n \"position_type\": \"text\",\n \"old_path\": paths[\"old_path\"],\n \"new_path\": paths[\"new_path\"],\n \"line_range\": {\n \"start\": dict(point),\n \"end\": dict(point),\n },\n }\n }\n\n\ndef post_discussion(host, project_id, mr_iid, payload):\n endpoint = f\"/projects/{project_id}/merge_requests/{mr_iid}/discussions\"\n return run_glab_api(host, endpoint, method=\"POST\", payload=payload)\n\n\ndef is_line_code_validation_error(error_text):\n return \"line_code\" in error_text and \"valid\" in error_text.lower()\n\n\ndef post_inline_comment(host, project_id, mr_iid, shas, diffs, file_path, line_number, body):\n \"\"\"\n Post a single inline comment on a MR diff using a JSON body.\n First try the simple new_line payload; if GitLab rejects it with a line_code\n validation error, compute the diff anchor and retry with position.line_range.\n Returns (disc_id, is_inline, used_line_code_retry) tuple.\n \"\"\"\n diff_entry = find_file_diff(diffs, file_path)\n\n try:\n r = post_discussion(host, project_id, mr_iid, build_inline_payload(shas, diff_entry, file_path, line_number, body))\n used_line_code_retry = False\n except Exception as e:\n error_text = str(e)\n if not is_line_code_validation_error(error_text):\n raise\n\n anchor = compute_diff_anchor(diff_entry.get(\"diff\", \"\"), line_number)\n retry_payload = build_line_range_payload(shas, diff_entry, file_path, body, anchor)\n r = post_discussion(host, project_id, mr_iid, retry_payload)\n used_line_code_retry = True\n\n note = r.get(\"notes\", [{}])[0]\n disc_id = r.get(\"id\")\n is_inline = note.get(\"position\") is not None\n\n return disc_id, is_inline, used_line_code_retry\n\n\n# ── Main ──────────────────────────────────────────────────────────────────────\n\ndef main():\n parser = argparse.ArgumentParser(\n description=\"Post inline diff comments on GitLab MRs via JSON body.\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n )\n parser.add_argument(\"--project\", required=True,\n help=\"GitLab project path, e.g. mygroup/myproject\")\n parser.add_argument(\"--mr\", required=True, type=int,\n help=\"MR IID (integer), e.g. 42\")\n parser.add_argument(\"--host\", default=\"https://gitlab.com\",\n help=\"GitLab host URL (must be HTTPS)\")\n parser.add_argument(\"--file\", help=\"File path in repo (single comment mode)\")\n parser.add_argument(\"--line\", type=int, help=\"Line number in new file (single comment mode)\")\n parser.add_argument(\"--body\", help=\"Comment text (single comment mode)\")\n parser.add_argument(\"--batch\", help=\"Path to JSON file with [{file, line, body}] array\")\n args = parser.parse_args()\n\n if not args.batch and not (args.file and args.line and args.body):\n parser.error(\"Provide either --batch or all of --file, --line, --body\")\n\n # Validate all inputs before touching the network\n host = validate_host(args.host)\n project = validate_project(args.project)\n project_id = urllib.parse.quote(project, safe=\"\")\n\n if args.batch:\n comments = load_batch_file(args.batch)\n else:\n comments = [{\n \"file\": validate_file_path(args.file),\n \"line\": validate_line(args.line),\n \"body\": validate_body(args.body),\n }]\n\n try:\n verify_glab_identity(host)\n except Exception as e:\n print(\n f\"ERROR: Could not verify glab identity: {sanitize_glab_error(str(e))}\",\n file=sys.stderr,\n )\n sys.exit(1)\n\n print(f\"Fetching current HEAD SHAs for MR !{args.mr}...\")\n try:\n shas = get_mr_versions(host, project_id, args.mr)\n diffs = get_mr_diffs(host, project_id, args.mr)\n except Exception as e:\n print(\n f\"ERROR: Could not fetch MR metadata/diffs: {sanitize_glab_error(str(e))}\",\n file=sys.stderr,\n )\n sys.exit(1)\n print(f\" head_sha: {sanitize_terminal(shas.get('head_sha'))[:12]}...\")\n\n results = []\n for c in comments:\n file_path = c[\"file\"]\n line_number = c[\"line\"]\n body = c[\"body\"]\n\n print(f\"\\nPosting: {file_path}:{line_number}\")\n print(f\" Body length: {len(body)} characters\")\n\n try:\n disc_id, is_inline, used_line_code_retry = post_inline_comment(\n host, project_id, args.mr, shas, diffs, file_path, line_number, body\n )\n if is_inline and used_line_code_retry:\n status = \"✅ INLINE (line_code retry)\"\n elif is_inline:\n status = \"✅ INLINE\"\n else:\n status = \"⚠️ GENERAL (position rejected — check line number)\"\n print(f\" {status} | disc_id: {sanitize_terminal(disc_id)}\")\n results.append({\n \"disc_id\": disc_id,\n \"is_inline\": is_inline,\n \"used_line_code_retry\": used_line_code_retry,\n \"file\": file_path,\n \"line\": line_number,\n })\n except Exception as e:\n print(f\" ❌ FAILED: {sanitize_glab_error(str(e))}\", file=sys.stderr)\n results.append({\"error\": str(e), \"file\": file_path, \"line\": line_number})\n\n # Summary\n print(f\"\\n{'=' * 50}\")\n inline_count = sum(1 for r in results if r.get(\"is_inline\") is True)\n retried_count = sum(1 for r in results if r.get(\"used_line_code_retry\") is True)\n general_count = sum(1 for r in results if r.get(\"is_inline\") is False)\n error_count = sum(1 for r in results if \"error\" in r)\n print(f\"Summary: {inline_count} inline ✅ {retried_count} retried-with-line_code 🔁 {general_count} general ⚠️ {error_count} failed ❌\")\n\n if general_count:\n print(\n \"\\n⚠️ Some comments posted as general (non-inline).\\n\"\n \" The line number doesn't correspond to an added (+) line in the diff.\\n\"\n \" Use the get_new_line_number() helper in glab-mr/SKILL.md to find valid lines.\"\n )\n\n disc_ids = [r[\"disc_id\"] for r in results if r.get(\"disc_id\")]\n if disc_ids:\n print(f\"\\nDiscussion IDs: {json.dumps(disc_ids)}\")\n\n return 0 if error_count == 0 else 1\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n","content_type":"text/x-python; charset=utf-8","language":"python","size":23863,"content_sha256":"a403d3dd332bc6693a164135040d5e3a2b76d7fed423d7b2564c111e295ff009"},{"filename":"scripts/sync-fork.sh","content":"#!/bin/bash\n# Sync Fork Script\n# Automates: fetch upstream → merge into current branch → push to origin\n\nset -e\n\nBRANCH=\"${1:-main}\"\nUPSTREAM_REMOTE=\"${2:-upstream}\"\n\necho \"🔄 Syncing fork with upstream...\"\necho \" Branch: $BRANCH\"\necho \" Upstream remote: $UPSTREAM_REMOTE\"\necho \"\"\n\n# Check if upstream remote exists\nif ! git remote get-url \"$UPSTREAM_REMOTE\" >/dev/null 2>&1; then\n echo \"❌ Upstream remote '$UPSTREAM_REMOTE' not found\"\n echo \"\"\n echo \"Add upstream remote first:\"\n echo \" git remote add upstream \u003cupstream-repo-url>\"\n echo \"\"\n echo \"Example:\"\n echo \" git remote add upstream https://gitlab.com/group/project.git\"\n exit 1\nfi\n\nUPSTREAM_URL=$(git remote get-url \"$UPSTREAM_REMOTE\")\necho \"Upstream: $UPSTREAM_URL\"\necho \"\"\n\n# Save current branch\nCURRENT_BRANCH=$(git branch --show-current)\n\n# Checkout target branch\nif [ \"$CURRENT_BRANCH\" != \"$BRANCH\" ]; then\n echo \"📍 Switching to $BRANCH...\"\n git checkout \"$BRANCH\"\nfi\n\n# Fetch upstream\necho \"⬇️ Fetching from upstream...\"\ngit fetch \"$UPSTREAM_REMOTE\"\n\n# Merge upstream changes\necho \"🔀 Merging upstream/$BRANCH into $BRANCH...\"\nif git merge \"$UPSTREAM_REMOTE/$BRANCH\" --ff-only; then\n echo \"✅ Fast-forward merge successful\"\nelse\n echo \"⚠️ Fast-forward merge failed - attempting regular merge...\"\n\n if git merge \"$UPSTREAM_REMOTE/$BRANCH\"; then\n echo \"✅ Merge successful (with merge commit)\"\n else\n echo \"❌ Merge failed - conflicts detected\"\n echo \"\"\n echo \"Resolve conflicts manually, then:\"\n echo \" git add .\"\n echo \" git commit\"\n echo \" git push origin $BRANCH\"\n exit 1\n fi\nfi\n\n# Push to origin\necho \"⬆️ Pushing to origin/$BRANCH...\"\ngit push origin \"$BRANCH\"\n\necho \"\"\necho \"✨ Fork synced successfully!\"\necho \"\"\n\n# Return to original branch if different\nif [ \"$CURRENT_BRANCH\" != \"$BRANCH\" ] && [ -n \"$CURRENT_BRANCH\" ]; then\n echo \"📍 Returning to $CURRENT_BRANCH...\"\n git checkout \"$CURRENT_BRANCH\"\nfi\n\necho \"Summary:\"\necho \" ✅ Fetched from $UPSTREAM_REMOTE\"\necho \" ✅ Merged upstream/$BRANCH into local $BRANCH\"\necho \" ✅ Pushed to origin/$BRANCH\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2176,"content_sha256":"9d56ef7a7ffba2f60d08876d77072816af707c6e43036a13c885efc841d3a15d"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"GitLab CLI Skills","type":"text"}]},{"type":"paragraph","content":[{"text":"Comprehensive GitLab CLI (glab) command reference and workflows.","type":"text"}]},{"type":"paragraph","content":[{"text":"Non-TTY table padding can align cells without a terminal-width cap; an explicit maximum column width can still truncate values. Treat text columns and wrapping as presentation; prefer supported JSON output for machine parsing.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick start","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# First time setup\nglab auth login\n\n# Common operations\nglab mr create --fill # Create MR from current branch\nglab issue create # Create issue\nglab ci view # View pipeline status\nglab repo view --web # Open repo in browser","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Multi-agent identity note","type":"text"}]},{"type":"paragraph","content":[{"text":"When you want different agents to appear as different GitLab users, give each agent its own GitLab bot/service account. Multiple personal access tokens on the same GitLab user still act as that same visible identity.","type":"text"}]},{"type":"paragraph","content":[{"text":"Use the ","type":"text"},{"text":"Actor identity","type":"text","marks":[{"type":"strong"}]},{"text":" for actor-authored GitLab comments, replies, approvals, and other writes. Use an ","type":"text"},{"text":"agent identity","type":"text","marks":[{"type":"strong"}]},{"text":" only when the GitLab action is explicitly that agent's own work product. Choose the intended visible actor ","type":"text"},{"text":"before the first GitLab write","type":"text","marks":[{"type":"strong"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Treat shell identity as sticky and unsafe by default. If another env file was sourced earlier in the same shell/session, ","type":"text"},{"text":"glab","type":"text","marks":[{"type":"code_inline"}]},{"text":" may still write as that previously loaded identity unless you deliberately switch and verify first.","type":"text"}]},{"type":"paragraph","content":[{"text":"A practical pattern is one env file per actor, for example ","type":"text"},{"text":"~/.config/openclaw/env/gitlab-actor.env","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"~/.config/openclaw/env/gitlab-reviewer.env","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"~/.config/openclaw/env/gitlab-release.env","type":"text","marks":[{"type":"code_inline"}]},{"text":". Keep these env files outside version control, restrict their permissions (for example ","type":"text"},{"text":"chmod 600","type":"text","marks":[{"type":"code_inline"}]},{"text":"), be mindful of backup exposure, and use least-privilege bot/service-account tokens. In a reused shell, clear stale GitLab auth vars first or start a fresh shell. If those files use plain ","type":"text"},{"text":"KEY=value","type":"text","marks":[{"type":"code_inline"}]},{"text":" lines, load them with exported vars before running ","type":"text"},{"text":"glab","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"unset GITLAB_TOKEN GITLAB_ACCESS_TOKEN OAUTH_TOKEN GITLAB_HOST\nset -a\nsource ~/.config/openclaw/env/gitlab-\u003cactor>.env\nset +a","type":"text"}]},{"type":"paragraph","content":[{"text":"Plain ","type":"text"},{"text":"source","type":"text","marks":[{"type":"code_inline"}]},{"text":" updates the current shell but may not export variables to child processes such as ","type":"text"},{"text":"glab","type":"text","marks":[{"type":"code_inline"}]},{"text":". If the token/host vars are not exported, ","type":"text"},{"text":"glab","type":"text","marks":[{"type":"code_inline"}]},{"text":" may silently fall back to shared stored auth from the active global glab config file, which can make the wrong account appear to perform the action.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Required pre-flight before any GitLab write","type":"text"}]},{"type":"paragraph","content":[{"text":"Run this immediately before any GitLab write, including ","type":"text"},{"text":"glab mr note","type":"text","marks":[{"type":"code_inline"}]},{"text":", review replies/approvals, and any ","type":"text"},{"text":"glab api","type":"text","marks":[{"type":"code_inline"}]},{"text":" ","type":"text"},{"text":"POST","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"PATCH","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"PUT","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"DELETE","type":"text","marks":[{"type":"code_inline"}]},{"text":" call:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"glab auth status --hostname \"$GITLAB_HOST\"\nglab api --hostname \"$GITLAB_HOST\" user","type":"text"}]},{"type":"paragraph","content":[{"text":"This assumes the target actor env file set ","type":"text"},{"text":"GITLAB_HOST","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the exact GitLab instance you intend to modify. Do not write until both commands clearly show the intended visible actor on that host.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Wrong-identity remediation","type":"text"}]},{"type":"paragraph","content":[{"text":"If a comment or reply was posted under the wrong identity:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Stop posting.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Delete the mistaken comment or reply if cleanup is needed.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"unset GITLAB_TOKEN GITLAB_ACCESS_TOKEN OAUTH_TOKEN GITLAB_HOST","type":"text","marks":[{"type":"code_inline"}]},{"text":" or start a fresh shell.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Source the correct env file with ","type":"text"},{"text":"set -a; source ...; set +a","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Rerun ","type":"text"},{"text":"glab auth status --hostname \"$GITLAB_HOST\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"glab api --hostname \"$GITLAB_HOST\" user","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Repost under the correct actor.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify the thread no longer shows the wrong visible author for the replacement message.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"If the wrong-identity write changed state beyond a comment or reply, do not treat the comment cleanup steps as sufficient. Re-auth as above, then use the matching GitLab reversal for that write under the correct actor and host, such as unapproving an MR or sending the compensating ","type":"text"},{"text":"glab api --hostname \"$GITLAB_HOST\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" mutation for the exact resource that was changed.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Skill organization","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill routes to specialized sub-skills by GitLab domain. Each is a standalone skill in a sibling directory; open its ","type":"text"},{"text":"SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for full details.","type":"text"}]},{"type":"paragraph","content":[{"text":"Core Workflows:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-mr","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-mr/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Merge requests: create, review, approve, merge","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-issue","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-issue/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Issues: create, list, update, close, comment","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-ci","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-ci/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - CI/CD: pipelines, jobs, logs, artifacts","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-repo","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-repo/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Repositories: clone, create, fork, manage","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Project Management:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-milestone","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-milestone/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Release planning and milestone tracking","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-iteration","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-iteration/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Sprint/iteration management","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-label","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-label/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Label management and organization","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-release","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-release/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Software releases and versioning","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-packages","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-packages/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Project package registry listing, filtering, and generic package uploads","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Authentication & Config:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-auth","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-auth/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Login, logout, Docker registry auth","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-config","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-config/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - CLI configuration and defaults","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-ssh-key","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-ssh-key/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - SSH key management","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-gpg-key","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-gpg-key/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - GPG keys for commit signing","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-token","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-token/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Personal, project, and group access tokens, including approved self-rotation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-deploy-token","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-deploy-token/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Project/group deploy-token metadata, active inventory, and approved creation with a protected one-time secret handoff","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-todo","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-todo/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Personal GitLab to-do triage and completion","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"CI/CD Management:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-job","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-job/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Individual job operations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-schedule","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-schedule/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Scheduled pipelines and cron jobs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-variable","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-variable/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - CI/CD variables and secrets","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-securefile","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-securefile/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Secure files for pipelines","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-runner","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-runner/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Runner management: list, assign/unassign, inspect jobs/managers, pause/unpause, delete","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-runner-controller","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-runner-controller/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Runner controller, scope, and token management (EXPERIMENTAL, admin-only)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Collaboration:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-user","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-user/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - User profiles and information","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-snippet","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-snippet/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Create project or personal code snippets","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-incident","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-incident/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Incident management","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-workitems","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-workitems/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Work items: tasks, OKRs, key results, next-gen epics","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Advanced:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-api","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-api/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Direct REST API calls","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-artifact-registry","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-artifact-registry/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Experimental short-lived Artifact Registry token exchange and access checks","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-cluster","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-cluster/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Kubernetes cluster integration","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-container-registry","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-container-registry/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Container registry repositories and tags","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-dependency-firewall","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-dependency-firewall/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Beta Dependency Firewall package checks, package-manager wrappers including Go, and local activity summaries","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-deploy-key","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-deploy-key/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Deploy keys for automation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-govern","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-govern/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Experimental AI agent governance hooks, diagnosis, and transcript-audit sync","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-orbit","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-orbit/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Managed Orbit CLI workflows for remote graph status/query/discovery and local code-graph indexing/search; use ","type":"text"},{"text":"glab-skills","type":"text","marks":[{"type":"code_inline"}]},{"text":" to install the remote Orbit wrapper skill (EXPERIMENTAL)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-quick-actions","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-quick-actions/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - GitLab slash command quick actions for batching state changes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-security","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-security/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Project security scan profile enable/disable/status management (EXPERIMENTAL)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-stack","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-stack/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Create, reorder, sync, and delete local stacked/dependent merge-request metadata","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-opentofu","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-opentofu/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Terraform/OpenTofu state management","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Utilities:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-alias","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-alias/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Custom command aliases","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-completion","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-completion/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Shell autocompletion","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-help","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-help/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Command help and documentation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-version","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-version/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Version information","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-check-update","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-check-update/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Update checker","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-whatsnew","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-whatsnew/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Release notes since the last viewed or post-upgrade baseline","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-changelog","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-changelog/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Changelog generation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-attestation","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-attestation/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Software supply chain security","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-duo","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-duo/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - GitLab Duo AI assistant","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-mcp","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-mcp/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Deprecated glab MCP compatibility; use the ","type":"text"},{"text":"GitLab MCP Server","type":"text","marks":[{"type":"link","attrs":{"href":"https://docs.gitlab.com/user/model_context_protocol/mcp_server/","title":null}}]},{"text":" for new integrations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"glab-skills","type":"text","marks":[{"type":"link","attrs":{"href":"../glab-skills/SKILL.md","title":null}},{"type":"code_inline"}]},{"text":" - Inspect bundled skills; install, list, and update bundled or curated remote skills, including the Orbit wrapper skill (EXPERIMENTAL)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to use glab vs web UI","type":"text"}]},{"type":"paragraph","content":[{"text":"Use glab when:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Automating GitLab operations in scripts","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Working in terminal-centric workflows","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Batch operations (multiple MRs/issues)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Integration with other CLI tools","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"CI/CD pipeline workflows","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Faster navigation without browser context switching","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Use web UI when:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Complex diff review with inline comments","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Visual merge conflict resolution","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Configuring repo settings and permissions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Advanced search/filtering across projects","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Reviewing security scanning results","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Managing group/instance-level settings","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Common workflows","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Daily development","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Start work on issue\nglab issue view 123\ngit checkout -b 123-feature-name\n\n# Create MR when ready\nglab mr create --fill --draft\n\n# Mark ready for review\nglab mr update --ready\n\n# Merge after approval\nglab mr merge --when-pipeline-succeeds --remove-source-branch","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Code review","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# List your review queue\nglab mr list --reviewer=@me --state=opened\n\n# Review an MR\nglab mr checkout 456\nglab mr diff\nnpm test\n\n# Approve\nglab mr approve 456\nglab mr note 456 -m \"LGTM! Nice work on the error handling.\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"CI/CD debugging","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check pipeline status\nglab ci status\n\n# View failed jobs\nglab ci view\n\n# Get job logs\nglab ci trace \u003cjob-id>\n\n# Retry failed job\nglab ci retry \u003cjob-id>","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Decision Trees","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"\"Should I create an MR or work on an issue first?\"","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Need to track work?\n├─ Yes → Create issue first (glab issue create)\n│ Then: glab mr for \u003cissue-id>\n└─ No → Direct MR (glab mr create --fill)","type":"text"}]},{"type":"paragraph","content":[{"text":"Use ","type":"text","marks":[{"type":"strong"}]},{"text":"glab issue create","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" + ","type":"text","marks":[{"type":"strong"}]},{"text":"glab mr for","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" when:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Work needs discussion/approval before coding","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tracking feature requests or bugs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Sprint planning and assignment","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Want issue to auto-close when MR merges","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Use ","type":"text","marks":[{"type":"strong"}]},{"text":"glab mr create","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" directly when:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Quick fixes or typos","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Working from existing issue","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Hotfixes or urgent changes","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"\"Which CI command should I use?\"","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"What do you need?\n├─ Overall pipeline status → glab ci status\n├─ Visual pipeline view → glab ci view\n├─ Specific job logs → glab ci trace \u003cjob-id>\n├─ Download build artifacts → glab ci artifact \u003cref> \u003cjob-name>\n├─ Validate config file → glab ci lint\n├─ Trigger new run → glab ci run\n└─ List all pipelines → glab ci list","type":"text"}]},{"type":"paragraph","content":[{"text":"Quick reference:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pipeline-level: ","type":"text"},{"text":"glab ci status","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"glab ci view","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"glab ci run","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Job-level: ","type":"text"},{"text":"glab ci trace","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"glab job retry","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"glab job view","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Artifacts: ","type":"text"},{"text":"glab ci artifact","type":"text","marks":[{"type":"code_inline"}]},{"text":" (by pipeline) or job artifacts via ","type":"text"},{"text":"glab job","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"\"Clone or fork?\"","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"What's your relationship to the repo?\n├─ You have write access → glab repo clone group/project\n├─ Contributing to someone else's project:\n│ ├─ One-time contribution → glab repo fork + work + MR\n│ └─ Ongoing contributions → glab repo fork, then sync regularly\n└─ Just reading/exploring → glab repo clone (or view --web)","type":"text"}]},{"type":"paragraph","content":[{"text":"Fork when:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"You don't have write access to the original repo","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Contributing to open source projects","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Experimenting without affecting the original","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Need your own copy for long-term work","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Clone when:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"You're a project member with write access","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Working on organization/team repositories","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No need for a personal copy","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"\"Project vs group labels?\"","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Where should the label live?\n├─ Used across multiple projects → glab label create --group \u003cgroup>\n└─ Specific to one project → glab label create (in project directory)","type":"text"}]},{"type":"paragraph","content":[{"text":"Group-level labels:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Consistent labeling across organization","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Examples: priority::high, type::bug, status::blocked","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Managed centrally, inherited by projects","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Project-level labels:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Project-specific workflows","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Examples: needs-ux-review, deploy-to-staging","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Managed by project maintainers","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Related Skills","type":"text"}]},{"type":"paragraph","content":[{"text":"MR and Issue workflows:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Start with ","type":"text"},{"text":"glab-issue","type":"text","marks":[{"type":"code_inline"}]},{"text":" to create/track work","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"glab-mr","type":"text","marks":[{"type":"code_inline"}]},{"text":" to create MR that closes issue","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Script: ","type":"text"},{"text":"scripts/create-mr-from-issue.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" automates this","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"CI/CD debugging:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"glab-ci","type":"text","marks":[{"type":"code_inline"}]},{"text":" for pipeline-level operations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"glab-job","type":"text","marks":[{"type":"code_inline"}]},{"text":" for individual job operations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Script: ","type":"text"},{"text":"scripts/ci-debug.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" for quick failure diagnosis","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Repository operations:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"glab-repo","type":"text","marks":[{"type":"code_inline"}]},{"text":" for repository management","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"glab-auth","type":"text","marks":[{"type":"code_inline"}]},{"text":" for authentication setup","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Script: ","type":"text"},{"text":"scripts/sync-fork.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" for fork synchronization","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Configuration:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"glab-auth","type":"text","marks":[{"type":"code_inline"}]},{"text":" for initial authentication","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"glab-config","type":"text","marks":[{"type":"code_inline"}]},{"text":" to set defaults and preferences","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"glab-alias","type":"text","marks":[{"type":"code_inline"}]},{"text":" for custom shortcuts","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"gitlab-cli-skills","author":"@skillopedia","source":{"stars":49,"repo_name":"gitlab-cli-skills","origin_url":"https://github.com/vince-winkintel/gitlab-cli-skills/blob/HEAD/gitlab-cli-skills/SKILL.md","repo_owner":"vince-winkintel","body_sha256":"93974096806afcad37ddca6b3a6e95c78292a53cba338f673452ce0d7033aca9","cluster_key":"bf8c0a4e1ddb80d395f1fa821a7b3899de8a879d37530a49459b4800d0b10255","clean_bundle":{"format":"clean-skill-bundle-v1","source":"vince-winkintel/gitlab-cli-skills/gitlab-cli-skills/SKILL.md","text_bytes":30456,"source_commit":"a999abede256f4142f982d3278b4ce873752dc66","skills_sh_rank":8776,"attachment_count":4,"text_attachments":4,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"gitlab-cli-skills/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"devops-infrastructure","metadata":{"openclaw":{"install":[{"id":"brew","bins":["glab"],"kind":"brew","label":"Install glab (brew)","formula":"glab"},{"id":"download","url":"https://gitlab.com/gitlab-org/cli/-/releases","kind":"download","label":"Download glab binary"}],"requires":{"bins":["glab"],"anyBins":["cosign"]}}},"openclaw":{"requires":{"network":[{"scope":"authenticated API calls only; HTTPS enforced; token never sent over HTTP","description":"Outbound HTTPS to your GitLab instance (default https://gitlab.com)"}],"credentials":[{"name":"GITLAB_TOKEN","fallback":"glab config (set via glab auth login)","required":false,"description":"GitLab personal access token with 'api' scope. Used by automation scripts (e.g. post-inline-comment.py) to post MR comments via the REST API. If not set, scripts fall back to reading the token from the active global glab CLI config.\n"}],"write_access":[{"description":"Scripts in this skill can post comments, resolve threads, and approve merge requests on your behalf. Review scripts/post-inline-comment.py before use in automated or agentic contexts.\n"}]}},"import_tag":"skills-sh-top20k-2026-11","description":"Comprehensive GitLab CLI (glab) command reference and workflows for all GitLab operations via terminal. Use when user mentions GitLab CLI, glab commands, GitLab automation, MR/issue management via CLI, CI/CD pipeline commands, Artifact Registry token exchange, repo operations, authentication setup, or any GitLab terminal operations. Routes to specialized sub-skills for auth, CI, MRs, issues, releases, repos, and 30+ other glab commands. Triggers on glab, GitLab CLI, GitLab commands, GitLab terminal, GitLab automation.","requirements":{"notes":"Requires GitLab authentication via 'glab auth login' (stores token in the active global glab config file).\nSome features may access sensitive files: SSH keys (~/.ssh/id_rsa for DPoP), Docker config (~/.docker/config.json for registry auth).\nReview auth workflows and script contents before autonomous use.\n","binaries":["glab"],"binaries_optional":["cosign"]}}},"renderedAt":1793671366922}

GitLab CLI Skills Comprehensive GitLab CLI (glab) command reference and workflows. Non-TTY table padding can align cells without a terminal-width cap; an explicit maximum column width can still truncate values. Treat text columns and wrapping as presentation; prefer supported JSON output for machine parsing. Quick start Multi-agent identity note When you want different agents to appear as different GitLab users, give each agent its own GitLab bot/service account. Multiple personal access tokens on the same GitLab user still act as that same visible identity. Use the Actor identity for actor-a…