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.