Filesystem layout
After install, everything
KATFORGE is under ~/.katforge/. Nothing scattered across ~/.local/bin, ~/.config/sops, or system-wide package managers.
~/.katforge/
├── bin/ PATH points here
│ ├── hearth symlink to ../.venv/bin/hearth
│ ├── sops
│ ├── age
│ ├── age-keygen
│ ├── kubectl
│ └── yq
├── .venv/ hearth's Python deps
├── age.txt your age private key (SOPS_AGE_KEY_FILE)
├── hearth/ the orchestrator (this repo)
│ ├── cli/ Python source for the `hearth` CLI
│ ├── env/<stage>/ per-stage env files (.yaml + .enc.yaml)
│ ├── compose.yaml dev stack
│ ├── k8s/ prod manifests
│ └── .sops.yaml who can decrypt
├── api.katforge.com/ PHP/Symfony API
├── katforge.com/ Marketing site (Nuxt)
├── geargoblins.com/ Gear Goblins
├── stumper.gg/ Stumper trivia
├── lextris.com/ Lextris
└── packages/
├── anvil/ ECS engine
├── codex/ Game data store
├── forge/ Game loop / Vue integration
├── katalyst/ Shared utilities
├── sdk/ Client SDK
├── spark/ Shared Vue component library
└── tactician/ AI / combat engine
~/Projects/katforge is symlinked to ~/.katforge so editor and terminal habits keep working.
What lives where
bin/
A self-contained PATH directory. The installer prepends it to your shell's PATH, so hearth, sops, kubectl, yq, and friends resolve without polluting ~/.local/bin or system directories.
The hearth entry is a symlink to the venv's console script — upgrades to the CLI don't require changing PATH again.
.venv/
Hearth is a Python CLI; the venv isolates its dependencies (typer, rich, etc.) from system Python.
age.txt
Your age private key. The shell rc block sets SOPS_AGE_KEY_FILE=$KATFORGE_ROOT/age.txt, which sops reads transparently — you never type the path.
If you lose this file, ask a maintainer to remove your public key from .sops.yaml and rotate any compromised secrets. See Secrets.
hearth/
The orchestrator repo (this one). Contains:
cli/— Python source for thehearthCLI itself.env/<stage>/— per-stage env files. Each stage has plaintext.yaml(URLs, ports, public flags) plus sops-encrypted.enc.yaml(secrets). Both are committed.compose.yaml— the dev compose stack (Postgres, API, pgAdmin, Mercure, Traefik, frontends).k8s/— production manifests applied byhearth ship..sops.yaml— the recipient list. Whose age public keys can decrypt which files.
Service repos
Top-level directories matching real domain names (api.katforge.com/, katforge.com/, stumper.gg/, etc.) are independent git repositories. Each one is a self-contained service with its own Dockerfile and CI.
The compose stack and k8s manifests reference them by relative path — ../api.katforge.com, etc. — so cloning into the canonical layout is what makes the stack build.
packages/
The @katforge/* workspace packages. These are also independent git repos but get hoisted into a single node_modules via the workspace bun install that runs as part of hearth up.
The ~/Projects/katforge symlink
Editors and terminals pick up project layouts in ~/Projects by habit. The installer creates ~/Projects/katforge as a symlink to ~/.katforge so:
cd ~/Projects/katforge/stumper.ggworks.- VS Code workspaces saved with that path keep working.
- Tab completion in shells trained on
~/Projectsstill finds everything.
Removing the symlink is harmless — ~/.katforge is the real location.