Skip to content
Development
Skill

/gitlab-ops

Use this skill when performing VCS operations on GitLab or GitHub repositories — creating, updating, or closing issues and MRs, applying label taxonomy, running `glab`/`gh` CLI commands, or resolving project paths dynamically. Acts as the single source of truth for CLI command

From plugin
session-orchestrator
5144 skills14 agents26 commands10 hooks
+1
Install
$ npx -y skills add Kanevry/session-orchestrator --skill gitlab-ops --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/gitlab-ops

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use this skill when performing VCS operations on GitLab or GitHub repositories — creating, updating, or closing issues and MRs, applying label taxonomy, running `glab`/`gh` CLI commands, or resolving project paths dynamically. Acts as the single source of truth for CLI command

SKILL.md

gitlab-ops.SKILL.md
name: gitlab-ops
user-invocable: false
tags: [reference, vcs, gitlab, github, issues]
model: haiku
model-preference: sonnet
model-preference-codex: gpt-5.4-mini
model-preference-cursor: claude-sonnet-4-6
description: >
  Use this skill when performing VCS operations on GitLab or GitHub repositories — creating, updating, or
  closing issues and MRs, applying label taxonomy, running `glab`/`gh` CLI commands, or resolving project
  paths dynamically. Acts as the single source of truth for CLI command syntax and label conventions;
  consuming skills reference this rather than duplicating logic. Triggers: "create a GitLab issue", "list
  open MRs", "apply priority label", "how do I resolve the project ID", "what's the carryover issue
  template". <example>Context: session-end needs to file a carryover issue for an incomplete task. user:
  "/close" assistant: "Creating carryover issue via glab with the Carryover Template from gitlab-ops —
  labels: carryover, priority::high."</example>

VCS Operations Reference

VCS Auto-Detection

Detect which VCS platform the current repo uses and select the right CLI:

# Check git remote
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
if echo "$REMOTE_URL" | grep -q "github.com"; then
  VCS=github    # use `gh`
else
  VCS=gitlab    # use `glab`
fi

**Session Config overrides:**

  • `vcs: github|gitlab` — force a specific platform
  • `gitlab-host: <host>` — override auto-detected GitLab host (glab reads host from git remote by default)

How Other Skills Reference This

**Directive:** Consuming skills MUST NOT duplicate VCS auto-detection logic or CLI command syntax inline. This skill is the single source of truth for all VCS operations.

When a skill needs VCS operations, include this reference block in its instructions:

> **VCS Reference:** Detect the VCS platform per the "VCS Auto-Detection" section of the gitlab-ops skill. > Use CLI commands per the "Common CLI Commands" section. For GitLab API operations, see "Canonical Project Identity."

**Canonical commands:** All `glab` and `gh` command syntax — flags, output formats, pagination options — is defined in the "Common CLI Commands" section below. Consuming skills must reference that section rather than redefining commands. If a skill needs a command variant not listed there, add it to this file first, then reference it.

**What consuming skills should include:**

  • The reference block above (copy-paste it verbatim)
  • Any skill-specific *parameters* they pass to commands (e.g., label names, issue templates)
  • They should NOT include raw `glab`/`gh` invocations or detection snippets

Canonical Project Identity

GitLab REST endpoints accept a URL-encoded `namespace/project` path. Select the GitLab host and project path explicitly; never derive a numeric project ID from `glab repo view`, search `projects?search=`, or use `:id` placeholders. Those forms can resolve through the ambient working directory or a stale search result and target another project after a rename, fork, or scaffold.

Set the identity once per operation sequence and reuse the encoded identifier without encoding it again:

GITLAB_HOST="<selected GitLab hostname>"
GROUP_PATH="<selected group path>"
PROJECT_NAME="<selected project name>"
PROJECT_PATH="$GROUP_PATH/$PROJECT_NAME"
ENCODED_PROJECT_PATH="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$PROJECT_PATH")"

For a link target in another project, use the same path-first shape instead of a numeric ID:

TARGET_PROJECT_PATH="<target namespace>/<target project>"
TARGET_ENCODED_PROJECT_PATH="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$TARGET_PROJECT_PATH")"

Pass `--hostname "$GITLAB_HOST"` to every `glab api` call. The endpoint itself then pins the project, including directly after creating a repository when the current directory does not yet identify the new project.

GitHub continues to use an `owner/repo` slug; `gh repo` takes it positionally and rejects `-R`:

gh repo view --json nameWithOwner -q '.nameWithOwner'

Canonical enumeration pattern

To enumerate ALL projects (or issues) in a group, a single page is never the whole result — paginate and guard against silent truncation:

# GitLab — paginate a group's projects, following x-next-page until empty
page=1
while [ -n "$page" ]; do
  resp=$(glab api --hostname "$GITLAB_HOST" "groups/<group-id>/projects?simple=true&include_subgroups=true&per_page=100&page=$page" --include)
  # parse the response body ($resp) for project ids/paths here, deduping by id.
  # Then advance by reading the `x-next-page` response header — an empty value
  # means this was the last page, so the loop exits (the guard above is what breaks).
  page=$(printf '%s\n' "$resp" | awk -F': *' 'tolower($1)=="x-next-page"{sub(/\r/,"",$2); print $2}')
done
  • **Follow pagination via the `x-next-page` response header** — loop until it comes back empty. A single-page read on a known-large group is a signal the loop stopped early, not proof the group is small.
  • **Dedupe by project id** — subgroup traversal can surface the same project more than once.
  • **Silent-zero guard:** `membership=true` can return a misleadingly small subset (e.g. a host that only sees a handful of a group's dozens of projects). If the count looks suspiciously low relative to the known group size, retry WITHOUT `membership` (rely on `include_subgroups=true` alone) before trusting the result. A zero/one-page result on a known-large group is a probable auth/pagination bug — treat it as a bug signal, never as ground truth that "the group is actually empty."

Label Taxonomy

**Taxonomy convention — `priority` REVERSED to scoped `::` (supersedes #727 for this one axis).**

  • **`priority::<level>` is canonical.** #727's stated rationale was that "this repo mirrors to GitHub, which has no scoped-label semantics … while a migration would break every existing label reference
Read more
Ships withsession-orchestrator

Give your agents a working rhythm. You type three commands: /session reads your repository, your open issues and the last session, proposes what to work on, and waits for your correction.

Get the whole plugin

Other skills on session-orchestrator.