CLI
clipless ships with @clipless/react — it needs your JSX to extract a workflow. It runs on Bun (it loads your TSX file directly), so bunx clipless … — your app itself needs no Bun.
bash
export CLIPLESS_API_KEY=cls_test_… # or --key; a secret keyIt talks to the hosted engine, https://api.clipless.dev. To point it at another one, such as an engine running locally, pass --url or set CLIPLESS_URL.
manifest
bash
bunx clipless manifest expense-claim.tsx # print the manifest
bunx clipless manifest expense-claim.tsx -o m.json # write itExtraction refuses what only the JSX can get wrong: an <Action> outside every stage, a field action that cannot run (on="enter" on a field, or inside a <FieldGroup>), <Remarks> or a <Deadline> in the wrong place. What the manifest itself says — a transition to a stage that does not exist, an action nothing runs, a blocking enter action, a {{placeholder}} that names nothing — the engine checks when you deploy, and deploy lists every problem it found.
deploy
bash
bunx clipless deploy expense-claim.tsx
bunx clipless deploy expense-claim.tsx --draft # without publishing
bunx clipless deploy expense-claim.tsx --dry-run # show what would be sentA deploy lands in one environment: the key's (a cls_test_… key deploys to test), or the one picked with clipless env use when you are logged in. New sessions there start on it; every other environment keeps running what it had. To take a workflow from test to production, deploy the same file with a production key — an unchanged workflow is the same revision, now running in both.
build
bash
bunx clipless build expense-claim.tsx --out dist/cliplessOne bundle per role, <workflowId>.<role>.js with a .d.ts: the file with every other role's <Stage> removed and every <Action> reduced to its id, on, type, blocking and title, then bundled and tree-shaken. @clipless/react and your packages stay external. A reviewer's panel, an AI prompt, a webhook URL never reach a browser that does not need them. <Stage actor> must be a string literal, and a field's <Action> needs an id.
With the bundler plugin, a ?role= import does the same inside your own build, and you don't need this step.
sessions / session
bash
bunx clipless sessions expense_claim_v1 # in flight, newest first
bunx clipless sessions expense_claim_v1 --status completed
bunx clipless sessions supplier_check_v1 --user acme --period 2026
bunx clipless session expense_claim_v1 Xk2… # the ledger, event by event, and the state
bunx clipless session expense_claim_v1 Xk2… --reveal # show pii and vault valuesRead-only. pii and vault values are masked unless --reveal. Rounds are listed when a stage came round more than once.
secrets
bash
bunx clipless secrets # names, and the signing secret's prefix
printf %s "$KEY" | bunx clipless secrets set ANTHROPIC_API_KEY
bunx clipless secrets delete ANTHROPIC_API_KEY
bunx clipless secrets signing-secret # create or rotate; printed onceValues come from stdin (or --value) so they stay out of your shell history.