Skip to content

chebykinn/factorio-planning-agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

factorio-planning-agent

Chat with Claude agents from inside Factorio. Agents plan builds as ghost entities, reason about throughput, rails, fluids and belt lanes, point at things with in-world annotations — and everything they know or plan lives in declarative state files that stay in sync with the game world in both directions, automatically.

MIT licensed. macOS and Linux.

Planning Agent mod thumbnail

Screenshots

Streaming chat with an agent, in game:

In-game chat UI

Agents mark and explain plans with in-world annotations instead of editing your factory:

In-world annotations

When a decision is yours to make, the agent asks with a form:

Agent asking a question

Architecture

            ┌───────────────────────────── game client (your normal profile, isolated mods)
            │ multiplayer
┌───────────▼───────────┐   RCON (poll / push / tool)   ┌──────────────────────────────┐
│  Factorio dedicated   │◄──────────────────────────────►│        agent daemon (bun)     │
│  server + mod (Lua)   │                                │                               │
│  · chat GUI, multi-   │                                │  · one Claude Agent SDK       │
│    chat, forms,       │                                │    session per chat (resumed  │
│    status bars        │                                │    across restarts)           │
│  · world tools        │                                │  · state watcher: file edits  │
│  · change journal     │                                │    auto-apply + verify        │
│  · staleness cells    │                                │  · world→file sync (journal)  │
│  · annotations        │                                │  · lane analyzer, watchdogs,  │
└───────────────────────┘                                │    idle reaper                │
                                                         └───────────┬──────────────────┘
                                                                     │ spawns, cwd =
                                                         ┌───────────▼──────────────────┐
                                                         │  agent-workspace/             │
                                                         │  · factorio-tool CLI          │
                                                         │  · .claude/skills (docs the   │
                                                         │    agent reads at start)      │
                                                         │  · lib/rails.js (engine-      │
                                                         │    derived rail router)       │
                                                         │  · state/  ← THE source of    │
                                                         │    truth for plans & factory  │
                                                         └──────────────────────────────┘

The core idea: files are the interface.

  • A construction is a JSON file in agent-workspace/state/: metadata, as_of_tick, and a ghosts array (with per-belt lane intents, machine recipes, train schedules, stop names). Saving the file deploys it: the daemon watches state/, applies changes within seconds, and writes the full result back into the file as a verify field — placements, failures with reasons, removals, lane warnings, staleness refusals.
  • The world syncs back into the files continuously: the mod journals every build/removal/rotation (player, bots, any chat) and the daemon files each change into whichever state file claims that entity (build progress counters, removal sync-logs, rotation updates) or into state/world/region_X_Y.json mirrors for unclaimed territory.
  • Staleness is enforced: layouts declare the tick of the scan they were planned against; if the target area changed since (16-tile dirty-cell tracking, ghosts included), the apply is refused with instructions to re-read, update, re-apply.
  • Agents can only add ghosts, mark, and point: deconstruction marks are restricted to natural clutter, upgrade marks to researched same-footprint tiers, and everything the player must do by hand is annotated in-world (entity-attached rings + labels that vanish when you do the thing, boundary boxes, map pins) — never bare coordinates.

The in-game mod provides multi-chat (each chat = an independent SDK session with persistent memory), streamed responses, AskUserQuestion forms, permission prompts, per-chat status bars with elapsed timers, and notification pings when an agent finishes or needs input while its window is closed.

The daemon provides: session resume across restarts (transcripts), a stall watchdog (hung API streams get interrupted), an idle reaper (sessions stop after 5 idle minutes, resume on the next message), API timeouts, reasoning effort control, and permission policy (factorio-tool pipelines and /tmp+workspace writes are pre-approved; anything else prompts in-game).

Agent-facing tooling (./factorio-tool --help for the full list): observation (scan_area with statuses/contents/lanes/fluid segments, get_occupancy tile grids with reserved-tile marking, trace_belt, trace_entity with fluid ports, find_entities, find_resources map-wide, get_power, get_rates, check_train_stop), planning (place_ghosts file-based/declarative/idempotent, lint), marking (mark_deconstruction, mark_upgrade), pointing (annotate, list_annotations, clear_annotations) — all fog-of-war-gated to what the players have charted.

Install

  1. Factorio 2.0 (full game for the client; the same binary runs the server). Auto-detected at:
    • macOS: /Applications/factorio.app
    • Linux: ~/factorio/bin/x64/factorio or the Steam library paths
    • anything else: FACTORIO_BIN=/path/to/factorio
  2. bun (runs the daemon and CLI), node (layout generation), jq (the agents' analysis workhorse), python3 (used by some scripts).
  3. Claude Code CLI, logged in — the Agent SDK uses its credentials.
git clone <this repo> && cd factorio-planning-agent
( cd daemon && bun install )

Optional: put a save at server-data/saves/starter.zip to use an existing world as the base (--fresh resets back to it); otherwise a new world is generated. Mod-list enables Space Age + Quality + Elevated Rails by default — edit scripts/enable-mod.mjs if your save differs.

Run

scripts/run.sh              # server + daemon + game client; quitting the game stops everything
scripts/run.sh --headless   # server + daemon only (Ctrl-C stops)
scripts/run.sh --fresh      # reset the world (reseeds from saves/starter.zip if present)

In game: click the Claude button (top-left). Create/rename/delete chats in the window header; each chat is an independent agent. Type a request — Enter sends (¶ toggles multi-line mode), ■ interrupts. Watch it scan, plan, drop a boundary box, and fill the area with ghosts for you or your bots to build.

Ops (all safe while the game runs):

scripts/start-daemon.sh     # restart just the daemon (sessions resume with memory)
scripts/reload-mod.sh       # mod changes: sync + bounce server; reconnect in the client
scripts/rcon-cli.ts         # ad-hoc: bun scripts/rcon-cli.ts '/silent-command rcon.print(game.tick)'

Daemon knobs (env for start-daemon.sh / run.sh):

var default effect
AGENT_MODEL session default pin a model, e.g. claude-sonnet-4-6 for snappier turns
AGENT_EFFORT medium reasoning effort: lowmax
API_TIMEOUT_MS 180000 hung API streams error out and retry
STALL_MS / SPIN_MS 240000/300000 watchdog: silence / thinking-without-progress before interrupt
IDLE_STOP_MS 300000 idle sessions stop (resume on next message)
RCON_PORT / RCON_PASS / GAME_PORT 27015/caludeagent/34197 networking

Development notes

  • Mod iteration: reload-mod.sh bounces the server only; clients re-read control.lua on rejoin (seconds). Prototype-stage changes (data.lua, info.json) need a full client restart. Keep the mod version stable across reloads — clients match versions at launch; init_storage() runs at every entrypoint instead of relying on version-triggered migrations.
  • Factorio RCON returns exactly one response packet per command (verified to 100 KB); commands must be single-line; /silent-command runs in the level context so mod state is only reachable via remote.call; Factorio Lua is 5.2 (no \u{} escapes); game.reload_mods()/reload_script() are silent no-ops on dedicated servers.
  • The rail connection graph in agent-workspace/lib/rails.js and the belt lane rules in daemon/lanes.ts were derived empirically by probing the engine — regenerate the same way if a game update changes rail geometry.
  • Logs: server-data/{server,daemon,client,create}.log; verify failures for malformed JSON land in agent-workspace/state/_verify.log.

About

A planning AI agent inside factorio

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors