Running Amp orbs on OrbStack and Fly.io Sprites

Two open-source Amp orb providers: one runs threads on your Mac with OrbStack, the other on Fly.io Sprites. How they work and when to use each.

Published
Length
7 min read
Filed under

In Why I love Amp, I wrote that you can run Amp’s cloud machines on your own infrastructure. I wanted to test that claim on hardware I already pay for, so I wrote two providers:

This post covers how a provider works, what each of these does differently, and when I’d pick one over the other.

What a provider does

Each Amp thread runs on its own machine, which Amp calls an orb. A self-hosted provider decides where that machine lives.

The provider is a long-running process, amp orb provider, that holds an outbound connection to Amp. When a thread needs a machine, Amp sends a job, and the provider runs a dispatch program you write. The program gets one of three operations:

  • spawn creates or resumes the machine and starts amp orb bootstrap inside it, which connects the machine back to Amp.
  • pause stops the machine and keeps its disk.
  • delete removes the machine.

Amp sends the details as environment variables, so the dispatch program can be a shell script:

case "$ORB_OPERATION" in
	spawn) spawn ;;
	pause) pause ;;
	delete) delete ;;
esac

Every operation has to be safe to repeat and finish within five minutes. Amp never connects into your network: the provider and the machines only make outbound connections. The agent loop and model calls still run at Amp, and the machine sends tool output, such as file contents and command results, back to the thread.

Both of my dispatch scripts are plain Bash, 136 and 179 lines, and run on the version of Bash that ships with macOS.

What both providers share

The two providers follow the same lifecycle:

  • One machine per thread. The machine is created on the first message and deleted with the thread.
  • Persistent disk. Files, installed packages, databases, and git state survive a pause. Running processes don’t, so dev servers restart when the thread resumes.
  • One-time provisioning. The first spawn installs the amp CLI and a few tools Amp expects, then writes a marker file. Later spawns skip that step.
  • Short-lived credentials. Every spawn writes a fresh token from Amp and restarts bootstrap. The token never appears in command arguments or logs.

Each repository also includes a smoke test that drives the dispatch script through spawn, repeated spawn, pause, resume with a new token, and delete, then cleans up. A provider bug shows up as a thread that never starts, which is slow to debug from inside Amp, so the test catches it first.

OrbStack: threads on your Mac

OrbStack runs lightweight Linux machines on macOS. The provider creates one per thread, so the agent works on your Mac’s CPU and disk, and there is no cloud bill.

Isolated by default. A normal OrbStack machine mounts your Mac’s files and can reach the host. An agent shouldn’t have that, so the provider creates isolated machines with network isolation turned on. The machine keeps internet access but can’t see your home directory, other machines, or services on your Mac. OrbStack notes that isolation shares a kernel and isn’t a full security boundary, which is a reasonable tradeoff for an agent working on your own repositories.

Setup caching. Amp can save a project snapshot: a machine with the repository cloned and .agents/setup already run, so new threads skip setup. OrbStack clones machines copy-on-write, so the provider saves a snapshot by cloning the stopped machine and starts a new thread by cloning the snapshot. Both take a few seconds and cost only the disk that changes afterward. The provider removes the token before the machine stops, so snapshots contain no credentials.

The tradeoff is availability. Threads live on one Mac. If it sleeps or OrbStack quits, those threads stop until it’s back. A first spawn takes about 90 seconds plus your setup script.

Fly.io Sprites: threads in the cloud

Sprites are persistent Linux VMs built for agents. Each has a 100 GB disk that survives sleep, and compute bills only while the Sprite runs. That matches how Amp threads behave: busy for a while, then idle for hours or days.

A first spawn takes about 20 seconds plus your setup script, and Sprites ship with Node, Go, Bun, Python, Ruby, Rust, and other runtimes, so many repositories need little setup.

Keeping a Sprite awake. Sprites suspend when idle and drop open connections, including the outbound connection that links the machine to Amp. A Sprite doing quiet work could fall asleep mid-thread. The provider solves this with a wrapper around bootstrap that renews a keep-awake task every 60 seconds, with a five-minute expiry. Pausing the thread deletes the task, and the Sprite suspends on its own. If the wrapper crashes, the task expires within five minutes, so a failure can’t keep a Sprite billing indefinitely.

No setup caching. Sprite checkpoints restore only into the Sprite that created them, so the provider can’t start a new thread from another thread’s snapshot. Every new thread runs .agents/setup from scratch. Resumed threads skip it, because their disk persists.

One cost risk. A Sprite stays awake until Amp sends a pause. If the provider is down at that moment, the Sprite keeps running until a later pause or delete reaches it. Run the provider as a service, and check for leftover amp-* Sprites now and then.

Which one to use

OrbStack Fly.io Sprites
Where threads run Your Mac Fly.io VMs in your organization
Cost Hardware you own CPU, memory, and storage while running
Available when The Mac is awake Always
First spawn ~90 seconds + setup ~20 seconds + setup
Setup caching Yes, copy-on-write snapshots No
Isolation Isolated machine on a shared kernel Separate VM per thread

I’d choose OrbStack when:

  • You work alone or want to try self-hosted orbs without a new account or bill.
  • You have a desktop Mac that stays on. Start a thread from your phone, and the work runs on the machine at home.
  • The repository or its data should stay on hardware you control.
  • You’re writing your own provider. Local machines make the spawn, pause, and delete loop fast to test.

I’d choose Sprites when:

  • A team shares the provider, and threads can’t depend on one person’s laptop.
  • Usage is bursty, and you want cost to follow active time.
  • You want each thread in its own VM rather than on a shared kernel.

Self-hosted orbs carry no Amp charge on the Hobby, Individual, and Teams plans, so either way the only cost is the infrastructure.

What I learned writing them

The dispatch contract is small, but a few details took most of the time:

  • Make create race-safe. Two spawns for the same orb can overlap. Both scripts treat “create failed, but the machine now exists” as success.
  • Keep secrets out of argv. Tokens go through stdin or a 0600 temp file, never a command-line argument that shows up in ps or logs.
  • Don’t start bootstrap at boot. Bootstrap starts only on spawn, after the fresh token is written. A machine cloned from a snapshot can’t connect with a stale token.
  • Read the platform’s sleep rules. The Sprites keep-awake wrapper exists because a suspended VM drops outbound connections too.

Is self-hosting worth it?

For most teams, no. I’d stick with Amp’s default orbs.

Amp-hosted orbs work with no setup. There’s no provider to keep running, no script to update when Amp or the platform changes, no leftover machines to clean up, and no debugging a thread that never starts. They also do things my providers can’t: they keep memory on pause, not only disk, and they support features that depend on Amp’s own image, such as Desktop.

The pricing reflects that. The $20 Individual plan includes 45,000 orb minutes, and the free Hobby plan pays as you go. For a small team, I’d expect the time spent maintaining a provider to cost more than the orb minutes it saves.

Self-hosting makes sense when where the code runs is a requirement, not a preference:

  • Larger organizations with data residency rules that require code to execute in a specific region or network.
  • Defense, government, and regulated work where confidential code can’t run on a vendor’s machines.
  • Organizations with existing compute commitments or spare capacity they want to use.

Check the details before assuming self-hosting meets your requirements. The agent loop and model inference still run at Amp, and the machine sends tool output, including file contents, command output, and diffs, back to Amp for storage in the thread. Self-hosting keeps execution on your infrastructure; it doesn’t keep everything there.

The lock-in point, made concrete

My earlier post said Amp doesn’t lock you in on compute. Two Bash scripts are the evidence: the same threads, sharing, and previews now run on a Mac or on VMs in my own Fly.io account, and moving between them is a choice in a dropdown.

Neither provider depends on anything beyond the platform CLI, amp, and jq. If your organization needs to self-host and runs compute somewhere Amp has no example for, the contract is small enough to implement in a single script, and these two are a reasonable starting point. For everyone else, knowing the option exists is the point. I’d stick with the default.