Skip to content

The cplat CLI

The slash commands are thin: they run scripts/cplat/cplat.py, show you a preview (--dry-run), and only then act. You can run it yourself.

cplat — deterministic implementation of the sdlc-foundry commands, grouped by noun (5.0).
The slash commands (plugins/*/commands/*.md) are thin: they run this script with --dry-run, show the plan to the user,
and run it for real. Everything that can be code is code (and has tests in tests/cplat).
cplat system new <manifest.yml> [--resume] [--no-github] [--dry-run] create a gitops-app repo + all component repos, one component PR
cplat system status [--context KUBE_CONTEXT] [--json] one table: components by environment, CI, Argo sync/health
cplat system ship start|status|phase|publish|next|repo|entry|complete|escalate|finish|gate ... /system:ship: a product spec → every repo → dev
cplat system autonomy show|set|pause|resume|undo|approve ... /system:autonomy: autonomy per environment, pause, undo, approve
cplat component new <name> <description…> [--type service|website|library] [--lang python|java|go|typescript] [--system OWNER/REPO] [--dry-run]
cplat component add|set|remove <component…> [--type T] [--lang L] [--expose] [--env K=V] [--instance ENV --replicas N] [--from-k8s] [--pr]
cplat component ship start|status|phase|pr|land|deploy|escalate|finish|gate ... /component:ship: spec → merged PR → dev
cplat component build schedule|merge|state|replan-commit|replan-abort|resolved ... /component:build Phase 2
cplat cluster new <name> [--org O] [--public] | add <owner>/<repo> [--name S] | remove <system> the cluster repo and the systems it installs
cplat api list [--system NAME] [--repo-dir DIR] [--json] the system's APIs with type, provider and consumers
cplat resource add|remove postgres [--version N] the system's database resource (system.yaml)
cplat resource upgrade <resource> --to MAJOR --env ENV [--context C] [--wait] [--json] one environment's major upgrade, as a PR
cplat resource backup <db> --env ENV [--context C] [--json] one base backup of a database now
cplat resource restore <db> --env ENV (--to TIME|latest | --switch | --discard) [--confirm prod] [--context C] [--dry-run] [--json] restore a database
cplat system restore <env> [--backup NAME or latest] [--replace] [--confirm prod] [--context C] [--json] restore an environment from its Velero backup
cplat instance promote <component…|--all> --to <env> [--version V] [--sha S] [--pr]
cplat instance secret set <component>/<env> <secret> <KEY> | list [--env dev] remote secrets of the local cluster (values never go to git)
cplat instance verify [ENV] [--base-url URL] [--spec SPEC] [--no-retry] [--json] the repo's smoke tests against a deployment
cplat issue triage list|show|setup-labels|apply ... issue intake (labels and comments only after you confirm; never closes)
cplat platform doctor [--json]
cplat platform versions [--json] [--diff REF] [--changelog] the versions table of this release; what changed since REF
cplat platform update [--migrate] [--data KEY=VALUE] [--dry-run]
cplat platform fleet update [--owner O] [--only owner/name] [--ref TAG] [--dry-run] [--json] bring every platform repo to this release
cplat platform release [--version X.Y.Z] [--dry-run] [--confirm merge|tag] prepare, merge, tag and publish a platform release
cplat platform runs init|flush|report|begin|phase|end|agent|gate|usage|benchmark ... private run records, agent metrics, usage and cost
cplat system set --env ENV [--promote RULE] [--policy POLICY] [--host HOST] one environment's promote rule, policy or host
cplat runs [--json] [--since DAYS] [--repo OWNER/NAME] [--spec ID] the run list (active and recent runs)
cplat needs [--json] [--repo-dir DIR] [--system NAME] what waits for your decision
cplat ui | cplat platform ui the local console
cplat platform retro [--week W] [--json] [--out DIR] | propose --dir DIR | post [--dir DIR] weekly platform retro
Plumbing keeps its name:
cplat shape [--repo DIR] shape + agent routing for the orchestrators; `shape check` is the platform's shape contract
cplat feedback --title T [--what …] [--details-file F] [--submit] draft (and file) a platform issue, secrets removed
cplat model show [--json] [--app APP] [--repo-dir DIR] the declared domain model of a gitops-app
cplat spec new|check|approve|set-status|task-done|hash|trace|index|list|migrate ... feature specs in docs/specs/ (ADR-026)
cplat pr wait|open … wait <number|url> [-R owner/repo] [--merge]: CI watch; open --title T: commit -s, push, PR in one step
cplat quiet [--raw] <script> run it with output in a log: one line on success, the failure summary and log path on failure (--raw: the tail)
cplat validate plan|run|final [--base REF] [--full] [--risk low|medium|high] change-aware validation of the inner loop
cplat headless <prompt> [--max-runs N] [--max-minutes M] [--quiet HH:MM-HH:MM] unattended claude -p runs that resume
cplat deps findings|patch|report ... patch fixable dependency findings of a red security gate
cplat alerts poll [--dry-run] [--app APP] firing alerts become issues
cplat budget show|gate|attempt|stage|resume ... one budget per run tree, no-progress stops, verified stages for resume
cplat adopt --type SHAPE [--data KEY=VALUE] bring an existing repo onto the platform template
usage: cplat system new [-h] [--org ORG] [--public] [--ref REF] [--dir DIR]
[--no-github] [--resume] [--skip-tasks] [--dry-run]
[--json]
manifest
`system new`: create a whole system (gitops-app repo + component repos) from a
manifest. Everything per repo is delegated to `new-service` (same rendering,
bootstrap commit, topics, plugin enablement); this module only adds the
manifest, the creation order, an all-or-nothing pre-flight and the
failure/resume handling. After the repos exist, one `compose add --pr` pins
every deployable component in the gitops-app repo.
positional arguments:
manifest path to the system manifest (system.yml)
options:
-h, --help show this help message and exit
--org ORG GitHub org/user (default: the manifest's org, else your gh
login)
--public create the GitHub repos as public (default: the manifest's
visibility, else private)
--ref REF platform git ref recorded for the plugin marketplace (default
main)
--dir DIR parent directory for the new repos (default: current
directory)
--no-github local repos only; print the GitHub and compose commands
instead of running them
--resume skip repos that already exist and continue with the rest
--skip-tasks skip the templates' bootstrap tasks (tests/CI)
--dry-run
--json
usage: cplat system status [-h] [--repo-dir REPO_DIR] [--system SYSTEM]
[--context CONTEXT] [--json]
`system status`: one table for a system — per component and environment what
is pinned, how CI is doing, and Argo's view.
options:
-h, --help show this help message and exit
--repo-dir REPO_DIR
--system SYSTEM
--context CONTEXT kube context to read ArgoCD applications from; ENV=CTX
per environment (repeatable)
--json
usage: cplat system ship [-h] [--repo REPO]
{start,status,phase,publish,next,repo,entry,complete,escalate,finish,gate}
...
`cplat system ship` — /system:ship: ship a whole product spec across the repos of its plan (spec 097, ADR-042).
Run in the gitops-app repo (`--repo DIR`, default `.`). State: <git dir>/cplat-app-ship.json (never committed).
cplat system ship start <spec> [--max N] [--context C] [--budget KEY=VALUE] refuse or begin/resume; prints phase, repo table and the next step
cplat system ship status [--json] the state and what the scheduler does next
cplat system ship phase <plan|publish|repos|complete|done>
cplat system ship publish [--timeout S] spec and plan on main: PR merged on green checks (nothing to do when they are)
cplat system ship next [--json] which repos start, run, wait, escalated; the action
cplat system ship repo start <id> mark running; prints the clone path (the entry: its worktree on compose/<spec>)
cplat system ship repo result <id> read the clone's finished ship, evaluate the gate (exit 1: escalated)
cplat system ship repo escalate <id> <reason> --cause C a repo that escalated before its ship existed (open questions)
cplat system ship entry pr <id> --title T --body-file F push the entry's branch and open (or reuse) its PR
cplat system ship entry land <id> [--timeout S] wait for all checks, merge through the merge slot
cplat system ship complete [--timeout S] spec done + plan completed through a PR merged on green; prints the report
cplat system ship escalate <reason> --cause C end the run escalated
cplat system ship finish archive the state (an unrecorded run is recorded abandoned)
cplat system ship gate Stop hook (reads the hook's JSON on stdin)
positional arguments:
{start,status,phase,publish,next,repo,entry,complete,escalate,finish,gate}
options:
-h, --help show this help message and exit
--repo REPO
usage: cplat system autonomy [-h] {show,set,pause,resume,undo,approve} ...
`cplat system autonomy show|set|pause|resume|undo|approve`: autonomy per
environment (spec 124, AC-124.5 to AC-124.8, AC-124.13, AC-124.21). `show`
reads system.yaml, the engines (`engine.status`), the audit events and the run
list; it exits 0 when an engine or the store fails. `set`, `pause` and
`resume` edit system.yaml with round-trip YAML, render, and with `--pr` signal
the engines (only to tighten), open the pull request and write the audit
event. `undo` and `approve` are `autonomy_actions`. Contract: design.md
"`cplat system autonomy`".
positional arguments:
{show,set,pause,resume,undo,approve}
show levels, guardrails, engines and what was done on its
own
set change one environment's autonomy
pause pause the engines of every environment
resume lift a pause
undo take back something an engine did
approve approve an engine's fix pull request and merge it
options:
-h, --help show this help message and exit
usage: cplat component new [-h] [--type TYPE_] [--lang LANG] [--python PYTHON]
[--org ORG] [--ref REF] [--system OWNER/REPO]
[--description DESCRIPTION] [--dir DIR]
[--no-github] [--public]
[--visibility {private,public}] [--data KEY=VALUE]
[--skip-tasks] [--dry-run] [--json]
[words ...]
`new-service`: create a repo of any registered shape from its Copier template
(and, optionally, on GitHub).
positional arguments:
words <name> [description words...]
options:
-h, --help show this help message and exit
--type TYPE_ service, website or library (default service)
--lang LANG python, java, go or typescript (default python)
--python PYTHON Python version (Python shapes only)
--org ORG GitHub org/user (default: your gh login)
--ref REF platform git ref recorded for the plugin marketplace
(default main)
--system OWNER/REPO the system's gitops repo: write .platform-app.yml
(deployable types)
--description DESCRIPTION
legacy alias; appended to the description words
--dir DIR parent directory for the new repo (default: current
directory)
--no-github local repo only; do not create a GitHub repo
--public create the GitHub repo as public (default: private);
same as --visibility public
--visibility {private,public}
visibility of the GitHub repo (default: private)
--data KEY=VALUE template option, e.g. needs_database=true (repeatable;
see the template's copier.yml)
--skip-tasks skip the template's bootstrap tasks (tests/CI)
--dry-run
--json
usage: cplat component [-h] [--system SYSTEM] [--repo-dir REPO_DIR]
[--env KEY=VALUE] [--expose [HOST]]
[--generate SECRET=KEY,KEY] [--secret SECRET=KEY,KEY]
[--secret-ref NAME] [--uses ADDON]
[--provides NAME[:TYPE]] [--consumes NAME]
[--replicas REPLICAS] [--instance ENV] [--port PORT]
[--from-k8s] [--type TYPE] [--lang LANG] [--pr]
[--dry-run] [--json]
{add,set,remove} component [component ...]
`component add|set|remove`: edit the components of a gitops-app repo's
system.yaml and render the manifests.
positional arguments:
{add,set,remove} set: change env, exposure, resource use or replicas of
a component
component component repo names (org/name, or just name =
<github_org>/name)
options:
-h, --help show this help message and exit
--system SYSTEM system name when the repo has several
--repo-dir REPO_DIR the gitops-app repo (default: current directory)
--env KEY=VALUE env var for the service (single service only)
--expose [HOST] publish through the Gateway (optional host label)
--generate SECRET=KEY,KEY
Secret whose values ESO generates randomly once per
environment (single service only)
--secret SECRET=KEY,KEY
Secret read from the secret store (set the values with
`cplat secret set`; single service only)
--secret-ref NAME existing Secret in the namespace to expose as env
vars, e.g. the one generated for another service
(single service only)
--uses ADDON resource or library the component needs (a database
gives DATABASE_URL and PG*, a bucket S3_* and AWS_*, a
cache REDIS_URL and REDIS_*); declare it first with
`cplat resource add <name> --type
database|bucket|cache`
--provides NAME[:TYPE]
API the component provides (TYPE: openapi, grpc,
graphql, events; default openapi; single component
only)
--consumes NAME API the component consumes; somebody must provide it
(single component only)
--replicas REPLICAS
--instance ENV with set: change this instance only (with --replicas)
--port PORT override the port (default: the service's template
answer, else the shape default)
--from-k8s seed port/probes/env/replicas/resources from the
service's existing k8s/base/deployment.yaml (v1 → v2
migration)
--type TYPE component type when its repo has no .copier-
answers.yml (service, website, library)
--lang LANG component language when its repo has no .copier-
answers.yml
--pr create branch, commit, push and open a pull request
--dry-run
--json
usage: cplat component ship [-h] [--repo REPO]
{start,status,phase,pr,gitops,land,deploy,escalate,finish,gate,unit}
...
`ship`: take an approved spec unattended to a merged PR and a running `dev` (specs 066, 067; ADR-028).
/component:ship does the judgement (plan, build, fix loops); this module keeps the run's state and does every step that
can be code: open the PR, wait for its checks, merge only when all of them passed, wait until `dev` runs the merge.
It needs no branch protection or auto-merge, so it works for private repos on GitHub Free.
cplat component ship start <spec> [--no-merge] [--system-dir DIR] [--budget KEY=VALUE] begin or resume; prints the state, the budget and the next step
(--system-dir: /system:ship only, links the run to a system ship, spec 097)
cplat component ship status [--json] the state of the current run
cplat component ship unit [--json] in a unit session ($CPLAT_UNIT): is the unit at its checkpoint (spec 131)
cplat component ship phase <phase> record progress (plan, build, pr, land, deploy, done)
cplat component ship pr --title T --body-file F [--no-spec] check the title and the spec rule, run `devbox run ci`, push and open (or reuse) its PR
cplat component ship gitops prepare <task> a checkout of a gitops task's repo on spec/<spec>-<task> (spec 076)
cplat component ship gitops pr <task> --title T --body-file F push it and open (or reuse) its draft PR
cplat component ship land [--timeout S] wait for the PR's checks (the first red one ends the wait, stuck runs are rerun
once); all green → merge the before-merge gitops PRs, then the PR
cplat component ship deploy [--timeout S] [--context C] wait until dev runs the merged build (pin PR merged, Argo healthy),
then merge the after-release gitops PRs and wait for every app they name
cplat component ship escalate <reason> a rule needs the user: stop here, the Stop hook lets the session end
cplat component ship finish end the run (archives the state)
cplat component ship gate Stop hook: keep an unfinished run going (reads the hook's JSON on stdin)
The state lives in `<git common dir>/cplat-ship.json`: local to the clone, shared by worktrees, never committed.
positional arguments:
{start,status,phase,pr,gitops,land,deploy,escalate,finish,gate,unit}
options:
-h, --help show this help message and exit
--repo REPO
usage: cplat component build [-h]
{schedule,state,merge,replan-commit,replan-abort,resolved}
...
cplat component build — /component:build Phase 2: the schedule, the conflict-
safe merge and the re-plan after a conflict (spec 094). cplat.py build
schedule <spec> [--json] cplat.py build merge <spec> <task> <branch> [--helper
PATH]... exit 0 merged, 3 set aside, 4 escalate cplat.py build state <spec>
[--json] cplat.py build replan-commit <spec> cplat.py build replan-abort
<spec> --reason TEXT cplat.py build resolved <spec> <task>
positional arguments:
{schedule,state,merge,replan-commit,replan-abort,resolved}
options:
-h, --help show this help message and exit
cplat — deterministic implementation of the sdlc-foundry commands, grouped by noun (5.0).
The slash commands (plugins/*/commands/*.md) are thin: they run this script with --dry-run, show the plan to the user,
and run it for real. Everything that can be code is code (and has tests in tests/cplat).
cplat system new <manifest.yml> [--resume] [--no-github] [--dry-run] create a gitops-app repo + all component repos, one component PR
cplat system status [--context KUBE_CONTEXT] [--json] one table: components by environment, CI, Argo sync/health
cplat system ship start|status|phase|publish|next|repo|entry|complete|escalate|finish|gate ... /system:ship: a product spec → every repo → dev
cplat system autonomy show|set|pause|resume|undo|approve ... /system:autonomy: autonomy per environment, pause, undo, approve
cplat component new <name> <description…> [--type service|website|library] [--lang python|java|go|typescript] [--system OWNER/REPO] [--dry-run]
cplat component add|set|remove <component…> [--type T] [--lang L] [--expose] [--env K=V] [--instance ENV --replicas N] [--from-k8s] [--pr]
cplat component ship start|status|phase|pr|land|deploy|escalate|finish|gate ... /component:ship: spec → merged PR → dev
cplat component build schedule|merge|state|replan-commit|replan-abort|resolved ... /component:build Phase 2
cplat cluster new <name> [--org O] [--public] | add <owner>/<repo> [--name S] | remove <system> the cluster repo and the systems it installs
cplat api list [--system NAME] [--repo-dir DIR] [--json] the system's APIs with type, provider and consumers
cplat resource add|remove postgres [--version N] the system's database resource (system.yaml)
cplat resource upgrade <resource> --to MAJOR --env ENV [--context C] [--wait] [--json] one environment's major upgrade, as a PR
cplat resource backup <db> --env ENV [--context C] [--json] one base backup of a database now
cplat resource restore <db> --env ENV (--to TIME|latest | --switch | --discard) [--confirm prod] [--context C] [--dry-run] [--json] restore a database
cplat system restore <env> [--backup NAME or latest] [--replace] [--confirm prod] [--context C] [--json] restore an environment from its Velero backup
cplat instance promote <component…|--all> --to <env> [--version V] [--sha S] [--pr]
cplat instance secret set <component>/<env> <secret> <KEY> | list [--env dev] remote secrets of the local cluster (values never go to git)
cplat instance verify [ENV] [--base-url URL] [--spec SPEC] [--no-retry] [--json] the repo's smoke tests against a deployment
cplat issue triage list|show|setup-labels|apply ... issue intake (labels and comments only after you confirm; never closes)
cplat platform doctor [--json]
cplat platform versions [--json] [--diff REF] [--changelog] the versions table of this release; what changed since REF
cplat platform update [--migrate] [--data KEY=VALUE] [--dry-run]
cplat platform fleet update [--owner O] [--only owner/name] [--ref TAG] [--dry-run] [--json] bring every platform repo to this release
cplat platform release [--version X.Y.Z] [--dry-run] [--confirm merge|tag] prepare, merge, tag and publish a platform release
cplat platform runs init|flush|report|begin|phase|end|agent|gate|usage|benchmark ... private run records, agent metrics, usage and cost
cplat system set --env ENV [--promote RULE] [--policy POLICY] [--host HOST] one environment's promote rule, policy or host
cplat runs [--json] [--since DAYS] [--repo OWNER/NAME] [--spec ID] the run list (active and recent runs)
cplat needs [--json] [--repo-dir DIR] [--system NAME] what waits for your decision
cplat ui | cplat platform ui the local console
cplat platform retro [--week W] [--json] [--out DIR] | propose --dir DIR | post [--dir DIR] weekly platform retro
Plumbing keeps its name:
cplat shape [--repo DIR] shape + agent routing for the orchestrators; `shape check` is the platform's shape contract
cplat feedback --title T [--what …] [--details-file F] [--submit] draft (and file) a platform issue, secrets removed
cplat model show [--json] [--app APP] [--repo-dir DIR] the declared domain model of a gitops-app
cplat spec new|check|approve|set-status|task-done|hash|trace|index|list|migrate ... feature specs in docs/specs/ (ADR-026)
cplat pr wait|open … wait <number|url> [-R owner/repo] [--merge]: CI watch; open --title T: commit -s, push, PR in one step
cplat quiet [--raw] <script> run it with output in a log: one line on success, the failure summary and log path on failure (--raw: the tail)
cplat validate plan|run|final [--base REF] [--full] [--risk low|medium|high] change-aware validation of the inner loop
cplat headless <prompt> [--max-runs N] [--max-minutes M] [--quiet HH:MM-HH:MM] unattended claude -p runs that resume
cplat deps findings|patch|report ... patch fixable dependency findings of a red security gate
cplat alerts poll [--dry-run] [--app APP] firing alerts become issues
cplat budget show|gate|attempt|stage|resume ... one budget per run tree, no-progress stops, verified stages for resume
cplat adopt --type SHAPE [--data KEY=VALUE] bring an existing repo onto the platform template
usage: cplat api list [-h] [--system SYSTEM] [--repo-dir REPO_DIR] [--json]
`api list`: print each declared API with its type, provider and consumers
(spec 114). Reads files only, writes nothing.
options:
-h, --help show this help message and exit
--system SYSTEM
--repo-dir REPO_DIR
--json
usage: cplat resource [-h] [--type TYPE] [--version VERSION]
[--replicas REPLICAS] [--storage STORAGE] [--versioning]
[--external] [--path PATH] [--app APP]
[--repo-dir REPO_DIR] [--pr] [--dry-run] [--json]
{add,remove} name
`resource add|remove`: declare or remove a named, typed resource in
system.yaml (ADR-020, ADR-054, ADR-057). `resource add <name> --type
database|bucket|cache|broker [--version N] [--replicas N] [--external [--path
P]]` writes `resources.<name>`; components then opt in with `component set
--uses <name>` (or `uses: [<name>]`). The name rule, types and database majors
mirror templates/gitops-app/scripts/render.py (the source; BROKER_VERSIONS
too). Observability is not a resource: it is set per environment under
`environments.<env>.observability`.
positional arguments:
{add,remove}
name resource name (lowercase letters, digits, hyphens; at
most 30 characters)
options:
-h, --help show this help message and exit
--type TYPE resource type: database, bucket, cache or broker
--version VERSION database major (15, 16, 17, 18) or broker version
(2.14, 2.15)
--replicas REPLICAS broker replicas: 1 or 3 (default 1)
--storage STORAGE bucket size, e.g. 10Gi (default 10Gi)
--versioning keep object versions in the bucket
--external the resource runs outside the cluster; its secret is
synced from the secret store
--path PATH secret store key template for --external ({system},
{env}, {resource}; a broker also {component})
--app APP
--repo-dir REPO_DIR
--pr
--dry-run
--json
usage: cplat resource upgrade [-h] [--to MAJOR] [--env ENV] [--verify] [--pr]
[--wait] [--context [ENV=]CTX]
[--component-dir C=DIR] [--app APP]
[--repo-dir REPO_DIR] [--dry-run] [--json]
name
`cplat resource upgrade <name> --to <major> [--env <env>]`: one environment's
engine upgrade of a database, cache or broker (spec 121). A major step moves
an environment to another major (`instances.<env>.version`, folded into
`resources.<name>.version` by the last environment); a pin move (`--to` equal
to the current major) moves the environment to the versions table's pin of
that major. Every check runs before anything is written; with `--pr` the step
is one signed-off commit on `resource/upgrade-<name>-<env>-<to>` and a pull
request. `--verify` and the verification after `--wait` are
`upgradeverify.run(ns)`.
positional arguments:
name the database, cache or broker resource
options:
-h, --help show this help message and exit
--to MAJOR the major to move to (17, 9, 2.15); the current major
moves the environment to this release's pin
--env ENV the environment (dev, staging, prod); default: the
first one where the resource has an instance
--verify verify the environment's step instead of making one
--pr branch, commit (signed off) and open a pull request
--wait with --pr: wait for the merge, then Argo CD, then
verify
--context [ENV=]CTX kube context (of one environment, or of all);
repeatable
--component-dir C=DIR
a checkout of a component for the smoke tests;
repeatable
--app APP
--repo-dir REPO_DIR
--dry-run
--json
usage: cplat resource backup [-h] --env ENV [--app APP] [--repo-dir REPO_DIR]
[--context CONTEXT] [--json]
name
`cplat resource backup <db> --env <env>`: one base backup on demand through
the Barman Cloud plugin (spec 117, AC-117.31, AC-117.32). Creates `Backup
<active>-manual-<YYYYMMDDHHMMSS>` for the active cluster of the database and
waits for it. Nothing in git changes and neither the schedule nor the
retention is touched.
positional arguments:
name the database resource
options:
-h, --help show this help message and exit
--env ENV
--app APP
--repo-dir REPO_DIR
--context CONTEXT kube context (default: the current one)
--json
usage: cplat resource restore [-h] --env ENV [--to TIME] [--switch]
[--discard] [--confirm CONFIRM] [--app APP]
[--repo-dir REPO_DIR] [--context CONTEXT]
[--dry-run] [--json]
name
`cplat resource restore <db> --env <env> (--to <time|latest> | --switch |
--discard)`: restore a database by generation (spec 117). `--to` adds a
restored instance `<system>-<db>-g<n>` next to the running one (state in git:
`restore-state.yaml`), `--switch` makes it the active one and repoints the
connection Secret, `--discard` removes the restored (else the previous)
instance with its volumes. The change goes through Argo CD (a pull request,
merged) when the addon application exists, else it is committed and applied
with kubectl.
positional arguments:
name the database resource
options:
-h, --help show this help message and exit
--env ENV
--to TIME restore to this RFC 3339 time (with an offset), or
latest
--switch make the restored instance the active one
--discard remove the restored (else the previous) instance and
its volumes
--confirm CONFIRM --switch and --discard in prod need --confirm prod;
--to needs none: it only adds a copy next to the
running database (#415)
--app APP
--repo-dir REPO_DIR
--context CONTEXT kube context (default: the current one)
--dry-run
--json
usage: cplat system restore [-h] [--backup BACKUP] [--replace]
[--confirm CONFIRM] [--app APP]
[--repo-dir REPO_DIR] [--context CONTEXT] [--json]
env
`cplat system restore <env>`: list the Velero backups of an environment or
restore one into its namespace (spec 117, AC-117.19 to .21). Without
`--backup` the backups are listed. With `--backup` the objects missing from
the namespace are restored (`existingResourcePolicy: none`); volumes that
still exist are refused, or replaced with `--replace` (the workload is
stopped, its PVCs deleted, and it comes back from the backup). Databases are
never touched. Every kubectl call goes through `backupstate.kubectl`.
positional arguments:
env
options:
-h, --help show this help message and exit
--backup BACKUP a backup name or latest (default: list the backups)
--replace stop the workloads whose volumes exist and replace the
volumes
--confirm CONFIRM prod: pass `prod` to do it
--app APP
--repo-dir REPO_DIR
--context CONTEXT kube context (default: the current one)
--json
usage: cplat instance promote [-h] [--to TO] [--all] [--version VERSION]
[--sha SHA] [--no-verify]
[--accept-digest-mismatch REASON] [--system APP]
[--repo-dir REPO_DIR] [--pr] [--dry-run]
[--json]
[component ...]
`instance promote`: pin components to a newer image in the next environment
(dev → staging → prod).
positional arguments:
component the components to promote (or --all)
options:
-h, --help show this help message and exit
--to TO the environment to promote into (the source is the
environment before it)
--all every component that has an instance in the source
environment
--version VERSION prod: release to pin (vX.Y.Z); default: newest release
tag with a published image
--sha SHA staging: full commit SHA to pin; default: head of the
service's main branch
--no-verify do not check that the image tag exists in GHCR
--accept-digest-mismatch REASON
prod: promote although the release image is not the
one staging tested; REASON is a sentence
--system APP the system (applications/<name>) when the repo holds
several
--repo-dir REPO_DIR
--pr
--dry-run
--json
usage: cplat instance secret [-h] {set,list} ...
`instance secret`: set / list the values of `remote` secrets in the local
cluster's secret store (ADR-018). `generate` secrets need nothing: External
Secrets Operator creates the values in the cluster. `remote` secrets are read
from the `platform-secrets` store, which locally is the `secrets-store`
namespace; values are written there with this command (from a hidden prompt or
stdin) and never touch git. Real clusters use their own store (Vault, AWS,
...).
positional arguments:
{set,list}
set write one value into the local secret store
list show declared secrets and whether remote values are present
options:
-h, --help show this help message and exit
usage: cplat instance verify run [-h] [--repo REPO] [--env ENV]
[--base-url BASE_URL] [--spec SPEC]
[--timeout TIMEOUT] [--no-retry] [--json]
[ENV]
positional arguments:
ENV the environment to verify (default dev)
options:
-h, --help show this help message and exit
--repo REPO
--env ENV
--base-url BASE_URL
--spec SPEC
--timeout TIMEOUT
--no-retry
--json
usage: cplat issue triage [-h] [-R REPO] {list,show,setup-labels,apply} ...
`triage`: the mechanical half of /issue:triage (ADR-025): list the intake
queue, show an issue, set up labels, apply a decision. Judgement
(classification, questions, wording) lives in the slash command. This module
never closes an issue, only reads issues and edits labels / posts comments the
user already confirmed. Issue text is untrusted input: it is redacted (tokens,
e-mail addresses, home directories) and fenced so a prompt cannot mistake it
for instructions.
positional arguments:
{list,show,setup-labels,apply}
list the intake queue
show one issue with its comments, redacted and fenced as
untrusted text
setup-labels create the missing labels (existing ones are left
alone)
apply add/remove labels and post a comment you have
confirmed; never closes
options:
-h, --help show this help message and exit
-R REPO, --repo REPO OWNER/REPO (default: the repo of the current
directory)
usage: cplat platform doctor [-h] [--repo REPO] [--json] [--context [ENV=]CTX]
`doctor`: preflight checks with a concrete fix for every problem.
options:
-h, --help show this help message and exit
--repo REPO
--json
--context [ENV=]CTX the kube context an environment (or, without ENV=,
every environment) runs on; operators are then checked
there and fail when missing or a major older
usage: cplat platform versions [-h] [--json] [--diff REF] [--changelog]
cplat platform versions [--json] [--diff <git ref>] [--changelog]: the
platform's versions table (spec 121, AC-121.1, AC-121.23). The rows come from
`versions_table()` of the platform's templates/gitops-app/scripts/render.py.
`--diff REF` compares them with the rows of that file at a git ref (a release
without `versions_table()` is read from its constants; absent rows count as
added).
options:
-h, --help show this help message and exit
--json
--diff REF
--changelog
usage: cplat platform update [-h] [--ref REF] [--data KEY=VALUE] [--repo REPO]
[--migrate] [--dry-run] [--json] [--verify]
[--context [ENV=]CTX] [--component-dir C=DIR]
[--app APP]
`update-service`: re-apply the platform template to an existing repo on a
review branch.
options:
-h, --help show this help message and exit
--ref REF platform ref being applied (informational; the running
checkout is the source)
--data KEY=VALUE change a template answer (repeatable)
--repo REPO repo to update (default: current directory)
--migrate 4.x → 5.0 (system.yaml, plugins; v1 `k8s/` removal
included)
--dry-run
--json
--verify after the update is merged and synced: operators,
moved dev pins, every environment's smoke tests (spec
121)
--context [ENV=]CTX with --verify: kube context (of one environment, or of
all); repeatable
--component-dir C=DIR
with --verify: a checkout of a component for the smoke
tests; repeatable
--app APP with --verify: the application (when the repo has
several)
usage: cplat platform fleet [-h] {update} ...
`fleet update`: bring every repo built from the platform to the installed release (spec 096).
cplat fleet update [--owner OWNER]... [--only OWNER/NAME]... [--ref TAG] [--timeout SECONDS] [--dry-run] [--json]
One PR per repo, made by `update-service`'s own resolve/execute on a fresh clone. A PR is squash-merged on green CI only
when the update is routine (nothing the repo added was overwritten, same major version, no conflict); every other PR stays
open with the label `platform-update: needs review` and a comment giving the reason. Exit 1 when any repo is left open or
failed.
positional arguments:
{update}
update bring every platform repo to the installed release
options:
-h, --help show this help message and exit
usage: cplat platform release [-h] [--version VERSION] [--dry-run]
[--confirm {merge,tag}] [--timeout TIMEOUT]
[--interval INTERVAL] [--repo REPO]
cplat platform release [--version X.Y.Z] [--dry-run] [--confirm merge|tag] [--timeout S] [--interval S] [--repo DIR]
Prepare, merge, tag and publish a platform release (spec 129). The progress is derived from git and GitHub on every run
(platrelease_state), never stored: a run that stopped continues at the first step not done. Two stops (exit 3) wait for
`--confirm merge` and `--confirm tag`. This module: preflight, dry run, prepare/commit/push/PR, the CI wait and the merge;
platrelease_publish: the upgrade e2e, the gate, the tag, the GitHub release and the release guard.
options:
-h, --help show this help message and exit
--version VERSION
--dry-run
--confirm {merge,tag}
--timeout TIMEOUT
--interval INTERVAL
--repo REPO
usage: cplat platform runs [-h] {init,flush,report,begin,phase,gate,end} ...
Private run records (spec 087, ADR-032).
positional arguments:
{init,flush,report,begin,phase,gate,end}
init create the private run store repo
flush write the local buffer to the store
report aggregate the stored runs
begin start a run record (for markdown commands)
phase open a phase of the current run
gate record the result of a gate of the current run
end end the current run
options:
-h, --help show this help message and exit
usage: cplat system set [-h] --env ENV [--promote RULE] [--policy POLICY]
[--host HOST] [--operators WHO] [--system SYSTEM]
[--repo-dir REPO_DIR] [--pr] [--dry-run] [--json]
`system set --env ENV`: change one environment's promote rule, policy, host or
operators in system.yaml and render the manifests.
options:
-h, --help show this help message and exit
--env ENV the environment to change
--promote RULE staging: after-dev-smoke|manual; prod: manual
--policy POLICY audit|enforce|off
--host HOST host template with {component}, {system}, {env}
--operators WHO owner (a cluster repo installs the operators) | install
(the system does)
--system SYSTEM system name when the repo has several
--repo-dir REPO_DIR the gitops-app repo (default: current directory)
--pr create branch, commit, push and open a pull request
--dry-run
--json
usage: cplat runs [-h] [--json] [--since DAYS] [--repo OWNER/NAME] [--spec ID]
List active and recent runs (spec 122).
options:
-h, --help show this help message and exit
--json
--since DAYS window in days (default 30, 0 = all)
--repo OWNER/NAME
--spec ID
usage: cplat needs [-h] [--json] [--repo-dir DIR] [--system NAME]
[--since DAYS]
List the open decision points of a system (spec 122).
options:
-h, --help show this help message and exit
--json
--repo-dir DIR a gitops-app clone (default .)
--system NAME
--since DAYS closed issues of the last DAYS days (default 90)
usage: cplat ui [-h] [--repo-dir REPO_DIR] [--port PORT] [--no-open]
[--no-notify]
cplat ui: the local console (spec 122).
options:
-h, --help show this help message and exit
--repo-dir REPO_DIR the gitops-app clone (default: the current directory)
--port PORT port on 127.0.0.1 (default: a free one)
--no-open do not open the browser
--no-notify do not start the notifier
usage: cplat platform retro [-h] [--week WEEK] [--json] [--out OUT]
cplat platform retro: the weekly platform retro (spec 090, ADR-039).
cplat platform retro [--week W] [--json] [--out DIR] build the report of the last complete week (reads only)
cplat platform retro propose --dir DIR [--model M] [--max-minutes N] headless Claude writes DIR/proposals.json (always exit 0)
cplat platform retro post [--dir DIR] [--week W] check the proposals, post the public issue and the full report to the run store
options:
-h, --help show this help message and exit
--week WEEK
--json
--out OUT
usage: cplat shape [-h] [--repo REPO]
`shape`: detect the repo's shape and print the agent routing the /component:*
orchestrators use (agent routing).
options:
-h, --help show this help message and exit
--repo REPO
usage: cplat feedback [-h] [--kind {bug,idea}] --title TITLE [--what WHAT]
[--command COMMAND] [--details-file DETAILS_FILE]
[--repo-dir REPO_DIR] [--submit]
`feedback`: turn a problem or idea into a GitHub issue on the platform repo,
with diagnostics and without secrets. Agents and commands tell the user to run
`/issue:report` when something fails in a way that looks like a platform
defect. This command drafts the issue (versions, shape, OS, tool availability,
the error text) and shows it; with `--submit` it files it through `gh`, or
prints a prefilled browser link when `gh` is missing or not logged in. Nothing
is sent unless `--submit` is passed, and every piece of text goes through
`redact()` first.
options:
-h, --help show this help message and exit
--kind {bug,idea}
--title TITLE one line, e.g. 'component new fails on Python 3.14'
--what WHAT what you did, what you expected, what happened
--command COMMAND the slash command or script that was running
--details-file DETAILS_FILE
file with the error output ('-' = stdin)
--repo-dir REPO_DIR
--submit actually file the issue (default: only show the draft)
usage: cplat model [-h] {show} ...
`model show`: print the declared domain model of a gitops-app (spec 113,
ADR-053). Reads files only, writes nothing.
positional arguments:
{show}
show print the declared model
options:
-h, --help show this help message and exit
usage: cplat spec [-h] [--repo REPO]
{new,check,adr-next,approve,set-status,task-done,hash,trace,index,list,publish,land,review,test-diff,ci,migrate}
...
`spec`: feature specs in docs/specs/<NNN>-<slug>/ (ADR-026) — create, check,
approve, trace, index, list, migrate. A spec folder holds spec.md (what:
stories, acceptance criteria AC-<NNN>.<n>, non-goals, open questions),
optional design.md (how, contract) and plan.md (tasks with `covers: [AC-…]`).
The slash commands do the judgement; every check and every state change of a
spec goes through this module so it is deterministic and tested. `trace
--chain` shows the chain from issue to environment (spec 109); `ci` warns
about tests naming withdrawn or unknown criteria.
positional arguments:
{new,check,adr-next,approve,set-status,task-done,hash,trace,index,list,publish,land,review,test-diff,ci,migrate}
new create docs/specs/<NNN>-<slug>/spec.md (draft)
check validate specs and plans (all if none given)
adr-next the next ADR number no pushed branch or open PR uses
(#337)
approve check a draft and set it approved
hash print the acceptance-criteria hash a plan records as
spec_hash
trace every active criterion must be named by at least one
test
index regenerate the spec table in docs/backlog.md
publish push the spec's branch and open or update its draft
PR; ask the owner to review (spec 122)
land approved spec: approve the review, mark the draft PR
ready and merge it (spec 122)
review post a changes-requested review, or list the PR's
review comments (spec 122)
test-diff acceptance tests changed only in formatting since
BASE? (exit 1 otherwise)
ci check every spec and trace built ones; GitHub
annotations (warnings unless --strict)
migrate convert STORY-NNN stories in docs/backlog.md into spec
folders
options:
-h, --help show this help message and exit
--repo REPO
usage: cplat pr [-h] {wait,open} ...
`pr wait`: wait for any pull request's CI and optionally merge it on green (spec 079).
cplat pr wait <number|url> [-R owner/repo] [--merge] [--timeout S]
The same watch as `cplat ship land` (spec 072): one line per concluded check, the first red check ends the wait, a
stale or stuck run is rerun once, and a job that failed on a transient error (a download, a registry, the network)
is rerun once before it counts. A PR that conflicts with its base is never green: GitHub runs no CI on it (#221). Every rerun is asked of the run's budget first (spec 102): a refusal ends the wait red with
`budget exhausted: reruns`. Exit 0: green (and merged with --merge); 1: red, with the failure summary of each red check and its saved log path (spec 108; the tails with summaries off).
positional arguments:
{wait,open}
open commit -s, push and open the PR in one step (spec 100)
options:
-h, --help show this help message and exit
usage: cplat validate [-h] {plan,run,final} ...
`cplat validate plan|run|final`: change-aware validation in the inner loop (spec 103, ADR-044).
Public API:
plan(root, base, full=, risk=) -> dict the plan: every check of the repo is run / reused / skipped with a rule and a reason
execute(root, plan) -> int run it quietly (one line per check), write evidence, record the `validation` section
record_final(run_id, check, result) a final-gate result: a failed check the loop skipped or reused is a miss
record_final_gate(root) after a red `devbox run ci`: attribute the failure to checks (used by ship.run_ci)
cplat validate plan [--base REF] [--full] [--risk low|medium|high] [--json]
cplat validate run [--base REF] [--full] [--risk ...] exit 0 green, 1 red
cplat validate final --check NAME passed|failed exit 0
Rules, the first match decides (deterministic, no model): full, mandatory:<category>, docs-only, mapped, no rule. An
agent's risk level can only add checks. Evidence of passed checks lives in `<git common dir>/cplat-evidence/<check>.json`
(`{inputs, result, run_id, at}`), never pushed; equal inputs and `passed` make a check `reused`. The final gate
(`devbox run ci`) is not planned here and always runs whole. Recording never raises into a caller.
positional arguments:
{plan,run,final}
options:
-h, --help show this help message and exit
usage: cplat headless [-h] [--repo REPO] [--max-runs MAX_RUNS]
[--max-minutes MAX_MINUTES] [--quiet QUIET] [--no-wait]
[--model MODEL] [--plugin-dir PLUGIN_DIR]
[--budget KEY=VALUE] [--dry-run]
prompt [prompt ...]
`headless`: run a slash command unattended with `claude -p`, and start it again until its ship run is finished (spec 070).
cplat headless "/component:ship 012" run in the current repo until done, escalated or out of runs
cplat headless "/component:ship 012" --quiet 23:30-07:00 never start a run inside that window (e.g. nightly jobs on the
same subscription); wait for it to end, or --no-wait to exit
cplat headless --dry-run "/component:fix ..." print the claude command
Each run is a fresh `claude -p` session with `--permission-mode acceptEdits` and the repo's committed permission allowlist:
file edits inside the repo are accepted, any other tool not allowlisted is refused instead of prompting, so nobody has to watch. A run ends when Claude stops, the
time is up, or the context runs out; if `cplat ship` state says the run is unfinished and not escalated, the next run
resumes it from disk (spec status, plan.md `done` flags, the ship state). Logs: ~/.cache/sdlc-foundry/headless/<repo>/.
The coordinator model (spec 100) is always passed as `--model`: the flag, else `coordinator_model` in the repo's
`.platform-settings.yml`, else in ~/.config/sdlc-foundry/settings.yml (see settings.py), else sonnet; only sonnet, opus
and haiku are accepted. `--plugin-dir PATH` (repeatable) loads a plugin from a folder for the sessions.
One budget (spec 102) covers the run and every ship under it: 180 min, 60 invocations, 6 CI reruns and $15 per spec in the
prompt; `--budget KEY=VALUE` (repeatable, a number or `off`) replaces a limit. The next session is not started once a limit
is used up: `budget exhausted: <limit>`, stop reason `budget`, exit 1.
Unit mode (spec 131): `/component:ship` and `/component:build` with at least one spec run one fresh session per unit of the
plan (cplat supervisor.py), saved at checkpoints; the same command again continues at the first unit without one. No session
or time cap applies unless `--max-runs`/`--max-minutes` is given. The legacy loop (other prompts and `/system:ship`) caps at
6 sessions and 240 minutes when they are not given.
Run allowlist (spec 131): for a ship, build or system ship the git, `gh pr create` and land commands of the run's feature
branch are printed and passed to every session as `--allowedTools` (refused rules such as force pushes, pushes to the
default branch and merges as `--disallowedTools`) and in `CPLAT_RUN_ALLOWLIST`; no settings file is written. Before any
session a preflight checks the settings layers, git identity, gh login and push access: `preflight failed: <category>: <detail>`,
exit 1, nothing started.
positional arguments:
prompt the prompt, usually a slash command such as
/component:ship 012
options:
-h, --help show this help message and exit
--repo REPO
--max-runs MAX_RUNS sessions in total (default: no cap in unit mode, 6
otherwise)
--max-minutes MAX_MINUTES
wall-clock budget for all sessions together, from the
first start (default: no cap in unit mode, 240
otherwise)
--quiet QUIET HH:MM-HH:MM: never start a session inside this window
--no-wait inside the quiet window: exit (code 3) instead of
waiting
--model MODEL coordinator model: sonnet (default), opus or haiku;
else the settings files
--plugin-dir PLUGIN_DIR
load a plugin from this folder (repeatable)
--budget KEY=VALUE replace a limit of the run's budget: minutes,
invocations, reruns, cost (a number or off; spec 102)
--dry-run
usage: cplat deps [-h] {findings,patch,report} ...
`cplat deps`: fixable dependency findings of a red security gate are patched
by the run (spec 095, ADR-034).
positional arguments:
{findings,patch,report}
options:
-h, --help show this help message and exit
usage: cplat alerts [-h] {poll} ...
firing alerts become issues (spec 092)
positional arguments:
{poll}
poll evaluate the alert sources and reconcile the issues
options:
-h, --help show this help message and exit
usage: cplat budget [-h] {show,gate,attempt,stage,resume} ...
Spec 102 (ADR-043): one budget per run tree, stops at safe points, no-progress stops, a recovery snapshot, verified stages.
Public API for the callers (headless, ship, pr wait, system ship, runs) and the hook:
parse_options(["minutes=45", "cost=off"]) -> dict `--budget KEY=VALUE`; PlatformError for a bad key or value
open_root(run_id, key, ships=, options=, repo=) open or continue the ledger of a root run (a child opens none)
root_of(run_id) -> run_id follows `parent` through the active records
check(run_id, point) -> limit name | None the exhausted limit at a safe point (a run's cost "unknown" is skipped)
allow_rerun(run_id) -> bool asked before a CI rerun; counts it, False when `reruns` is used up
count_invocation(run_id) / stop(run_id, limit, point) one more session / write the `budget` section of a stop
limits_line(run_id) -> str | None the start output ("budget: minutes 180, ...")
attempt(repo, stage, error, failing, names=) -> reason | None third equivalent failure without progress stops
snapshot(repo, stage, excerpt, criteria) <git dir>/cplat-recovery.json (local only)
record_stage(repo, name, result) verified stage result for HEAD + inputs
on_finish(run_id, usage) called by runs.finish: the record's section, the ledger carry
cplat budget show [--json] | gate [--invocation] | attempt <stage> --failing N [--names a,b] (--error-file F | --error T)
| stage <name> passed|failed | resume [--json]
The ledger is `runs.state_dir()/budgets/<sha1 of key>.json`; it outlives the run records (one record per resumed run).
Every function that records or reads for a caller swallows its own failure: a broken ledger never stops a run.
positional arguments:
{show,gate,attempt,stage,resume}
show limits, usage and the root run
gate PreToolUse hook: exit 2 refuses a subagent when the
budget is used up
attempt record a failed fix round; exit 3 and the reason when
nothing improves
stage record a verified stage result for HEAD + inputs
resume per stage: skip (passed for this HEAD and inputs) or
run
options:
-h, --help show this help message and exit
usage: cplat adopt [-h] --type TYPE [--data KEY=VALUE] [--repo REPO]
[--dry-run] [--json]
`adopt`: bring an existing repo that was not created from a template onto the platform (spec 071).
cplat adopt --type service-python [--data module_name=app] [--dry-run]
Renders the shape's template with answers taken from the repo (name and org from `origin`, the description from the
README) into a scratch directory and copies over only what the repo lacks: CLAUDE.md, .claude/settings.json, devbox
recipes, spec and ADR scaffolding, CI files. Nothing that exists is overwritten: devbox.json gets the template's
missing recipes and packages added (yours win), .gitignore the missing lines, and every other file that differs is
listed so you can compare it with the template. Starter app code and tests are never added. Afterwards the repo has a
.copier-answers.yml and .platform-version, so `/platform:update` and every /component:* command work. One commit on
chore/adopt-platform; nothing is pushed.
options:
-h, --help show this help message and exit
--type TYPE the shape this repo is (see shapes.yml)
--data KEY=VALUE a template answer (repeatable)
--repo REPO
--dry-run
--json