Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
go-version-file: go.mod
- name: Tidy
run: |
go mod tidy
Expand All @@ -46,7 +46,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
go-version-file: go.mod
- uses: golangci/golangci-lint-action@v7
with:
version: v2.12.2
24 changes: 24 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# cli-common — agent entrypoint

Shared libraries and the normative standards docs for the Open CLI Collective
CLI family. This repo is the standards home, so the source-of-truth links
below are local files, not GitHub URLs.

Read first:

- [`docs/development.md`](docs/development.md) — repo-local facts: package
map, build/test commands, hermetic-test rules, release/tagging policy for
this library.
- [`docs/README.md`](docs/README.md) — the standards index: a one-line "use
this when…" per doc, plus the cross-doc conflict-resolution order.

Shared automation:

Source of truth: https://github.com/open-cli-collective/.github
Local convenience copy, if present: `../.github`

When editing a standards doc, keep per-CLI divergences in that doc's
"Current divergences" section, and follow
[`docs/agent-implementation.md`](docs/agent-implementation.md) for how agent
guidance is shaped and where a repeated failure mode gets enforced (docs,
tests, lint, CI, or shared helpers).
24 changes: 24 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# cli-common — agent entrypoint

Shared libraries and the normative standards docs for the Open CLI Collective
CLI family. This repo is the standards home, so the source-of-truth links
below are local files, not GitHub URLs.

Read first:

- [`docs/development.md`](docs/development.md) — repo-local facts: package
map, build/test commands, hermetic-test rules, release/tagging policy for
this library.
- [`docs/README.md`](docs/README.md) — the standards index: a one-line "use
this when…" per doc, plus the cross-doc conflict-resolution order.

Shared automation:

Source of truth: https://github.com/open-cli-collective/.github
Local convenience copy, if present: `../.github`

When editing a standards doc, keep per-CLI divergences in that doc's
"Current divergences" section, and follow
[`docs/agent-implementation.md`](docs/agent-implementation.md) for how agent
guidance is shaped and where a repeated failure mode gets enforced (docs,
tests, lint, CI, or shared helpers).
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
.PHONY: check tidy lint test build

# CI gate: everything that must pass before merge.
check: tidy lint test
# CI gate: everything that must pass before merge (repo-layout.md §2.1 —
# check mirrors CI, including the build step).
check: tidy lint test build

# Tidy and verify the module is clean. Catches both modified tracked and
# newly-generated untracked go.mod/go.sum (the latter once deps are added).
Expand Down
52 changes: 52 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Development guide — cli-common

Repo-local facts for working in this repository. Family-wide policy lives in
[`README.md`](README.md) (the standards index) and the standards docs beside
it — do not copy policy prose here.

## What this repo is

The shared-library and standards home for the Open CLI Collective. No binary
ships from here; consumers depend on it as a Go module
(`github.com/open-cli-collective/cli-common`). It follows the **library-repo
profile** in [`repo-layout.md`](repo-layout.md) §2.1.

## Packages

| Package | Implements |
|---|---|
| `credstore` | OS-keyring credential store — [`working-with-secrets.md`](working-with-secrets.md) §1.3–§1.5, §1.8, §1.12, §2.1 |
| `statedir` | config/cache/data path resolver — [`working-with-state.md`](working-with-state.md) §6a |
| `statedirtest` | hermetic test helper (8-var env override) — [`working-with-state.md`](working-with-state.md) §3.1 / §5.3 |
| `cache` | tier-1 cache core: envelope, atomic write, freshness — [`working-with-state.md`](working-with-state.md) §6b |

## Build / test

```sh
make check # tidy + lint + test + build — mirrors CI
```

Requires Go per the `go` directive in `go.mod` (the single version source,
`repo-layout.md` §3) and golangci-lint v2.

Tests MUST be hermetic: use the in-memory credstore backend
(`Options.Backend = BackendMemory`) and `statedirtest.Hermetic` (not
`t.Parallel`-safe — use sequentially). Tests never touch the developer's real
OS keychain or home directories; that class of leak is exactly what
`statedirtest` exists to prevent.

## Releases

No auto-release, no `version.txt` (library profile, `repo-layout.md` §2.1).
Semver tags are cut manually. Any exported API **or behavior** change in any
exported package (`credstore`, `statedir`, `statedirtest`, `cache`) is either
purely additive or rides the coordinated consumer release train in
[`working-with-state.md`](working-with-state.md) §6 — no tag until every
ported consumer is green against the candidate SHA.

## Known dependency cost

`byteness/keyring` compiles its 1Password openers (and transitively wazero /
jaeger) into every consumer — documented in
[`working-with-secrets.md`](working-with-secrets.md) §1.10; remediation
tracked in cli-common#57.
2 changes: 1 addition & 1 deletion docs/output-and-rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ The new docs are forward-looking. The following current divergences from this st

- **Resource-read JSON is widespread.** slck, sfdc, nrq, cfl all expose JSON on resource reads via global `-o json`; gro exposes it via per-command `--json`. Only jtk holds the §2 line (reserves JSON for `automation export`). New CLIs MUST NOT add resource-read JSON.
- **gro has no root `--no-color` flag** — `google-readonly/internal/cmd/root/root.go:107-109` registers a global `--verbose` and the credstore backend flag but no color flag. Its lipgloss styling at `google-readonly/internal/view/view.go:34` honors the `NO_COLOR` env natively, which papers over the gap for users who set the env, but the missing flag is a divergence from §8.
- **isatty gating is expected via library defaults but unverified per CLI.** §8 (as amended 2026-06-11) requires color to auto-disable on non-TTY output; fatih/color and lipgloss do this by default, so conformance is expected unless a CLI overrides it — a per-CLI verification pass is tracked in cli-common#55.
- **isatty gating: verified family-wide 2026-06-11** (cli-common#55). §8 requires color to auto-disable on non-TTY output. Audited every color path — color-package imports plus raw-ANSI-literal sweep of non-test source — across the family: atlassian-cli@af0b0b0 (jtk+cfl, all color in `shared/view/view.go`), google-readonly@d61bbc2, newrelic-cli@ed6e6a4, slack-chat-api@edf1aa0 (no color paths at all), salesforce-cli@f62ccc8. No raw ANSI writers, no `color.NoColor = false` / `EnableColor` / forced renderer profiles anywhere; every override found is a *disable* (`--no-color` plumbing; gro additionally drops to `termenv.Ascii`). Library TTY-detection defaults are therefore in effect in all six CLIs — conformant with §8's **isatty-gating requirement** specifically (gro's missing root `--no-color` flag, above, remains an open §8 divergence).
- **No CLI has output goldens.** Per §9.5 this is recommended-not-normative pending the cli-common helper.

Command-surface divergences (init flag-skip failures, missing `set-credential`) are catalogued in `command-surface.md` §9. Scriptability divergences (missing `--non-interactive`, `me` not exiting non-zero) are catalogued in `scriptability.md` §9.
2 changes: 2 additions & 0 deletions docs/working-with-secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ In automation, prefer `set-credential` per-secret over `init` for everything: it

A note on what credstore exposes: as of #24, `credstore` recognizes six backend names — `keychain`, `wincred`, `secret-service`, `file`, `pass`, `memory`. `pass` is the only external secret manager exposed natively; it shells out to the `pass` CLI binary and has no Go SDK dependencies. KeePassXC users get native runtime resolution today through Secret Service (no separate backend needed). 1Password native backends are deliberately not exposed: ByteNess's `op` / `op-connect` / `op-desktop` openers all depend on the upstream `github.com/1password/onepassword-sdk-go` package, which is still pre-1.0 — exposing them here would put a beta SDK on the credential-access critical path. The "default path" above remains the recommendation for most users; `pass` is an opt-in alternative for users who specifically want runtime resolution and accept the per-backend availability/version coupling.

**Known dependency cost (documented trade-off).** Not exposing the 1Password backends does not remove their code: `byteness/keyring` imports its op openers unconditionally, so the 1Password SDKs — and transitively a WASM runtime (`wazero` via `extism`) and the archived `jaeger-client-go` — compile into every credstore consumer. Measured 2026-06-11 against keyring v1.9.3 on a real consumer binary (`slck`): 63 packages in the import graph, ~10.6 MB of attributable symbols, no dead-code elimination (the openers are `init()`-registered). The accepted interim posture is this documented cost; the remediation — an upstream opt-out build tag in ByteNess/keyring — is committed in cli-common#57, and when it lands the consumer build flag becomes part of this standard's build configuration.

## §1.11 Compliance criteria

A CLI is compliant with this standard when all of the following are true at runtime, observable from the user's perspective:
Expand Down
Loading