Skip to content

The gamemanager.toml descriptor

<project>/.forge/gamemanager.toml is the single descriptor for your project’s systems. The Game Manager tab reads it, the per-system editors mutate it, and the agent’s scaffold tool registers new systems into it. If you want to know what systems your project has, this is the file to read.

A freshly scaffolded Platformer bundle’s gamemanager.toml looks roughly like this:

schema = 1
id = "01923456-789a-7bcd-8def-0123456789ab"
createdAt = "2026-05-17T19:34:21Z"
updatedAt = "2026-05-17T19:41:08Z"
engine = "web-phaser"
language = "typescript"
startupOrder = [
"ProjectConfig",
"EventBus",
"ThemeManager",
"StateMachine",
"SaveSystem",
"AudioManager",
"InputManager",
"SettingsManager",
"CharacterController",
]
[systems.ProjectConfig]
templateVersion = "1.0.0"
sourcePath = "src/systems/project-config.ts"
dependsOn = []
[systems.ProjectConfig.config]
entries = [
{ key = "player.moveSpeed", type = "float", default = 220.0, range = { min = 0, max = 800 }, hint = "Walk velocity in px/s" },
# … the rest of the player feel constants
]
[systems.AudioManager]
templateVersion = "1.0.0"
sourcePath = "src/systems/audio-manager.ts"
dependsOn = ["EventBus"]
[systems.AudioManager.config]
voicePoolSize = 16
buses = [
{ name = "Master", defaultDb = 0 },
{ name = "Music", parent = "Master", defaultDb = -6 },
{ name = "SFX", parent = "Master", defaultDb = -3 },
{ name = "Dialog", parent = "Master", defaultDb = 0 },
]
duckingRules = [
{ whenBus = "Dialog", duck = [
{ bus = "Music", amountDb = -8, attackMs = 80, releaseMs = 250 },
{ bus = "SFX", amountDb = -6, attackMs = 80, releaseMs = 250 },
] }
]
FieldTypeWhat it does
schemaintFormat version. Currently 1. A future loader will refuse mismatches loudly rather than silently corrupting your file.
idstringUUIDv7 unique to this descriptor. Stable across renames.
createdAt / updatedAtISO-8601Timestamps. Forge bumps updatedAt on every mutation.
enginestringDetected engine: web-phaser / web-threejs / web-vanilla / godot / unity / generic. Determines which template variants the scaffold uses.
languagestringtypescript / gdscript / csharp. Picked by engine detection.
startupOrderstring arrayCanonical system names in initialization order. Validated as a topological sort of the per-system dependsOn graph before any source regen.
systemstableOne table per registered system, keyed by canonical name.
FieldTypeWhat it does
templateVersionstringSemver of the template that produced this system. Forge uses this to diff against the latest bundled template when you upgrade a system.
sourcePathstringProject-relative POSIX path to the canonical source file the spine instantiates.
dependsOnstring arrayNames of sibling systems this one depends on at startup. Validated as a DAG when reordering.
configinline tableSchema-validated config. Shape varies per system. Each system editor knows the expected shape and round-trips through here.

Each system’s config shape is documented on its own page: see AudioManager, EventBus, ProjectConfig, StateMachine, SaveSystem, InputManager, SettingsManager, CharacterController, and ThemeManager.

The descriptor is plain TOML. You can edit it by hand; the next time the Game Manager tab loads, the editors will round-trip your edits. Validation runs on save:

  • schema mismatch refuses to load (you’ll see an error banner in the Game Manager tab).
  • An unknown system in startupOrder is dropped silently with a warning in the developer console.
  • A cyclic dependsOn graph refuses to load and surfaces the cycle.
  • Invalid config (e.g. unknown bus parent in AudioManager) blocks the save and shows the validation error inline in the editor.

If you want to add a system the editors don’t know about yet, the file format is forward-compatible: extra fields in config are preserved across reads and writes.

Every system scaffold also writes <project>/.forge/scaffolds/<scaffold-id>.json. The sidecars record which files the scaffold touched, with SHAs, so Forge can run conflict detection if you later re-scaffold or upgrade the same system. See The Game Manager spine for what that flow looks like in practice.

You don’t normally edit sidecars. If you remove a system via the Game Manager tab, Forge deletes the sidecar and reverts the files (asking first if any have changed).

The descriptor is the source of truth. The system source files are derived from it: their config blocks (the AudioManager bus tree, the InputManager action map, etc.) are regenerated from config on save. If you edit a source file and then edit the descriptor, the descriptor wins for the config block; your other hand-edits are preserved.

If you don’t want this round-tripping, just don’t use the editor. Hand-edit the source file directly. The descriptor records the templateVersion and sourcePath, but it won’t fight you for code you wrote yourself.