Skip to content

cliq

cliq is Sartiq's unified devops CLI — one self-contained Go binary that covers the day-to-day operations a backend/full-stack dev reaches for: spinning up the local stack, managing the shared seed dataset, standing up per-branch preview environments, running the e2e suite, and opening a shell on an environment VM.

It ships from releases.sartiq.com/cliq/ and self-updates.

Flag-level reference: every flag and edge case lives next to the code in the cliq repo README. This page is the feature catalog — what each command does, when to reach for it, and how it fits the workflow. When in doubt, cliq <command> --help is always authoritative for your installed version.


Feature map

Command group What it does Reach for it when…
cliq local Bring up / tear down / inspect the full local stack (backend + compute + webapp) You want everything running on your laptop
cliq seed Pull, push, and verify the shared seed dataset (DB rows + image assets) You need realistic data, or want to publish a new canonical state
cliq preview Create & manage full-stack preview environments on a public URL You need to share a build, demo with real OAuth, or repro a prod-shaped bug
cliq ssh Open a cert-authed shell on a dev/staging/prod VM You need to poke at a long-lived environment directly
cliq e2e Run the Playwright e2e suite (full stack, or fast MSW mode) You're validating end-to-end behavior before a PR
cliq init / cliq login One-time config + credential setup First run, or after rotating a token
cliq upgrade / cliq changelog Self-update and read what changed A new release is out
cliq completion Install shell-completion scripts You want tab completion

Install

curl -fsSL https://releases.sartiq.com/cliq/install.sh | bash

The installer detects your OS/arch and drops the binary into ~/.local/bin/cliq — make sure that's on your PATH. To pin a version:

CLIQ_VERSION=v0.14.0 curl -fsSL https://releases.sartiq.com/cliq/install.sh | bash

(CLIQ_INSTALL_DIR and CLIQ_BASE_URL override the install dir and release host respectively.)


First-run setup

cliq init     # interactive wizard — captures local repo paths + Cloudflare account
cliq login    # creates + verifies a Cloudflare token, then optionally a GitHub PAT

cliq init captures, into ~/.config/sartiq/cliq/config.yaml:

  • Your local checkouts of shootify-backend, shootify-webapp, and shootify-compute-server — so cliq local, cliq e2e, and cliq preview know where each repo lives.
  • The Sartiq Cloudflare account ID.
  • The R2 bucket + prefix for the seed dataset (defaults sartiq-misc / seed-data).

cliq login is a detect-then-prompt flow — it reuses a known-good credential and only prompts when one is missing, expired, or you decline. It walks you through:

  1. A Cloudflare User API Token (profile-scoped, so it auto-invalidates when you leave the org). Needs Workers R2 Storage / Edit; cliq preview additionally needs Zone / DNS / Edit, and User Details / Read is optional for attribution.
  2. A GitHub classic PAT (optional — press Enter to skip if you don't use previews). Needs repo + write:packages / read:packages / delete:packages.

Run cliq login --verify to silently re-check existing credentials without prompts.

Where things live

Config: ~/.config/sartiq/cliq/config.yaml. Credentials: ~/.config/sartiq/cliq/credentials.yaml (mode 0600). A pre-0.3 ~/.config/cliq directory is migrated automatically on first run.


local — isolated local environments

Run multiple independent full-stack environments side by side on one machine, each keyed by a slug. Every slug owns its own Docker projects, internal network, databases, Redis, volumes, loopback ports, host webapp process, generated env, storage, and (optionally) public tunnels — so you can validate one task in isolation while another stack keeps running. Backend and compute hot-reload edited source live via Compose develop.watch; the webapp runs bun run dev on the host with full Next.js HMR.

The legacy singleton cliq local up --profile dev|e2e model is retired. cliq e2e is now a separate top-level command with its own mock-stack orchestration; it does not share the slug-based surface.

cliq local up my-task --task SAR-1234        # isolated full stack from the task's worktrees
cliq local up hotfix --path-backend ../backend-hotfix
cliq local ls                                 # every environment you own
cliq local status my-task                     # one env's plan, ports, health (--json for machine use)
cliq local logs my-task backend/backend -f    # tail a Compose service (webapp = host dev log)
cliq local exec my-task backend/backend -- alembic upgrade head
cliq local restart my-task --services backend,webapp
cliq local env diff my-task                   # what changed in the generated env
cliq local env refresh my-task                # apply non-owned env inputs without rotating secrets
cliq local extend my-task 2h                  # renew the R2 lease and rotate scoped credentials
cliq local gc                                 # dry-run report of stale / orphaned resources
cliq local down my-task

The exhaustive command and flag reference lives next to the code in the cliq repo README and its isolated local environments doc. This page is the feature catalog; cliq local --help is authoritative for your installed version.

Source resolution

Per-repo: --path-<repo> wins over --path, which wins over a matching --task worktree, which wins over the configured checkout. --task SAR-1234 resolves each repo from worktrees/SAR-1234/* (offering to create one for an existing branch), fast-forwards it to origin, and never switches or mutates the main checkout. --branch / --branch-<repo> check out a requested branch and refuse to switch a dirty tree. Dirty sources are always called out in the plan before startup; -y skips the confirmation but not the plan.

Storage

R2 is the default. The preview-host provisions an owner-scoped, leased bucket (shootify-media-local-<key>) plus a media domain, seeds canonical media server-side, and returns short-lived scoped credentials kept in a separate mode-0600 env file. cliq local extend <slug> <duration> renews the lease, rotates those credentials, and recreates only the storage-reading containers. --storage minio is the fully-offline fallback (isolated local bucket + port per slug; cannot be combined with --expose).

Exposure

A plain up creates no public tunnel — the environment is reachable only on loopback. --expose (requires R2) opens managed webapp and backend API tunnels after local readiness; compute stays internal. Useful for sharing a build, running a real-OAuth demo from another device, or pointing a webhook at your laptop. Credentials refresh on extend and restart; disconnected tunnels are reconciled by preview-host.

up flag reference

Flag Effect
--storage r2\|minio Storage provider; default r2
--lease 1..24 R2 lease hours; default 8
--task <ID> Resolve each repo from the task's worktrees
--path, --path-<repo> Explicit all / per-repo source checkout
--branch, --branch-<repo> All / per-repo branch to check out
--no-backend / --no-compute / --no-webapp Omit selected application services
--no-seed Skip canonical DB + media restoration
--no-watch Disable Compose source watches (required on macOS today)
--expose Expose webapp + backend API; requires R2
--build Rebuild backend/compute images (live code otherwise syncs via watch)
-y, --yes Skip the dirty/fallback source confirmation

Notes

  • Slugs match ^[a-z][a-z0-9-]{0,39}$. State and generated env live under ~/.cache/cliq/local/<slug>/; secrets are mode 0600. down is idempotent and can recover Docker resources from ownership labels even when state is missing; clean --force removes every owned environment (add --legacy to also tear down the retired singleton stack).
  • Shared service names (db, redis, …) must be qualified for logs or exec — backend/db, compute-server/redis — since both stacks define them. The host-side webapp supports logs and restart but not exec.
  • Capacity warnings (advisory, never blocking): 4+ existing envs, <10 GiB free on the state filesystem, or 25+ Docker networks (the default address pool is near exhaustion — run docker network prune).

seed — the shared test dataset

Local dev needs realistic data. The seed dataset — a curated Postgres dump plus an image-asset tree — lives in Cloudflare R2 at sartiq-misc/seed-data/ and mirrors into your local db (Postgres) and minio containers. pull and push are the two halves of the loop.

cliq seed pull        # restore the canonical seed into your local stack
cliq seed push        # publish your current local state as the new canonical
cliq seed verify      # check your local schema revision is shipped on origin/dev
cliq seed doctor      # diagnose the local stack (db + minio reachable, bucket OK)
  • pull is destructive on the DB side (drops + recreates the public schema, then restores the dump in a single transaction) and incremental on the asset side (ETag short-circuit — unchanged objects aren't re-downloaded). It refuses to run over an existing populated DB unless you pass --force. --skip-dump / --skip-assets do one side only.
  • push is destructive on the shared dataset — it overwrites the one canonical seed every dev pulls, with no backup. It makes you type the R2 prefix to confirm (--yes to skip, required in CI). As an unconditional pre-flight it runs the verify check: your local alembic head must already be on origin/dev, otherwise publishing would break everyone else's pull. There is no bypass — merge the migration to dev first.

See Storage → Local-Dev Seed Dataset for the dataset layout.


preview — per-branch environments

A preview is a short-lived, branch-scoped deployment of the full stack on a public <code>.preview.sartiq.com URL, running on the shared GCP preview-host VM. Reach for one when cliq local up isn't enough — to share a build with product, demo with real OAuth, exercise Cloudflare image transforms, or repro a bug that only shows up against real Postgres + R2.

Deep dive: the architecture, identifiers, lease-vs-auto-shutdown timers, image flow, and seeding are all documented in Preview Environments. This is the command summary.

Lifecycle

cliq preview create sar-23           # resolve branches, build images on CI, stand the stack up
cliq preview list                    # all active previews
cliq preview status sar-23           # one preview's detail
cliq preview logs sar-23 backend -f  # tail a service (backend|scheduler|celery_worker|
                                     #   compute_server|compute_worker|webapp)
cliq preview rebuild sar-23          # new code: re-resolve branches, fresh images, keep data
cliq preview recreate sar-23         # no rebuild: redeploy stack + pick up env changes
cliq preview seed sar-23             # re-seed DB + bucket from the canonical dataset
cliq preview destroy sar-23          # tear down + drop DB, bucket, image tags
  • create resolves a branch per repo by matching <code>* on origin, falling back to dev (override with --branch / --branch-<repo>). By default the host builds the images on GitHub Actions (faster push, dedups against dev's buildcache); pass --local-build to build + push from your laptop instead (useful when iterating on a Dockerfile not yet on dev). Seeds from the canonical dataset unless you pass --no-seed. --lease <hours> sets the initial lease; --yes accepts dev-branch fallbacks unprompted.
  • rebuild vs recreate: rebuild builds fresh images (use after pushing code); recreate just redeploys the existing images and re-snapshots env (use right after preview env set). Both keep the DB, bucket, and Redis index. Both take --services backend,webapp,… to act on a subset only.

Keeping a preview alive

Two independent timers — see Lease vs auto-shutdown:

cliq preview extend sar-23 2h     # push out the GC lease (when the preview is reaped)
cliq preview hold   sar-23 1h     # block the host's idle auto-shutdown (the VM stopping)

You generally want both before a demo.

Per-preview env values

The host owns the locked tier (DB/R2/secrets); cliq preview env manages the feature-tier env values layered on top. Writes affect future previews and existing ones on rebuild --refresh-env / recreate — they never silently mutate a running preview (each pins an immutable snapshot at create time).

cliq preview env list                          # current shared store (redacted)
cliq preview env set FOO bar --service backend # upsert into one or more services
cliq preview env sync --service backend        # diff your <repo>/.env into the store, apply missing keys
cliq preview env show  sar-23                  # the snapshot this preview is pinned to
cliq preview env diff  sar-23                  # what a --refresh-env rebuild would change

Keys must be UPPER_SNAKE_CASE; host-owned names (POSTGRES_*, R2_*, COMPUTE_SERVER_*, hostnames) are rejected server-side, so adding a feature env var never needs a cliq release.

Host wake & diagnostics

The preview-host idle auto-stops. Every preview subcommand probes /healthz first and dispatches the wake workflow on its own if the host is asleep — so you rarely run wake by hand.

cliq preview doctor    # check host reachability + Cloudflare/GitHub auth
cliq preview wake      # warm the host ahead of time (no-op if already awake)

Pass --no-wake to any preview (or ssh) command to fail fast instead of waiting through a ~5-min cold boot — handy in CI.

Tunnels

cliq preview tunnel opens an ad-hoc reverse tunnel exposing a localhost port at <slug>--tunnel.preview.sartiq.com through the same host (up stays foreground; list / rm manage slugs). See docs/spike-tunnel.md in the repo for the design.


ssh — shell into an environment VM

Open an interactive shell on a long-lived environment VM (backend | compute × dev | staging | production). Auth is a short-lived per-VM certificate minted by the preview-host CA — no per-dev SSH key is installed on the target, and a leaked cert is scoped to exactly one (server, env) pair.

cliq ssh backend --env production
cliq ssh compute --env dev

Like preview, it auto-wakes the preview-host (which issues the cert); --no-wake opts out.


e2e — the end-to-end suite

Run the webapp's Playwright suite against a real stack, with teardown handled for you. Ctrl+C is honored — the bun/Playwright child gets SIGINT, the stack is torn down, and no containers are orphaned.

cliq e2e run            # full stack: local up --profile e2e → test:e2e:real → local down
cliq e2e run --msw      # fast inner loop: mock the backend in-browser, no Docker
cliq e2e run --keep     # leave the stack up after tests (iterate)
cliq e2e run --no-up    # assume the e2e stack is already up
cliq e2e run --grep "checkout"   # pass-through to playwright --grep

--msw runs test:e2e with the backend mocked by a service worker — the fastest loop, no stack required. The default --no-msw flow runs test:e2e:real against backend + compute (compute mocked, outbound internet hard-blocked).


Staying current

cliq upgrade            # download + atomically replace the running binary
cliq upgrade --check    # report current vs. latest without installing
cliq upgrade --force    # reinstall current version (repair)
cliq changelog          # print the latest release section baked into this binary
cliq changelog --since 0.10.0   # everything newer than a given version

cliq upgrade reads the version pointer from releases.sartiq.com/cliq/latest/VERSION (it does not hit the GitHub Releases API — the repo is private). cliq also runs a background update probe on every invocation and prints a one-line notice when a newer version exists. If self-update ever breaks, re-running the install one-liner is always a safe fallback.


Shell completion

cliq completion install   # install per-user scripts and (for zsh) offer to wire it up
cliq completion zsh       # or print a script to stdout (also: bash, fish, powershell)

Config & credentials reference

File Holds Notes
~/.config/sartiq/cliq/config.yaml repo paths, account_id, bucket/prefix, preview_host_url, show_banner written by cliq init
~/.config/sartiq/cliq/credentials.yaml Cloudflare token, GitHub PAT mode 0600, written by cliq login

Set show_banner: false in config.yaml to silence the ASCII banner.