Features are exports
A trait, a system and one line in src/main.ts. Kiln names everything after its export, so file layout never matters and errors name the thing you wrote.
A fixed-step loop, a Koota ECS and a Three.js render bridge, built so a coding agent can add a feature with a few exports and one scheduling line, then check it headlessly.
// src/systems.ts
/** Integrates Velocity into Transform. */
export const Movement = system([Mut(Transform), Velocity], ([t, v], { time }) => {
t.x += v.x * time.step
t.z += v.z * time.step
})
// src/main.ts
export default () =>
createApp(config)
.use(CorePlugins)
.add(Startup, SpawnLevel)
.add(Fixed, chain(PlayerMove, Movement, CollectCoins))kiln describe # the schedule: phases, systems, reads/writes/order
kiln test # headless scenario tests (bun test)
kiln run --steps 600 --snapshot Transform # the world as JSON after 10 simulated seconds
kiln shot out.png # one frame from headless Chromium
kiln docs # AGENTS.md from the code and its JSDoc