Compute over bash
Models reflexively compute by shelling out (python3 -c "print(2**64)", node -e, bc, echo $((...))). In pi, the
compute tool is the better default for pure computation: it runs JavaScript in a sandboxed WASM VM, returns the value
of the final expression, and - because it has no filesystem, network, or process access - never triggers a permission
prompt. Use it as your first move for calculation and data shaping; reserve bash for work that genuinely touches the
system.
When to use compute
Route to compute when the task is self-contained computation over values you already have:
- Arithmetic and big numbers - exact integer math,
BigInt, modular arithmetic, combinatorics.
- Base / radix conversion - hex/binary/decimal, parsing or formatting numbers.
- Date and time math - day/second differences, ISO formatting, "N days from X" (
Date is available).
- String and regex work - parsing, reformatting, counting matches, slicing.
- Reshaping data - map/filter/reduce/group over an array or object; pass the data in via the
input argument.
- Hashing -
sha256(string | bytes) returns a hex digest.
- Encoding -
btoa / atob for base64; TextEncoder / TextDecoder for UTF-8 byte work.
When NOT to use compute (use bash instead)
compute is pure compute only. Use bash the moment the task needs anything outside the sandbox:
- Reading or writing files, listing directories, globbing.
- Network access (HTTP, DNS, sockets) - use
ai-fetch-web or curl.
- Environment variables, subprocesses, or installed CLIs.
- Running the project's own code or tests (
npm test, pytest, a build).
- Anything asynchronous -
compute is synchronous only (no await, no dynamic import).
If you find yourself wanting require('fs'), fetch, or process.env inside compute, that is the signal to switch
to bash.
How compute behaves
- Returns the last expression.
const n = 2 ** 16; n * n returns 4294967296. Use console.log(...) for
intermediate output - it is captured alongside the value.
- Pass data via
input. Large or structured inputs go in the input argument and appear inside the sandbox as the
global input (already parsed - no JSON.parse needed).
- Bounded. Calls are capped on wall-clock time, memory, and output size; an infinite loop is killed, not hung.
- Deterministic and prompt-free. No approval dialog, no side effects.
Before / after
Before (shells out, hits the permission dialog):
python3 -c "import hashlib; print(hashlib.sha256(b'hello').hexdigest())"
After (one compute call, no prompt):
sha256('hello');
Before:
node -e "const xs=[3,1,2]; console.log(xs.reduce((a,b)=>a+b,0))"
After - call compute with code: "input.reduce((a, b) => a + b, 0)" and input: [3, 1, 2].
Anti-patterns
- Shelling out to an interpreter purely to calculate.
python3 -c, node -e, bc, expr, echo $((...)) for a
value with no I/O is exactly what compute is for.
- Reaching for
compute to do I/O. It has no filesystem or network; do not try to read a file or fetch a URL
through it. Use bash / ai-fetch-web.
- Re-deriving a hash or base64 by hand when
sha256, btoa, or atob are already available in the sandbox.
- Asking
compute to run the project's tests or build. That is bash's job - compute cannot spawn processes.
1---2name: compute-over-bash3description: Reach for the `compute` tool (sandboxed JavaScript) instead of shelling out to `python3 -c`, `node -e`, `bc`, `expr`, or `jq` whenever the task is pure calculation or data transformation - arithmetic, big-number math, base/radix conversion, date math, string/regex work, reshaping JSON, hashing (sha256), base64, or UTF-8 byte work. Skip it - and use bash - the moment the task needs files, network, environment, subprocesses, or anything asynchronous.4---56# Compute over bash78Models reflexively compute by shelling out (`python3 -c "print(2**64)"`, `node -e`, `bc`, `echo $((...))`). In pi, the9`compute` tool is the better default for pure computation: it runs JavaScript in a sandboxed WASM VM, returns the value10of the final expression, and - because it has no filesystem, network, or process access - never triggers a permission11prompt. Use it as your first move for calculation and data shaping; reserve bash for work that genuinely touches the12system.1314## When to use `compute`1516Route to `compute` when the task is self-contained computation over values you already have:1718- **Arithmetic and big numbers** - exact integer math, `BigInt`, modular arithmetic, combinatorics.19- **Base / radix conversion** - hex/binary/decimal, parsing or formatting numbers.20- **Date and time math** - day/second differences, ISO formatting, "N days from X" (`Date` is available).21- **String and regex work** - parsing, reformatting, counting matches, slicing.22- **Reshaping data** - map/filter/reduce/group over an array or object; pass the data in via the `input` argument.23- **Hashing** - `sha256(string | bytes)` returns a hex digest.24- **Encoding** - `btoa` / `atob` for base64; `TextEncoder` / `TextDecoder` for UTF-8 byte work.2526## When NOT to use `compute` (use bash instead)2728`compute` is pure compute only. Use bash the moment the task needs anything outside the sandbox:2930- Reading or writing **files**, listing directories, globbing.31- **Network** access (HTTP, DNS, sockets) - use `ai-fetch-web` or `curl`.32- **Environment** variables, **subprocesses**, or installed CLIs.33- Running the **project's own code or tests** (`npm test`, `pytest`, a build).34- Anything **asynchronous** - `compute` is synchronous only (no `await`, no dynamic `import`).3536If you find yourself wanting `require('fs')`, `fetch`, or `process.env` inside `compute`, that is the signal to switch37to bash.3839## How `compute` behaves4041- **Returns the last expression.** `const n = 2 ** 16; n * n` returns `4294967296`. Use `console.log(...)` for42 intermediate output - it is captured alongside the value.43- **Pass data via `input`.** Large or structured inputs go in the `input` argument and appear inside the sandbox as the44 global `input` (already parsed - no `JSON.parse` needed).45- **Bounded.** Calls are capped on wall-clock time, memory, and output size; an infinite loop is killed, not hung.46- **Deterministic and prompt-free.** No approval dialog, no side effects.4748## Before / after4950**Before (shells out, hits the permission dialog):**5152```bash53python3 -c "import hashlib; print(hashlib.sha256(b'hello').hexdigest())"54```5556**After (one `compute` call, no prompt):**5758```js59sha256('hello');60```6162**Before:**6364```bash65node -e "const xs=[3,1,2]; console.log(xs.reduce((a,b)=>a+b,0))"66```6768**After** - call `compute` with `code: "input.reduce((a, b) => a + b, 0)"` and `input: [3, 1, 2]`.6970## Anti-patterns7172- **Shelling out to an interpreter purely to calculate.** `python3 -c`, `node -e`, `bc`, `expr`, `echo $((...))` for a73 value with no I/O is exactly what `compute` is for.74- **Reaching for `compute` to do I/O.** It has no filesystem or network; do not try to read a file or fetch a URL75 through it. Use bash / `ai-fetch-web`.76- **Re-deriving a hash or base64 by hand** when `sha256`, `btoa`, or `atob` are already available in the sandbox.77- **Asking `compute` to run the project's tests or build.** That is bash's job - `compute` cannot spawn processes.