# AGENTS.md ## Project Overview `vault-tools` is a Go monorepo of small CLIs for managing Vault tokens across multiple vault instances ("contexts"): - **`vctl`** — logs in to / renews Vault tokens per context (`login`, `renew`, `list`), with `--all`, `--method` and `--user` flags. Caches each token under `~/.cache/vault/` as JSON (token + accessor + policies + TTL/expiry). - **`vctx`** — thin wrapper around the real `vault` CLI: `vctx --context ` resolves the context, sets `VAULT_ADDR`/`VAULT_TOKEN`/`VAULT_NAMESPACE`, and execs `vault`. Both tools share the `shared/` package (config parsing, token cache, Vault HTTP client) and read the SAME config file (`~/.config/vault/vctl.yaml` or `config.yaml`) and token cache so one `~/.config/vault/` configures everything. ## Structure ``` shared/ # config.go, cache.go, vault.go (+ *_test.go) vctl/main.go # vctl CLI (module main package) vctx/main.go # vctx CLI (module main package) docs/vctl.md # per-command docs docs/vctx.md go.mod # module git.unkin.net/unkin/vault-tools Makefile # build / test / lint / completions / rpm / version-bump packaging/nfpm.yaml# nfpm spec (envsubst-templated) for the RPM (both binaries) scripts/build-rpm.sh .woodpecker/ # CI: build, test, pre-commit (PR) + release (tag) dist/ # build output: binaries, completions, RPM (not committed) ``` Each tool is a separate `main` package under its own folder, so `make build` builds each with its own `-o` (a single `go build ./...` can't emit multiple mains to one file). ## Build / test ```bash make build # -> dist/vctl, dist/vctx make test # go test -race ./... make completions # -> dist/completions/{vctl,vctx}.{bash,fish}, _{vctl,vctx} make rpm # build + nfpm RPM (bundles completions) go build ./... && go test ./... ``` ## Conventions - Config/cache dirs honour `$XDG_CONFIG_HOME` / `$XDG_CACHE_HOME`. - Context names may contain slashes (`staging/sydney`) and nest in the cache; names are validated to prevent path traversal (see `shared/cache.go`). - Token files are `0600`, their parent dirs `0700`; writes are atomic (temp file + rename). - `shared/vault.go` is a small hand-rolled Vault HTTP client (no `hashicorp/vault/api` dependency) — only `cobra`, `yaml.v3`, `x/term`. ## Releasing Releases run in Woodpecker on `v*` tags. `make patch|minor|major` tags + pushes. The release pipeline cross-compiles both binaries, builds an RPM (with completions), PUTs it to the artifactapi `rpm-internal` yum repo, and cuts a Gitea release. Every pipeline step sets k8s resources and `serviceAccountName: default`; the release step uses the `RELEASER_TOKEN` Woodpecker secret.