Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
"The context IS the world as seen from inside the closure."
— Dave Ungar, on lexical scope
What Is It?
The world object is passed to every compiled closure. It provides:
Standard keys — Always present (adventure, player, room, turn)
Extended keys — Contextual (object, target, npc)
Skill namespaces — Skills register state under world.skills.skill_name
Utility functions — API for interacting with the world
Why "world" not "ctx"?
More evocative — closures see the WORLD
Self-documenting — world.player, world.room
Matches the mental model
Standard Keys
Always present in every world:
world.turn// Current simulation turn
world.timestamp// ISO timestamp
world.adventure// Root adventure state
.name
.flags// Global boolean flags
.world_state// Global key/value state
world.player// Current player
.id
.name
.location// Path to current room
.inventory// Array of item ids
.buffs// Active buffs
world.room// Current room
.id
.name
.path
.exits
.objects
.is_dark
.is_dangerous
world.party// Party state
.members
.leader
Extended Keys
Present when relevant:
// When running object simulate/methods:
world.object// The object being simulated
.id
.state// Object's mutable state// Methods are bound: world.consume_fuel(1)// When action targets something:
world.target// The target
.id
.type// "object", "character", "room"// When NPC is simulating:
world.npc// The NPC
.id
.goals
.state
Skill State Namespaces
Skills register state under world.skills.<skill_name> using underscores:
guard:"player has the key AND room is not dark"guard_js:(world)=>world.has("brass-key")&&!world.room.is_dark
Example: Score Calculation
score_if:"player is tired OR room is dark"score_if_js:(world)=>world.has_buff("tired")||world.room.is_dark
Example: Skill State
# Skill "economy" needs to check goldguard:"player has at least 10 gold"guard_js:(world)=>world.skills.economy.gold>=10# Skill "pie-menu" checks last selectionscore_if:"last pie menu selection was north"score_if_js:(world)=>world.skills.pie_menu.last_selection==="north"
Design Principles
Structured, Not Arbitrary
world is NOT just a bag of key/values. It has defined structure:
Standard keys are always present
Extended keys appear in context
Skills namespace their state (with underscores!)
Functions are bound methods
Skill Namespaces (Underscores!)
Skills don't pollute root world. They register under world.skills.skill_name:
CRITICAL: We always generate BOTH _js AND _py versions of compiled expressions.
# Natural languageguard:"player has the key AND room is not dark"# BOTH generated:guard_js:(world)=>world.has("brass-key")&&!world.room.is_darkguard_py: lambda world:world.has("brass-key")andnotworld.room.is_dark
Why Dual Runtimes?
Runtime
Purpose
Python
Server-side simulation, testing, LLM tethering
JavaScript
Browser runtime, standalone play
Keeping Them In Sync
Same semantics — Both should produce identical results
Same world structure — world.player, world.room, etc.
Same utility functions — world.has(), world.emit(), etc.
Generated together — LLM produces both in one pass
The Compilation Event
-event:COMPILE_EXPRESSIONfield:guardsource:"player has the key"targets:-field:guard_jslanguage:javascript-field:guard_pylanguage:pythonexpected_type:boolean
Python Runtime Class
classWorld:
"""Python runtime context — mirrors JavaScript World class."""def__init__(self, adventure_data):
self.turn = 0self.adventure = adventure_data
self.player = adventure_data['player']
self.room = None# Set on navigationself.party = adventure_data['party']
self.object = None# Set during object simulationself.skills = {} # Skill state namespacesdefhas(self, item_id: str) -> bool:
return item_id inself.player.get('inventory', [])
defflag(self, name: str) -> bool:
returnself.adventure.get('flags', {}).get(name, False)
defemit(self, message: str):
print(message) # Or queue for outputdeftrigger_event(self, name: str, data=None):
# Event system handles thispass
JavaScript Runtime Class
classWorld {
/** JavaScript runtime context — mirrors Python World class. */constructor(adventureData) {
this.turn = 0;
this.adventure = adventureData;
this.player = adventureData.player;
this.room = null; // Set on navigationthis.party = adventureData.party;
this.object = null; // Set during object simulationthis.skills = {}; // Skill state namespaces
}
has(itemId) {
return (this.player.inventory || []).includes(itemId);
}
flag(name) {
return (this.adventure.flags || {})[name] || false;
}
emit(message) {
console.log(message); // Or queue for UI
}
triggerEvent(name, data) {
// Event system handles this
}
}
Protocol Symbol
RUNTIME-CONTEXT — The world passed to closures (Python + JavaScript)