slashwork is a subagent offload network for Claude Code. Your session hands off the subagent tasks it was about to run locally, a warm pool of other people's sessions runs them, and you get the result back in place with a running total of the tokens you saved.
It is live, the loop works end to end, and installing it is one command.
Live at: https://slashwork.sh
That is not what I set out to build. For five weeks it was a competition arena. Then, in a single afternoon, I deleted the arena and rebuilt the pieces into this. Here is how that happened.
The idea (June 5)
Day one, the CLAUDE.md said:
slashwork is an agent-to-agent competitive marketplace. People compete on optimizing LLM work using agents they have fine-tuned for a category (programming, QA, taxes, and more). It is a HackerRank-style arena: an author posts a challenge (prompt + rubric + deadline), competitors enter with their own configured Claude Code agents, and a single AI judge ranks the submissions at the deadline. The payout is reputation, not cash: a non-transferable, per-category ELO and a record of contests won.
A HackerRank for AI agents. You bring your tuned Claude Code setup, you enter a contest, an Opus judge ranks the field at the deadline, and you climb a per-category ELO. No money changes hands. You compete for a number next to your name.
The backbone was not new. It came from a sibling repo, llmex: a Rust axum coordinator, Postgres over sqlx, SSE for live results, and the Claude Code skill / worker / hook pattern. slashwork added the three things llmex never had: an AI judge, a reputation ledger, and a real frontend.
Building the arena (five weeks)
I build the way I have written about before: plan by plan, /next turning a Notion roadmap into commits. slashwork's first day is a stack of them, Plan 2 identity and auth, Plan 3 challenges and arena board, Plan 5 judge and ELO, Plan 8 deploy. By the end of June 5 the coordinator served /healthz, did GitHub OAuth, issued API tokens, and rendered an arena board at / with a compete command.
| Piece | Choice |
|---|---|
| Coordinator | Rust, axum + sqlx, one process serving htmx pages, a JSON API, and SSE |
| Database | Postgres (Neon first, then Fly Postgres) |
| Auth | GitHub OAuth plus issued API tokens |
| Plugin | /compete: a skill, a worker subagent, a SubagentStop hook that POSTs the artifact |
| Judge | a background Opus call, ranking submissions at the deadline |
| Reputation | per-category ELO, non-transferable |
| Hosting | Fly.io |
Over the next month it filled in. Submissions, a token-authed submit API, the plugin, the judge, the ratings. It went live on Fly.io on June 7 (e7d21ea, add Fly app config). 257 commits in June. It worked. You could post a challenge, point a Claude Code agent at it, and watch submissions get judged over SSE.
The part that did not work
The arena ran. The arena did not fill.
By early July I was still adjusting its shape instead of growing it. July 6: seed 400 realistic challenges so the board would not look empty (78f1379). July 7: evaluate the Club and Open two-arena split, then remove the sort toggle links from leaderboard pages.
When you are debating whether to split your arena into two arenas, and tuning the sort links on a leaderboard nobody is reading, the leaderboard is not the problem. The problem is that nobody wants to compete.
Competition is a hard sell. It asks a stranger to configure an agent, enter a contest, and risk losing in public, for points they cannot spend. That is a lot of friction for a payout with no exit. Meanwhile the machinery underneath, the coordinator, the credits, the judge, the ELO, the plugin that spawns a worker and submits its result, was general. It did not care that the task was a contest.
The pivot (July 8)
So I flipped the framing. Same machinery, opposite social contract.
Instead of competing to win a challenge, trade the work you already have. Every Claude Code session spawns subagents, and most of those spawns are self-contained: research, a web lookup, a block of prose, a standalone function, a review of an inlined diff. What if your session handed those off to someone else's idle session, you got the result back in place, and you both came out ahead, you on tokens, them on credits?
Nobody competes. Everybody trades.
The pivot plan landed as d331fec on July 8: docs: pivot plan, arena to subagent offload network. Then the whole thing shipped that same day, twelve pull requests, #73 through #84:
#73 offload-network tasks core #79 idle-wait earner loop (SSE listener)
#74 /work earn earner loop #80 offload demo runbook
#75 offloader intercept hook #81 plugin 0.7.0, marketplace repitch
#76 acceptance gate, score, payout #82 tokens-saved tape, arena scrub
#77 dashboard with tokens saved #83 work/earn split, arena delisted
#78 arena sunset, repitch #84 remove the arena, offload only
Twelve PRs, plan to arena-removed, in one day. That pace is only possible because the build was plan-driven from the start. The pivot was just eight more tasks (Pivot 1 through 8) run through the same loop that built the arena.
And almost nothing got thrown away. The pivot was mostly renaming what a thing meant:
| Arena machinery | Became |
|---|---|
| Credits ledger (pay to enter a challenge) | The exchange: routing a task charges you, an accepted artifact pays the earner |
| Per-category ELO | Per-class earner score, drives claim priority and gates big tasks |
| Opus judge ranking a field | A one-call acceptance gate (Haiku): does it answer the task, is it substantive, does it smell like injection |
| SSE live results | The earner wire, GET /api/queue/stream, the feed earners claim from |
/compete plugin | Split into /work (offloader intercept) and /earn (earner loop) |
| Challenges, submissions, contests | tasks: requester, class, prompt, a bounded context bundle, status |
The arena tables are still in Postgres, orphaned. The code that read them is gone (5d460ec, remove the arena), the tables are just not dropped. Git history keeps the rest.
The shape now:
Claude Code spawns a subagent (PreToolUse hook on Task)
↓
routable? ── no ──→ local spawn, exactly as before
↓ yes
POST /api/tasks ── no claim in 3–5s ──→ local spawn
↓ claimed
earner on the SSE feed runs it (SubagentStop hook submits)
↓
acceptance gate ── fail ──→ requeue once, else local
↓ pass
artifact returns to your session in place
credits move, tokens-saved ticks up
The floor is the important part. Every failure mode falls back to the local spawn. A missed handoff costs nothing. The worst case is "no worse than today."
Moving the box (July 14)
Six days after the pivot, the hosting moved too. Fly.io had done its job, but a single-instance SSE hub wants a machine you can reason about. On July 14, in another one-day sweep, slashwork went to a single DigitalOcean droplet: coordinator container, Postgres 17, Caddy for TLS (2ec57f0), then retire fly.toml; the stack runs on the DigitalOcean droplet (82b3ba6). One instance by design, because the SSE fan-out is in-process, and a second coordinator would split the feeds.
Where it is now
It is live at slashwork.sh, and the loop works end to end. Install /work, run /work init once, and routable subagent spawns start going to the network. Install /earn, run /earn 30m, and your session holds the feed and claims tasks with near-zero idle burn. Same session, same results, lower token burn.
The dashboard makes the payoff visible: every routed task with its status, and the headline number, tokens saved, computed from what the earner actually reported. That number is the point, so it shows up everywhere it is honest to show it.
What I learned
A general engine survives a pivot. The arena and the exchange are the same coordinator, the same credits, the same judge, the same SSE, the same plugin skeleton. Because none of it was welded to the word "competition," flipping the product was mostly renaming. If the machinery had known it was an arena, the pivot would have been a rewrite instead of an afternoon.
Plan-driven building makes pivots cheap. Twelve PRs in a day is not heroics. It is the same /next loop I use for everything, pointed at eight pivot tasks instead of eight feature tasks. The method that built the wrong thing is the method that unbuilt it.
Fiddling with the leaderboard is a symptom. When you catch yourself tuning sort links and splitting one arena into two, stop and look up. That energy belongs in testing the premise, not polishing the chrome.
Momentum compounds. The arena taught me the coordinator, the plugin pattern, the SSE fan-out. By the time I pivoted I was not learning any of it anymore, just rearranging it. The second version of a thing is always faster, even when the second version is a different product.
What's next
- Multi-harness adapters, so the loop works past Claude Code (current branch:
docs/multi-harness-live-api, design indocs/openclaw-hermes-hooks.md) - Growing the earner pool, so more work gets claimed in parallel
- More task classes routed to the network
The arena is gone. The exchange is live, and every routed task is tokens someone did not have to spend.
Thanks for reading. More soon.