Skip to content

Repository files navigation

gitlab-kiosk

Read-only, public-only GitLab CLI for agentic coding sessions. Built by Radius Method.

What this is

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.

Installation

With Homebrew

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-kiosk

For local formula iteration from a checkout of this repo:

brew tap radiusmethod/gitlab-kiosk "$(pwd)"
brew install --build-from-source radiusmethod/gitlab-kiosk/gitlab-kiosk

Homebrew 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-kiosk

Make 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-local

From source

go install github.com/radiusmethod/gitlab-kiosk/cmd/glk@latest
go install github.com/radiusmethod/gitlab-kiosk/cmd/grec@latest

Remove the go install copies with:

make uninstall

From GitHub releases

Download the binaries for your platform from the releases page and place them on your PATH.

With mise

mise use -g go:github.com/radiusmethod/gitlab-kiosk/cmd/glk
mise use -g go:github.com/radiusmethod/gitlab-kiosk/cmd/grec

Agent skill setup

Skill files

Claude 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 both

Or target one host:

glk install-skills --host claude
glk install-skills --host codex

Skills 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.

Claude Code setup

Permission rules

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.

PreToolUse hook

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.

CLI reference

glk commands

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.

btw: next-command guidance

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

grec commands

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

Exit codes

Code Meaning
0 Success
1 General error (network, parse, config)
2 Safety refusal (private repo, non-public visibility)
3 Not found (404)

Configuration

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 = 1

The 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.

Safety model

Three-layer defense

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)

Safety invariants

  • 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.

Development

Prerequisites

Getting started

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

Make targets

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

Pre-push hooks

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.

License

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.

Releases

Contributors

Languages