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

# Code buttons

> Wrap a shell, Python, or Node script as a pressable, typed action.

A code button is a script the runtime executes every time you press it. The script lives as a file inside the button folder, so you can edit it the same way you edit any other file.

## The default flow: scaffold, edit, press

The simplest way to create a button is to let Buttons scaffold a placeholder script you can fill in. Declare the args you'll need up front — they're part of the button spec and can't be added later without recreating the button:

```bash theme={null}
buttons create greet --arg name:string:required
# Created button: greet
#   Edit:  /Users/you/.buttons/buttons/greet/main.sh
#   Press: buttons press greet
```

Open the scaffolded `main.sh` — it has a shebang, a TODO comment, and a hint about where args arrive:

```bash theme={null}
#!/bin/sh
set -eu

# TODO: add your command here
# Args arrive as $BUTTONS_ARG_<NAME>
```

Edit it to whatever you want:

```bash theme={null}
#!/bin/sh
echo "Hello, $BUTTONS_ARG_NAME"
```

Press:

```bash theme={null}
buttons press greet --arg name=Ada
# → Hello, Ada
```

<Note>
  Args are declared at create time and stored in `button.json`. If you need to change them, delete and recreate the button — your `main.sh` is at the same path each time, so you can copy your edits over.
</Note>

## Scaffold in Python or Node

Pass `--runtime` to scaffold with the right shebang and extension:

```bash theme={null}
buttons create parse-json --runtime python --arg input:string:required
# → scaffolds main.py with:
#     #!/usr/bin/env python3
#     # TODO: add your code here
#     # Args arrive as os.environ["BUTTONS_ARG_<NAME>"]
```

```bash theme={null}
buttons create transform --runtime node --arg payload:string:required
# → scaffolds main.js
```

| Flag value        | Interpreter used | File written |
| ----------------- | ---------------- | ------------ |
| `shell` (default) | `/bin/sh`        | `main.sh`    |
| `python`          | `python3`        | `main.py`    |
| `node`            | `node`           | `main.js`    |

## Shortcuts for when you already know the code

Three shortcuts let you skip the edit step when the script is trivial or already on disk.

### `--code 'one-liner'`

Pass a one-line script inline. Useful when the body is a single command and quoting isn't painful:

```bash theme={null}
buttons create hostname --code 'hostname -f'
buttons create ls-home --code 'ls -la ~' --runtime shell
```

Inline code is capped at **64 KB**. Beyond that, write it to a file and use `--file`.

### `--file ./path/to/script.sh`

Copy an existing script into the button folder. The file is copied (not symlinked) so the button is self-contained:

```bash theme={null}
buttons create deploy \
  --file ./scripts/deploy.sh \
  --arg env:string:required \
  --arg version:string:required \
  -d "Deploy a tagged release"
```

If the script has a shebang, the OS uses that interpreter directly — no need to pass `--runtime`. Without a shebang and without `--runtime`, Buttons defaults to `/bin/sh`.

## Argument injection

Arguments are never interpolated into the script body. They arrive as environment variables named `BUTTONS_ARG_<NAME>` (uppercased):

```bash theme={null}
# Declared:  --arg bucket:string:required
# Available:
echo "$BUTTONS_ARG_BUCKET"           # shell
os.environ["BUTTONS_ARG_BUCKET"]     # python
process.env.BUTTONS_ARG_BUCKET       # node
```

This prevents shell injection regardless of what the caller passes at press time.

## Where the code lives

After `buttons create`, the button folder contains:

```
~/.buttons/buttons/<name>/
  button.json     # spec: args, runtime, timeout
  main.sh         # your code (or main.py / main.js)
  AGENT.md        # notes for agents pressing this button
  pressed/        # run history, one JSON file per press
```

Edit `main.sh` any time. Changes take effect on the next press — no recreate needed.

## Example: wrap a deploy script

```bash theme={null}
# scripts/deploy.sh
#!/bin/bash
set -euo pipefail

ENV=$BUTTONS_ARG_ENV
VERSION=$BUTTONS_ARG_VERSION

echo "Deploying $VERSION to $ENV..."
kubectl set image deployment/app app=registry.example.com/app:$VERSION -n $ENV
kubectl rollout status deployment/app -n $ENV
```

Import it:

```bash theme={null}
buttons create k8s-deploy \
  --file ./scripts/deploy.sh \
  --arg env:string:required \
  --arg version:string:required \
  -d "Roll out a new image version to a Kubernetes namespace"
```

## Related

* [Prompt buttons](/buttons/prompt) — attach an instruction to any button for the consuming agent
* [Arguments](/concepts/arguments) — declare and pass typed args
* [JSON output](/concepts/json-output) — capture results programmatically
* [Folder structure](/concepts/folder-structure) — what lives inside a button folder
