Fire-and-Forget Agents with Sprites
January 20, 2026
I've been running Claude Code on my machine for months. It's fast, it has full context, it can edit files and run commands. But there's a friction point: when I'm deep in a feature branch and notice an unrelated bug, I have two choices. File an issue and context-switch later. Or abandon my current work to fix it now.
Neither is great. Issues pile up. Context switches kill flow.
Sprites offer a third option: fire-and-forget agent sessions that draft PRs while I keep working.
The Setup
Sprites.dev is Fly.io's new sandbox product. You get stateful VMs with 8GB RAM, checkpoint/restore in ~300ms, and pay-per-use pricing. Claude Code comes pre-installed. The checkpoint system is the key innovation—you can snapshot an entire machine state and restore it instantly.
I created a "warm checkpoint" with my monorepo cloned, dependencies installed, and packages pre-built:
sprite create trip-warm
sprite exec git clone https://... /home/user/workspace
sprite exec npm install -g pnpm
sprite exec bash -c "cd /home/user/workspace && pnpm install"
sprite exec bash -c "cd /home/user/workspace && pnpm build --recursive"
sprite checkpoint create # → v1
This checkpoint is my "golden image." Every new task restores from it in milliseconds, starts with a clean main branch, and has everything ready to go—no cold starts, no dependency fetching.
What to Sprite, What to Drive
Not every task is a sprite candidate. The key question: can you describe the fix without needing to discover it?
Good sprite candidates (fire-and-forget):
- One-shot fixes: "The button text says 'Sumbit', should be 'Submit'"
- Obvious bugs: "Dates are displaying in UTC, should use local timezone"
- Mechanical changes: "Add loading states to all async buttons"
- Well-scoped issues: "Implement the design from Figma link X"
- Clear patterns: "Add error handling like we have in similar components"
Keep these human-driven:
- Exploratory work: "The app feels slow, figure out why"
- Architectural decisions: "Should we use Redux or Zustand?"
- Tricky bugs: "Sometimes the form submits twice, not sure when"
- Large features: Multi-file, multi-day work with unclear boundaries
- Anything requiring back-and-forth clarification
The sprite workflow shines when the task is well-defined but interruptive. You know exactly what needs to happen, you just don't want to context-switch to do it right now.
Think of it as: would you mass-assign this to a junior dev with confidence they'd nail it? If yes, sprite it.
GitHub App Tokens
Sprites need to push branches and create PRs. You could use a personal access token, but that's your identity—broad permissions, long-lived, and if leaked, it's your account.
Instead, I use a GitHub App. The app is installed on my repo with just the permissions sprites need (contents, pull requests, issues). Each sprite task generates a fresh installation token that expires in one hour.
The flow:
- Create a GitHub App with repo permissions
- Install it on your repository
- Store the private key locally
- Before each sprite task, generate a JWT, exchange it for an installation token
# Generate JWT from app credentials
jwt=$(generate_jwt $APP_ID $PRIVATE_KEY)
# Exchange for short-lived installation token
token=$(curl -X POST \
-H "Authorization: Bearer $jwt" \
"https://api.github.com/app/installations/$INSTALL_ID/access_tokens" \
| jq -r .token)
# Pass to sprite
sprite exec -env "GH_TOKEN=$token,GITHUB_TOKEN=$token" ...
The sprite gets GH_TOKEN and GITHUB_TOKEN environment variables. The gh CLI and git both pick these up automatically. When the sprite finishes, the token is either expired or close to it.
The Slash Command
I wrote a /sprite slash command for Claude Code. When I run /sprite Fix the timezone bug in DatePicker, my local Claude:
- Gathers context—searches the codebase, reads relevant files, checks if it references a GitHub issue
- Generates a task slug—a short identifier like
fix-datepicker-tzfor tracking - Crafts a prompt—including relevant code excerpts and patterns to follow
- Launches a sprite—restores checkpoint, passes the prompt, exits immediately
That's it. No branch creation, no git operations on my machine. My local state is untouched. The sprite handles everything autonomously—creates its own branch, makes changes, pushes, opens a draft PR.
# The launcher script (simplified)
sprite restore -s trip-warm $CHECKPOINT_ID
sprite exec -s trip-warm bash -c "git fetch && git reset --hard origin/main"
sprite exec -s trip-warm \
-dir "/home/user/task-${TASK_SLUG}" \
-env "GH_TOKEN=$TOKEN,GITHUB_TOKEN=$TOKEN,ANTHROPIC_API_KEY=$KEY" \
claude --dangerously-skip-permissions --max-turns 30 \
-p "$(cat /tmp/sprite-prompt.txt)"
Identifying Running Sprites
When you have multiple sprites running in parallel, how do you tell them apart? Sessions only have numeric IDs, but the sprite sessions list command shows the working directory:
$ sprite sessions list -s trip-warm
ID Command Workdir Started
13041 claude /home/user/task-fix-datepicker 2m ago
13047 claude /home/user/task-issue-995 5m ago
13052 claude /home/user/task-add-loading 30s ago
The trick: create a symlink /home/user/task-<slug> pointing to the workspace, then run Claude with that as the working directory. The symlink resolves to the repo, but the task name shows in the sessions list.
The Prompt Engineering
The sprite has the full codebase—it can grep, read files, run pnpm typecheck, everything. So why bother with a detailed prompt?
Direction and focus. The sprite could figure things out itself, but that burns tokens and time. By front-loading relevant context—which files matter, what patterns to follow, what the actual bug is—I'm giving it a head start. Think of it less as "providing information it can't access" and more as "pointing it at the right place to start."
You are Claude Code running autonomously in a Sprites.dev sandbox.
Refer to /.sprite/llm.txt for environment capabilities.
TASK: Fix timezone handling in DatePicker component
CONTEXT:
- File: src/components/DatePicker.tsx (lines 45-120)
- The bug: dates are converted to UTC on selection, losing local timezone
- Pattern: other date components use date-fns-tz for timezone handling
STEPS:
1. Create branch: git checkout -b sprite/fix-datepicker-timezone
2. Make the fix
3. Validate: pnpm exec oxlint src/components/DatePicker.tsx
4. Commit, push, create draft PR
LLM-Aware Environment
Sprites include a /.sprite/llm.txt file that documents the environment for AI agents. It points to detailed docs about services, network policies, and checkpoints.
One interesting capability: the sprite can checkpoint itself mid-task using sprite-env checkpoints create. If Claude gets into a bad state, it could restore to a previous checkpoint. The last 5 checkpoints are even mounted at /.sprite/checkpoints for direct file access.
I just point the sprite at /.sprite/llm.txt and let it discover what's available. The environment is designed for autonomous agents.
Auto-Exit with Stop Hooks
One problem with fire-and-forget: how does the sprite know when to stop? Claude Code doesn't naturally terminate after completing a task—it keeps exploring.
The solution is a Stop hook baked into the checkpoint. When Claude finishes, the hook runs kill -TERM $PPID, which kills the parent process. The sprite session ends cleanly, and Fly auto-sleeps it after inactivity.
The flow: Claude completes task → Stop hook fires → kills parent → sprite auto-sleeps.
This makes the economics work. Idle sprites cost only storage (~$0.49/GB/month). Active time runs about $0.46 for a 4-hour session. A focused sprite task that completes in minutes costs almost nothing, and you don't need to manually clean up.
The Mental Model Shift
This isn't about getting perfect PRs from sprites. It's about getting past the blank page.
Traditional workflow: Notice bug → File issue → Context-switch later → Write code → PR → Review
Sprite workflow: Notice bug → /sprite → Continue working → Review draft PR later
The sprite doesn't need to nail it. It needs to produce something that's cheaper to edit than write from scratch. A 70% solution with the right structure is a great starting point.
And here's the key: a draft PR triggers CI. By the time you look at it, GitHub Actions have run, tests have reported, and automated reviewers like Greptile have left comments. You're not starting from a blank PR—you're starting from a PR with feedback already attached. The sprite did the first draft. CI and code review bots did the first round of feedback. You pick it up with context already built.
What This Enables
Parallel agents. Sprites are cheap. You could /sprite five issues in the morning and have five draft PRs—each with CI results and review comments—by lunch.
Interrupt immunity. Colleague asks about a quick fix unrelated to your work? /sprite it instead of context-switching. Zero impact on your local git state.
Session forking. The checkpoint system means you can spawn unlimited parallel universes from the same clean state. Each sprite is isolated. They can't conflict.