@khaale/glc
v0.1.0
Published
LLM-agent native GitLab explorer CLI
Readme
glc
glc is a GitLab explorer CLI built for agents and shell users.
It is designed around a few constraints that matter in practice:
- explicit resource-first commands
- no interactive login, prompts, or pagers
- brief default list output instead of full GitLab payloads
- built-in
jqfiltering and projection - data-only stdout so it works well with pipes
- local JSON-file caching to avoid repeated expensive API reads
The intended use case is exploration and inspection of GitLab groups, projects, repositories, pipelines, and jobs, especially from low-grade LLMs and shell scripts.
Status
This repository currently contains a first working scaffold:
groups list|get|treeprojects list|get|treerepos tree|refs|filepipelines list|getjobs list|get|tracecache status|clear|warm
The CLI is GitLab-only and read-oriented in this version.
Why glc
GitLab CLIs tend to be optimized for human operators who already know the product model and are comfortable with mixed modes, aliases, and interactive flows.
glc takes a different approach:
- commands follow one stable grammar:
glc <resource> <verb> ... - selectors are explicit:
--group,--project,--pipeline,--job - list commands return a restricted stable schema by default
- full payloads are opt-in with
--full - output can be refined with
--fieldsor--jq
That makes the next command easier to generate for both people and weaker models.
Installation
Node.js 22+ is required.
For development in this repo:
npm install
node ./bin/glc.jsIntended package usage:
npm install -g @khaale/glc
glc --helpor:
npx @khaale/glc --helpAuthentication
glc reads GitLab connection settings from environment variables.
export GITLAB_HOST=https://gitlab.example.com
export GITLAB_TOKEN=glpat-xxxxxxxxPowerShell:
$env:GITLAB_HOST="https://gitlab.example.com"
$env:GITLAB_TOKEN="glpat-xxxxxxxx"There is no interactive login flow in v1.
Basic Usage
Command shape:
glc <resource> <verb> [flags]Resources:
groupsprojectsrepospipelinesjobscache
Common selectors:
--group <full-path>--project <path-with-namespace>--pipeline <id>--job <id>--ref <name>--path <repo-path>
Common output flags:
--fields a,b,c--full--json--jsonl--raw--compact--jq '<expression>'
Common control flags:
--limit <n>--page <n>--all--refresh--verbose
Examples
Discover groups and projects
List top-level groups:
glc groups listList subgroups under a group:
glc groups list --group platformShow a namespace tree:
glc groups tree --group platformList projects inside a group:
glc projects list --group platformInspect one project:
glc projects get --project platform/apiShow a project resource tree:
glc projects tree --project platform/apiExplore repositories
Browse repository files:
glc repos tree --project platform/api --ref mainBrowse a subdirectory:
glc repos tree --project platform/api --ref main --path src/List repository refs:
glc repos refs --project platform/apiFetch a file:
glc repos file --project platform/api --ref main --path package.jsonExplore pipelines and jobs
List recent pipelines:
glc pipelines list --project platform/api --limit 10Inspect one pipeline:
glc pipelines get --project platform/api --pipeline 8123List jobs in a pipeline:
glc jobs list --project platform/api --pipeline 8123Inspect one job:
glc jobs get --project platform/api --job 99123Read a job trace:
glc jobs trace --project platform/api --job 99123Output Model
The output rules are intentionally simple:
listcommands default to JSON Linesgetcommands default to pretty JSONtreecommands default to a text treetracecommands return raw text
Formatting flags control the rendered form:
--json: force JSON object/array output--jsonl: force JSON Lines output--raw: emit raw scalar values without JSON quotes--compact: remove pretty indentation from JSON output--fields a,b,c: project a smaller field set before rendering--full: bypass the default summary schema and emit full GitLab objects
Current --compact behavior is narrow by design:
- it affects JSON output
--rawis the right choice when--jqreturns strings for shell loops- it does not change tree output
- it does not change raw trace/file output
- JSON Lines are already compact one-object-per-line output
List output is intentionally restricted by default. It should provide enough information for the next step, not a full API dump.
Examples:
glc projects list --group platformExample row:
{"id":102,"path":"api","path_with_namespace":"platform/api","web_url":"https://gitlab.example.com/platform/api","ssh_url_to_repo":"[email protected]:platform/api.git","http_url_to_repo":"https://gitlab.example.com/platform/api.git","last_activity_at":"2026-03-19T08:10:00Z"}Select a smaller schema:
glc projects list --group platform --fields id,path_with_namespaceRequest full GitLab objects:
glc projects list --group platform --fullForce pretty JSON instead of JSON Lines for a list:
glc projects list --group platform --jsonForce JSON Lines explicitly:
glc projects list --group platform --jsonlReturn compact JSON for a single object:
glc projects get --project platform/api --compactCombine --json and --fields on a tree command:
glc groups tree --group platform --jsonBuilt-in jq
glc can run jq expressions internally through --jq. This lets you filter or reshape output without an extra process in the common case.
Examples:
Project projection:
glc projects list --group platform --jq '{project: .path_with_namespace, last_activity: .last_activity_at}'Only failed pipelines:
glc pipelines list --project platform/api --jq 'select(.status == "failed")'Compact chaining-friendly output:
glc jobs list --project platform/api --pipeline 8123 --jq '{id, name, status}' --compactExtract project nodes from a group tree:
glc groups tree --group platform --json --jq '.. | objects | select(.kind? == "project") | .data.path_with_namespace'Extract raw project paths for a shell loop:
glc projects list --group platform --jq '.path_with_namespace' --rawjq must be available in PATH.
grep and pipes
glc is designed so stdout contains data only. That makes it work cleanly with shell tools.
Examples:
glc pipelines list --project platform/api | grep failed
glc jobs trace --project platform/api --job 99123 | grep -n ERROR
glc projects list --group platform --fields path_with_namespace | grep authCaching
Read commands use cache automatically unless --refresh is passed.
Cache logging is silent by default. Use --verbose if you want to see cache-hit diagnostics on stderr.
Cache examples:
glc cache status
glc cache warm --group platform
glc cache clear --project platform/api
glc projects list --group platform --verboseRefresh a command explicitly:
glc pipelines list --project platform/api --refreshCache location:
- Linux:
~/.cache/glc/or$XDG_CACHE_HOME/glc/ - macOS:
~/Library/Caches/glc/ - Windows:
%LocalAppData%/glc/cache/
Tests
Run the current test suite:
npm testCurrent coverage includes:
- argument parsing
- output mode and field projection
- tree rendering
- JSON-file cache behavior
- CLI help and missing-env error handling
Repository Layout
- bin/glc.js: executable entrypoint
- src/cli.js: command dispatch and top-level runtime
- src/commands: resource handlers
- src/lib: shared config, cache, output, jq, and GitLab client logic
- docs/design.md: user-facing design document
Limitations
Current gaps in this first implementation:
- no write operations
- no interactive auth/config flow
- no retry/backoff policy yet
- no dedicated integration tests against a real GitLab instance
--jqdepends on an installedjqexecutable
Next Steps
Useful next improvements:
- package publishing under a real npm scope
- integration tests with recorded or mocked GitLab API responses
- richer pagination and sorting behavior
- clearer field-profile support for list and tree output
- command-specific help and examples
