OPM CLI — command-line interface for Open Platform Model workflows. Build, validate, render, deploy, inspect portable app releases defined with CUE. Focus: type safety, clear command behavior, Kubernetes-oriented workflows.
Stack: cobra, CUE Go SDK, Kubernetes client-go, charmbracelet/log, testify.
For coding agents working in cli/.
- Small, independently verifiable changes;
CONSTITUTION.mdprefers tiny batches. - Update existing packages over new abstractions unless duplication/coupling justifies it.
Read when entering cli/:
CONSTITUTION.md- repo principles + change-shaping constraints.CLAUDE.md- implementation guidance, commands, package map.README.md- product purpose, command groups, user workflows.docs/STYLE.md- doc prose style rules.
adr/- Architecture Decision Recordscmd/opm/- CLI entrypoint + root command wiring.internal/cmd/- Cobra command implementations.internal/cmdutil/- shared flags, annotations, command-facing helpers.internal/config/- config resolution, schema validation, defaults.internal/kubernetes/- cluster ops, status, apply, delete, events.internal/output/- terminal formatting, log output, tables, manifests.internal/instancefile/- instance file detection + loading.internal/workflow/- shared render/apply/query orchestration.pkg/loader/- CUE loading for modules, providers, releases.pkg/render/- render pipeline logic.pkg/errors/- shared structured errors; alias asoerrors.tests/integration/- integration programs viago run.tests/e2e/- end-to-end Go tests.
- Go version in
go.mod:1.26.0. - Integration + CUE workflows need registry config.
- Local dev defaults:
export OPM_REGISTRY='opmodel.dev=localhost:5000+insecure,registry.cue.works'
export CUE_REGISTRY='opmodel.dev=localhost:5000+insecure,registry.cue.works'task build- build./bin/opmfrom./cmd/opmwith version ldflags.task build:all- cross-compile for Linux, macOS, Windows.task install- install CLI with version ldflags into$GOPATH/bin.task clean- removebin/,coverage.out,coverage.html.task generate- rungo generate ./....
task fmt- rungo fmt ./...andgoimports -w ..task vet- rungo vet ./....task lint- rungolangci-lint run ./....task lint:fix- rungolangci-lint run --fix ./....task tidy- rungo mod tidy.task check- runfmt,vet,lint, all tests.
task test- run unit, integration, e2e suites.task test:unit- rungo test ./internal/...andgo test ./pkg/....task test:integration- run integration programs; needs live kind cluster.task test:e2e- rungo test ./tests/e2e/... -v.task test:verbose- rungo test -v ./....task test:coverage- rungo test -coverprofile=coverage.out ./...then generatecoverage.html.
- Preferred:
task test:run TEST=TestName. - Direct:
go test -v ./... -run "TestName". - Narrow to one package for speed:
go test ./internal/config -run TestLoad -vgo test ./pkg/render -run TestFinalize -v
- Single subtest: use full regexp name via
go test -run.
task cluster:create- create localkindclusteropm-dev.task cluster:status- check cluster running.task cluster:delete- remove local cluster.task cluster:recreate- recreate cluster from scratch.task test:integrationchecks for contextkind-opm-devbefore running.
- Follow
gofmtandgoimports; no hand-formatting imports. - Keep command packages thin; orchestration in
internal/workflowor focused internal/pkg packages. - Explicit behavior over magic inference;
CONSTITUTION.mdfavors clear inputs + early validation. - Preserve cross-platform behavior; no hardcoded Unix-only paths or shell assumptions.
- Standard Go order: stdlib, third-party, internal project imports.
- Blank lines between groups as
goimportsproduces. - Alias
github.com/open-platform-model/cli/pkg/errorsasoerrors. - No unnecessary aliases unless collision or strong clarity reason.
- Concrete structs as return values; interfaces at boundaries for testability.
- No
interface{}/anyunless API genuinely needs open-ended data. - Config, flags, render inputs: strongly typed.
- Propagate
context.Contextthrough I/O, Kubernetes calls, longer workflows. - Fresh CUE contexts per command/workflow, not one global mutable context.
- Exported: PascalCase; unexported: camelCase.
- Descriptive domain names:
ReleaseSelectorFlags,ResolveModulePath,BootstrapRegistry. - Booleans read naturally:
HasWarnings,configHasProviders. - Error sentinels follow Go conventions; linter enables
errname+ revive naming rules. - Package names: short, lowercase, responsibility-focused.
- Validate early, fail before execution on invalid flags/config/inputs.
- Wrap errors with context via
%w:fmt.Errorf("loading module: %w", err). - Actionable user-facing errors with hints over raw internal failures.
- Reuse
pkg/errorstypes, especiallyDetailError+ validation helpers. - Commands use
RunE, return errors — no print-and-exit inline. - Preserve sentinel errors via wrapping for
errors.Is/errors.As.
- Commands parse flags + delegate; no core business logic.
internal/depends onpkg/;pkg/stays reusable + command-agnostic.- Output formatting separate from data generation.
- Small focused functions over large multipurpose helpers.
- Table-driven tests for multiple scenarios.
requirefor setup/fatal preconditions;assertfor non-fatal expectations.t.Helper()in test helpers.t.TempDir()over manual fixture dirs when practical.- Name
TestXxxwith behavior suffixes, e.g.TestRenderFromReleaseFile_NilConfig.
golangci-lintruns in readonly module download mode.- Key linters:
errorlint,errname,gocritic,gocyclo,gosec,revive,staticcheck,tparallel. nolintcomments must be specific with explanation.gocyclothreshold: 15; refactor before complexity grows.- Tests relax
dupl,errcheck,goconst,gosec. examples/,experiments/,third_party/,builtin/excluded from lint/format.
- ASCII-safe output in docs, examples, terminal text.
- Box-drawing:
[x]/[ ]not Unicode checkmarks. - CLI docs: emphasize what happened + how to fix failures.
- Follow SemVer + Conventional Commits for user-visible changes.
- Read touched package + nearby tests before editing.
- Run targeted tests first, broader checks if warranted.
- Changed formatting files → run
task fmt. - Changed behavior → run smallest relevant
go test+ affected task. - Before finishing substantial work →
task lint+ relevant test suite.