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

# Folder structure

> How Buttons stores buttons, drawers, history, secrets, and runtime state.

Buttons stores data under `~/.buttons/` by default. In a project initialized with `buttons init`, the active data directory is the closest `.buttons/` folder in the current directory tree.

Each button gets its own subdirectory with a spec file, optional code file, agent context, and run history. Drawers get the same pattern for workflow specs and workflow history.

## Directory layout

```
~/.buttons/ or .buttons/
├── buttons.json              # project manifest; desired buttons and version policy
├── buttons-lock.json         # resolved exact versions, hashes, and sources
├── history.json              # local create/edit/install/update history; gitignored
├── buttons/
│   ├── deploy/
│   │   ├── button.json       # button spec
│   │   ├── main.sh           # script (code and file buttons)
│   │   ├── AGENT.md          # agent instructions (agent buttons)
│   │   └── pressed/
│   │       ├── 2026-04-10T12-00-00Z.json
│   │       └── 2026-04-10T14-32-11Z.json
│   ├── get-user/
│   │   ├── button.json
│   │   └── pressed/
│   └── summarize-pr/
│       ├── button.json
│       ├── AGENT.md
│       └── pressed/
├── drawers/
│   └── release-flow/
│       ├── drawer.json
│       └── pressed/
├── batteries.json            # secret/env values; gitignored for project-local dirs
├── webhook.json              # Cloudflare tunnel config; gitignored for project-local dirs
├── idempotency/              # cached successful press results
└── queues/                   # file-lock semaphore state
```

## button.json

The spec file for a button. It describes the button type, arguments, runtime, and all other configuration. Newly created specs use `"schema_version": 2`.

```json theme={null}
{
  "schema_version": 2,
  "name": "deploy",
  "description": "Deploy a tagged release to an environment",
  "runtime": "shell",
  "args": [
    { "name": "env", "type": "string", "required": true },
    { "name": "version", "type": "string", "required": true }
  ],
  "created_at": "2026-04-10T11:00:00Z"
}
```

See [button.json](/concepts/button-json) for every field, including HTTP host locks, queues, output schemas, package metadata, and required batteries.

## drawer.json

The workflow spec for a drawer. It stores inputs, steps, refs, triggers, return values, and error handling.

```json theme={null}
{
  "schema_version": 1,
  "name": "release-flow",
  "steps": [
    { "id": "build", "kind": "button", "button": "build" },
    { "id": "publish", "kind": "button", "button": "publish" }
  ]
}
```

See [drawer.json](/concepts/drawer-json) for the full workflow schema.

## buttons.json and buttons-lock.json

`buttons.json` at the root of `.buttons/` declares the desired project buttons and version policy.

`buttons-lock.json` records the exact resolved versions, sources, and content hashes. Commit it with `buttons.json` so teammates can recreate the same installed buttons.

## history.json

`history.json` records local create, edit, install, update, delete, rollback, and failed resolution events. Commands write explicit events; file hooks can record manual edits to tracked button and drawer files.

In a team repo, commit `buttons.json`, `buttons-lock.json`, and authored button/drawer files. Do not commit `history.json`; it is a local runtime artifact.

When installed buttons are generated entirely from a registry, the repo can recreate them from the manifest and lock file. When a button is authored directly in the project, commit its folder under `buttons/`.

## main.\*

The script file for [code buttons](/buttons/code). The extension matches the runtime: `main.sh` for shell, `main.py` for Python, `main.js` for Node. HTTP and prompt-only buttons do not have a `main.*` file.

## AGENT.md

Present on every button. For [prompt buttons](/buttons/prompt), contains the raw instruction text stored at create time via `--prompt`; when pressed, the contents are returned in the `prompt` field of the JSON output. For other button types, AGENT.md holds notes and context an agent can read to understand when and how to press the button.

## pressed/

One JSON file per run, named by timestamp. Each file records the input arguments, exit code, stdout, stderr, duration, and whether the run succeeded.

```json theme={null}
{
  "button": "deploy",
  "pressed_at": "2026-04-10T14:32:11Z",
  "args": { "env": "staging", "version": "v1.4.2" },
  "exit_code": 0,
  "stdout": "Deploying v1.4.2 to staging...\nDone.",
  "stderr": "",
  "duration_ms": 3241
}
```

## batteries.json

Batteries are key/value pairs injected into button presses as `BUTTONS_BAT_<KEY>`.

Project-local batteries live at `.buttons/batteries.json`. Global batteries live at `~/.buttons/batteries.json`. Local values override global values on key collision.

## webhook.json

Named webhook setup stores Cloudflare tunnel configuration in `webhook.json`. It is machine-specific and should not be committed.

## idempotency/

Successful presses with `--idempotency-key` are cached here until their TTL expires.

## queues/

Buttons with a `queue` declaration use file locks here to enforce concurrency limits.

## Overriding the home directory

Set `BUTTONS_HOME` to use a different base directory:

```bash theme={null}
BUTTONS_HOME=/tmp/test-buttons buttons create test-btn --code 'echo ok' --runtime shell
```

This is useful in CI, tests, or container environments where you want an isolated state directory.

<Note>
  The `~/.buttons/` directory and all files inside it are created with mode `0700` / `0600`. Other users on the same system cannot read button specs or run history.
</Note>

## Related

* [button.json](/concepts/button-json) — button spec fields
* [drawer.json](/concepts/drawer-json) — workflow spec fields
* [History](/concepts/history) — local audit history
* [JSON output](/concepts/json-output) — the shape of history records
* [Code buttons](/buttons/code) — how `main.*` is populated from scaffolded or imported scripts
