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 templateOptions per command
Section titled “Options per command”system new
Section titled “system new”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 amanifest. Everything per repo is delegated to `new-service` (same rendering,bootstrap commit, topics, plugin enablement); this module only adds themanifest, the creation order, an all-or-nothing pre-flight and thefailure/resume handling. After the repos exist, one `compose add --pr` pinsevery 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 --jsonsystem status
Section titled “system status”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 whatis 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) --jsonsystem ship
Section titled “system ship”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 REPOsystem autonomy
Section titled “system autonomy”usage: cplat system autonomy [-h] {show,set,pause,resume,undo,approve} ...
`cplat system autonomy show|set|pause|resume|undo|approve`: autonomy perenvironment (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 runlist; 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` signalthe engines (only to tighten), open the pull request and write the auditevent. `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 exitcomponent new
Section titled “component new”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 --jsoncomponent add
Section titled “component add”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'ssystem.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 --jsoncomponent ship
Section titled “component ship”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 thatcan 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 REPOcomponent build
Section titled “component build”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 buildschedule <spec> [--json] cplat.py build merge <spec> <task> <branch> [--helperPATH]... 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 exitcluster
Section titled “cluster”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 templateapi list
Section titled “api list”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 --jsonresource add
Section titled “resource add”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 insystem.yaml (ADR-020, ADR-054, ADR-057). `resource add <name> --typedatabase|bucket|cache|broker [--version N] [--replicas N] [--external [--pathP]]` writes `resources.<name>`; components then opt in with `component set--uses <name>` (or `uses: [<name>]`). The name rule, types and database majorsmirror templates/gitops-app/scripts/render.py (the source; BROKER_VERSIONStoo). 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 --jsonresource upgrade
Section titled “resource upgrade”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'sengine upgrade of a database, cache or broker (spec 121). A major step movesan environment to another major (`instances.<env>.version`, folded into`resources.<name>.version` by the last environment); a pin move (`--to` equalto the current major) moves the environment to the versions table's pin ofthat major. Every check runs before anything is written; with `--pr` the stepis one signed-off commit on `resource/upgrade-<name>-<env>-<to>` and a pullrequest. `--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 --jsonresource backup
Section titled “resource backup”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 throughthe Barman Cloud plugin (spec 117, AC-117.31, AC-117.32). Creates `Backup<active>-manual-<YYYYMMDDHHMMSS>` for the active cluster of the database andwaits for it. Nothing in git changes and neither the schedule nor theretention 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) --jsonresource restore
Section titled “resource restore”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 arestored instance `<system>-<db>-g<n>` next to the running one (state in git:`restore-state.yaml`), `--switch` makes it the active one and repoints theconnection 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 appliedwith 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 --jsonsystem restore
Section titled “system restore”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 orrestore one into its namespace (spec 117, AC-117.19 to .21). Without`--backup` the backups are listed. With `--backup` the objects missing fromthe namespace are restored (`existingResourcePolicy: none`); volumes thatstill exist are refused, or replaced with `--replace` (the workload isstopped, its PVCs deleted, and it comes back from the backup). Databases arenever 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) --jsoninstance promote
Section titled “instance promote”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 --jsoninstance secret
Section titled “instance secret”usage: cplat instance secret [-h] {set,list} ...
`instance secret`: set / list the values of `remote` secrets in the localcluster's secret store (ADR-018). `generate` secrets need nothing: ExternalSecrets Operator creates the values in the cluster. `remote` secrets are readfrom the `platform-secrets` store, which locally is the `secrets-store`namespace; values are written there with this command (from a hidden prompt orstdin) 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 exitinstance verify
Section titled “instance verify”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 --jsonissue triage
Section titled “issue triage”usage: cplat issue triage [-h] [-R REPO] {list,show,setup-labels,apply} ...
`triage`: the mechanical half of /issue:triage (ADR-025): list the intakequeue, show an issue, set up labels, apply a decision. Judgement(classification, questions, wording) lives in the slash command. This modulenever closes an issue, only reads issues and edits labels / posts comments theuser already confirmed. Issue text is untrusted input: it is redacted (tokens,e-mail addresses, home directories) and fenced so a prompt cannot mistake itfor 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)platform doctor
Section titled “platform doctor”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 olderplatform versions
Section titled “platform versions”usage: cplat platform versions [-h] [--json] [--diff REF] [--changelog]
cplat platform versions [--json] [--diff <git ref>] [--changelog]: theplatform'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 releasewithout `versions_table()` is read from its constants; absent rows count asadded).
options: -h, --help show this help message and exit --json --diff REF --changelogplatform update
Section titled “platform update”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 areview 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)platform fleet
Section titled “platform fleet”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 onlywhen the update is routine (nothing the repo added was overwritten, same major version, no conflict); every other PR staysopen with the label `platform-update: needs review` and a comment giving the reason. Exit 1 when any repo is left open orfailed.
positional arguments: {update} update bring every platform repo to the installed release
options: -h, --help show this help message and exitplatform release
Section titled “platform release”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 REPOplatform runs
Section titled “platform runs”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 exitsystem set
Section titled “system set”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 oroperators 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 --jsonusage: 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 IDusage: 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 notifierplatform retro
Section titled “platform retro”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 OUTusage: 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 REPOfeedback
Section titled “feedback”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 platformdefect. This command drafts the issue (versions, shape, OS, tool availability,the error text) and shows it; with `--submit` it files it through `gh`, orprints a prefilled browser link when `gh` is missing or not logged in. Nothingis 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 exitusage: 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 aspec goes through this module so it is deterministic and tested. `trace--chain` shows the chain from issue to environment (spec 109); `ci` warnsabout 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 REPOusage: 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, astale 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 exitvalidate
Section titled “validate”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. Anagent'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 exitheadless
Section titled “headless”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, thetime is up, or the context runs out; if `cplat ship` state says the run is unfinished and not escalated, the next runresumes 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, opusand 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 theprompt; `--budget KEY=VALUE` (repeatable, a number or `off`) replaces a limit. The next session is not started once a limitis 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 theplan (cplat supervisor.py), saved at checkpoints; the same command again continues at the first unit without one. No sessionor time cap applies unless `--max-runs`/`--max-minutes` is given. The legacy loop (other prompts and `/system:ship`) caps at6 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 featurebranch are printed and passed to every session as `--allowedTools` (refused rules such as force pushes, pushes to thedefault branch and merges as `--disallowedTools`) and in `CPLAT_RUN_ALLOWLIST`; no settings file is written. Before anysession 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-runusage: cplat deps [-h] {findings,patch,report} ...
`cplat deps`: fixable dependency findings of a red security gate are patchedby the run (spec 095, ADR-034).
positional arguments: {findings,patch,report}
options: -h, --help show this help message and exitalerts
Section titled “alerts”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 exitbudget
Section titled “budget”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 exitusage: 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 theREADME) into a scratch directory and copies over only what the repo lacks: CLAUDE.md, .claude/settings.json, devboxrecipes, spec and ADR scaffolding, CI files. Nothing that exists is overwritten: devbox.json gets the template'smissing recipes and packages added (yours win), .gitignore the missing lines, and every other file that differs islisted 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 onchore/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