← Control PlaneCONTENT HISTORY

Update to Control Plane

Snapshot Sep 30, 2026 · 23:00 UTC · version 1.0.1

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "cpln",
  "description": "Writes cpln CLI commands and workflows for Control Plane. Use when the user asks about cpln login, cpln apply, cpln workload, CLI or CI/CD deploys, container debugging with cpln exec/logs, or any cpln resource command.",
  "included_files": [],
  "skill_md_contents": "---\nname: cpln\ndescription: \"Writes cpln CLI commands and workflows for Control Plane. Use when the user asks about cpln login, cpln apply, cpln workload, CLI or CI/CD deploys, container debugging with cpln exec/logs, or any cpln resource command.\"\n---\n\n# cpln CLI\n\n**MCP first; the CLI is the fallback** — use it when the MCP server is unavailable or unauthenticated, for the CLI-only operations below, and for interactive debugging or scripted GitOps. **In CI/CD the CLI is the primary interface** — pipelines authenticate with a service-account key in `CPLN_TOKEN`, build and push images (`cpln image build --push`, or `--remote` on a runner with no Docker daemon), and apply resources (`cpln apply --ready`). Platform rules (resource model, secrets, destructive ops, production defaults, scale-to-zero, firewall) live in the operating guide (`get_cpln_rules`); this skill is the CLI mechanics.\n\n**Never write a `cpln` command from memory.** Verify every verb and flag with `cpln <command> --help` before quoting it. If a command isn't in the resource command map below, assume it isn't real.\n\n## CLI-only operations\n\nNo MCP equivalent — the CLI's primary job:\n\n| Command | Purpose |\n|---|---|\n| `cpln image build` | Build a container image — locally with Docker, or on Control Plane with `--remote` (no daemon) — and push to the org registry |\n| `cpln image copy` | Copy an image between orgs |\n| `cpln port-forward` | Forward local ports to a running workload |\n| `cpln convert` | Convert Kubernetes manifests to Control Plane specs (Compose is `cpln stack`) |\n| `cpln cp` | Copy files in or out of a running container |\n| `cpln apply` | Scripted GitOps — declarative create-or-update from files |\n\nOne-shot and interactive container commands, TTY sessions (`workload connect`, `exec -it`), and streamed logs (`cpln logs --tail`) are also CLI-only; MCP's `get_workload_logs` covers bounded log fetches. Everything else — discovery and CRUD — prefer the MCP tools (generic `list_resources` / `get_resource` / `delete_resource` with a `kind`, typed `create_*`/`update_*` for mutations).\n\nWhen no MCP tool covers a resource, field, or sub-endpoint, use the `cpln` CLI for that piece (ground the command in this skill and `--help`) or tell the user what is missing. The raw-API escape hatch (`cpln_api_request`) is disabled by default — it bypasses the typed tools' pre-call validation.\n\n## Setup & auth\n\n```bash\ncpln login                                       # interactive (opens a browser); creates the \"default\" profile\ncpln profile update default --org ORG --gvc GVC  # set defaults (\"update\" creates the profile if missing)\n```\n\n**CI/CD needs no profile.** With `CPLN_TOKEN` set (service-account key, from `cpln serviceaccount add-key`), the CLI runs a profile-less session against `api.cpln.io`. Add `CPLN_ORG` / `CPLN_GVC` for defaults and `CPLN_SKIP_UPDATE_CHECK=1` to silence update checks. Resolution everywhere is **flag, then env var, then profile**: `--org` beats `CPLN_ORG` beats the profile default — same for `--gvc`/`CPLN_GVC`, `--profile`/`CPLN_PROFILE`, `--endpoint`/`CPLN_ENDPOINT`, `--token`/`CPLN_TOKEN`. Profiles live in `~/.config/cpln` (override with `CPLN_HOME`).\n\n**Never pass `--token`** — it leaks into logs and shell history; use `CPLN_TOKEN` or a profile. Inspect context with `cpln profile get` — **there is no `cpln whoami`.** **`cpln profile token` (prints the profile's live access JWT) is break-glass** — it exposes a live credential: never suggest it or run it on your own; use it only when the user explicitly asks. **Secret data commands are off-limits entirely** — never run or suggest `cpln secret reveal`, `cpln secret create-*`, `cpln secret edit`, or `cpln secret delete`; the user manages secret values and lifecycle themselves. Explain any profile state changes so operators can revert them.\n\n## Command structure & shared flags\n\n```\ncpln <resource> <action> [REF] [--flags]\n```\n\nStandalone (break the pattern): `cpln apply`, `delete`, `logs`, `port-forward`, `cp`, `convert`, `login`. Aliases: `workload`=`w`, `identity`=`id`, `serviceaccount`=`sa`, `location`=`loc`, `stack`=`compose`. Shell completion: `cpln misc install-completion` (bash/zsh/fish).\n\nFlags on nearly every command — never list per-command:\n- **Context**: `--profile`, `--org`, `--gvc`\n- **Output**: `--output`/`-o` (`text|json|yaml|json-slim|yaml-slim|tf|crd|names`), `--color`, `--ts` (`iso|local|age`), `--max` (default 50; `0` = all)\n- **Request**: `--token`, `--endpoint`, `--insecure`/`-k` · **Debug**: `--verbose`/`-v`, `--debug`/`-d`\n\n- **Always use `yaml-slim`/`json-slim` for round-tripping.** Plain `yaml`/`json` include server-side fields (`status`, `id`, `created`, `lastModified`, `links`) that break `cpln apply`.\n- **Include `--org` (and `--gvc`) explicitly on every mutation**, even with profile defaults. `--gvc` exists on all subcommands of GVC-scoped resources (workload, identity, volumeset) plus helm, stack, apply, convert, cp, delete, port-forward — but **not** on `cpln logs` (GVC goes inside the LogQL query).\n- **Cap lists with `--max`.** Omit only when targeting a specific named resource.\n\n## Standard CRUD\n\n| Action | Syntax | Notes |\n|---|---|---|\n| **List** | `cpln <resource> get` | No args = list all. **There is NO `list` subcommand.** |\n| **Get** | `cpln <resource> get REF...` | |\n| **Create** | `cpln <resource> create --name NAME` | Also `--description`, `--tag K=V` |\n| **Delete** | `cpln <resource> delete REF...` | Multiple refs |\n| **Edit** | `cpln <resource> edit REF` | Opens YAML in `$EDITOR`. `--replace` replaces instead of merging |\n| **Patch** | `cpln <resource> patch REF --file FILE` | |\n| **Tag** | `cpln <resource> tag REF... --tag K=V` | Remove: `--remove-tag KEY` |\n| **Update** | `cpln <resource> update REF --set PROP=VAL` | Also `--unset PROP`; array props take `+=` / `=` / `-=` |\n| **Clone** | `cpln <resource> clone REF --name NEW` | Spec only. Not on every kind (map below) |\n| **Audit** | `cpln <resource> audit [REF]` | `--since` (default 7d), `--from`/`--to`, `--subject`, `--context` |\n| **Query** | `cpln <resource> query` | See below |\n\nAlso on most kinds: `access-report REF`, `eventlog REF`, `permissions` (no args). **`eventlog` has the alias `log`** — `cpln workload log` shows platform events, NOT container logs (those come from `cpln logs`).\n\n### Query\n\n```bash\ncpln workload query --match all --tag environment=production --tag region=europe\ncpln workload query --match any --rel gvc=gvc-a --rel gvc=gvc-b\ncpln workload query --property name=my-workload\n```\n\n`--match` (`all` default / `any` / `none`); `--tag KEY=VALUE`, `--property`/`--prop NAME=VALUE` (e.g. `status.phase=running`), `--rel KIND=VALUE` — all repeatable. The `gvc`, `policy`, and `group` create commands accept `--query-match`/`--query-tag`/`--query-property`/`--query-rel` (group also `--query-kind user`) for dynamic targeting. Full language: `query-spec` skill.\n\n## Resource command map\n\nCore anti-hallucination reference. **Scope**: org = needs `--org`; gvc = needs `--org` + `--gvc`; local = no API call. \"Full\" = create, get, delete, edit, patch, tag, update (audit, eventlog, query, access-report, permissions exist nearly everywhere).\n\n| Resource | Scope | CRUD | Non-standard subcommands |\n|---|---|---|---|\n| **workload** (`w`) | gvc | Full + clone | `connect`, `exec`, `run`, `cron` (get/run/start/stop), `replica` (get/stop), `force-redeployment`, `get-deployments`, `open`, `start`, `stop` |\n| **gvc** | org | Full + clone | `add-location`, `remove-location` (both `--location`, repeatable), `delete-all-workloads` |\n| **secret** | org | get only — secret data and lifecycle are managed by the user | — |\n| **policy** | org | Full + clone | `add-binding`, `remove-binding` |\n| **identity** (`id`) | gvc | Full, **no clone** | — |\n| **volumeset** | gvc | Full, no clone | `expand`, `shrink`, `snapshot` (create/delete/get/restore), `volume` (delete/get) |\n| **domain** | org | create, delete, edit, patch, tag — **no update**, no clone | — |\n| **cloudaccount** | org | **No generic create, no update** | `create-aws`, `create-azure`, `create-gcp`, `create-ngs` |\n| **image** | org | get, delete, edit, patch, tag only | `build`, `copy`, `docker-login` |\n| **agent** | org | Full, no clone | `info`, `manifest`, `up` |\n| **group** | org | Full + clone | `add-member`, `remove-member` (`--email`, `--serviceaccount`) |\n| **ipset** | org | Full + clone | `add-location`, `remove-location`, `update-location` |\n| **serviceaccount** (`sa`) | org | **No update**; clone | `add-key` (`--description` required), `remove-key` |\n| **mk8s** | org | **No create**; clone | `dashboard`, `health`, `join`, `kubeconfig` |\n| **user** | org | No create | `invite` (`--email`, optional `--group`) |\n| **org** | — | create (needs `--accountId`, `--invitee`); **no delete** | — |\n| **profile** | local | get, delete, update (creates if missing; alias `create`) | `login`, `set-default`, `token` |\n| **helm** | gvc | — | `install` (alias `apply`), `upgrade`, `uninstall`, `get`, `list`, `history`, `rollback`, `template` |\n| **stack** (`compose`) | gvc | — | `deploy` (alias `up`), `manifest`, `rm` (alias `down`) |\n| **location** (`loc`) | org | create, delete (BYOK locations only), edit, patch — no update | `install`, `uninstall` |\n| **auditctx** | org | Full + clone, **no delete** | — |\n| **quota** | org | get, edit, patch | — |\n| **task** | org | get, delete | `complete`, `get-mine` |\n| **account** | — | get only | — |\n| **rest** | — | — | `get`, `post`, `put`, `patch`, `delete`, `create`, `edit` against raw API paths |\n| **operator** | local | — | `install`, `uninstall` |\n\n## Non-standard commands\n\n### cpln apply / cpln delete\n\n```bash\ncpln apply --file ./manifests/ --gvc GVC --ready   # DIRECTORY — recursive over .yaml/.yml/.json\ncpln apply --file all.yaml --ready                 # MULTI-DOC file (resources split by ---)\ncpln apply --file - < manifest.yaml                # stdin\ncpln delete --file manifest.yaml                   # delete the resources listed in a file\n```\n\n**Apply multi-resource deploys in one call** (directory or multi-doc file) — the CLI sorts resources into dependency order before applying: `agent, secret, cloudaccount, gvc, identity, volumeset, policy, workload` (other kinds after); `cpln delete --file` runs the same order reversed. Splitting into multiple calls reintroduces the ordering problem. Apply is a PUT upsert — it prints `Created`/`Updated` per resource. `--ready` polls workloads (5s interval, up to 5 min) until ready. `--k8s` converts Kubernetes manifests inline (Deployment/Secret/ConfigMap/PVC; pull secrets get linked onto the GVC).\n\nGVC targeting for GVC-scoped resources:\n- **Single-GVC bundle** (common): pass `--gvc GVC` — it fills in the GVC for every resource that doesn't declare one.\n- **Multi-GVC bundle**: declare `gvc:` inline as a top-level field (same level as `kind`/`name`) and omit the flag.\n- Inline `gvc:` plus a **different** `--gvc` value = hard error; they must agree.\n- Org-scoped resources ignore the GVC field/flag entirely.\n\n```yaml\nkind: workload\nname: my-app\ngvc: prod          # target GVC declared inline\nspec: { ... }\n```\n\n### cpln logs\n\n```bash\ncpln logs '{gvc=\"GVC\", workload=\"WORKLOAD\"}' --org ORG --tail\n```\n\n- The query is a **positional argument** (first arg, single quotes, LogQL). `--gvc` is **not** a flag here.\n- Labels: `container`, `gvc`, `location`, `provider`, `replica`, `stream`, `workload`. Special: `container=\"_accesslog\"` for HTTP access logs.\n- Filters: `|= \"error\"` (contains), `!= \"debug\"` (excludes), `|~ \"timeout|crash\"` (regex).\n- Streaming: `--tail` (also `-t`/`-f`). **`--follow` does NOT exist.**\n- `--limit N` (default 30; `0` = unlimited, auto-paginates), `--since` (default `1h`), `--from`/`--to`, `--direction forward|backward`, and its own `-o default|raw|jsonl` (`raw` strips labels and timestamps). Full LogQL: `logql-observability` skill.\n\n### cpln workload create\n\n```bash\ncpln workload create --name APP --image IMAGE --gvc GVC [flags]\n```\n\n`--type` (`serverless|standard`, default `standard`) — **`stateful` and `cron` CANNOT be created via CLI flags; use `cpln apply --file`.** Other flags: `--port` (default 8080 — must match the container's listening port), `--public`, `--identity`, `--env KEY=VALUE`, `--cpu` (default 50m), `--memory`/`--mem` (default 128Mi), `--volume`, `--container-name`, `--inherit-env`. Internal images: `//image/NAME:TAG`.\n\n### Debugging — exec / connect / run / cron / replica\n\n- **exec** — one-shot command in an existing replica: `cpln workload exec APP --gvc GVC -- ls -la`. **The `-- CMD ARG1 ARG2...` part must be last on the line** — every cpln flag (`--container`, `--location`, `--replica`, `--stdin`/`-i`, `--tty`/`-t`, `--quiet`/`-q`) goes before the `--`; everything after it runs in the replica (same rule for `run` and `cron run`)\n- **connect** — interactive shell: `cpln workload connect APP --gvc GVC` (`--shell`, default `bash`; same targeting flags)\n- **run** — temporary workload + command: `cpln workload run --image IMAGE --gvc GVC -- CMD` (`--clone WORKLOAD`, `--rm`, `-i`, `--cpu`, `--memory`, `--command`/`-c`, `--arg`/`-a`, `--location`)\n- **cron run** — one-off execution of a cron workload: `cpln workload cron run --gvc GVC -- CMD` (`--background`/`-b`, `--timeout` default 600s, `--identity`, `--image`, `--env`)\n- **cron start** — trigger the job now, optionally overriding `--env`, `--command`, `--arg`, `--active-deadline-seconds`; **cron stop** REF needs `--replica-name` + `--location` (both required); **cron get** REF lists job executions\n- **replica get / stop** — list replica names per location; `stop` requires `--replica-name` + `--location`\n\nWhen `--location` / `--replica` / `--container` are omitted, the CLI defaults to the GVC's first location, the first replica, and the only container (multi-container: the first one with `ports`, else the first) — it prints a \"defaulting to\" notice. Pass all three explicitly on multi-location or multi-container workloads.\n\n### cpln policy add-binding\n\n```bash\ncpln policy add-binding POLICY --permission reveal --identity //gvc/GVC/identity/ID\n```\n\n`--permission` required; at least one principal flag required; **all repeatable** (`--email`, `--serviceaccount`, `--group`, `--identity` — name or full link).\n\n### cpln port-forward / cp\n\n```bash\ncpln port-forward WORKLOAD [LOCAL:]REMOTE... --gvc GVC   # --address (default localhost), --location, --replica\ncpln cp LOCAL WORKLOAD:PATH --gvc GVC                    # reverse the args (WORKLOAD:PATH LOCAL) to copy out; --container, --location, --replica\n```\n\n### Migration tools\n\n- `cpln convert --file K8S.yaml` — Kubernetes manifest to Control Plane spec (`--protocol http|http2|grpc|tcp` for container ports)\n- `cpln helm install RELEASE CHART --gvc GVC` — Helm charts and template catalog installs (`--wait`, `--timeout` default 300s, `--set`, `--values`)\n- `cpln stack deploy --gvc GVC` — Docker Compose from the current directory (`--dir`, `--compose-file` for alternative naming, `--build` default true)\n\n### Volumeset command verbs\n\nDedicated verb per operation; the flags are **singular** — `--location`, `--volume-index` (plural forms don't exist):\n\n| Operation | Command | Risk |\n|---|---|---|\n| Expand volume | `cpln volumeset expand REF --new-size GIB [--location LOC] [--volume-index N]` | Safe |\n| Create snapshot | `cpln volumeset snapshot create REF --snapshot-name NAME [--location LOC] [--volume-index N]` | Safe |\n| Restore snapshot | `cpln volumeset snapshot restore REF --snapshot-name NAME --location LOC --volume-index N` (all required) | Overwrites volume state |\n| Delete snapshot | `cpln volumeset snapshot delete REF --snapshot-name NAME` | Destructive |\n| Delete volume | `cpln volumeset volume delete REF [--location LOC] [--volume-index N]` | Destructive (data loss) |\n| Shrink volume | `cpln volumeset shrink REF --new-size GIB [--location LOC]` | **DESTRUCTIVE — permanent data loss** |\n\n`shrink` provisions a new, smaller volume and removes the old one — data is **not** migrated. Safe only with built-in redundancy (Kafka replication; Cassandra/CockroachDB), on `ext4`/`xfs` (not `shared`). Apply the destructive-op confirmation from the operating guide (`get_cpln_rules`) first. Detail: `stateful-storage` skill.\n\n## Commands that don't exist\n\n| Wrong | Correct |\n|---|---|\n| `cpln <resource> list` | `cpln <resource> get` (no args = list all) |\n| `cpln logs --follow` | `cpln logs --tail` (or `-t` / `-f`) |\n| `cpln workload log` for container logs | that's the `eventlog` alias (platform events); container logs = `cpln logs '{gvc=\"GVC\", workload=\"W\"}'` |\n| `cpln cloudaccount create` | `cpln cloudaccount create-aws` / `create-azure` / `create-gcp` / `create-ngs` |\n| `cpln mk8s create` | `cpln apply --file mk8s-manifest.yaml` |\n| `cpln workload update REF --identity X` | `cpln workload update REF --set spec.identityLink=//identity/X` |\n| `cpln gvc update REF --location LOC` | `cpln gvc add-location REF --location LOC` |\n| `cpln identity clone` | identity has no clone — `get -o yaml-slim`, edit the name, `cpln apply` |\n| `cpln volumeset ... --locations / --volume-indexes` | singular: `--location`, `--volume-index` |\n| `cpln whoami` | `cpln profile get` (context) / `cpln account get` |\n\n## Building & referencing images\n\n`cpln image build` puts an image in the org's **private registry** — the registry referenced in workload specs as `//image/NAME:TAG`. Two ways to run it:\n\n```bash\ncpln image build --name my-app:v1.0 --remote   # builds on Control Plane, pushes for you — no Docker\ncpln image build --name my-app:v1.0 --push     # builds through the local Docker daemon\n```\n\n- **`--remote`**: uploads `--dir` (default `.`, filtered by `.dockerignore` or `.gitignore`, capped at 500 MB / 20,000 files), or builds a GitHub/GitLab HTTPS repo given with `--repo` (+ `--branch`). The service picks Dockerfile vs generated build and always produces `linux/amd64`. `--detach` returns a build id; `Ctrl+C` stops watching but not the build.\n- **Local**: Dockerfile auto-detected in `--dir` or passed with `--dockerfile PATH`, built with Docker (buildx when available); no Dockerfile means a buildpack build via `pack` (auto-downloaded), default builder `heroku/builder:24_linux-amd64`, everything after `--` goes to `pack`. `--platform` defaults to `linux/amd64`; multi-arch lists need buildx and `--push`. `--env` is **build-time only**, never runtime.\n- **`--dockerfile`, `--builder`, `--buildpack`, `--env`, `--env-file`, `--trust-builder`, `--trust-extra-buildpacks`, `--platform`, and `--push` are rejected with `--remote`**; `--repo`, `--branch`, and `--detach` error without it.\n- **A Docker daemon is required for a local build only.** On thin CI runners use `--remote`, or `docker build` + `docker push` against the org registry after `cpln image docker-login`.\n- Cross-org copy: `cpln image copy NAME:TAG --to-org ORG2 [--to-name NEW] [--to-profile P]` — logs into both registries, then pulls, tags, pushes. **`copy` has no `--remote` mode; it still needs a local daemon.**\n\nImage reference rules in workload specs:\n\n| Source | Reference in spec | Pull secret? |\n|---|---|---|\n| **Your org's registry (internal)** | `//image/NAME:TAG` — never the `ORG.registry.cpln.io` hostname | No |\n| **Public Docker Hub** | bare name (`nginx:latest`) — never add `docker.io/` | No |\n| **Other public registry** | exact host path (`gcr.io/...`, `ghcr.io/...`) | No |\n| **External private registry** (ECR, GCR, ACR, private Docker Hub, another CPLN org) | exact host path | **Yes** — `docker`/`ecr`/`gcp` secret on GVC `spec.pullSecretLinks` |\n\nFull image workflow (remote vs local build detail, buildx fallback, cross-org copy, pull-secret setup): `image` skill.\n\n## Workflow: Deploy a workload\n\nThe CLI runbook (also the CI/CD path):\n\n```bash\ncpln gvc create --name my-gvc --location aws-us-west-2 --org my-org\ncpln image build --name my-app:v1.0 --push          # or --remote, with no Docker daemon\ncpln workload create --name my-app --gvc my-gvc --image //image/my-app:v1.0 --port 8080 --public\ncpln workload get-deployments my-app --gvc my-gvc   # verify readiness\n```\n\n## Workflow: Grant secret access (3 steps)\n\nThe 3-step rule (identity + policy + reference) is owned by the operating guide (`get_cpln_rules`). The secret must already exist (created by the user — offer to draft the manifest for them to fill and apply; `setup-secret` skill). CLI fallback:\n\n```bash\ncpln identity create --name my-app-identity --gvc my-gvc --org my-org\ncpln workload update my-app --gvc my-gvc --set spec.identityLink=//identity/my-app-identity\ncpln policy create --name secret-access --target-kind secret --resource db-password --org my-org\ncpln policy add-binding secret-access --permission reveal \\\n  --identity //gvc/my-gvc/identity/my-app-identity --org my-org\ncpln workload update my-app --gvc my-gvc \\\n  --set spec.containers.main.env.DB_PASSWORD.value=cpln://secret/db-password.payload\n```\n\n## Workflow: GitOps with cpln apply\n\n```bash\ncpln gvc get my-gvc -o yaml-slim > manifests/gvc.yaml              # export (slim strips server fields)\ncpln workload get my-app --gvc my-gvc -o yaml-slim > manifests/workload.yaml\ncpln apply --file ./manifests/ --gvc my-gvc --ready                # idempotent; run on every push\n```\n\n## Workflow: Rename or clone (names are immutable)\n\nNo `rename` exists. **Preferred — `clone`** (on workload, gvc, policy, group, ipset, serviceaccount, mk8s, auditctx; duplicates spec only; secrets are off-limits — the user clones them):\n\n```bash\ncpln workload clone old-name --name new-name --gvc my-gvc\ncpln workload get-deployments new-name --gvc my-gvc      # verify healthy\ncpln workload delete old-name --gvc my-gvc               # only after verification\n```\n\nKinds without clone (identity, volumeset, domain, agent): `get -o yaml-slim`, edit the name, `cpln apply`. Renaming a workload changes its internal hostname (`WORKLOAD.GVC.cpln.local`) and public URL — update domain routes (`spec.ports[].routes[].workloadLink`), policy `targetLinks`/`targetQuery`, internal-DNS callers, and external clients. Never delete the old workload before the new one is verified healthy.\n\n## Workflow: Debug a failing workload\n\n```bash\ncpln logs '{gvc=\"my-gvc\", workload=\"my-app\"}' --org my-org --tail        # stream logs\ncpln logs '{gvc=\"my-gvc\", workload=\"my-app\"} |= \"error\"' --org my-org    # filter (LogQL, not a shell pipe)\ncpln workload exec my-app --gvc my-gvc -- ls /app                        # inspect the container filesystem\ncpln workload connect my-app --gvc my-gvc                                # interactive shell\ncpln port-forward my-app 8080:8080 --gvc my-gvc                          # probe locally\n```\n\n**Cron workloads — query logs per execution, not per workload.** A plain `{gvc=, workload=}` query mixes every past run. Enumerate executions with `cpln workload cron get NAME --gvc GVC`, then scope the LogQL with the `replica` label plus a time window. Full pattern: `logql-observability` skill.\n\n## Platform rules & integration\n\nScale-to-zero/autoscaling, production defaults/probes, Template Catalog first, destructive ops, secrets, and firewall rules live in the operating guide (`get_cpln_rules`) and their dedicated skills — not duplicated here. Before authoring any apply YAML / CI manifest / API body, call `get_resource_schema`. IaC: Terraform (`controlplane-com/cpln` provider), Pulumi (`@pulumiverse/cpln`), K8s Operator (`cpln operator install`).\n\n## Related skills\n\n| Need | Skill |\n|---|---|\n| Remote vs local build detail, buildx fallback, pull secrets | `image` |\n| LogQL beyond the basics, per-execution cron queries | `logql-observability` |\n| Query language (`--match` / `--tag` / `--rel`) | `query-spec` |\n| Volumeset semantics and shrink safety | `stateful-storage` |\n| K8s / Compose / Helm migration | `migration-patterns` |\n| Pipelines and GitOps patterns | `gitops-cicd` |\n| Terraform / Pulumi / K8s operator | `iac-terraform-pulumi`, `k8s-operator` |\n\n## Documentation\n\n- Platform guardrails & resource model: the operating guide (`get_cpln_rules`)\n- [Control Plane Docs](https://docs.controlplane.com) · [AI page index](https://docs.controlplane.com/llms.txt) · [CLI Reference](https://docs.controlplane.com/cli-reference/overview.md)\n"
}

SHA-256: 582ff43bf232b22534d29bb5e2bf6660d9ef45818d301e5b0e5a32bdf35ce419