Skip to content

Commit d4aab7d

Browse files
tashianclaude
andcommitted
Add CLAUDE.md agent guidance
Document the module's purpose, verified Makefile/CI commands, package layout, how command registration wires STEP_* env vars and defaults.json, and the conventions (urfave/cli v1, pkg/errors, testify) contributors and coding agents should follow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JuSZFSx1cTEnqY55oquacV
1 parent f30d8ef commit d4aab7d

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code when working with code in this repository.
4+
5+
## Overview
6+
7+
`cli-utils` (module `github.com/smallstep/cli-utils`) is a small Go library of shared building blocks for Smallstep's `urfave/cli`-based command-line tools. Its main consumers are [`step`](https://github.com/smallstep/cli) and [`step-ca`](https://github.com/smallstep/certificates), which pin it at a tagged version. It is a public, Apache-2.0 library but is not a stable API: the README warns that other projects should not depend on it and that the API can change at any time. There is no binary here, only packages.
8+
9+
## Commands
10+
11+
```bash
12+
make bootstrap # install golangci-lint, govulncheck, gotestsum
13+
make test # unit tests via gotestsum (-short, coverage); this is what `make ci` runs
14+
make race # unit tests with the race detector
15+
make lint # golangci-lint (config fetched from smallstep/workflows) + govulncheck
16+
make fmt # goimports -l -w on all .go files
17+
make # lint + test
18+
```
19+
20+
Plain `go` works too and needs no special environment (no private modules, no Docker, no `go generate`):
21+
22+
```bash
23+
go build ./...
24+
go test -short ./...
25+
go test -run TestParse ./token/ # single test
26+
```
27+
28+
`make test` and `make lint` require the tools from `make bootstrap` on `$PATH`. `make lint` needs network access to download the shared golangci config. CI (`.github/workflows/ci.yml`) calls the shared `goCI` reusable workflow with `run-build: false`, so tests and lint are what gate a PR; CodeQL runs with `go build ./...`.
29+
30+
## Architecture
31+
32+
```
33+
cli-utils/
34+
├── command/ # Global command registry for urfave/cli apps
35+
│ ├── command.go # Register/Retrieve commands; ActionFunc captures the ctx; IsForce()
36+
│ └── version/ # `version` command, registered in init()
37+
├── errs/ # Error constructors with user-facing messages for flag/argument misuse
38+
├── fileutil/ # File writes with overwrite prompts (WriteFile, WriteSnippet, AppendNewLine, ...)
39+
├── step/ # $STEPPATH layout, contexts (profile + authority), defaults.json flag loading
40+
│ ├── config.go # Path(), Home(), BasePath(), Version(), file-location helpers
41+
│ └── context.go # Context/CtxState, contexts.json, SetEnvVar, getConfigVars
42+
├── token/ # JWT claim builders (token.Options) and parsing for step provisioning tokens
43+
│ └── provision/ # provision.Token: builds a signed JWT from token.Options
44+
├── ui/ # promptui-based interactive prompts, validators, colored output to stderr
45+
├── usage/ # Custom help templates and renderer (markdown-ish help text, HTML export)
46+
└── pkg/blackfriday/ # Vendored fork of russross/blackfriday v2 used by usage/ (own LICENSE.txt)
47+
```
48+
49+
### How the pieces fit
50+
51+
- A CLI registers each `cli.Command` with `command.Register`. That calls `step.SetEnvVar`, which gives every flag an `EnvVar` of `STEP_<FLAG_NAME>` (uppercased, `-` to `_`) unless one is already set, and installs `getConfigVars` as the command's `Before` hook so unset flags are filled from the active context's `defaults.json`. Set a flag's `EnvVar` to `step.IgnoreEnvVar` to opt it out of both.
52+
- `step` resolves the config root from `STEPPATH` (default `$HOME/.step`) once, via `sync.Once`. With contexts enabled, per-authority config lives under `authorities/<name>/` and profiles under `profiles/<name>/`; `contexts.json` and `current-context.json` sit at the root. Call `step.Init()` before using these helpers.
53+
- `usage` overrides urfave/cli's `help` command and templates. Command `Description`/`UsageText` strings use a lightweight markdown dialect (`**bold**`, `'''` fenced blocks, `## SECTIONS`) that `usage.Render` turns into terminal output via `pkg/blackfriday`; `step help --html <dir>` exports the same content as HTML.
54+
- `fileutil.WriteFile` and friends consult `command.IsForce()`; without `--force` they prompt through `ui` before overwriting.
55+
- `ui` prints prompts and messages to stderr (never stdout) so command output stays pipeable; `ui_windows.go`/`ui_other.go` are build-tagged for console-mode handling.
56+
57+
## Conventions
58+
59+
**CLI framework**: `urfave/cli` v1 (`github.com/urfave/cli`), not v2. Errors returned to users go through `errs` constructors so messages are consistent across `step` commands.
60+
61+
**Error wrapping**: `github.com/pkg/errors` throughout (`errors.Errorf`, `errors.Wrapf`); `errs.Wrap` normalizes causes for display. Do not introduce `fmt.Errorf("%w")` in a file that otherwise uses `pkg/errors`.
62+
63+
**Logging**: none. Output goes to `ui.Print*` (stderr) or `fmt.Print*` (stdout) as appropriate.
64+
65+
**Testing**: `testify` (`assert`/`require`) for new tests; a few older tests still use `github.com/smallstep/assert`. Tests that touch `$STEPPATH` use `t.TempDir()` plus `t.Setenv(step.HomeEnv, ...)` to stay hermetic. Fixtures live in `token/testdata/` (certificates and keys) and `pkg/blackfriday/testdata/` (markdown/HTML pairs). `command/`, `fileutil/`, and `usage/` have no tests.
66+
67+
**Vendored code**: `pkg/blackfriday/` is a copy of an upstream library with its own license and README. Keep changes there minimal and clearly motivated; the rest of the repo is where Smallstep-specific behavior belongs.
68+
69+
**Compatibility**: `step` and `step-ca` are the callers. Renaming or changing the signature of an exported symbol breaks them on their next dependency bump, so prefer additive changes and check both consumers before removing anything.
70+
71+
## Environment Variables
72+
73+
- `STEPPATH` — root of the step configuration directory (default `$HOME/.step`)
74+
- `HOME` — used to derive the default `STEPPATH`; falls back to `os/user`
75+
- `STEP_<FLAG>` — auto-derived per-flag overrides for any command registered via `command.Register`
76+
- `STEP_IGNORE_ENV_VAR` — sentinel value, not a variable to set: assign it to a flag's `EnvVar` to disable env and defaults.json lookup for that flag
77+
78+
## Releases
79+
80+
Versions are git tags (`v0.12.x`). After tagging, bump the dependency in `step` and `step-ca`; there is no release workflow in this repo.

0 commit comments

Comments
 (0)