Documentation Index
Fetch the complete documentation index at: https://docs.buttons.sh/llms.txt
Use this file to discover all available pages before exploring further.
Drawer workflows, live streaming, webhooks, and more
Drawers graduate from a concept into a full workflow engine with typed steps, cross-step data flow, CEL expressions, sub-drawers, iteration, conditionals, retries, and error handlers. The CLI gains live output streaming, idempotency keys, concurrency queues, and a webhook trigger system.New features
-
Drawer workflow engine — chain buttons into typed, schema-validated workflows with
buttons drawer create,buttons drawer add, andbuttons drawer press. Steps reference upstream outputs via${step.output.field}expressions, wired automatically or explicitly withbuttons drawer connect. Per-step retry policies with exponential backoff handle transient failures. See the drawer CLI reference. -
CEL expressions —
${...}contents now support full CEL expressions: string concatenation, arithmetic, ternaries, and null coalescing. Simple dotted paths like${build.output.version}still work unchanged. - Sub-drawers — compose workflows from reusable building blocks. Add a child drawer to a parent and its return values flow back into the parent’s step context.
-
for_eachsteps — iterate over an array, running nested steps per item. Setparallelismto run iterations concurrently with a bounded worker pool. Useon_item_failure: continueto tolerate per-item errors without aborting the whole step. -
switchsteps — conditional branches using CEL predicates. The first truthy case runs, the rest are skipped. -
aggregatesteps — pluck a field from each entry in an array into a flat list. -
waitsteps — pause for a duration or until a specific timestamp. Honors cancellation so Ctrl-C aborts cleanly. -
Drawer-level
on_errorhandler — declare a fallback drawer that runs when any step fails. The handler receives the error payload and context so it can notify, roll back, or triage. -
buttons summary— one command, full workspace snapshot: buttons, drawers, recent runs, active runs, recent failures, and webhook listener state. Pass--jsonfor structured output or--deepto inline full schemas and run history. Running barebuttonswith no subcommand now invokes summary automatically. -
--summaryuniversal flag — attach--summaryto any mutating command to preview the plan without executing. Never mutates, never touches the network. -
buttons press --follow— stream a button’s stdout and stderr to your terminal as the press runs. The final structured result still goes to stdout so you can pipe tojqwhile watching progress on stderr. See the press CLI reference. -
buttons NAME logs --follow— follow the latest press’s output as plain-text JSONL on stdout. Pipes cleanly with no TUI or color codes. -
Live output in the board — pressing a button on the board now auto-opens the logs pane and streams stdout/stderr in real time with a
● livebadge that flips to· donewhen the press finishes. -
buttons tail— follow a button’s structured progress events in real time. Scripts emit JSONL progress events thatbuttons tail -fstreams to stdout. -
Idempotency keys —
buttons press --idempotency-key=K --idempotency-ttl=24hcaches successful results. A second press with the same key within the TTL returns the cached result instantly. Only successful results are cached — failures always retry. - Per-button concurrency queues — declare a queue with a name and concurrency limit. Multiple buttons sharing the same queue name pool their slots. An optional key scopes concurrency per dimension (e.g. three concurrent presses per user).
-
buttons ignore/buttons unignore— keep scratch or test buttons out of git without touching your repo’s.gitignore. Pass--ignoreonbuttons createto ignore a new button in one step. -
Webhook triggers — drawers can now be invoked by incoming HTTP requests, routed through a Cloudflare tunnel to your local machine. Run
buttons webhook setuponce to configure, thenbuttons webhook listento start the dispatcher. See the webhook CLI reference. - Webhook auth — four built-in auth modes: open (default), HTTP Basic, arbitrary header, and HS-family JWT with optional claim checks. Secrets can reference environment variables so you don’t commit sensitive values.
-
Webhook dry-run — test webhook-triggered drawers locally with
buttons drawer press --webhook-bodywithout needing a running listener.
Updates
-
NAME-first log syntax —
buttons NAME logsis now the canonical form; the verb-firstbuttons logs NAMEstill works. Same for drawer logs. - Retry policies on drawer steps — each step can declare error handling with configurable max attempts, exponential backoff with optional jitter, and a retry-on allowlist of error codes.
- Output schemas on buttons — optional JSON Schema describing a button’s stdout shape. Drawers use it at connect time to type-check references before you press.
- HTTP button host-locking — the scheme and host of an HTTP button’s URL are now locked at create time. Template arguments can no longer modify the host portion of the URL, closing a class of request-routing vulnerabilities. See SSRF protection.
Webhook reliability fixes
Bug fixes
-
Graceful shutdown for webhook listeners — pressing Ctrl+C while
buttons webhook listenhas in-flight presses no longer abandons them. The listener now drains running presses for up to 30 seconds before exiting, so webhook-triggered drawers finish cleanly instead of being dropped mid-run. See the webhook CLI reference. -
Stronger tunnel readiness check —
buttons webhook listennow verifies that the Cloudflare tunnel is fully connected end-to-end before accepting requests. Previously, a stale DNS record could cause the readiness check to pass prematurely. The listener now confirms the tunnel routes all the way back to your local process before reporting ready. - Fixed a memory leak in the webhook dispatcher — long-running webhook listeners no longer accumulate stale tracking state for completed requests. The dispatcher now cleans up immediately after each request finishes.