button.json spec in its button folder. It is the source of truth for runtime, arguments, HTTP settings, metadata, concurrency, and packaging fields.
.buttons/buttons/<name>/. App buttons (created with --app) live under apps/<name>/ instead — see App buttons. The agent prompt file is AGENTS.md; an older AGENT.md is still read as a fallback but never written.
Example
runtime, env, timeout_seconds, and mcp_enabled even when empty or default; the example omits the zero-value ones for brevity.
Core fields
Code buttons
Code buttons useruntime: shell, bash, python, or node. The script lives next to button.json as main.sh, main.py, or main.js. Both shell runtimes use main.sh; shell executes it with /bin/sh, while bash resolves and executes Bash from PATH.
Arguments arrive as environment variables:
BUTTONS_BAT_<KEY>.
HTTP buttons
HTTP buttons are created with--url. They have no main.* file and carry an empty runtime; the url field identifies them.
Prompt buttons
Prompt-only buttons useruntime: prompt and do not have a main.* file. Their instruction lives in AGENTS.md and is returned in the prompt field when pressed.
Code and HTTP buttons can also carry AGENTS.md instructions; in that case the command runs first and the prompt is attached to the result.
App buttons
App buttons setkind: "app" and live under apps/<name>/ instead of buttons/<name>/. They are created by cloning a git URL or copying a local path:
main.* file. Instead they carry a serve block describing how the app builds and runs:
CreateApp defaults serve to { "type": "static", "output": "dist" }.
Arguments
Args are declared at create time:string, int, bool, and enum.
Output schema
output_schema is optional JSON Schema for the button’s JSON stdout. Drawers use it to type-check refs and auto-connect compatible fields.
${step_id.output.<field>}.
Queues
queue limits concurrent presses.
key scopes that pool per press, so one queue can enforce a per-user or per-account limit.
Packaging fields
Buttons published to or installed from a registry can include package metadata. The root dependency manifest is.buttons/buttons.json; the exact resolved versions and hashes live in .buttons/buttons-lock.json. button.json remains the runtime/package spec for one button.
Example package fields:
@your-desk/hello is later published as 2, buttons status can report it by reading .buttons/buttons.json and .buttons/buttons-lock.json. buttons update moves it only when the manifest requested "latest".
Triggers
A button can carry atriggers array so it fires automatically on cron, file-watch, or webhook events. Triggers run under buttons serve and are managed with buttons trigger add|list|rm.
Board metadata
pinned: true surfaces a button as a large card at the top of buttons board.