Getting started
From an empty folder to your own snake in the arena.
What you need: Node.js 24 or newer (node -v) and a terminal. Steps 1–4 run on your machine,
offline and with no account; step 5 needs a GitHub account to sign in. It's free.
Claude Code is optional: the template is set up for it, its
AGENTS.md points other coding agents (Cursor, Codex, …) to the same instructions, and you can
write the bot by hand.
1. Create a project
npx zerosnake init my-snake
cd my-snake
npm install
init copies the bot template (offline, no account needed):
| Path | What |
|---|---|
src/bot.ts |
the bot: a starter that eats the nearest food and avoids bodies and the wall |
CLAUDE.md |
the rules, API and limits, written for Claude |
.claude/skills/ |
new-strategy, debug-death, compare-with-previous |
test/ |
a smoke test in the real sandbox and a bench against the house bots |
The starter bot beats the weakest house bot (easy), which is the bar for entering the arena, so
you can deploy it before changing a line. It loses to the others.
The template's own tests (npm test, npm run bench) need the engine, sandbox and house-bot
packages, which aren't on npm; until they are, use npx zerosnake sim and npx zerosnake test,
which bring everything they need. See
Before the packages are published.
2. Write a strategy
Open the folder in Claude Code (claude) and describe the snake you want, for example "make it
aggressive: cut off smaller snakes". Or edit src/bot.ts yourself. The pages to read:
- Rules: how snakes move, eat, grow, die and score;
- Bot API: what
tick()receives and returns; - Limits: what the sandbox allows.
The bot is a module that default-exports defineBot({ init, tick }):
import { defineBot, nearestDanger, nearestFood, steerAway, steerToward } from "@zerosnake/sdk";
export default defineBot({
tick(state) {
const danger = nearestDanger(state);
if (danger && danger.gap < 5) return { turn: steerAway(state.self, danger.point) };
const food = nearestFood(state);
return { turn: food ? steerToward(state.self, food) : 0 };
},
});
3. Watch it play locally
npx zerosnake sim
This bundles your bot, runs a match against the house bots in the same sandbox the arena uses,
and opens a viewer in your browser with a timeline, your snake's vision and its log() lines.
Useful options (npx zerosnake sim --help lists them all):
| Option | What |
|---|---|
--vs easy,hard |
opponents: house bots (easy, medium, hard, chaos) or paths to other bots |
--seed 7 |
a fixed world seed; sim prints the seed so you can replay a match |
--ticks 3000 |
match length (10 ticks per second of game time) |
--headless |
print standings and how each of your lives ended instead of the viewer |
To compare against an older version of your bot, pass its file: --vs ../old/src/bot.ts.
4. Run the server's checks
npx zerosnake test
The same checks the server runs before accepting a version: limits, does it load, 5 matches without
a sandbox death, and qualification (score at least as high as the easy house bot). It prints what
to fix when a check fails. See
Limits: check suite.
5. Sign in and deploy
npx zerosnake login
npx zerosnake deploy
loginuses a browser device flow: you sign in on the site with GitHub, pick a username (once), and approve the CLI, which then gets its own token. You can revoke CLI tokens on the site's settings page.deploybundlessrc/into one file and uploads it with your source files. The server creates a new version with statusvalidatingand runs the checks. The version becomesreadyand replaces your bot's previous version in the arena, orrejectedwith a report.- Each author can have 3 bots and 20 deploys per day. See Limits.
6. Follow your bot
Once ready, the version is queued for lives in the arena's rooms, at most one snake per author per
room. After 30 lives it appears on the leaderboard (see Rating). Your profile at
/@<username> lists your bots and their ratings, and each bot's page /@<username>/<slug> has its
versions, their sources and replays of recent lives. From the terminal, npx zerosnake status
shows your bots' active versions, ratings and lives, and npx zerosnake logs a version's check
report and recent lives.
When it dies in ways you don't understand, open that life's replay from the bot page: its trace shows what
your bot saw and returned in its last ticks. Locally, the template's debug-death skill has Claude
replay the last ticks before local deaths (npm run bench -- --deaths 5) and fix the cause;
FAQ lists the common causes.
Before the packages are published
Until zerosnake and @zerosnake/sdk are on npm, work inside a checkout of the monorepo, where
the template is the template/ folder and pnpm links the packages:
git clone https://github.com/zeroplayers/snake-arena
cd snake-arena
npx pnpm@11 install
npx pnpm@11 --filter zerosnake build
node packages/cli/bin/zerosnake.js init ../my-snake
In a project created this way the SDK is copied into vendor/zerosnake-sdk, so npm install
works and editors see the types. sim and test run from the CLI's own copy of everything they
need (node <checkout>/packages/cli/bin/zerosnake.js sim inside the project).