One static binary drives your whole stack — deploys, environments and
secrets, databases, and copy-on-write branches. The grammar is usually
flicker <noun> <verb> [name]
(a few verbs like deploy
are top-level); branch ensure
and deploy
are idempotent, and every command exits non-zero on failure, so a pipeline never leaks
a preview database or hides a broken step.
This page mirrors the CLI's own help — run flicker help <topic>
or flicker <noun> <verb> --help
for the same content
in your terminal. New here? Walk through
Getting started
first.
Getting started
flicker quickstart
from zero to a deployed app and a forked DB in five commands
Get a working setup end-to-end. You need a Flicker API token (mint one in the web UI under Settings → API Keys) and a database to act on: authenticate the CLI, point at a database, fork a branch, deploy, and tear the branch down.
$ flicker auth login flk_xxx # org resolved from the key; stored in ~/.config/flicker/config.toml $ flicker database set my-app # write database = "my-app" to ./flicker.toml $ flicker branch create pr-1234 --ttl 2h --label pr=1234 # ephemeral CI fork $ flicker deploy --from-local # tar cwd + build on Flicker + rolling, health-gated deploy $ flicker branch delete pr-1234 -y # or let the TTL reaper handle it
flicker auth
sign the CLI in, as a person or as a machine
`flicker auth login` with NO arguments signs you in through a browser — device authorization (RFC 8628), the same flow as `gh auth login`. It prints a one-time code, opens the verification page, and waits while you approve the request; what it stores is a USER token covering EVERY organization you belong to, so the organization becomes CONTEXT you pick with `org set <slug>` rather than a property of the credential. It still works with no browser: over SSH, in a container, or with --no-browser, the URL and code are printed for entry on any other machine and the CLI polls exactly the same. There are TWO deliberate kinds of credential. A USER token (`auth login`) is for humans at a terminal and is valid only for /whoami and the agent-config routes — it cannot deploy, read a secret, or touch a database. A MACHINE key (`auth login <key>`, an ORG API KEY `flk_` minted under your org's Settings → API Keys) acts as the ORGANIZATION, is long-lived and scopable, and is what CI uses; it is unchanged — the org is resolved from the key, the key is stored under that org in ~/.config/flicker/config.toml (0600), and that org becomes current. In CI set FLICKER_TOKEN instead of running login; it takes priority over stored keys. `auth logout` forgets the browser login on this machine only — it does not touch org API keys (use `org remove <slug>`) and does not revoke anything server-side; revoke a lost machine under Account Settings → CLI access, which kills it without rotating any other credential. `auth user <token>` is the older single-organization personal token (`flk_usr_`, minted under Account Settings → CLI access); it still works and is the answer for a machine that cannot reach a browser at all. FLICKER_USER_TOKEN is the CI form of either — an org key is never used in its place. `auth list` shows whether this machine holds a browser login, plus every org it holds a key for.
$ flicker auth login # browser sign-in; covers every org you belong to $ flicker auth login --no-browser # print the URL + code instead of launching a browser $ flicker auth login flk_live_abc123 # machine key: org resolved from the key, stored, made current $ flicker auth logout # forget the browser login on this machine $ flicker auth list # what this machine is signed in as $ FLICKER_TOKEN=flk_live_abc123 flicker database list # one-off override (CI)
flicker context
how flicker resolves which org and database a command acts on
Every command needs to know which org and database it acts on. Org is auth-centric — `auth login <key>` resolves it from the key. Resolution order (earlier wins): --org flag, ./flicker.toml, FLICKER_ORG, then the current org in the global config. Database is named per call or set as a default with the same precedence. Commit flicker.toml so the whole team and CI share one context without remembering flags.
$ flicker auth login flk_live_abc123 # org inherited from the key $ flicker database set my-app # writes database = "my-app" to ./flicker.toml $ flicker org set acme --local # per-directory org override in ./flicker.toml $ flicker --database other branch list # one-off override $ FLICKER_DATABASE=other flicker branch list # env-var override (CI)
Projects
flicker project
the umbrella that owns your databases + apps
A project is the container that owns Databases + Apps + environments + secrets — it is NOT a Postgres instance (that's `database`). Put an app and its database in the SAME project and Flicker auto-wires DATABASE_URL (the branch's internal connection string) at deploy — never hand-set it. Every project has a `main` environment (its root, ≈ production); other envs branch from it. `project use` sets the default project in ./flicker.toml so `database create` and `app create` land in it without --project. `project set-primary <database>` records WHICH database that bare DATABASE_URL wires to: a single-database project never needs it, but once a project owns several Flicker refuses to guess, so an app created there gets no auto-wired database edge until you name one (the database must already belong to the project; org-wide API key required). `project set-default-branch <environment>` records what a factory run's `factory` branch is forked FROM (#1843) — without it every run forks whatever environment happens to be named `staging`. The environment must belong to the project, and the project's production environment is refused: forking it would hand every sandbox a copy of real data. Pass an empty environment to clear it. `project delete` is a SOFT delete: an empty project (no apps, no databases) is marked archived and drops out of `project list`, but its row, environments and scoped secrets are kept — find them with `project list --archived` and bring one back with `project restore`.
| Flag | Description |
|---|---|
--archived |
list archived (soft-deleted) projects instead of live ones |
--yes |
confirm `project delete` |
$ flicker project create my-app # create the umbrella (name only; mints its main env) $ flicker project list # all projects in the current org $ flicker project show my-app # its databases, apps, and environments $ flicker project use my-app # set as default in ./flicker.toml $ flicker project set-default-branch staging # what factory runs fork their branch from $ flicker project set-primary my-app-db # the database DATABASE_URL auto-wires to in a multi-database project $ flicker project delete my-app --yes # archive an empty project $ flicker project list --archived # the archived ones $ flicker project restore my-app # bring an archived project back
flicker health
observed health of your project, apps, and databases
Read the last stored observed-health result for a project, app, or database you own. Authenticated and tenant-scoped — not the public platform status page, and it never probes live. A never-checked resource is `unknown` with a null timestamp, never a default `healthy`. `health project` rolls up every app and database plus a per-resource breakdown. `health app` includes readiness and the requested image; running-vs-requested lives in `health.checks.image`. `health database` exposes CNPG, query, and backup checks. Last-checked is always present. Omitting `<ref>` on `health project` uses the default project from flicker.toml.
$ flicker health project acme # rollup plus each app and database $ flicker health app web # readiness, requested image, last check $ flicker health database acme-db # ready / connectable / backup checks $ flicker health project --json # machine-readable; uses flicker.toml project
Tickets & memory
flicker ticket
manage Flicker Tickets from the terminal
Tickets are Flicker's work units. They belong to a project, can nest under a parent, move through a fixed workflow (backlog → selected_for_dev → in_progress → done), and carry versioned markdown documents. Inspect them with `list`, `tree`, and `show`; add work with `create` (`--parent` makes it a child of another ticket). `move` atomically transfers one or more tickets to another project in the same organization, carries documents and event history, and detaches parent links that would cross project scope. Move workflow state with named transitions rather than setting a status directly: `select-for-dev`, `start`, and `complete` move it forward; `reopen` sends a done ticket back to backlog; `defer` parks active work. `document` reads and writes markdown documents by kind, and `checkout` / `pull` / `push` sync them to local files. Backlog discipline (flicker #1539): backlog means deliberately punted work, not "not started yet." Deferring or reopening into backlog requires `--reason` plus at least one revisit trigger (`--until`, `--condition`, or an open blocker). `ticket backlog-audit` buckets backlog tickets into ready-to-reconsider, needs-judgment, and untriaged. A ticket with an open (non-done) blocker cannot `select-for-dev` or `start`, and the refusal names the blocking ids; `ticket blocker list` shows a ticket's blockers (so does `ticket show`), and `ticket blocker add/remove` manages that. `ticket backlog-set` backfills `--reason`/`--until`/`--condition` on a ticket already in backlog without a status transition.
| Flag | Description |
|---|---|
--project <slug> |
project to operate on when omitted positionally |
--parent <id> |
create a child ticket under a parent ticket |
--to-project <slug|id> |
with move: destination project in the same organization |
--body <text> |
ticket body or document body |
--title <text> |
document title |
--history |
with document read: show every version |
--out <dir> |
with checkout/pull: output directory (default flicker-tickets) |
--force |
with checkout/pull: replace existing local ticket markdown files |
--reason <text> |
with defer/reopen/backlog-set: why this is deliberately punted |
--until <date> |
with defer/reopen/backlog-set: an ISO date/datetime revisit trigger |
--condition <text> |
with defer/reopen/backlog-set: a free-text revisit trigger |
--by <id> |
with blocker add/remove: the blocking ticket (blocker list needs no --by) |
--json |
machine-readable output for skills |
$ flicker ticket list my-project # board-order ticket list $ flicker ticket tree --project my-project # recursive execution tree $ flicker ticket create "Implement checkout" --project my-project --body "Acceptance notes" # create work $ flicker ticket create "Write tests" --project my-project --parent 42 # create child work $ flicker ticket move 42 43 --to-project new-project # move tickets atomically and detach cross-project parent links $ flicker ticket checkout my-project --out .flicker/tickets # write local markdown files with lock_version metadata $ flicker ticket push .flicker/tickets/000042-implement-checkout.md # push markdown edits with optimistic concurrency $ flicker ticket select-for-dev 42 # backlog → selected_for_dev $ flicker ticket start 42 # selected_for_dev → in_progress $ flicker ticket complete 42 # in_progress → done $ flicker ticket reopen 42 # done → backlog (pick a finished ticket back up) $ flicker ticket defer 42 --reason "waiting on #99" --until 2026-09-01 # punt with a reason and a date trigger $ flicker ticket blocker list 42 # what is blocking 42, and whether it is still open $ flicker ticket blocker add 42 --by 99 # 42 cannot select-for-dev/start until #99 is done $ flicker ticket backlog-audit --project my-project # which backlog tickets are ready to reconsider $ flicker ticket backlog-set 42 --reason "pre-dates the discipline" --condition "triage in next planning pass" # backfill reason+trigger on a ticket already in backlog $ flicker ticket document write 42 task_contract --body "$(cat plan.md)" # write a versioned document $ flicker ticket document read 42 task_contract --history # read document history
flicker memory
write, search, and traverse project memory
Memory is searchable evidence for agents and humans. Search is project-scoped by default (when a project context exists) and can span every project in the org with --all-projects. Ranking is Postgres full-text search; there are no embedding claims. Every result carries a temporal state: current when nothing supersedes it, historical when something does (the replacement is shown), and unknown when it was superseded but the replacement cannot be read. Superseded results are shown and labeled rather than hidden, because "what did we decide" often has an answer that was later replaced; pass --current-only to drop them. --as-of answers as of a past instant. This is valid time with provenance, not a bitemporal store. expand walks the citation graph one or two hops from a node and prints each neighbour with the direction of the edge that reached it. write records a deliberate note, anchored to --ticket or to the project's memory journal.
| Flag | Description |
|---|---|
--project <slug> |
project to operate on when omitted positionally |
--all-projects |
search every project in the org (memory search only) |
--current-only |
drop superseded results (they are shown and labeled by default) |
--as-of <iso8601> |
answer as of a past instant |
--depth <n> |
hops to walk with memory expand (capped at 2) |
--ticket <id> |
anchor a memory write to a ticket |
--title <text> |
title for memory write or add |
--body <text> |
body for memory write or add |
--json |
machine-readable output for skills |
$ flicker memory search "regression evidence" --project my-project # search tickets, documents, and events $ flicker memory search "cross-project decision" --all-projects # search every project in the org $ flicker memory search "retry policy" --current-only # hide superseded results $ flicker memory write "Session pooler pins a backend per connection" --ticket 1274 # record a durable learning $ flicker memory expand ticket 1274 --depth 2 # walk the citation graph around a ticket $ flicker memory search "task contract" --json # JSON output for skills
Factory
flicker factory
start factory runs and read their ordered traces
Factory commands are thin clients over the control-plane run API. `run` starts a run for one or more tickets under a named roster. With no `--environment` it forks itself a fresh `factory` branch; `--from` names what that branch is forked FROM, defaulting to the project's default branch environment and falling back to `staging`. `--environment` is the other half of the same decision — it works in an environment that already exists, so nothing is forked and `--from` is refused alongside it. It may not be a staging or production environment, or any environment that copies production secret values: the run is given its environment's secrets, so those are refused. A project's production environment is never a fork parent. `roster` manages rosters and the agent steps inside them without a browser: `list`, `show`, `create`, `add-entry`, `update-entry`, `remove-entry`. A roster with no entries cannot run — it dies at pod launch — so `list` and `show` print the entry count and `create` names the `add-entry` command to run next. The `show` command takes the roster's numeric id, not its name. Entry field flags change only what you pass, which is what makes `--phase ""` (unbind this step) a different act from omitting `--phase`; `--profile` is repeatable and its order is the profiles' order. `repo set-test-command <connection-id> -- <command...>` sets (an empty argv after `--` clears) a repository connection's factory verify-gate command — argv exec'd directly with no shell, so a pipeline needs `-- bash -lc "a && b"`. A connection with no command configured is a RECORDED outcome (`unconfigured`), not a pass: its run's test phase is judged by the agent's own report rather than an actual suite run. `repo set-sidecars <connection-id> <json|->` sets (an empty list clears) the sandbox pod's optional service containers — a JSON list of `{name, image, port}` plus optional `env`, `run_as_user`, and `cpu`/`memory`/`cpu_limit`/`memory_limit`, or `-` to read it from stdin. They share the pod's network namespace, so the suite reaches them on `localhost` at the declared port, and the kubelet holds every phase until each one is accepting connections. `trace` prints append-only events in sequence order; `--follow` polls from the last seen sequence until the run passes, fails, or is cancelled. `watch` prints the same readable tail as `trace --follow` plus a STATUS line on every status change, stopping at a terminal status; every line you type + Enter queues a steer for the run's agent, and run inside a herdr-managed pane it also reports its identity to herdr over its own local socket protocol, so the run shows up in `herdr agent list` like any other tracked agent — outside herdr it is a no-op report and watch still works standalone. `steer` queues one message for a live run's agent, delivered exactly once at the agent's next turn boundary — mid-phase on the agent's own session, or folded into the next phase's prompt when the run is between phases. `pause` parks a run between phases: the in-flight phase finishes, the next one waits until `resume`; stopping an agent mid-turn stays what it always was — cancel. Both are idempotent. `herdr sync` reconciles this user's active runs in the current project against herdr's pane list, giving any run missing one a pane running `flicker factory watch` (requires herdr on PATH); `--all-projects` widens it to every project in the organization, so one herdr session holds every agent the org is running instead of one session per project, and each pane is named for and scoped to its run's OWN project rather than the working copy's. `answer` answers a question the agent itself asked: an agent that hits an ambiguity the tickets do not settle may park the run and ask instead of guessing, and this hands its question a person's reply — delivered as a steer, resuming the agent in the same session it asked from. `cancel` deliberately ends a run that has not finished: the workspace is destroyed first (the run only turns cancelled once that destruction is confirmed), remaining phases are marked failed, and the run's credentials are revoked.
| Flag | Description |
|---|---|
--ticket <id>[,<id>...] |
with run: ticket ids; repeatable or comma-separated |
--roster <name> |
with run: roster to execute (required) |
--name <name> |
with roster add-entry/update-entry: the step's name |
--phase <phase> |
with roster add-entry/update-entry: phase to bind ('' unbinds) |
--model <model> |
with roster add-entry/update-entry: model id on the connection |
--connection <id> |
with roster add-entry/update-entry: provider connection id |
--harness <name> |
with roster add-entry/update-entry: codex | pi | opencode |
--thinking <level> |
with roster add-entry/update-entry: off..max |
--purpose <text> |
with roster add-entry/update-entry: what the step is for |
--position <n> |
with roster add-entry/update-entry: order within the roster |
--tools <a>[,<b>] |
with roster add-entry/update-entry: repeatable tool allowlist |
--writes <glob>[,...] |
with roster add-entry/update-entry: repeatable write allowlist |
--protected-file <p>[,...] |
with roster add-entry/update-entry: repeatable protected paths |
--profile <name|id> |
with roster add-entry/update-entry: repeatable, ordered agent-config profiles |
--description <text> |
with roster create: the roster's description |
--environment <name> |
with run: work in this existing environment (skips forking) |
--from <name> |
with run: environment the run's factory branch is forked from |
--message <text> |
with run: supplemental operator instruction |
--project <slug> |
with run, watch, herdr sync: project (else flicker.toml project) |
--all-projects |
with herdr sync: every project in the org, not just the selected one |
--follow |
with trace: poll for new events until the run is terminal |
--json |
run: machine-readable result; trace: raw event array |
$ flicker factory run --ticket 1719 --roster default # start one run on a fresh factory branch $ flicker factory run --ticket 1719 --roster default --from staging # fork the factory branch from staging $ flicker factory run --ticket 1719 --roster default --environment factory/1719 # start one run $ flicker factory run --ticket 1719,1720 --ticket 1721 --roster default --environment factory/1719 --message "focus CLI" # start a multi-ticket run $ flicker factory cancel 27 # deliberately end a run (workspace destroyed first) $ flicker factory roster list # rosters in this project, with entry counts $ flicker factory roster create nightly --description "the overnight lane" # create an empty roster $ flicker factory roster add-entry 4 --name engineer --phase implement --model anthropic/claude-sonnet-4 --connection 2 --profile engineers # add a step and give it a profile $ flicker factory roster show 4 # the roster and every step in it $ flicker factory roster update-entry 9 --phase "" # unbind the step from its phase $ flicker factory roster remove-entry 9 # delete a step $ flicker factory repo set-test-command 12 -- mix test # set the connection's factory verify-gate command (argv, no shell) $ flicker factory repo set-test-command 12 -- # clear the verify-gate command (recorded as unconfigured, not a pass) $ flicker factory repo set-sidecars 12 '[{"name":"postgres","image":"pgvector/pgvector:pg16","port":5555,"run_as_user":999,"env":{"POSTGRES_USER":"postgres","PGPORT":"5555"}}]' # run Postgres beside the runner on localhost:5555 $ flicker factory repo set-sidecars 12 - # read the service list from stdin (a reviewed file, not shell history) $ flicker factory trace 27 # print current trace $ flicker factory trace 27 --follow # follow until terminal $ flicker factory trace 27 --json # raw event array $ flicker factory watch 27 # readable tail; type a line + Enter to steer; reports to herdr when run inside a herdr pane $ flicker factory steer 27 "prefer the small fix" # queue a message for the run's agent $ flicker factory answer 27 "use the existing table, do not add one" # answer the question the agent parked the run on $ flicker factory pause 27 # park the run after the current phase $ flicker factory resume 27 # let the next phase launch again $ flicker factory herdr sync # give every active run of yours a herdr pane $ flicker factory herdr sync --all-projects # one herdr session covering every project in the org
Databases & branches
flicker database
manage your databases
A database is an isolated Postgres environment — its own instance, with a main branch and any number of forks. Provisioning is async (~1–5s on a warm host); the CLI blocks until active by default. `database import` loads an existing database into main from a connection URL — an in-cluster pgstream snapshot Job, not host-side pg_dump/pg_restore — create an empty database first, then import into it. Two independent backup settings, often confused. `database backup-mode <pitr|daily>` chooses WHETHER write-ahead log is archived: `pitr` archives WAL continuously, `daily` takes daily volume snapshots and archives no WAL. `database barman-backend <in-tree|plugin>` chooses HOW that archive is declared to CloudNativePG: `in-tree` (the default, and what every existing database is on) writes the cluster's own `spec.backup.barmanObjectStore`, which CNPG deprecated in 1.26 and intends to remove; `plugin` writes a separate `barmancloud.cnpg.io` ObjectStore and binds it through the cluster's `spec.plugins`. The barman configuration itself — bucket, endpoint, credentials, WAL compression and parallelism — is built once and used by both forms, so they archive to the same place; retention and the daily volume snapshots are untouched. In `daily` mode there is no WAL archive to declare, so the setting is inert until PITR is on. Switching is risky in one direction only: CNPG accepts a cluster that binds a plugin the cell does not actually run, and that cluster comes up healthy and archives NOTHING. So `barman-backend plugin` prompts for confirmation (pass --yes to skip) and you should confirm the archive is advancing after the reprovision; going back to `in-tree` restores the form the cluster already had and is not prompted.
| Flag | Description |
|---|---|
--no-wait |
return immediately with status = pending instead of polling |
--yes |
skip the confirmation prompt (delete, resize, barman-backend plugin) |
$ flicker database create my-app # provision, wait until active $ flicker database list # all databases in the current org $ flicker database set my-app # set as default in ./flicker.toml $ flicker database import postgresql://user:pw@host/db --database my-app # import an external database $ flicker database backup-mode pitr --database my-app # archive WAL continuously (point-in-time recovery) $ flicker database barman-backend plugin --database my-app # declare the WAL archive through the Barman Cloud plugin (prompts) $ flicker database barman-backend in-tree --database my-app # go back to spec.backup.barmanObjectStore
flicker branch
fork, reset, and tear down database branches
Branches are copy-on-write Postgres clones of a parent (typically main) that come up in seconds and share storage until they diverge. The killer use case is per-PR test databases. `--from` clones any branch, including a non-main branch (nested forks). Branching is OPT-IN (branch-rules v2): `branch create` defaults to an EMPTY rule — nothing forks or deploys, but secrets still inherit so `flicker secrets pull` yields a working DATABASE_URL. Opt entities IN with `--copy <entity>[:method]` (repeatable), where entity is `db` (the branch's own database) or an app slug, and method overrides the type default — db: clone (default); app: fork (default) | fork+copy-files | fork+empty-files | shared. `--copy-all` opts in the project's full composition (db + every app). `branch create` with no `--copy` on a terminal shows an interactive picker (entities + methods); piped/CI input falls through to the empty default. `branch create` is idempotent on the name. `branch reset` re-forks from the parent (discards changes), re-stamps a fresh app password so the connection string keeps working, and redeploys the branch's included app forks so the apps running against it pick that new credential up; `branch delete` removes it permanently. Protected branches (main by default) cannot be deleted or reset. `branch disk` and `branch resize` read and grow a branch's data volume; `branch compute` reads the CPU and memory its cluster is RESERVING — a fork's CPU request is chosen by a rule rather than by you (floored at the nano request, so an idle branch cannot hold a core the parent needs), and the live spec was previously only visible through kubectl. A side the cluster leaves unset reads `not set` rather than 0, because no floor and a floor of zero are different states. `branch ensure` / `branch destroy` provision or tear down a git-bound preview in one idempotent call — `--base` is the git base to diff, `--from` is the data fork-parent. On `ensure`, a `--from` that names no branch in one of the project's databases is REFUSED — the fork errors rather than quietly cloning that database's default branch, so a multi-DB preview can never end up half-forked from production. By default `ensure` INHERITS the parent env's rule (a preview off main gets main's full composition); `--copy` / `--copy-all` OVERRIDE it, but only when ensure first creates the env — an existing env keeps its persisted rule, so CI never undoes a local override.
| Flag | Description |
|---|---|
--from <branch> |
branch to clone (default: the database's default branch); any branch, incl. nested forks |
--ref <ref> |
git ref for ensure/destroy (e.g. feat/x); main = prod deploy |
--base <ref> |
git base ref to diff against (ensure; default: main) |
--sha <sha> |
exact commit to pin on ensure |
--ttl <dur> |
auto-expire after duration, e.g. 2h, 30m, 1d — reaped server-side |
--label k=v |
metadata tag, repeatable (e.g. --label pr=1234) |
--copy <entity>[:method] |
opt an entity INTO the branch, repeatable (db[:clone], <app>[:fork|fork+copy-files|fork+empty-files|shared]); create defaults to empty, TTY prompts if omitted |
--copy-all |
opt in the project's full composition (db + every app at type defaults) |
--idempotency-key <k> |
safe-retry key (defaults to the branch name) |
--no-wait |
return immediately with status = creating |
$ flicker branch create dev # empty rule — secrets only (nothing forks; TTY shows a picker) $ flicker branch create dev --copy db # fork only the database $ flicker branch create dev --copy db --copy web:shared # fork the DB; reference web without forking it $ flicker branch create dev --copy-all # full composition (db + every app) $ flicker branch create pr-1234 --copy-all --from main --ttl 2h --label pr=1234 # ephemeral CI fork of the full stack $ flicker branch list # show all branches + connection strings $ flicker branch disk dev # volume capacity + usage for the dev branch $ flicker branch compute dev # CPU/memory the dev branch's cluster reserves $ flicker branch reset dev # re-fork from main + fresh app password (destroys changes in dev) $ flicker branch delete dev -y # permanent delete, skip confirmation $ flicker branch ensure --ref feat/x --base main --ttl 48h --label pr=42 # PR preview env, inheriting main's rule (CI) $ flicker branch ensure --ref feat/x --copy db # override inherited rule: fork only the DB $ flicker branch destroy --ref feat/x # tear down on PR merge/close (CI)
flicker ext
enable/disable PostgreSQL extensions
Extensions are baked into the Flicker Postgres image, so enabling one is just a CREATE EXTENSION away — no rebuild. The setting lives on the database and applies to every branch automatically: new branches get it on clone, existing branches are reconciled by a background job. Only runtime extensions (no container restart) are exposed.
$ flicker ext list # catalog + enabled state for the current database $ flicker ext enable vector # turn on pgvector across all branches $ flicker ext disable hstore # remove an extension from all branches
flicker preview
opt-in per-ticket preview environments
Give a ticket or PR a live, prod-shaped environment: a copy-on-write database fork plus (for source-bound apps) forked app deploys, provisioned in seconds and TTL-reaped like any git-bound branch. `preview ensure` provisions or redeploys the environment for a ref (idempotent per ref); `preview down` tears it down. Both are thin wrappers over the same machinery as `branch ensure` / `branch destroy`. Previews are OPT-IN per repo and DEFAULT OFF — they cost real compute, so nothing is provisioned implicitly. Enable them by committing `preview_envs = true` to the repo's ./flicker.toml; without the opt-in, both verbs refuse with an explanation.
| Flag | Description |
|---|---|
--ref <ref> |
git ref for the preview (e.g. pr-42); required |
--ttl <dur> |
auto-expire after a duration, e.g. 48h — reaped server-side |
--label k=v |
metadata tag, repeatable (e.g. --label pr=42) |
$ flicker preview ensure --ref pr-42 --ttl 48h --label pr=42 # provision (or redeploy) the PR's preview environment $ flicker preview down --ref pr-42 # tear down the forked resources on merge/close
Apps & deploy
flicker app
manage hosted web apps (containers)
An app is a container image running on Flicker, optionally reachable at a domain over HTTPS (the platform terminates TLS and routes traffic to it). Source builds and prebuilt images are both supported. Use `flicker deploy` for normal deploys — the verbs here are for explicit app management. App and database lists show observed HEALTH and CHECKED separately from LIFECYCLE; an unhealthy row names the check that failed, e.g. `unhealthy (rollout_incomplete)`. New apps default to TCP readiness on their primary port (the default port included); existing apps stay unenrolled. Use `--readiness http` with an explicit path for HTTP readiness. Probe changes take effect on the next deploy. Flicker adds no automatic liveness probe; opt one in per app with `liveness_probe_path` in flicker.toml, pointed at a dependency-free endpoint (a liveness path that touches your database restart-loops the app on the first blip). Note the two log verbs are different: `app logs` is the RUNNING app's container output, while `app build-logs` is the BuildKit output from the build that produced its image. Build secrets are redacted from a build log before it is stored. `app show <name>` reads an app back — status, image, and its dependency wiring (which database each env var is bound to), plus the managed-injected vs stored env-var split (flicker #726); `app env` shows the full per-key provenance. There is no `--domain` flag: a custom routing domain is attached via Settings → Domains in the web UI (register it, verify ownership over DNS, then attach it to the app) — not at create/update/deploy time (flicker #1556).
| Flag | Description |
|---|---|
--image <ref> |
registry image, e.g. myorg/web:v2 (alternative to --build) |
--port <N> |
container's listening port (default 8080; a new app's primary port defaults to TCP readiness) |
--readiness <mode> |
disabled, tcp, or http; persists now and takes effect on next deploy |
--readiness-path <path> |
absolute HTTP readiness path; required with --readiness http |
--env k=v |
environment variable, repeatable (stored encrypted at rest) |
--build-secret KEY=VALUE |
secret for build time only, repeatable (Fly parity, e.g. FLUXON_LICENSE_KEY) |
--release-command <cmd> |
run once before cutover, e.g. /app/bin/migrate |
$ flicker app scaffold web # scaffold an [app] table in flicker.toml $ flicker app create web --image traefik/whoami --port 80 # new apps default to TCP readiness on their primary port $ flicker app create web --image myorg/web --port 4000 --readiness http --readiness-path /health # explicit HTTP readiness $ flicker app update web --readiness disabled # disable readiness on the next deploy $ flicker app list $ flicker app show web # status, wiring (db → env var), managed vs stored vars $ flicker app deploy web --image myorg/web:v3 # re-deploy with a new image $ flicker app logs web # tail the running app's container logs $ flicker app builds web # list recent builds with status + duration $ flicker app build-logs web # the latest build's captured BuildKit output $ flicker app delete web -y
flicker deploy
deploy the [app] in flicker.toml — manifest-driven or local-source
Two deploy modes, one command. Manifest mode (`flicker deploy`) reads [app] (+ optional [build], [config]) from ./flicker.toml and deploys exactly what's pinned — a registry image, or a git repo + ref the platform builds for you. Reproducible and reviewable in a PR — the right primary for CI. Local mode (`flicker deploy --from-local`) tars the working dir, POSTs it to the app's /push endpoint, and the platform builds the image for you (BuildKit), including uncommitted changes. Pass `--build-secret KEY=VALUE` (repeatable) to expose a secret to the build only (Fly parity, e.g. FLUXON_LICENSE_KEY) — it reaches BuildKit as a --secret mount and never lands in the runtime image. Both modes converge on the same rolling cutover; the new version takes traffic only once it's up, so a failed release leaves the old version serving.
| Flag | Description |
|---|---|
--from-local |
tar cwd, upload, build on Flicker (dev mode) |
--image <ref> |
override the manifest's image (manifest mode only) |
--build-secret KEY=VALUE |
build-time-only secret, repeatable (Fly parity, e.g. FLUXON_LICENSE_KEY) |
--no-wait |
return immediately instead of polling to running |
--release-command <cmd> |
run once before cutover, e.g. /app/bin/migrate |
$ flicker deploy # manifest mode — pin image or [build] repo in flicker.toml $ flicker deploy --from-local # tar cwd, build on Flicker, deploy $ flicker deploy --from-local --build-secret FLUXON_LICENSE_KEY=... # expose a build-only secret $ flicker deploy --image myorg/web:v3 # manifest mode w/ image override (CI on a SHA)
flicker manifest
flicker.toml — context + the [app] / [build] / [config] tables
Per-repo config file. Holds context (top-level `org` / `database`) and the app spec — [app] plus an optional [build] table for source builds (repo/ref/dockerfile/context) and a [config] manifest ($ref-ing the per-environment secret pool). flicker.toml is meant to be committed: edit it, `flicker deploy`, done.
$ flicker app scaffold web # scaffold the [app] table $ flicker database set my-app # write the database context $ flicker org set acme --local # optional per-directory org override
flicker domains
register, verify and attach custom routing domains to apps
A custom routing domain is an org-wide resource: register it once, prove you own it over DNS, then attach it to an app — the platform terminates TLS and routes the hostname to that app from its next deploy. `domains add <domain>` registers the name (routing only; email stays off — see `mail domains`) and prints the ownership TXT record to publish at `_flicker-challenge.<domain>`. Flicker checks pending records automatically every five minutes, backing off to hourly after 24 hours; `domains verify <domain>` runs an immediate check. `domains show <domain>` reports the last check and pending reason. `domains attach <domain> --app <app>` wires a verified domain to the app — if it was already attached when ownership verifies, Flicker redeploys it automatically. `domains detach <domain>` removes the wiring. Same record as Settings → Domains in the web UI.
| Flag | Description |
|---|---|
--app <app> |
with attach: the app (slug or name) that should serve the domain |
$ flicker domains add app.acme.com # register a routing domain; prints the TXT challenge $ flicker domains verify app.acme.com # live check of the _flicker-challenge TXT record $ flicker domains attach app.acme.com --app web # route the domain to web (redeploy to apply) $ flicker domains list # every org domain, ownership state and attached app
flicker mail
manage sending domains and wire an app to managed transactional email
Two halves: sending DOMAINS (org-wide) and an app's mail WIRING. `mail domains add <domain>` registers a sending domain and prints the DKIM / SPF / DMARC records to publish. Flicker checks pending records automatically every five minutes, backing off to hourly after 24 hours; `mail domains verify <domain>` runs an immediate DNS check. `mail domains list` shows each domain's verification state, last check, and pending reason. `mail domains disable <domain>` stops sending from that domain and keeps its DKIM keys for later re-enabling. `mail enable --app <app>` wires the app to Flicker's managed mail credential (a `:mail` edge, mirroring how DATABASE_URL works) — the credential is minted server-side and injected as `FLICKER_MAIL_API_KEY` at deploy, and the CLI never prints it, so redeploy to pick it up. `mail disable --app <app>` removes the edge and revokes the credential. `mail status --app <app>` shows this app’s actual from-domains and verification state, its last send time, or org domains it could send from when it has never sent.
| Flag | Description |
|---|---|
--app <app> |
with enable / disable / status: the target app (slug or name) |
$ flicker mail domains add mail.acme.com # register a sending domain; prints the DNS records $ flicker mail domains verify mail.acme.com # live DNS check of DKIM/SPF/DMARC $ flicker mail domains disable mail.acme.com # stop sending from the domain; keep DKIM keys $ flicker mail enable --app web # wire the app to managed mail (redeploy to apply) $ flicker mail status --app web # app sent-from domains, verification state, and last send
flicker suggestions
wire an app to a project's suggestion inbox
Let an app submit its users' bug reports and feature requests to a project without anyone handling a bearer token. `suggestions enable --app <app>` creates a `:suggestions` edge from the app to a project — the same managed-dependency shape as DATABASE_URL and mail. Flicker mints a credential scoped to THAT ONE PROJECT's suggestion routes, stores it server-side, and injects it as `FLICKER_API_KEY` plus `FLICKER_SUGGESTIONS_PROJECT_ID` at deploy time, so redeploy to pick them up. `--project` targets a project other than the app's own. `suggestions disable --app <app>` removes the edge and revokes the credential after a short grace window, so an in-flight deploy keeps working. `suggestions status --app <app>` shows whether the edge is present, which project receives the reports, and when that project last received one. There is no key-minting command by design: the injected key cannot reach any other project or any other resource.
| Flag | Description |
|---|---|
--app <app> |
the target app (slug or name); required |
--project <project> |
project that receives the suggestions (default: the app's own project) |
$ flicker suggestions enable --app enventory # wire the app to its project's inbox $ flicker suggestions status --app enventory # edge present? which project? last report? $ flicker suggestions disable --app enventory # remove the edge + revoke the credential
Environments & secrets
flicker env
manage named environments and sync their secrets to .env files
Environments are named configs (production, preview/pr-42, dev/giovanni) holding governed secrets. Apps bind to one; deploys resolve it. `env pull` downloads the environment's own resolved values (restricted keys excluded) into a local .env — by default your personal config dev/<user>, auto-created on first pull. Present-but-unset keys are reported after the pull (and left as `# KEY is unset` comment lines in the file) — never a parent env's values. Pulled files carry a provenance header; a .env without it is presumed hand-maintained and pull refuses to overwrite it unless --force. Values are never printed to stdout. `env diff` prints key-level status (added/removed/changed) — names only, never values. Env names are unique PER PROJECT, so `main`/`dev`/`staging` name one environment in each project: `env delete` and `env policy` scope to the current project (flicker.toml `project` or --project) and the server refuses with a 409 rather than guessing when a bare name matches several projects. A project's `main` environment cannot be deleted at all — it is the project's root, holding the production secrets and anchoring every other environment's inheritance chain, so `env delete main` answers 422; delete the PROJECT if that is what you meant. Deleting any other environment also deletes the environments that inherit from it, deepest first, and the apps and database branches those environments forked (their pods and branch data included); resources only shared from a parent environment are untouched. `env create --forks-nothing` marks an environment a deliberately empty fork parent: forking from it creates the child environment and copies nothing — no database branch, no forked app. An environment that merely has no inclusion rows makes the opposite claim (not composed yet) and forks the project's full composition. At fork every parent key exists in the child: `env create --copy-values` records the NEW env as values-forked (it snapshots the parent's values into its own rows; later edits on either side do not cross); `--keys-only` records it as keys-only forked (keys WITHOUT values, and deploys bound to it are refused until each key is set; default for kind staging, copy_values otherwise). `env policy` changes the recorded fork mode of an EXISTING env but moves NO values — fill them with `secrets copy --from <parent-env>`; the recorded mode only gates future forks made through the env toward production. A key added to the parent later appears in every child as unset either way: keys always flow, values never flow after fork.
| Flag | Description |
|---|---|
--environment <name> |
target a specific environment instead of personal dev/<user> |
--project <slug> |
which project's environment to act on (delete/policy) |
--out <path> |
the local .env path (default ./.env) |
--force |
overwrite a .env that lacks the flicker provenance header |
--kind <kind> |
with create: production|staging|preview|dev (default production) |
--copy-values |
fork snapshots the parent's values (create); records a values-fork (policy, moves nothing) |
--keys-only |
fork takes keys without values (create); records a keys-only fork (policy, moves nothing) |
--forks-nothing |
with create: forking this env copies no database and no app |
$ flicker env pull # personal config dev/<user> → ./.env (created on first pull) $ flicker env pull --environment production --out .env.prod # explicit env + path $ flicker env diff # what would change locally if you pulled now $ flicker env list # all environments in the org $ flicker env create preview/pr-42 $ flicker env create staging --kind staging --forks-nothing # a fork parent that carries nothing $ flicker env create staging --kind staging --keys-only # a staging fork taking keys without values $ flicker env policy preview/pr-42 --copy-values # record the fork as values-carrying (moves no values) $ flicker env delete preview/pr-42 -y
flicker secrets
set, unset, list, and read individual secrets in an environment
Operates on one environment's secrets — by default your personal config dev/<user>, or pass --environment <name>. `set` upserts KEY=VALUE pairs and `unset` deletes keys; each command is one versioned change (one bundle, at most one redeploy of bound apps). Values are never echoed back. `list` shows names + metadata (visibility, version, updated time) — always allowed. `get` is the one deliberate value read: governed (only the org-wide key or an environment-scoped key bound to this exact environment may read), and access-logged. Restricted secrets never return a value to anyone. `copy` clones user-secret values from --from into --to (default personal dev/<user>): generate mints fresh, derive re-renders, seal copies readable values; managed DATABASE_URL/FLICKER_ENV names are skipped; existing dest values are left alone.
| Flag | Description |
|---|---|
--environment <name> |
target environment (default: personal dev/<user>) |
--plain |
with get: print the bare value only (for scripting) |
--from <env> |
with copy: source environment |
--to <env> |
with copy: destination environment (default: personal dev/<user>) |
$ flicker secrets set STRIPE_KEY=sk_test_123 --environment production $ flicker secrets unset OLD_FLAG --environment production $ flicker secrets list --environment production # names + metadata, never values $ flicker secrets get DATABASE_URL --plain # governed value read (access-logged) $ flicker secrets copy --from production # seed personal dev/<user> from production
Config
flicker org
select which connected organization commands act as
An organization is the tenant boundary — databases, branches, apps, and API keys all belong to one. Connecting an org is `auth login <key>` (the org is inherited from the key); the org verbs only SELECT among the orgs you're already authenticated to. `--local` writes a per-directory override into ./flicker.toml. Orgs are created in the web UI, not via the CLI.
| Flag | Description |
|---|---|
--local |
with set/unset: act on the ./flicker.toml override, not the global current org |
$ flicker org list $ flicker org set acme # switch the global current org $ flicker org set acme --local # pin this directory to acme via flicker.toml $ flicker org current $ flicker org remove acme # forget acme's key on this machine
flicker current
show the fully-resolved context for this invocation
Prints every selectable axis at once — org, database, environment, API base, and key status. With a stored token it also asks the server which org and key scope the token resolves to: organization (org-wide), app (single-app deploy token), or environment (environment-read-scoped secrets token). An unreachable server degrades to the local view instead of failing.
$ flicker current $ flicker current --json # machine-readable, incl. whoami when reachable
flicker skill
install the portable Flicker agent skill into your AI harness
Ships the operating knowledge an agent needs to drive Flicker correctly — the project/app/database model, the wiring rules, and the common footguns — into whatever AI coding harness you run. The skill body is embedded in the CLI binary, so it works with no repo and no network. `skill print` writes it to stdout. `skill install` places it where a harness reads it; with no `--agent` it auto-detects, and `--all` installs to every harness. Re-running is idempotent. `skill update` reinstalls the embedded bundle at user scope (never in the background). Pass `--workflow` for the Tickets lifecycle bundle (shared contract + plan/implement/test/release/ship/recall/triage). Layout: Pi, Claude Code, and Grok Build get real skill dirs under `.pi` / `.claude` / `.grok`; Grok Bot writes `/home/box/agent-data/workflows/<name>/SKILL.md` when that directory exists (else `~/.grok-bot/skills`); Codex gets a short managed pointer block in `AGENTS.md` plus the full contract at `.flicker-agent/shared/flicker-workflow.md` — the full bundle is never inlined into `AGENTS.md`, and content outside the managed markers is preserved. After install/update run `flicker doctor` and restart the harness.
| Flag | Description |
|---|---|
--workflow |
install the workflow stage skills instead of the platform skill |
--agent cc|codex|pi|grok|grokbot |
target a specific harness (default: auto-detect) |
--all |
install to every known harness |
--global |
install at user scope (~/.claude, ~/.pi/agent, ~/.grok, ~/.grok-bot or /home/box/agent-data/workflows, ~/AGENTS.md) instead of the repo |
--json |
machine-readable output |
$ flicker skill install # auto-detect harnesses and install the platform skill $ flicker skill install --workflow --global # install the plan→ship workflow skills globally $ flicker skill update --workflow --global # refresh all harness installs from this CLI embed $ flicker skill print # write the skill to stdout
flicker harness
canonical skill pool + machine profile, written into every agent harness
Org library of skills, MCP specs, rules. A PROFILE is a bag of enabled entries: own membership plus, for non-org-base profiles, every same-org org-base source not opted out. Inherited entries stay on and locked while any enabled source supplies them; disable those sources to unlock. This machine picks one profile and `sync` writes the effective bag into whichever agent harnesses are present in the working copy. Daily path: `harness use-profile <name>` once per machine, `harness init` once per working copy, `harness list` to see the library and what is in effect. `harness init` adopts a working copy so nobody has to remember to sync it: it detects the harnesses present, gitignores what sync projects, installs a SessionStart hook that syncs before the first turn of every session, and performs the first sync. `--no-hook` adopts without the hook and `--remove-hook` is the documented way out, which leaves the projected config in place. A session starting while Flicker is unreachable projects this machine's LAST GOOD answer and says so with the date; a working copy that was never synced writes nothing and says that instead, because an empty projection would read to the adapters as `nothing is assigned`. An authoritative refusal (401/403/404) is never served from that cache. Registering or publishing still puts content into the library; `harness profile` manages membership and per-source inheritance from the CLI (#1700) — create/list/show/delete/rename a profile, `--org-base` marks one as a source every other profile inherits by default, `add`/`remove` change direct membership, and `inherit <name> <source> false` opts a profile out of one org-base source (there is no per-membership disable, only inherited/direct). A membership PINS the entry version that was current when it was added, and publishing a newer version does not move that pin — so an entry can be published while every profile still renders the version before it; `profile pin <name> <entry>... --latest` (or `--all`) moves the pin in place, `harness doctor` reports a profile that is behind, and `rule add`/`publish` name the profiles that will not render what was just published (#1877). The same operations are also in the web UI. (The old assign/unassign project grid is RETIRED, #1528.) (`skill install` ships Flicker's own embedded platform/workflow skill; `harness` is the other direction — your library projected out.) Where things land: Claude Code `.claude/skills/<name>/SKILL.md` with MCP servers merged into `.mcp.json`; Grok (Build TUI) `.grok/skills/<name>/SKILL.md`; Grok Bot `.grok-bot/skills/<name>/SKILL.md`; Codex files under `.flicker-agent/agent-config/` plus an index block in `AGENTS.md`; Pi `.pi/skills/<name>/SKILL.md`; opencode `.opencode/skills/<name>/SKILL.md`. Rules project into `AGENTS.md` only when the profile enables them — a profile with zero rules leaves a hand-written AGENTS.md alone. Sync is a sync, not an append: each harness gets a manifest under `.flicker-agent/harness/`, files Flicker never wrote are never deleted, a first sync that would overwrite an unmanaged skill parks it under `.flicker-agent/parked/<harness>/<name>/` (restore with mv), and `--check` is the CI probe (exit 0 fresh, exit 1 stale, no writes to the working copy) while `--dry-run` previews the whole run — writes, removals, skips — writing nothing to the working copy and exiting as a real sync would (#1633); both may still fetch a declared machine-fetched skill and populate this machine's content cache, which is outside the working copy. Profile precedence: `--profile` > `.flicker/local.toml` > `flicker.local.toml` > global `harness_profile`. An entry with no description is a DRAFT and never projects. `harness doctor` checks declared-vs-actual on disk, profile-first (no project binding needed, #1633), and names the profile it judged through: drift, MCP server registration, scope, groups with no members, the description-index budget, whether this profile's pins are behind what is published, machine adoption (hand-installed skills classified by selected PROFILE membership — never library membership — with dangling symlinks reported as dangling, never as coverage), and two-tier delivery (natively indexed vs staged off-index, and whether staged ones are discoverable). `harness adopt` reads what this machine already has (`~/.claude/skills`, `~/.agents/skills`, repo lockfiles) and proposes a library — a dry run until `--apply`. `harness pack import` registers each skill in a directory as its own library entry; `--as-group` fronts a pack with one group skill. `--curate` has a model write or tighten descriptions. `harness install skill --source <uri> --ref <pin>` declares machine-fetched delivery (hash-verified on every sync). When sync cannot deliver it writes what it can, names what is missing, and exits non-zero; it never writes a stub for content it could not get.
| Flag | Description |
|---|---|
--profile <name> |
one-shot profile override (else .flicker/local.toml, flicker.local.toml, global harness_profile) |
--personal |
act as YOU: uses the personal CLI token, writes user-owned config |
--harness <name> |
repeatable: cc|grok|grokbot|codex|pi|opencode — target one harness |
--org-base |
with profile create: inherited by every other profile in the org |
--latest |
with profile pin: move the pin onto the entry's latest published version |
--all |
with profile pin: every membership whose pin is behind |
--pack <name> |
group entry into a named pack (default: directory's name) |
--curate |
with pack import/skill publish/adopt: an LLM writes or tightens the DESCRIPTION |
--as-group |
with pack import: front the pack with ONE group skill; members go off-index |
--group-name <name> |
with --as-group: the group entry's name (default: pack's) |
--group-description <t> |
with --as-group: the one line the session index pays for |
--skill-dir <dir> |
with doctor: repeatable — measure THESE index paths, not user-scope ones |
--apply |
with adopt: WRITE the plan (adopt is a dry run without it) |
--dry-run |
with adopt: default — print the plan, write nothing; with sync: preview writes/removals/skips, writes nothing into the working copy (#1633) |
--to <seq> |
with revert: version to restore (default: one before the latest) |
--check |
with sync: report staleness, write nothing (exit 1 = stale) |
--quiet |
with sync: print only changes, staleness and failures — the mode the session hook runs |
--no-hook |
with init: adopt the working copy but install no session hook |
--remove-hook |
with init: remove Flicker's session hook, keeping the config |
--source <uri> |
with install skill: git+https://…//path or npm:pkg; with pack import: public URL → unowned canonical |
--public |
with skill publish / pack import: authored visibility public (default private) |
--ref <pin> |
with --source: commit, tag or version to install (required) |
--offline |
with sync/doctor: install delivery may use its cache and must not touch the network |
--overlay |
with import: render to .flicker-agent/, never to repo's AGENTS.md |
--title <t> |
with rule add: rule's heading, if the body has none |
--body <text> |
with rule add: rule's markdown, instead of a file or stdin |
--yes |
with delete: skip the confirmation prompt |
--no-apply |
with install: publish and assign, but don't sync |
--out <dir> |
with export/skill new: output directory |
--json |
machine-readable output |
$ flicker harness use-profile giovanni-dev # select this machine's profile (global) $ flicker harness init # adopt this working copy: gitignore, session and worktree hooks, first sync $ flicker harness init --remove-hook # stop syncing automatically in this working copy $ flicker harness sync # project the selected profile into harnesses here $ flicker harness sync --check # CI: exit 1 when stale, writes nothing $ flicker harness sync --dry-run # preview writes/removals/skips, writes nothing into the working copy $ flicker harness sync --allow-user-scope # write plugin pins into $HOME (owned enabledPlugins pointer) $ flicker harness sync --profile staging # one-shot profile override $ flicker harness list # the library, plus what is in effect here $ flicker harness profile create org-base --org-base # a source every other profile inherits $ flicker harness profile add org-base ponytail # give it content $ flicker harness profile create foodfeed # a per-project profile, inherits org-base by default $ flicker harness profile show foodfeed # direct entries + effective (post-inheritance) count $ flicker harness profile inherit foodfeed org-base false # opt this profile out of that source $ flicker harness profile pin foodfeed dev-commands --latest # render the version you just published, not the pinned one $ flicker harness profile pin foodfeed --all --latest # move every pin that is behind $ flicker harness add git+https://github.com/acme/skills # import a public source into the canonical pool $ flicker harness skill publish ./commit-style # authored register / version $ flicker harness pack import ~/.agents/skills --pack ios # authored: one library entry per skill, tagged ios $ flicker harness pack import ./skills --source git+https://github.com/acme/skills # unowned public identity, not an org copy $ flicker harness pack import ./skills --curate # import and tighten every description by model $ flicker harness pack import ~/.agents/skills/ios --pack ios --as-group # 84 skills behind ONE description in the index $ flicker harness adopt # read this machine's real setup; print the plan, write nothing $ flicker harness adopt --apply # same, then register it all $ flicker harness import # adopt this repo's AGENTS.md: it becomes generated $ flicker harness import --overlay # same, without ever writing repo's AGENTS.md $ flicker harness rule add acme.review ./review.md # register a prose rule and re-render $ flicker harness doctor # is the declared config actually on disk, complete? $ flicker harness doctor --json # the same findings, machine-readable $ flicker harness export --out agent-config # plain files, no harness dialect $ flicker harness install skill ./mine --personal # your own config, not the org's
flicker runner
run one agent phase in a working copy and stream a checked trace
Machine-facing phase runner. It enforces write/protected paths, validates the final JSON envelope against the real diff, runs declared gates, and streams JSONL trace events. Exit 0 means passed, 1 means the phase ran and failed, and 2 means the spec or machine prevented a verdict.
| Flag | Description |
|---|---|
--spec <path> |
phase spec file, or - to read it from stdin |
$ flicker runner phase --spec phase.json # run the phase, stream JSONL to stdout $ flicker runner phase --spec - < phase.json # read the spec from stdin
flicker update
replace this binary from the control plane
Downloads the same binary `curl -fsSL https://flickercloud.com/install.sh | sh` installs (`/download/cli/<os>-<arch>`) and replaces the current executable in place. CLI versions ship with every control-plane deploy — there is no separate release pipeline. `FLICKER_INSTALL_DIR` overrides the destination (install.sh parity). After updating, refresh workflow skills if needed: `flicker skill update --workflow --global`, then `flicker doctor`.
| Flag | Description |
|---|---|
--json |
print planned download/path; do not rewrite the binary |
$ flicker update # replace the binary from the API host $ flicker version # show running binary's version stamp
flicker version
print this binary's version stamp and install path
Shows the link-time version (git SHA on deploy builds, "dev" for a local `go build`), GOOS/GOARCH, and the resolved path of the executable.
| Flag | Description |
|---|---|
--json |
machine-readable output |
$ flicker version # human-readable $ flicker version --json # for scripts
Global flags
Accepted by every command:
| Flag | Description |
|---|---|
--org <slug> |
override default org (else flicker.toml > FLICKER_ORG > global config) |
--project <slug> |
target an existing project (for app/database create) |
--database <slug> |
override default database |
--token <key> |
override API token |
--user-token <token> |
override the personal CLI token used by --personal |
--api <url> |
override API base URL |
--json |
machine-readable JSON output |
--no-wait |
return immediately instead of polling to ready/running |
--yes, -y |
skip confirmation prompts |