Code mode · for Claude Code and Codex
One script instead of forty tool calls.
A second endpoint with three tools. The assistant reads a typed API for your world, writes a short TypeScript script and runs it in a sandbox. Bulk edits, filters and multi-step tasks finish in one round trip, and you get a trace of every call.
docsread
The API index for your session: 19 domains, 118 methods, typed signatures. Locked methods are marked 🔒 with the tier that unlocks them, so the assistant knows before it writes a line.
queryread-only
Runs a script that only reads. Writes are refused before the script starts, with the line number.
executeread · write · delete
Runs a script with the full API. Budgets per script: 150 calls, 150 writes, 30 deletions, 60 seconds of wall time, 15 seconds of CPU.
A real run
From a sentence to an imported encounter
// "Build a goblin warren encounter for four level-5 characters" const folder = await foundry.folders.create({ name: "Encounter: Goblin Warren", type: "Actor" }); const picks = await foundry.dnd5e.filterCompendiumActors({ packIds: ["dnd5e.monsters"], crMin: 1, crMax: 3 }); const chosen = picks.results.filter(m => ["Bugbear","Dire Wolf","Ogre","Green Hag"].includes(m.name)); for (const m of chosen) await foundry.actors.createFromCompendium({ uuid: m.uuid, folder: folder.id }); return { imported: chosen.map(m => m.name), xp: chosen.reduce((s, m) => s + m.xp, 0) }; --- 6 calls, 2.9 s, execution 063b3918 --- ✓ folders.create 38 ms id=kQ2… ✓ dnd5e.filterCompendiumActors 640 ms ✓ actors.createFromCompendium ≈120 ms id=… ×4 → { imported: [Bugbear, Dire Wolf, Ogre, Green Hag], xp: 1550 }
What tool mode would do
Eight to twelve separate calls, each result read back into the context before the next one. Same outcome, several times the tokens and a minute of waiting.
Nothing is hidden
The trace lists every call with its timing, category and the ids it touched. A script that fails half-way tells you exactly what already happened.
Guarded by design
The sandbox holds
Checked before it runs
Every foundry.* call is found statically. A locked method, an unknown one or dynamic access stops the script with the line number, and nothing has touched the world.
Isolated while it runs
Each script gets a fresh QuickJS isolate inside a worker: no network, no filesystem, no timers, CPU and memory limits, and only the API you see in docs.
Bounded when it writes
150 calls, 150 writes and 30 deletions per script; results over 48 KB are cut with a warning. Calls that fail carry a category, never a stack trace.
[tier] The script was not started: the static check found calls it cannot make. Locked calls: 🔒 foundry.tokens.move (line 2) — requires the Dungeon Master tier Tiers are unlocked on Patreon (free trial available): https://www.patreon.com/c/nitromoon
Who gets it
Every tier, with a daily quota
The tier of your key applies inside a script exactly as it does to tools: a Free key can read actors and roll dice in a script, and hits the same 🔒 on tokens as it would in tool mode.
| Guest | 10 runs a day |
|---|---|
| Free | 30 runs a day |
| Adventurer | 100 runs a day |
| Dungeon Master | No daily limit |
Quotas reset at midnight UTC. One script at a time per world; Dungeon Masters go first in the queue.
Connect
Same key, second endpoint
Claude Code
claude mcp add --transport http foundry-code https://foundry-mcp.com/mcp/code
# then /mcp → Authenticate, sign in with PatreonCodex CLI
codex mcp add foundry-code --url https://foundry-mcp.com/mcp/code codex mcp login foundry-code
Claude connector (web or desktop)
Settings → Connectors → Add custom connector, paste the URL, leave client id and secret empty, connect.
https://foundry-mcp.com/mcp/codeKeep /mcp too
Code mode does not replace the 121 tools. Keep both connected: the assistant picks tools for one-step asks and a script for the rest.