-
Notifications
You must be signed in to change notification settings - Fork 0
Headless CLI Design
Auto-generated from the repo docs by
tools/sync_wiki.sh— edit the source Markdown in the repo, not this wiki page.
📁 ARCHIVED NOTE — frozen 2026-08-08, not maintained. The original design note; it was built, and parts of the speculation below were superseded by the build. Current reference: Headless-CLI.md.
BUILT — see Headless-CLI.md for the real, current reference.
rebuild-model+cleanverified;build-modwired to the game's ownModuleEditor.BuildModification(full build+deploy, headless). This file is the original design/reasoning; the "build-mod needs discovery / build stays in the editor" speculation below was superseded once theMercury ▸ Mod Editorbuild method was found and called via reflection.
Status: designed, not built. The documentation work made HAF readable by AI (llms.txt, the Pages site). This is
the complement: a command-line surface that makes the editor's functions operable without the GUI — so an agent, a
script, or CI can author, validate, and bake content the same way a human does in Tools ▸ HAF, minus the clicking.
Unity + the ENCReload project are already a hard requirement to use the authoring tools. A batch-mode CLI therefore
adds no new requirement — it just drives the existing, GUI-free pipeline from the command line. The bake tests already
prove this works: BakeSmokeTest / BakeFeatureTest run the real ConfigFor → UniversalBaker path as static methods
with no window open. The CLI is the same invocation, parameterised.
| Capability | Needs Unity? | How |
|---|---|---|
| Edit data-only registries (resize, formations, era, sound overrides, retexture config) | No | plain JSON (pack.json, haf_*.json) — editable directly or by a standalone verb |
| Validate a pack (bones/paths/GUIDs/schema) | No (mostly) | the pack validator core — pure logic + file checks |
| Convert a model file (GLB/glTF/OBJ/FBX) | No |
glbconv.exe (already standalone) |
| Blender prep (rig/decimate/clip extract) | No | already headless (blender -b) |
Bake Skeleton / Atlas / ClipCollection / district FxMesh |
Yes | the Amplitude SDK is Unity-bound → Unity batch mode |
So: everything except baking the Amplitude assets can run with no Unity at all; baking runs headless in Unity batch mode. There is no way to bake Amplitude assets on a machine without Unity — that's the one hard limit, stated plainly.
Two different targets hide behind this:
-
The editor's own code — nothing to reverse-engineer; it's our code, already factored behind
ConfigFor → UniversalBakerand already called headless by the bake tests. The CLI just invokes it via batch mode. This is the pragmatic path, full-fidelity, no RE. -
The Amplitude asset format (to bake with zero Unity) — HAF already understands the data side deeply from
decompiling the runtime (Skeleton/ClipCollection buffers, bone TRS, pose data, atlas layout — see
Animated-Runtime.md). But the part that ties baking to Unity isn't the data — it's Unity's
serialization + asset-bundle envelope: emitting valid
.assetfiles with correct meta-GUIDs and packaging them into the loadable Resources/bundle the game reads. That envelope is what the SDK importers do; replicating it standalone is large, version-fragile, and duplicates working tooling for the sole benefit of removing a dependency the editor already requires. Not recommended — the payoff (no Unity) is exactly the requirement we've accepted as fine.
A single entry class HAF.Cli in the ENCReload editor assembly (where ConfigFor/UniversalBaker/the registries
live), invoked via:
Unity.exe -batchmode -quit -projectPath <ENCReload> -logFile - -executeMethod HAF.Cli.Run -- <request.json>
wrapped in a small haf shim (.bat / .sh) so callers don't hand-write the Unity path. -batchmode -quit means no
GUI and a clean exit; -logFile - streams to stdout.
Fast path (optional): pure-data verbs (validate, list, simple registry edits) touch only JSON and need no Unity —
they can be a standalone .exe (like glbconv) to avoid Unity's ~1-minute batch startup per call. Recommended split:
standalone for data/validate (instant), Unity batch mode for bake (necessarily slow). One requirement, two speeds.
Request in, structured result out — no interactive prompts (batch mode has no console input).
| Verb | Unity? | Does | Reuses |
|---|---|---|---|
list [--kind models|districts|formations|sounds] |
no | dump current registry entries as JSON | the registries |
validate <pack> |
no | pre-flight content check → {warnings, errors}
|
ValidateEntry (validator) |
bake <request.json> |
yes | bake one model/district/prop from a JSON bake request → produce assets + upsert registry |
ConfigFor → UniversalBaker
|
set-resize / set-formation / silence-sound … |
no | scripted data-only edits (thin wrappers over the registries) |
ModelRegistry etc. |
bake request = the JSON form of a BakeConfig (model file, pawn, size, shading, animated/clip, strip, etc.) — the
same fields the Factory/Animation Lab collect. Mapping through ConfigFor (the single shared config path the GUI and the
tests already use) means the CLI can't drift from the GUI's behaviour.
-
Structured output: every verb prints a single JSON object to stdout —
{ ok, produced: [...asset paths], registry: "...", warnings: [], errors: [] }. -
Exit codes:
0ok,2validation failed,3bake failed,4bad request — so a caller can branch without parsing prose. - No prompts, no partial state: validate-before-bake by default; registries are already corruption-guarded (an unparsable file is never overwritten) and git-backed, so an agent's mistake is recoverable.
- Deterministic: same request → same assets (the bake pipeline is already deterministic; see the golden regression tests).
A rebuilt model isn't in the game until the mod is built ("referencing ≠ rendering — it needs a Build for the MeshCollection"). So the CLI needs both, and they differ sharply in difficulty:
-
rebuild-model— ready. Reuses the exact GUI/BakeSmokeTestpath:ModelRegistry.Load()→ModelFactoryWindow.ConfigFor(def)→UniversalBaker.Build / BuildAnimated→ copy theBakeResultGUIDs back →ModelRegistry.Upsert. A batch-mode-executeMethod HAF.Cli.RebuildModelis a direct implementation. (Honor the def'sreuseExtracted/keepTexture so a rebuild doesn't clobber hand-edited extracted textures; offer-freshto force a re-slim.) -
build-mod— needs discovery. This is not HAF's code nor this project's editor DLLs (those are inspectors).Assets/Configurations/ModdingSettings.txtpoints at the Humankind Mod Tools (Steam app 1718880) — the mod build is the modding SDK's pipeline. Its programmatic/headless entry point is unknown: candidates are a build method inAmplitude.Framework.Editor.dll(decompile + test), a Unity-executeMethodtarget the SDK exposes, or a CLI the Mod Tools app itself provides. Open question for the author: how is the mod built today (which menu / button / tool)? That answer targets this verb directly instead of guessing.
-
Phase 1 (proof):
HAF.Cli.Bake— one-executeMethodcommand that bakes a single existing registry entry headless and prints the result JSON. Proves batch mode works in this project/Unity before building more. ~half a day. -
Phase 2: the standalone data/validate
.exe(list,validate,set-*) — no Unity, instant, pairs with the validator. -
Phase 3: the
hafshim + abake <request.json>that accepts arbitrary bake requests, plus docs + an example request. This is the point an agent (or CI) can author → validate → bake end-to-end.
- Not a way to bake without Unity — the SDK is Unity-bound (see the boundary table).
-
Schema surface: the
bakerequest and the data verbs are another consumer of the registry schema (theModelDef↔ModelEntryduplication that was deliberately left un-refactored). Route everything throughConfigForand the registry classes — don't hand-roll a third schema — and extendcheck_schema_parity.shto cover the request shape. -
Maintenance: a new surface to keep in step with the GUI. Mitigated by reusing
ConfigForand the registries rather than reimplementing. - Complements, doesn't replace, the editor windows (Editor-Tools.md) — the GUI stays the human path; the CLI is the scriptable/agent path to the same pipeline.
Get started
- Getting Started
- Installation
- Troubleshooting
- Authoring State and Deployment
- Mod Editor version.xml Recovery
- Building
- Backup
Author models and behavior
- Editor Tools
- Factory Manual
- Vehicle Lab Quickstart
- Animated Models
- Animation Pitfalls
- Textures
- Unit Size
- Unit Combat Behavior
- Formations
- Pawn Props
- Projectiles
- Game Sound Lab
- Firing on Attack
- Turn Ease
- Facing Persistence
- Donor Clip Flight
Districts and wonders
Ship and operate
Internals and project