fxsh.

A small, security- and privacy-focused scripting language for coding agents.

$ curl -fsSL https://example.invalid/install.sh | sh
Linux (x86_64, aarch64) · macOS (aarch64) · manual install

Help us improve fxsh — install it, use it from your agent, and run fxsh telemetry collect to share where the language was insufficient. We rely on your feedback to complete the language.

Algebraic effects

Effects like proc.spawn and net.fetch are values. Handlers decide how (or whether) they execute — letting the host swap real I/O for sandboxes, fixtures, or audit logs without touching script code.

Security-focused

The host wraps each script in a transaction-level policy. Each effect handler only performs the side effects that a policy allows.

Single binary

No runtime install. One statically-linked binary, dropped into ~/.local/bin by curl | sh.

State

fxsh today is in its investigation phase. We're shipping the language without policy enforcement first — we want to learn how well agents can write scripts in it and what features are missing.

To do that, we collect telemetry data locally and anonymously, which we hope you will choose to upload (see the telemetry section). Once the language is sufficiently useful, we'll ship policy enforcement too.

Until policy enforcement ships: run fxsh inside an agent sandbox, or review the scripts your agent runs before letting them execute.

Quick taste

$ fxsh -c 'fn main() {
    let urls = re.scan_all(fs.read("notes.md"), r"https?://\S+")
    for u in urls { stdout.write(u) }
}'

Run a script: fxsh script.fxs. Read from stdin: fxsh -. Full language reference: fxsh --doc.

Telemetry

Each script run emits one structured record to stderr (also mirrored to a local JSONL file) — outcome, error kind, source hash, model name.

Upload them with fxsh telemetry collect when you've got a few. You can review (and edit) the exact data before it's sent. We use this information to make the language more useful; fxsh telemetry collect --help spells out what gets shared.

Telemetry collection for sandboxed agents is currently supported only for Claude Code. More platforms coming (next planned is Copilot).

Manual install

The curl | sh line on the install card downloads the right prebuilt binary for your platform, verifies its checksum, drops it into ~/.local/bin, and offers to register fxsh with Claude Code. If you'd rather see what's happening before running it — or you're on a platform we don't ship a binary for (Intel Mac, Windows, BSD) — here's the same thing, by hand.

Option A: prebuilt binary

Pick the asset matching your platform from https://https://pub-c19bb22cdb2d42909de545e416be1e90.r2.dev/latest/ — currently fxsh-linux-x86_64, fxsh-linux-aarch64, or fxsh-darwin-aarch64. Each has a sibling .sha256 file with its checksum.

$ ASSET=fxsh-linux-x86_64   # adjust for your platform
$ curl -fsSL -o fxsh        "https://https://pub-c19bb22cdb2d42909de545e416be1e90.r2.dev/latest/$ASSET"
$ curl -fsSL -o fxsh.sha256 "https://https://pub-c19bb22cdb2d42909de545e416be1e90.r2.dev/latest/$ASSET.sha256"
$ sha256sum -c fxsh.sha256  # or `shasum -a 256 -c` on macOS
$ chmod +x fxsh
$ mv fxsh ~/.local/bin/

Option B: build from source

If you'd rather build, the same source tarball our release pipeline uses lives next to the binaries. Needs a Rust toolchain (install via rustup.rs) but no submodule fetch or workspace setup. Pin a specific version by substituting v0.0.0 (or whichever) for latest.

$ curl -fsSL https://https://pub-c19bb22cdb2d42909de545e416be1e90.r2.dev/latest/fxsh-src.tar.gz | tar xz
$ cd fxsh-*-src
$ cargo build --release -p fxsh
$ cp target/release/fxsh ~/.local/bin/

Tell Claude Code about fxsh

Either install path drops the binary on your PATH but doesn't tell your coding agent it exists. Append a short blurb to ~/.claude/CLAUDE.md (global) or any project-local CLAUDE.md so agents can pick it up. The guard skips the append if the snippet is already there, so this is safe to re-run:

$ grep -qx '## fxsh' ~/.claude/CLAUDE.md 2>/dev/null \
    || curl -fsSL https://example.invalid/claude-snippet.md >> ~/.claude/CLAUDE.md

Or view the snippet and paste it into a CLAUDE.md of your choice.