Skip to main content
A drawer is a workflow made of steps. Its source of truth is drawer.json.
~/.buttons/drawers/<name>/
  drawer.json
  pressed/
Project-local drawers use the same shape under .buttons/drawers/<name>/.

Example

{
  "schema_version": 1,
  "name": "release-flow",
  "inputs": [
    { "name": "env", "type": "enum", "required": true, "values": ["staging", "prod"] }
  ],
  "steps": [
    { "id": "build", "kind": "button", "button": "build-artifact" },
    {
      "id": "publish",
      "kind": "button",
      "button": "publish-artifact",
      "args": {
        "env": "${inputs.env}",
        "version": "${build.output.version}"
      }
    }
  ],
  "return": {
    "version": "${build.output.version}",
    "url": "${publish.output.url}"
  }
}

Top-level fields

FieldMeaning
schema_versionDrawer spec version. Current version is 1.
nameDrawer name.
descriptionHuman-readable one-liner.
inputsValues supplied at drawer press time.
stepsOrdered workflow steps.
output_schemaOptional JSON Schema for values exposed when called as a sub-drawer.
returnMap of output fields to ${...} expressions.
triggersAutomatic invocation sources. Webhook triggers are live today.
on_errorOptional drawer to call after failure.

Step kinds

KindStatusPurpose
buttonLivePress a button.
drawerLiveCall another drawer as a sub-workflow.
for_eachLiveIterate nested steps over an array.
switchLiveRun the first matching branch.
aggregateLivePluck values out of an array, often after for_each.
waitLivePause for a duration or until an RFC3339 time.
split, merge, transform, batchReservedSchema-reserved for future runtimes.

References

Step args and drawer fields can use ${...} expressions. The expression body is CEL.
${inputs.env}
${build.output.version}
${env.GITHUB_TOKEN}
${webhooks.on-scrape-done}
${inputs.count * 2}
${has(build.output.url) ? build.output.url : "missing"}
Hyphenated step IDs are supported in refs; Buttons rewrites them internally so CEL can parse them.

Inputs

Drawer inputs mirror button args and add secret redaction:
{
  "inputs": [
    { "name": "api_key", "type": "string", "required": true, "secret": true }
  ]
}
Secret inputs can still flow into a step’s resolved args, but they are redacted from drawer history.

Failure handling

Step-level on_failure controls one step:
{
  "on_failure": {
    "action": "retry",
    "max_attempts": 3,
    "backoff": {
      "strategy": "exponential",
      "initial_ms": 500,
      "factor": 2,
      "max_ms": 10000,
      "jitter": true
    }
  }
}
Supported actions are stop, continue, and retry. Drawer-level on_error calls another drawer after a failed run. The handler receives drawer, run_id, failed_step, error, and redacted inputs.

Webhook triggers

Webhook triggers are stored in triggers.
{
  "triggers": [
    {
      "kind": "webhook",
      "path": "/apify-done",
      "auth": {
        "type": "header",
        "header_name": "X-Buttons-Token",
        "header_value": "$ENV{APIFY_WEBHOOK_TOKEN}"
      }
    }
  ]
}
Inside the drawer, the request appears as ${inputs.webhook.body}, plus headers, query, method, path, and received_at.

Schema

Print the embedded JSON Schema:
buttons drawer schema
The published copy lives at docs/schemas/drawer.schema.json.