Skip to main content
Arguments let a button accept input. You declare them at create time with a name, type, and whether they are required or optional. At press time you supply values with --arg.

Declaring arguments

Pass --arg once per argument during buttons create:
The format is name:type:required or name:type:optional. For an enum argument, append the allowed values as a final pipe-separated list:

Supported types

Buttons validates types at press time and returns a VALIDATION_ERROR if the value does not match (including an enum value outside the declared set).

Passing values at press time

Use --arg key=value for each argument:
Pass multiple values by repeating --arg:

Required vs optional

Required arguments cause a MISSING_ARG error if omitted. Optional arguments are silently absent — the button must handle their absence gracefully.

How arguments reach code buttons

For code buttons, including buttons created from imported files with --file, each argument is injected as an environment variable named BUTTONS_ARG_<NAME> where <NAME> is the argument name uppercased:
Values are never interpolated directly into the script body. This prevents shell injection regardless of what string is passed. Beyond your declared args, the engine sets one more variable on every press: BUTTONS_PROGRESS_PATH, a file your script can append JSONL progress events to and follow live with buttons tail -f. See reporting progress.

How arguments reach HTTP buttons

For HTTP buttons, argument values are substituted into {{name}} placeholders in the URL, headers, and body. The substitution is context-aware — path segments, query parameters, JSON bodies, and form bodies each encode values differently. See URL and body templates for details.