> ## 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.

# JSON output

> Every command supports structured JSON output for programmatic use.

Every Buttons command can emit structured JSON instead of human-readable text. This makes it straightforward to use Buttons inside scripts, pipelines, and agent loops.

## Enabling JSON output

Pass `--json` to any command:

```bash theme={null}
buttons press weather --arg city=Miami --json
buttons list --json
buttons history deploy --json
```

**Auto-detection:** when stdout is not a TTY (e.g. inside a script, piped to another command, or running in a container), Buttons switches to JSON automatically. You do not need to pass `--json` explicitly in non-interactive contexts.

## Output contract

Every response is a JSON object with an `ok` boolean at the top level.

**Success:**

```json theme={null}
{
  "ok": true,
  "data": {
    "button": "weather",
    "status": "ok",
    "stdout": "{\"current_condition\": [...]}",
    "stderr": "",
    "exit_code": 0
  }
}
```

**Failure:**

```json theme={null}
{
  "ok": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "button 'weather' does not exist"
  }
}
```

The shape of `data` varies by command, but `ok` is always present, and on a failure `error.code` and `error.message` are always present and stable. Some errors also carry two optional fields: `error.hint` (a recovery suggestion, e.g. the exact command to run) and `error.spec` (structured context). Both are omitted when empty.

## Error codes

| Code | When it occurs |
| - | - |
| `NOT_FOUND` | The named button or drawer does not exist |
| `MISSING_ARG` | A required argument was not supplied |
| `VALIDATION_ERROR` | An argument value did not match its declared type |
| `TIMEOUT` | The button execution exceeded its timeout |
| `SCRIPT_ERROR` | The subprocess exited with a non-zero exit code |
| `RUNTIME_MISSING` | The required interpreter (`bash`, `python3`, `node`, etc.) is not on `$PATH` |
| `QUEUE_TIMEOUT` | The press waited too long for a free slot in the button's concurrency queue |
| `INTERNAL_ERROR` | An unexpected error inside the Buttons runtime |
| `KIND_NOT_IMPLEMENTED` | A drawer step used a step kind not yet implemented in the v1 executor |

This is the common subset. Individual commands surface their own codes — for example `AMBIGUOUS` (`drawer connect`), `IMPORT_ERROR` (`import`), `INSTALL_ERROR` / `PUBLISH_ERROR` (registry), `DNS_CONFLICT` / `ZONE_MISMATCH` (`webhook setup`), and `NOT_APPLICABLE` (`board --json`).

## Checking exit codes

Buttons exits with code `0` on success and `1` on any error, regardless of `--json`. Use the exit code in shell scripts:

```bash theme={null}
if buttons press deploy --arg env=production --json > result.json; then
  echo "Deploy succeeded"
else
  code=$(jq -r '.error.code' result.json)
  echo "Deploy failed: $code"
fi
```

## Writing JSON in Go

Inside the Buttons codebase, use `config.WriteJSON()` and `config.WriteJSONError()` — never `fmt.Println` with raw JSON strings. This ensures consistent formatting and respects the `--json` / non-TTY detection logic.

## Related

* [Arguments](/concepts/arguments) — `MISSING_ARG` and `VALIDATION_ERROR` details
* [Quick start](/quickstart) — see JSON output in a real example


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.