Read-only, public-only GitLab CLI for agentic coding sessions. Built by Radius Method.
Two Go binaries that give Claude safe, structured access to public GitLab repositories:
glk— Talks to the GitLab API. Search projects, read issues and MRs, browse files, check pipelines.grec— Manages a local repo cache. Index your existing clones, look up paths, shallow-clone new repos.
Both enforce a strict safety model: GET-only HTTP, public-only visibility checks, pinned host, no credentials by default. The GitLab host is required — there is no default — so every request goes to an instance you explicitly configured.
This repo carries its own Formula/gitlab-kiosk.rb, and Homebrew builds both binaries locally from source. That avoids macOS Gatekeeper complaints about downloaded unsigned release binaries.
brew tap radiusmethod/gitlab-kiosk https://github.com/radiusmethod/gitlab-kiosk.git
brew install --build-from-source radiusmethod/gitlab-kiosk/gitlab-kioskFor local formula iteration from a checkout of this repo:
brew tap radiusmethod/gitlab-kiosk "$(pwd)"
brew install --build-from-source radiusmethod/gitlab-kiosk/gitlab-kioskHomebrew clones the tapped repo, so it sees committed changes. For uncommitted formula edits, commit first or copy the formula into the cloned tap under $(brew --repository)/Library/Taps/radiusmethod/homebrew-gitlab-kiosk/Formula/.
Upgrade after a new tagged release:
brew update
brew upgrade radiusmethod/gitlab-kiosk/gitlab-kioskMake helpers for the Homebrew flows:
make brew-tap-remote
make brew-install-remote
make brew-uninstall-remote
make brew-untap-remote
make brew-tap-local
make brew-install-local
make brew-uninstall-local
make brew-untap-localgo install github.com/radiusmethod/gitlab-kiosk/cmd/glk@latest
go install github.com/radiusmethod/gitlab-kiosk/cmd/grec@latestRemove the go install copies with:
make uninstallDownload the binaries for your platform from the releases page and place them on your PATH.
mise use -g go:github.com/radiusmethod/gitlab-kiosk/cmd/glk
mise use -g go:github.com/radiusmethod/gitlab-kiosk/cmd/grecClaude Code and Codex discover glk and grec through Skill files, not MCP tool schemas. The canonical copies live in this repo under skill/.
Install or refresh both hosts:
glk install-skills --host bothOr target one host:
glk install-skills --host claude
glk install-skills --host codexSkills install to:
~/.claude/skills/gitlab-kiosk/SKILL.md~/.claude/skills/grec/SKILL.md~/.codex/skills/gitlab-kiosk/SKILL.md~/.codex/skills/grec/SKILL.md
These load on demand — zero token overhead when the tools aren't needed.
When glk install-skills updates an existing managed file, it first writes an adjacent backup like SKILL.md.<epoch>.bak.
Auto-approve both binaries in ~/.claude/settings.json:
{
"permissions": {
"allow": [
"Bash(glk *)",
"Bash(grec *)"
]
}
}Safe because the binaries themselves enforce read-only, public-only access.
The hook catches cases where Claude reaches for curl or glab instead of glk. It's a subcommand of the binary — nothing extra to install.
Add to ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|WebFetch",
"hooks": [
{
"type": "command",
"command": "glk hook run"
}
]
}
]
}
}When glk install-hooks updates an existing config file, it first writes an adjacent backup like settings.json.<epoch>.bak.
The hook reads the configured host from config.toml. To guard multiple hosts, add them to your config file's [gitlab] section.
| Command | Description |
|---|---|
glk search <keyword> |
Search public projects |
glk code-search [project] <query> [--filename GLOB] [--group] |
Search code in a public project or group |
glk project <owner/repo> |
Project metadata |
glk issues <owner/repo> |
List issues |
glk issue <owner/repo> <iid> |
Single issue detail |
glk mrs <owner/repo> |
List merge requests |
glk mr <owner/repo> <iid> |
Single MR detail |
glk file <owner/repo> <path> |
Read file contents (base64 decoded) |
glk tree <owner/repo> [path] |
Browse repository tree |
glk pipelines <owner/repo> |
List pipelines |
glk pipeline <owner/repo> <id> |
Pipeline detail (--wait to poll) |
glk pipeline-jobs <owner/repo> <pipeline-id> |
List jobs for a pipeline |
glk job-trace <owner/repo> <job-id> |
Job trace output (--tail N) |
glk releases <owner/repo> |
List releases |
glk doctor |
Check local binary and skill health |
glk config show |
Print resolved configuration |
glk version |
Version and build info |
All list commands accept --limit N and --page N. Default to headerless TSV for exploratory reads and simple lookups. Use --json only when TSV omits a field you need or when you will actually parse the structure.
Need to debug live network behavior? Add --http-log-level=debug to any glk command to emit one stderr line per HTTP request without polluting stdout.
glk keeps stdout machine-readable and uses stderr for operational guidance. Lines prefixed with btw: are just-in-time next-command suggestions for agents. They fire when glk sees a common failure precursor, such as an empty search, a nested group path that failed lookup, a failed CI job, or raw trace/artifact output that the agent is likely to save.
The goal is not generic help text. btw: reinforces the preferred command shape at the moment an agent would otherwise guess, wrap, or retry:
btw: use the preferred glk command shape for CI triage: glk job-trace big-bang/bigbang 50001 --tail 2000 --output FILE; glk artifacts big-bang/bigbang 50001 --recursive --match REGEX
Common exploratory read, TSV first:
glk issues big-bang/bigbang --limit 5| Command | Description |
|---|---|
grec index build |
Spider local dirs, build repo index |
grec index list [pattern] |
List indexed repos (glob or substring) |
grec index status |
Index age and entry count |
grec locate <owner/repo> |
Look up local path (no clone) |
grec checkout <project> |
Find locally or shallow-clone, return path |
grec config show |
Print resolved configuration |
grec version |
Version and build info |
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error (network, parse, config) |
| 2 | Safety refusal (private repo, non-public visibility) |
| 3 | Not found (404) |
Both binaries read $XDG_CONFIG_HOME/glk/config.toml (defaults to ~/.config/glk/config.toml). Run glk init to scaffold one — it writes a gitlab.example.com placeholder you must edit before the tool will reach anything.
gitlab.host is required — there is no default host. Set it to the GitLab instance you want to read from (for example gitlab.com, or repo1.dso.mil for Platform One). Commands that make network calls fail with an actionable error until it is set; glk doctor reports it as a problem.
A filled-in config looks like:
[gitlab]
host = "gitlab.com"
# Optional: per-host tokens for rate-limit relief.
# Public-only access is still enforced regardless of token scope.
[gitlab.tokens]
"gitlab.com" = "glpat-xxxxxxxxxxxxxxxxxxxx"
[output]
limit = 20
format = "tsv" # or "json"
[index]
scan_dirs = ["~/code", "~/work", "~/go/src"]
[checkout]
cache_dir = "~/.cache/glk/repos"
depth = 1The GITLAB_TOKEN environment variable overrides all configured tokens. GITLAB_HOST sets the GitLab host, overriding the config file. Override the config file path with GLK_CONFIG.
glk also keeps a short-lived known-safe cache at $XDG_CACHE_HOME/glk/known-safe.sqlite (defaults to ~/.cache/glk/known-safe.sqlite). It stores only namespace and project entries already verified public, with a 60-second TTL.
| Layer | What it does | Security boundary? |
|---|---|---|
| CLI binary | Enforces GET-only, public-only, pinned host, no credentials by default | Yes |
| Permission allow rules | Auto-approves Bash(glk *) and Bash(grec *) |
No (convenience) |
| PreToolUse hook | Blocks curl/glab/WebFetch calls targeting the configured GitLab host |
No (nudge) |
- Read-only — Only HTTP GET requests. No codepath for any other method.
- Public-only — Verifies
visibility == "public"before returning any project data. - Allowlist-only known-safe cache — Persists only public namespace/project proofs in SQLite. Private or internal objects are never cached durably. Expired or failed refreshes fall back to re-verification or suppression.
- Pinned host — All requests go to the configured host. Cross-host redirects are rejected.
- No credentials by default — No auth headers unless a token is explicitly configured for rate-limit relief.
- Go 1.26+
- golangci-lint
- lefthook (optional, for pre-push hooks)
git clone https://github.com/radiusmethod/gitlab-kiosk.git
cd gitlab-kiosk
cp .envrc.example .envrc # edit and `direnv allow`
lefthook install # optional
make build| Target | What it does |
|---|---|
make build |
Build glk and grec binaries |
make test |
Run all tests |
make vet |
Run go vet |
make lint |
Run golangci-lint |
make clean |
Remove built binaries |
Lefthook runs go vet, go test, and golangci-lint before each push. Same commands as make and CI — one source of truth for each check.
Apache-2.0 — see LICENSE.
This software is provided "AS IS", without warranty or condition of any kind, express or implied. Radius Method, Inc. accepts no liability for any damages arising from its use or inability to be used. See sections 7 and 8 of the LICENSE for the full disclaimer and limitation of liability.