guide

Runek for agents

The fast path for a coding agent: find components, install them, write a world as JSON, check it, and preview it.

⌖ Explore the library in 3D → · View as Markdown

Runek is built to be driven by coding agents as much as by people. A world is JSON, every prop is described by a published schema, and the CLI checks your work and prints errors you can act on. This page is the short version of everything else in these docs.

1. Discover

npx @runek/cli list --json        # the catalog: name, title, category, description
npx @runek/cli info bench         # one component: props, types, defaults, deps, an example
npx @runek/cli info bench --json  # the same, as JSON

2. Install

npx @runek/cli init                         # once: writes runek.config.json, creates src/runek/
npx @runek/cli add player terrain bench sky # copies source into src/runek/, installs npm deps

add resolves everything a component needs (other components as source, npm packages including @runek/core). Pass --no-install to print the install command instead of running it. The copied files are yours to edit.

3. Compose a world

Write the world as data. Start the file with $schema so editors (and you) get validation and completion:

{
  "$schema": "https://runek.nullorder.org/r/world.schema.json",
  "version": 1,
  "time": "17:30",
  "nodes": [
    { "type": "Sky" },
    { "type": "LightRig" },
    { "type": "Terrain", "props": { "size": [80, 80], "seed": 3 } },
    { "type": "Bench", "anchor": "ground", "props": { "position": [2, 0, -4], "rotation": [0, 1.57, 0] } },
    { "type": "Player", "props": { "position": [0, 2, 6] } }
  ]
}

Render it with WorldRenderer and a registry map of the components you added (keys are the node types):

import { type ComponentRegistry, parseWorld, WorldRenderer } from '@runek/core'
import { Bench } from './runek/Bench'
import { LightRig } from './runek/LightRig'
import { Player } from './runek/Player'
import { Sky } from './runek/Sky'
import { Terrain } from './runek/Terrain'
import worldJson from './world.json'

const registry: ComponentRegistry = { Bench, LightRig, Player, Sky, Terrain }
const world = parseWorld(JSON.stringify(worldJson))

export const App = () => <WorldRenderer data={world} registry={registry} />

Or skip the JSON and write the same world as JSX inside <World> (see Getting started). Both are equivalent; JSON is easier to generate, diff, and check.

4. Check

npx @runek/cli validate world.json         # unknown types, unknown props, wrong value types, with "did you mean"
npx @runek/cli check-world world.json      # things buried in or floating above the ground
npx @runek/cli check-world world.json --fix  # write the suggested heights back into the file

Both take --json for structured output and --strict to exit non-zero (for CI). Fix what validate reports before you look at the scene: a misspelled prop renders silently with its default.

5. Preview

npx @runek/cli preview world.json

prints a link to the workshop with your world loaded: walk it, tune props in the inspector, and copy the edited JSON back. Nothing is uploaded; the world travels in the link itself.

Conventions

Common mistakes

MistakeFix
{ "type": "bench" }{ "type": "Bench" }: the PascalCase title.
{ "type": "Bench", "position": [0, 0, 0] }Put it under props: { "type": "Bench", "props": { "position": [0, 0, 0] } }.
"rotation": [0, 90, 0]Radians: [0, 1.5708, 0].
Props float or sink on hilly terrainAdd "anchor": "ground" and set position[1] to 0, or run check-world --fix.
A component renders but isn’t in your appIt needs npx @runek/cli add <name> and an entry in your registry map.
No "version": 1Every world file starts with it.

The agent skill

The same workflow, condensed into a skill file your coding agent loads on its own when you work with Runek:

npx @runek/cli skill                          # writes .claude/skills/runek/SKILL.md
npx @runek/cli skill --out path/to/SKILL.md   # anywhere else your agent reads skills from

The source is served at /r/agents/SKILL.md.