An AI agent SDK for playing Planescape: Torment via Claude Code. Inspired by the Fallout 2 SDK architecture, rebuilt from scratch for the Infinity Engine (GemRB).
Claude Code (CLI) ──→ reads game/agent_state.json
──→ writes game/agent_cmd.json
↕
Agent Bridge (Python + C++ shim)
↕
GemRB Engine (Infinity Engine reimplementation)
↕
Planescape: Torment game data
3-layer stack:
-
Python Bridge (
src/agent_state.py,src/agent_commands.py,src/agent_bridge.py) — Serializes GemRB game state to JSON, dispatches JSON commands via GemRB's Python scripting API. This replaces ~5300 lines of C++ from the Fallout 2 bridge with Python leveraging GemRB's existing bindings. -
Executor Scripts (
scripts/executor*.sh) — Bash abstractions over raw JSON commands. Provides high-level functions likedo_combat,move_and_wait,talk,cast_spell_atthat handle polling, retries, and state monitoring. -
Claude Code — The AI agent running the observe/decide/act loop. Reads game state, makes decisions, executes actions through the executor.
| Aspect | Fallout 2 | Planescape: Torment |
|---|---|---|
| Combat | Turn-based (AP) | Real-time with pause |
| Magic | None | Full D&D 2e spellcasting |
| Stats | SPECIAL (7 stats) | D&D (6 stats + THAC0/AC/saves) |
| Party | 1-3 companions, limited control | Up to 6, fully controllable |
| Navigation | Hex grid + world map | Pixel coordinates, area transitions |
| Death | Game over → reload | TNO resurrects (immortal) |
| Bridge | C++ only (~6000 LOC) | ~70% Python, ~30% C++ shim |
| Dialogue | Short conversations | Novel-length, stat-gated, alignment-shifting |
# 1. Clone with submodules
git clone --recursive https://github.com/Wondermonger-daydreaming/torment-sdk.git
cd torment-sdk
# 2. Configure game data path
cp sdk.cfg.example sdk.cfg
# Edit sdk.cfg: set PST_DIR to your PS:T installation
# 3. Setup (copies game data, initializes knowledge files)
./scripts/setup.sh
# 4. Build GemRB with agent bridge
./scripts/build-gemrb.sh
# 5. Launch the game
cd game && ../engine/gemrb/build/gemrb/gemrb -c GemRB.cfg
# 6. In Claude Code, load the executor
source scripts/executor.sh
executor_helppst-sdk/
├── src/ # Agent bridge (Python + C++ shim)
│ ├── agent_bridge.py # Main tick loop, init/exit
│ ├── agent_state.py # State serialization (GemRB → JSON)
│ ├── agent_commands.py # Command dispatch (JSON → GemRB)
│ ├── agent_shim.cpp # C++ shim (overlay, focus, tick)
│ └── agent_shim.h
├── scripts/ # Executor and utility scripts
│ ├── executor.sh # Main executor (core I/O, state, help)
│ ├── executor_world.sh # Movement, exploration, interaction
│ ├── executor_combat.sh # RTwP combat monitoring
│ ├── executor_dialogue.sh # Dialogue, persona, thoughts
│ ├── float_response.sh # Hook: floating text overlay
│ ├── game_state_hook.py # Hook: compact state injection
│ ├── setup.sh # First-time setup
│ ├── build-gemrb.sh # Build GemRB with bridge
│ ├── apply-patches.sh # Apply engine patches
│ └── generate-patches.sh # Generate patches from changes
├── docs/ # Documentation
│ ├── default-persona.md # The Nameless One persona template
│ └── gameplay-guide.md # PS:T mechanics reference
├── engine/ # Engine integration
│ ├── gemrb/ # GemRB submodule
│ └── patches/ # Engine patches
├── game/ # Runtime data (git-ignored)
│ ├── agent_state.json # Game state (bridge → Claude)
│ ├── agent_cmd.json # Commands (Claude → bridge)
│ ├── knowledge/ # Persistent game knowledge
│ ├── persona.md # Active character persona
│ └── GemRB.cfg # Engine configuration
├── .claude/ # Claude Code hooks and skills
│ ├── settings.json # Hook configuration
│ ├── game-epiphany/ # /game-epiphany skill (pre-edit reflection)
│ ├── game-note/ # /game-note skill
│ ├── game-recall/ # /game-recall skill
│ ├── game-log/ # /game-log skill
│ └── run-codex/ # /run-codex skill
├── CLAUDE.md # Agent instructions
└── README.md # This file
| Context | When |
|---|---|
gameplay_exploration |
Walking, interacting with the world |
gameplay_combat_paused |
Combat active, game paused for orders |
gameplay_combat_running |
Combat active, real-time flow |
gameplay_dialogue |
NPC conversation |
gameplay_container |
Looting a container |
gameplay_store |
Shopping at a store |
gameplay_inventory |
Inventory management |
gameplay_journal |
Reading the journal |
gameplay_spellbook |
Managing spells |
gameplay_character_record |
Character sheet |
gameplay_levelup |
Level-up screen |
gameplay_map |
Area map |
gameplay_resurrection |
TNO resurrecting after death |
An autonomous daemon that monitors the agent's evolving identity:
# Start the seismograph in a separate terminal
./scripts/psyche_seismograph.sh # watch persona.md
./scripts/psyche_seismograph.sh --all # watch persona.md + knowledge/
./scripts/psyche_seismograph.sh --commit # auto-commit each shift to gitThe seismograph uses inotifywait to detect writes to persona.md, computes a diff against the previous version, correlates with game state (location, context, last action), and logs each identity shift to game/psyche/psyche_shifts.log.
The /game-epiphany skill complements the seismograph: invoke it before editing persona.md to narrate why the agent's beliefs are changing. The seismograph captures what changed; the epiphany captures why.
Together they create an auditable trail of the agent's philosophical evolution — from first awakening in the Mortuary to whatever answer it gives Ravel.
Requires: inotify-tools, jq
MIT License. See LICENSE.
GemRB is licensed under the GPL v2. Planescape: Torment game data is proprietary (you must own a copy).