From a3d9ae393be10fd23adeaadfa3936779cafeda3a Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Thu, 10 Sep 2026 09:11:58 -0700 Subject: [PATCH 1/3] Add CLAUDE.md agent guidance Document build/test/lint/generate commands, the cmd/ layout, the shared command flow over go.step.sm/crypto/kms, build-tag and release conventions, and related repos for agents working in this repository. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01JuSZFSx1cTEnqY55oquacV --- CLAUDE.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..763093d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,88 @@ +# CLAUDE.md + +This file provides guidance to Claude Code when working with code in this repository. + +## Overview + +`step-kms-plugin` is a small Cobra CLI (module `github.com/smallstep/step-kms-plugin`, Apache-2.0) that creates keys, signs, encrypts/decrypts, and manages certificates on cloud KMSs, HSMs, TPMs, YubiKeys, and the macOS keychain. It runs standalone or as a `step` plugin: `step kms ` execs `step-kms-plugin ` with the same arguments. Nearly all KMS logic lives upstream in `go.step.sm/crypto/kms`; this repo is the CLI surface over that library. `main.go` blank-imports every KMS backend (`awskms`, `azurekms`, `capi`, `cloudkms`, `mackms`, `pkcs11`, `platform`, `softkms`, `sshagentkms`, `tpmkms`, `yubikey`) so they self-register. + +## Commands + +```bash +make build # go build -> bin/step-kms-plugin (needs cgo + libpcsclite for pkcs11/yubikey) +make build-fips # same with GOFIPS140 and -tags noyubikey +make test # go test -coverprofile=coverage.out ./... +make lint # golangci-lint (config fetched from smallstep/workflows) + govulncheck +make fmt # goimports with --local for this module and go.step.sm/crypto +make generate # go generate ./... then regenerate completions/* from the built binary +make bootstrap # install golangci-lint, govulncheck, gotestsum +make release-dry-run # goreleaser-cross-pro in Docker; needs GORELEASER_KEY +``` + +There are currently no `_test.go` files, so `make test` only compiles the packages (coverage reports 0%). `make build` takes about 20s cold on macOS with no extra setup. CI (`.github/workflows/ci.yml`) calls the shared `smallstep/workflows` `goCI.yml` with `os-dependencies: libpcsclite-dev`, `only-latest-golang: false`, and CodeQL enabled, so lint, vulncheck, and the build must pass on every supported Go version, not just the latest. + +Run the binary locally with `bin/step-kms-plugin ` or, after putting it on `$PATH` or in `$(step path --base)/plugins`, as `step kms `. + +Cross-compiling with cgo (`.goreleaser.yml`) sets a per-target `CC`; `make build` on the host is the normal dev loop. `CGO_ENABLED=0` builds still work (see `docker/Dockerfile.cloud`) but drop pkcs11, yubikey, and the macOS keychain backends via the `!cgo` build files in `go.step.sm/crypto/kms/*`. + +## Generated Code — Do Not Edit + +| Pattern | Generator | +|---------|-----------| +| `completions/{bash,fish,powershell,zsh}_completion` | `make generate` (Cobra `completion` subcommand of the built binary); shipped in release archives and deb/rpm packages | + +## Architecture + +``` +step-kms-plugin/ +├── main.go # imports cmd + blank-imports all go.step.sm/crypto/kms backends +├── cmd/ +│ ├── root.go # rootCmd, persistent --kms flag, openKMS(), URI helpers, PromptPassword hook +│ ├── create.go # create : --kty/--crv/--size/--alg/--pss, YubiKey pin/touch policy, TPM AK/attest-by +│ ├── key.go, key_delete.go # key (print public key), key delete +│ ├── certificate*.go # certificate (print), certificate copy, certificate delete +│ ├── sign.go # sign [digest]: --in file, --alg, --pss, --format (base64/hex/jws/raw) +│ ├── encrypt.go, decrypt.go # RSA-OAEP/PKCS#1 encrypt with a public key, decrypt with a KMS key +│ ├── attest.go # attest : YubiKey/TPM attestation certs and ACME device-attest-01 objects +│ ├── search.go # search : list keys in a KMS that implements SearchKeys (anonymous interface) +│ ├── ctk.go # darwin+cgo only: list CryptoTokenKit identities +│ └── version.go # Version/ReleaseDate set via -ldflags -X (Makefile and goreleaser) +├── internal/ +│ ├── flagutil/ # MustString/MustInt/MustBool + allow-listed pflag.Value helpers +│ ├── termutil/ # password prompt on the controlling terminal (borrowed from age) +│ └── darwin/{corefoundation,security}/ # cgo bindings to CoreFoundation and Security.framework (darwin+cgo) +├── completions/ # generated shell completions +├── docker/ # Dockerfile (alpine), .debian, .cloud (CGO_ENABLED=0), .wolfi (build-fips) +├── scripts/ # package-upload.sh, package-repo-import.sh (goreleaser publisher hooks) +├── .goreleaser.yml # cross builds (linux/darwin/windows), archives, nfpm deb/rpm, SBOMs +└── Makefile +``` + +### Command flow + +Every command follows the same shape: + +1. Validate positional args; on misuse return `showErrUsage(cmd)` so Cobra prints usage. +2. Read flags with `flagutil.Must*` (panics on a typo in the flag name, which is intentional: the flag must be defined in `init()`). +3. Resolve the KMS URI. The persistent `--kms ` flag configures the backend; the positional `` names the key. `getURIAndNameForFS` / `openKMS` in `root.go` merge them, add the `:` scheme suffix if missing (`--kms tpmkms` works), and for `tpmkms:` inject `storage-directory=$(step path)/tpm` after calling `step.Init()` from `cli-utils`. +4. `kms.New(ctx, apiv1.Options{...})` returns an `apiv1.KeyManager`; commands type-assert the optional interfaces they need (`apiv1.CertificateManager`, `CertificateChainManager`, `Attester`, `Decrypter`, or an inline interface for `SearchKeys`) and return a clear error when the backend does not implement one. +5. Output goes to stdout as PEM (`outputCert`, `pemutil`) or `--json` where supported. + +Adding a subcommand: new file in `cmd/`, define a `*cobra.Command`, register it in that file's `init()` with `rootCmd.AddCommand(...)` (or `certificateCmd`/`keyCmd` for nested commands), set `SilenceUsage = true` on commands that should not dump usage on runtime errors, then `make generate` to refresh completions. + +## Conventions + +- **CLI**: Cobra + pflag. Flags only, no config file and no env-var binding. `Long` and `Example` strings on every command are the primary user documentation, so keep them accurate; the README examples mirror them. +- **Errors**: stdlib `errors` and `fmt.Errorf` with `%w`. No `pkg/errors`. Return errors from `RunE`; do not `os.Exit` inside commands. +- **Logging**: none. Commands print results to stdout and rely on Cobra to print errors to stderr. +- **Passwords/PINs**: `pemutil.PromptPassword` is wired to `termutil.ReadPassword` in `root.go`; PINs can also come from the URI (`pin-value=`, `pin-source=`). +- **Build tags**: darwin-only cgo code is guarded with `//go:build darwin && cgo`. Upstream backends honor `noyubikey` / `nopkcs11` tags (used by `build-fips`). Keep cross-platform code out of `internal/darwin/`. +- **Imports**: three groups (stdlib, third-party, `go.step.sm/crypto`, then this module) as enforced by `make fmt`. +- **License headers**: Go files carry the Apache-2.0 header; `internal/termutil` keeps its original BSD header from age. +- **Releases**: pushing a `v*` tag runs `release.yml` (GitHub release, goreleaser-pro archives + deb/rpm, four Docker images). Version strings come from the tag; do not hand-edit `cmd.Version`. + +## Related Repos + +- `go.step.sm/crypto` (github.com/smallstep/crypto) provides every KMS implementation; most feature work starts there and this repo just exposes it. To develop against a local checkout add `replace go.step.sm/crypto => ../crypto` to `go.mod` temporarily (never commit it). +- `github.com/smallstep/cli-utils` supplies `step.Init()` / `step.Path()` for the TPM storage directory. +- `github.com/smallstep/cli` (`step`) invokes this binary for `step kms ...` and for `--kms` on `step certificate create/sign`. From 49e7e8a34708e6f22d21cc3f31daf7723a97af14 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Thu, 10 Sep 2026 09:19:36 -0700 Subject: [PATCH 2/3] Move guidance to AGENTS.md, import it from CLAUDE.md AGENTS.md is the vendor-neutral file read by other coding agents. Claude Code does not read it natively, so CLAUDE.md becomes a one-line @AGENTS.md import that loads the same content. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01JuSZFSx1cTEnqY55oquacV --- AGENTS.md | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 89 +------------------------------------------------------ 2 files changed, 89 insertions(+), 88 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b2b2a51 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,88 @@ +# AGENTS.md + +Guidance for AI coding agents working in this repository. Claude Code loads it through the one-line `@AGENTS.md` import in `CLAUDE.md`. + +## Overview + +`step-kms-plugin` is a small Cobra CLI (module `github.com/smallstep/step-kms-plugin`, Apache-2.0) that creates keys, signs, encrypts/decrypts, and manages certificates on cloud KMSs, HSMs, TPMs, YubiKeys, and the macOS keychain. It runs standalone or as a `step` plugin: `step kms ` execs `step-kms-plugin ` with the same arguments. Nearly all KMS logic lives upstream in `go.step.sm/crypto/kms`; this repo is the CLI surface over that library. `main.go` blank-imports every KMS backend (`awskms`, `azurekms`, `capi`, `cloudkms`, `mackms`, `pkcs11`, `platform`, `softkms`, `sshagentkms`, `tpmkms`, `yubikey`) so they self-register. + +## Commands + +```bash +make build # go build -> bin/step-kms-plugin (needs cgo + libpcsclite for pkcs11/yubikey) +make build-fips # same with GOFIPS140 and -tags noyubikey +make test # go test -coverprofile=coverage.out ./... +make lint # golangci-lint (config fetched from smallstep/workflows) + govulncheck +make fmt # goimports with --local for this module and go.step.sm/crypto +make generate # go generate ./... then regenerate completions/* from the built binary +make bootstrap # install golangci-lint, govulncheck, gotestsum +make release-dry-run # goreleaser-cross-pro in Docker; needs GORELEASER_KEY +``` + +There are currently no `_test.go` files, so `make test` only compiles the packages (coverage reports 0%). `make build` takes about 20s cold on macOS with no extra setup. CI (`.github/workflows/ci.yml`) calls the shared `smallstep/workflows` `goCI.yml` with `os-dependencies: libpcsclite-dev`, `only-latest-golang: false`, and CodeQL enabled, so lint, vulncheck, and the build must pass on every supported Go version, not just the latest. + +Run the binary locally with `bin/step-kms-plugin ` or, after putting it on `$PATH` or in `$(step path --base)/plugins`, as `step kms `. + +Cross-compiling with cgo (`.goreleaser.yml`) sets a per-target `CC`; `make build` on the host is the normal dev loop. `CGO_ENABLED=0` builds still work (see `docker/Dockerfile.cloud`) but drop pkcs11, yubikey, and the macOS keychain backends via the `!cgo` build files in `go.step.sm/crypto/kms/*`. + +## Generated Code — Do Not Edit + +| Pattern | Generator | +|---------|-----------| +| `completions/{bash,fish,powershell,zsh}_completion` | `make generate` (Cobra `completion` subcommand of the built binary); shipped in release archives and deb/rpm packages | + +## Architecture + +``` +step-kms-plugin/ +├── main.go # imports cmd + blank-imports all go.step.sm/crypto/kms backends +├── cmd/ +│ ├── root.go # rootCmd, persistent --kms flag, openKMS(), URI helpers, PromptPassword hook +│ ├── create.go # create : --kty/--crv/--size/--alg/--pss, YubiKey pin/touch policy, TPM AK/attest-by +│ ├── key.go, key_delete.go # key (print public key), key delete +│ ├── certificate*.go # certificate (print), certificate copy, certificate delete +│ ├── sign.go # sign [digest]: --in file, --alg, --pss, --format (base64/hex/jws/raw) +│ ├── encrypt.go, decrypt.go # RSA-OAEP/PKCS#1 encrypt with a public key, decrypt with a KMS key +│ ├── attest.go # attest : YubiKey/TPM attestation certs and ACME device-attest-01 objects +│ ├── search.go # search : list keys in a KMS that implements SearchKeys (anonymous interface) +│ ├── ctk.go # darwin+cgo only: list CryptoTokenKit identities +│ └── version.go # Version/ReleaseDate set via -ldflags -X (Makefile and goreleaser) +├── internal/ +│ ├── flagutil/ # MustString/MustInt/MustBool + allow-listed pflag.Value helpers +│ ├── termutil/ # password prompt on the controlling terminal (borrowed from age) +│ └── darwin/{corefoundation,security}/ # cgo bindings to CoreFoundation and Security.framework (darwin+cgo) +├── completions/ # generated shell completions +├── docker/ # Dockerfile (alpine), .debian, .cloud (CGO_ENABLED=0), .wolfi (build-fips) +├── scripts/ # package-upload.sh, package-repo-import.sh (goreleaser publisher hooks) +├── .goreleaser.yml # cross builds (linux/darwin/windows), archives, nfpm deb/rpm, SBOMs +└── Makefile +``` + +### Command flow + +Every command follows the same shape: + +1. Validate positional args; on misuse return `showErrUsage(cmd)` so Cobra prints usage. +2. Read flags with `flagutil.Must*` (panics on a typo in the flag name, which is intentional: the flag must be defined in `init()`). +3. Resolve the KMS URI. The persistent `--kms ` flag configures the backend; the positional `` names the key. `getURIAndNameForFS` / `openKMS` in `root.go` merge them, add the `:` scheme suffix if missing (`--kms tpmkms` works), and for `tpmkms:` inject `storage-directory=$(step path)/tpm` after calling `step.Init()` from `cli-utils`. +4. `kms.New(ctx, apiv1.Options{...})` returns an `apiv1.KeyManager`; commands type-assert the optional interfaces they need (`apiv1.CertificateManager`, `CertificateChainManager`, `Attester`, `Decrypter`, or an inline interface for `SearchKeys`) and return a clear error when the backend does not implement one. +5. Output goes to stdout as PEM (`outputCert`, `pemutil`) or `--json` where supported. + +Adding a subcommand: new file in `cmd/`, define a `*cobra.Command`, register it in that file's `init()` with `rootCmd.AddCommand(...)` (or `certificateCmd`/`keyCmd` for nested commands), set `SilenceUsage = true` on commands that should not dump usage on runtime errors, then `make generate` to refresh completions. + +## Conventions + +- **CLI**: Cobra + pflag. Flags only, no config file and no env-var binding. `Long` and `Example` strings on every command are the primary user documentation, so keep them accurate; the README examples mirror them. +- **Errors**: stdlib `errors` and `fmt.Errorf` with `%w`. No `pkg/errors`. Return errors from `RunE`; do not `os.Exit` inside commands. +- **Logging**: none. Commands print results to stdout and rely on Cobra to print errors to stderr. +- **Passwords/PINs**: `pemutil.PromptPassword` is wired to `termutil.ReadPassword` in `root.go`; PINs can also come from the URI (`pin-value=`, `pin-source=`). +- **Build tags**: darwin-only cgo code is guarded with `//go:build darwin && cgo`. Upstream backends honor `noyubikey` / `nopkcs11` tags (used by `build-fips`). Keep cross-platform code out of `internal/darwin/`. +- **Imports**: three groups (stdlib, third-party, `go.step.sm/crypto`, then this module) as enforced by `make fmt`. +- **License headers**: Go files carry the Apache-2.0 header; `internal/termutil` keeps its original BSD header from age. +- **Releases**: pushing a `v*` tag runs `release.yml` (GitHub release, goreleaser-pro archives + deb/rpm, four Docker images). Version strings come from the tag; do not hand-edit `cmd.Version`. + +## Related Repos + +- `go.step.sm/crypto` (github.com/smallstep/crypto) provides every KMS implementation; most feature work starts there and this repo just exposes it. To develop against a local checkout add `replace go.step.sm/crypto => ../crypto` to `go.mod` temporarily (never commit it). +- `github.com/smallstep/cli-utils` supplies `step.Init()` / `step.Path()` for the TPM storage directory. +- `github.com/smallstep/cli` (`step`) invokes this binary for `step kms ...` and for `--kms` on `step certificate create/sign`. diff --git a/CLAUDE.md b/CLAUDE.md index 763093d..43c994c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,88 +1 @@ -# CLAUDE.md - -This file provides guidance to Claude Code when working with code in this repository. - -## Overview - -`step-kms-plugin` is a small Cobra CLI (module `github.com/smallstep/step-kms-plugin`, Apache-2.0) that creates keys, signs, encrypts/decrypts, and manages certificates on cloud KMSs, HSMs, TPMs, YubiKeys, and the macOS keychain. It runs standalone or as a `step` plugin: `step kms ` execs `step-kms-plugin ` with the same arguments. Nearly all KMS logic lives upstream in `go.step.sm/crypto/kms`; this repo is the CLI surface over that library. `main.go` blank-imports every KMS backend (`awskms`, `azurekms`, `capi`, `cloudkms`, `mackms`, `pkcs11`, `platform`, `softkms`, `sshagentkms`, `tpmkms`, `yubikey`) so they self-register. - -## Commands - -```bash -make build # go build -> bin/step-kms-plugin (needs cgo + libpcsclite for pkcs11/yubikey) -make build-fips # same with GOFIPS140 and -tags noyubikey -make test # go test -coverprofile=coverage.out ./... -make lint # golangci-lint (config fetched from smallstep/workflows) + govulncheck -make fmt # goimports with --local for this module and go.step.sm/crypto -make generate # go generate ./... then regenerate completions/* from the built binary -make bootstrap # install golangci-lint, govulncheck, gotestsum -make release-dry-run # goreleaser-cross-pro in Docker; needs GORELEASER_KEY -``` - -There are currently no `_test.go` files, so `make test` only compiles the packages (coverage reports 0%). `make build` takes about 20s cold on macOS with no extra setup. CI (`.github/workflows/ci.yml`) calls the shared `smallstep/workflows` `goCI.yml` with `os-dependencies: libpcsclite-dev`, `only-latest-golang: false`, and CodeQL enabled, so lint, vulncheck, and the build must pass on every supported Go version, not just the latest. - -Run the binary locally with `bin/step-kms-plugin ` or, after putting it on `$PATH` or in `$(step path --base)/plugins`, as `step kms `. - -Cross-compiling with cgo (`.goreleaser.yml`) sets a per-target `CC`; `make build` on the host is the normal dev loop. `CGO_ENABLED=0` builds still work (see `docker/Dockerfile.cloud`) but drop pkcs11, yubikey, and the macOS keychain backends via the `!cgo` build files in `go.step.sm/crypto/kms/*`. - -## Generated Code — Do Not Edit - -| Pattern | Generator | -|---------|-----------| -| `completions/{bash,fish,powershell,zsh}_completion` | `make generate` (Cobra `completion` subcommand of the built binary); shipped in release archives and deb/rpm packages | - -## Architecture - -``` -step-kms-plugin/ -├── main.go # imports cmd + blank-imports all go.step.sm/crypto/kms backends -├── cmd/ -│ ├── root.go # rootCmd, persistent --kms flag, openKMS(), URI helpers, PromptPassword hook -│ ├── create.go # create : --kty/--crv/--size/--alg/--pss, YubiKey pin/touch policy, TPM AK/attest-by -│ ├── key.go, key_delete.go # key (print public key), key delete -│ ├── certificate*.go # certificate (print), certificate copy, certificate delete -│ ├── sign.go # sign [digest]: --in file, --alg, --pss, --format (base64/hex/jws/raw) -│ ├── encrypt.go, decrypt.go # RSA-OAEP/PKCS#1 encrypt with a public key, decrypt with a KMS key -│ ├── attest.go # attest : YubiKey/TPM attestation certs and ACME device-attest-01 objects -│ ├── search.go # search : list keys in a KMS that implements SearchKeys (anonymous interface) -│ ├── ctk.go # darwin+cgo only: list CryptoTokenKit identities -│ └── version.go # Version/ReleaseDate set via -ldflags -X (Makefile and goreleaser) -├── internal/ -│ ├── flagutil/ # MustString/MustInt/MustBool + allow-listed pflag.Value helpers -│ ├── termutil/ # password prompt on the controlling terminal (borrowed from age) -│ └── darwin/{corefoundation,security}/ # cgo bindings to CoreFoundation and Security.framework (darwin+cgo) -├── completions/ # generated shell completions -├── docker/ # Dockerfile (alpine), .debian, .cloud (CGO_ENABLED=0), .wolfi (build-fips) -├── scripts/ # package-upload.sh, package-repo-import.sh (goreleaser publisher hooks) -├── .goreleaser.yml # cross builds (linux/darwin/windows), archives, nfpm deb/rpm, SBOMs -└── Makefile -``` - -### Command flow - -Every command follows the same shape: - -1. Validate positional args; on misuse return `showErrUsage(cmd)` so Cobra prints usage. -2. Read flags with `flagutil.Must*` (panics on a typo in the flag name, which is intentional: the flag must be defined in `init()`). -3. Resolve the KMS URI. The persistent `--kms ` flag configures the backend; the positional `` names the key. `getURIAndNameForFS` / `openKMS` in `root.go` merge them, add the `:` scheme suffix if missing (`--kms tpmkms` works), and for `tpmkms:` inject `storage-directory=$(step path)/tpm` after calling `step.Init()` from `cli-utils`. -4. `kms.New(ctx, apiv1.Options{...})` returns an `apiv1.KeyManager`; commands type-assert the optional interfaces they need (`apiv1.CertificateManager`, `CertificateChainManager`, `Attester`, `Decrypter`, or an inline interface for `SearchKeys`) and return a clear error when the backend does not implement one. -5. Output goes to stdout as PEM (`outputCert`, `pemutil`) or `--json` where supported. - -Adding a subcommand: new file in `cmd/`, define a `*cobra.Command`, register it in that file's `init()` with `rootCmd.AddCommand(...)` (or `certificateCmd`/`keyCmd` for nested commands), set `SilenceUsage = true` on commands that should not dump usage on runtime errors, then `make generate` to refresh completions. - -## Conventions - -- **CLI**: Cobra + pflag. Flags only, no config file and no env-var binding. `Long` and `Example` strings on every command are the primary user documentation, so keep them accurate; the README examples mirror them. -- **Errors**: stdlib `errors` and `fmt.Errorf` with `%w`. No `pkg/errors`. Return errors from `RunE`; do not `os.Exit` inside commands. -- **Logging**: none. Commands print results to stdout and rely on Cobra to print errors to stderr. -- **Passwords/PINs**: `pemutil.PromptPassword` is wired to `termutil.ReadPassword` in `root.go`; PINs can also come from the URI (`pin-value=`, `pin-source=`). -- **Build tags**: darwin-only cgo code is guarded with `//go:build darwin && cgo`. Upstream backends honor `noyubikey` / `nopkcs11` tags (used by `build-fips`). Keep cross-platform code out of `internal/darwin/`. -- **Imports**: three groups (stdlib, third-party, `go.step.sm/crypto`, then this module) as enforced by `make fmt`. -- **License headers**: Go files carry the Apache-2.0 header; `internal/termutil` keeps its original BSD header from age. -- **Releases**: pushing a `v*` tag runs `release.yml` (GitHub release, goreleaser-pro archives + deb/rpm, four Docker images). Version strings come from the tag; do not hand-edit `cmd.Version`. - -## Related Repos - -- `go.step.sm/crypto` (github.com/smallstep/crypto) provides every KMS implementation; most feature work starts there and this repo just exposes it. To develop against a local checkout add `replace go.step.sm/crypto => ../crypto` to `go.mod` temporarily (never commit it). -- `github.com/smallstep/cli-utils` supplies `step.Init()` / `step.Path()` for the TPM storage directory. -- `github.com/smallstep/cli` (`step`) invokes this binary for `step kms ...` and for `--kms` on `step certificate create/sign`. +@AGENTS.md From 9a7d0e36cbeb9a1d3acf06ba6f16bb84d0b41386 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Thu, 10 Sep 2026 09:39:04 -0700 Subject: [PATCH 3/3] Move Claude Code stub to .claude/CLAUDE.md Per review: keep the repo root to AGENTS.md and put the Claude Code import stub under .claude/, importing @../AGENTS.md. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01JuSZFSx1cTEnqY55oquacV --- .claude/CLAUDE.md | 1 + AGENTS.md | 2 +- CLAUDE.md | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 .claude/CLAUDE.md delete mode 100644 CLAUDE.md diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md new file mode 100644 index 0000000..dba71e9 --- /dev/null +++ b/.claude/CLAUDE.md @@ -0,0 +1 @@ +@../AGENTS.md diff --git a/AGENTS.md b/AGENTS.md index b2b2a51..fa5e63b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # AGENTS.md -Guidance for AI coding agents working in this repository. Claude Code loads it through the one-line `@AGENTS.md` import in `CLAUDE.md`. +Guidance for AI coding agents working in this repository. Claude Code loads it through the one-line `@../AGENTS.md` import in `.claude/CLAUDE.md`. ## Overview diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 43c994c..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -@AGENTS.md