Docs / Commands

Run scripts with execute

Updated

TL;DR — `tokenade execute --lang python --script '…'` runs a script with a scrubbed environment, a 30-second default timeout and a 1 MiB output cap, and returns only stdout. Pipe data in to filter it where it is produced. It is not a security sandbox.

tokenade execute runs a short script and hands back only what it prints. Use it when the answer is a derived value (a count, a filter, a sum) and the data it comes from would be expensive to put in your agent's context. Aliases: exec, run-script.

Usage

tokenade execute --lang <name> [--script CODE | -] [--cwd DIR] \
[--timeout SECS] [--cap BYTES] [--no-compact] [--no-redact]
tokenade execute --list # show supported interpreters
FlagDefaultEffect
--lang <name>requiredbash, sh, python, node, ruby, awk, jq, perl
--script CODESource to run. --script - reads the script from stdin
--script-file FRead the script from a file, with no shell quoting to get wrong
--cwd DIRcurrent directoryWorking directory
--timeout SECS30 (max 600)Kill the script after this many seconds
--cap BYTES1 MiB (max 16 MiB)Stdout cap
--no-compactoffSkip the post-run compactor
--no-redactoffSkip secret redaction (not recommended)
--sandboxoffRun under bubblewrap (bwrap): whole filesystem read-only, a fresh writable /tmp, no network. Also TOKENADE_EXEC_SANDBOX=1
--sandbox-netoffAllow network inside the sandbox. Also TOKENADE_EXEC_SANDBOX_NET=1
--listPrint supported interpreters and exit
--jsonWith --list, print the interpreters as JSON

What "sandbox" means here

By default the script runs in a separate process with a scrubbed environment, a timeout and output caps. It is not a syscall jail: it runs as you, with your filesystem and your network. Treat a script here exactly as you would treat running it in your own shell.

--sandbox adds real confinement on Linux through bubblewrap. If bwrap is not installed, execute refuses to run rather than run unconfined.

Examples

$ tokenade execute --list
Available interpreters:
bash (binary: bash)
sh (binary: sh)
python (binary: python3)
node (binary: node)
ruby (binary: ruby)
awk (binary: awk)
jq (binary: jq)
perl (binary: perl)
$ tokenade execute --lang python --script 'print(sum(range(101)))'
5050

Data you pipe in reaches the script's stdin, so a large output is reduced where it is produced:

$ cat orders.json | tokenade execute --lang python \
--script 'import json,sys; print(len(json.load(sys.stdin)["items"]))'
2

A long or quote-heavy script is easier from a file:

tokenade execute --lang python --script-file ./count_errors.py < build.log

Exit codes

CodeMeaning
Script's own codeexecute returns the exit code of the script (sys.exit(3) gives 3)
255Timed out. Stdout produced before the kill is kept
127Unknown --lang

On timeout the message says how to raise it:

tokenade execute: timed out after 1.01s (ceiling 1s). Raise it with `--timeout <secs>` (max 600), or narrow the script. …

Gotchas

  • jq runs with -n. Read piped data explicitly with input: --script 'input | .items | length'. A plain .items | length sees no input and prints 0.
  • --script - uses stdin for the script itself, so you cannot also pipe data in. The same applies to a bash or sh script over 64 KiB. Use --script-file instead.
  • Output is redacted for secrets by default, then compacted and capped. If the result looks trimmed, raise --cap or narrow what the script prints.
  • Keep scripts short. execute is for throwaway computation; code you will edit and rerun belongs in a real file.