Home CLI & Developer Guide

CLI & Developer Guide


1. Binaries

Binary Package Default port Purpose
flatland3 tools/flatland Account / agent CLI (auth, character, inventory --json) — not the play client
flatland3-gfx tools/flatland-gfx Only maintained play client — Macroquad + egui (make dev-play-gfx)
flatland-gateway tools/gateway TCP 7373 Player TCP front door → worker wire
flatland-worker tools/worker Wire 7391 Region sim (30 Hz) for one shard
flatland-control-plane tools/control-plane HTTP 7380 Accounts, sessions, API tokens
flatland-server tools/server TCP 7373 Legacy combined launcher (prefer gateway+worker)
flatland-admin tools/flatland-admin World content admin + schema discovery
flatland-bot tools/bot-harness Headless load / movement harness
flatland-dev tools/flatland-dev Retired — was embedded TUI play; use gfx + dev gateway

Build from repo root:

cargo build --workspace

2. Environment variables

Variable Used by Default Purpose
DATABASE_URL control-plane Postgres connection string
REDIS_URL control-plane Redis (sessions, login rate limit)
FLATLAND_HTTP_ADDR control-plane 127.0.0.1:7380 HTTP listen address
FLATLAND_API_URL flatland auth http://127.0.0.1:7380 Control plane base URL
FLATLAND_CONTROL_PLANE_URL gateway, worker Control plane for game auth / mint
FLATLAND_WORKER_ADDR gateway Worker wire address (127.0.0.1:7391)
FLATLAND_WORKER_LISTEN worker 127.0.0.1:7391 Worker wire bind
FLATLAND_GATEWAY_LISTEN gateway 127.0.0.1:7373 Player TCP bind
FLATLAND_REGION_ID worker r1 Region routing key
FLATLAND_ALLOW_DEV_LOCAL gateway 1 Allow DevLocal Hello without account
FLATLAND_STARTER_SEGMENT control-plane repo default Spawn point for new characters
RUST_LOG all varies tracing filter (info, debug, …)

Session file (after flatland auth login):

~/.config/flatland/session.json

{
  "api_base": "http://127.0.0.1:7380",
  "session_token": "flat_sess_…"
}

3. Local stack quickstart

cp .env.example .env
make db-up
cargo run -p flatland-control-plane-bin    # terminal 1 — HTTP :7380
cargo run -p flatland-gateway              # terminal 2 — game TCP :7373
cargo run -p flatland-worker               # terminal 3 — region sim
make dev-play-gfx NAME=YourCharacter       # terminal 4 — play (gfx)

Health check:

curl -s http://127.0.0.1:7380/v1/health | jq

4. flatland CLI

4.1 Capabilities overview

Mode Command Status
Play flatland3-gfx / make dev-play-gfx Only maintained play client
Character flatland3 character create/list ✅ Explicit create; names unique per account
Play (TUI) flatland3 (default) Retired — no new work
Play local flatland-dev --bots N Retired — use make dev-restart + make dev-play-gfx
Auth register flatland3 auth register ✅ Create account + auto-login
Auth login flatland3 auth login ✅ Email/password → session file
API tokens flatland3 auth token create/list/revoke ✅ Agent automation tokens
Capabilities flatland3 capabilities ✅ Print this reference in terminal
JSON output flatland3 --json ✅ Subcommands that support it

Run flatland3 --help, flatland3 auth --help, or flatland3 capabilities for built-in help.

4.2 Auth → character → play

flatland3 auth login --email you@example.com --password '…'
flatland3 character create MadSin          # once; session auth only
flatland3 character list
make dev-play-gfx NAME=MadSin              # play (gfx client)

Names: 1–32 chars; start with a letter; only A–Z, 0–9, _, -. No spaces or :.
Play uses flatland3-gfx — not the flatland3 default command (TUI play retired).

4.3 Play

# Dev stack (recommended)
make dev-restart
make dev-control-plane   # terminal 1
make dev-worker          # terminal 2
make dev-gateway         # terminal 3
make dev-play-gfx NAME=MadSin

# Or run gfx directly against gateway
flatland3-gfx --name MadSin --server 127.0.0.1:7373

Controls: WASD move, f use world, 1–9 hotbar, c dodge, q block, Space stop, Ctrl+Q quit. In-game ? for keybinds.

4.3 Auth

# Register (logs in automatically; use --no-login to skip)
flatland auth register --email you@example.com --password 'your-password' --name You

# Login only (saves session to ~/.config/flatland/session.json)
flatland auth login --email you@example.com --password 'your-password'

# Override control plane URL
flatland auth login --email you@example.com --password '…' --api http://127.0.0.1:7380

4.4 API tokens (agents / CI / LLM)

Requires login session. Token plaintext is shown once at creation.

flatland auth token create --name "ci-bot" --scope play,read
flatland auth token create --name "read-only" --scope read
flatland auth token list
flatland auth token revoke <token-uuid>

Scopes (v1):

Scope HTTP Game (planned)
read GET /v1/me, character reads
write Account mutations (future)
play Connect game TCP with token
write PUT/DELETE /v1/admin/* World content mutations

Prefixes: flat_live_ (production), flat_test_ (with --test on create).

Agent env convention:

export FLATLAND_API_TOKEN=flat_live_…
export FLATLAND_API_URL=http://127.0.0.1:7380

5. Control plane HTTP API (v1 shipped)

Base: http://127.0.0.1:7380/v1

All responses use the agent envelope:

{ "ok": true, "data": { }, "error": null }

Errors: { "ok": false, "data": null, "error": { "code", "message", "details" } }

5.1 Health

Method Path Auth
GET /health, /v1/health none

Returns database and redis status.

5.2 Auth & account (shipped)

Method Path Auth Body / notes
POST /v1/auth/register none { email, password, display_name }
POST /v1/auth/login none { email, password }session_token
POST /v1/auth/logout session Authorization: Bearer flat_sess_…
GET /v1/me session or token (read) Account profile

Password rules: argon2id hash; minimum 8 characters.
Sessions: Redis, 24 h TTL, sliding on use. Prefix flat_sess_.
Login rate limit: 5 failures / 15 min per email+IP; 20 / IP.

5.3 API tokens (shipped)

Method Path Auth Body / notes
POST /v1/me/tokens session only { label, scopes[], expires_at?, test? }token once
GET /v1/me/tokens session only List metadata (prefix, label, scopes)
DELETE /v1/me/tokens/{id} session only Revoke

5.4 Characters & game (shipped)

Method Path Auth
GET /v1/characters session / token read
POST /v1/characters session
POST /v1/game/validate-connect body { auth, character_id? } (game server)
POST /v1/game/checkpoint body { auth, character_id, position_* }

5.5 World admin (shipped)

Method Path Auth
GET /v1/admin/segments session / token read
GET/PUT/DELETE /v1/admin/segments/{id} read / write
GET/PUT/DELETE /v1/admin/item-templates/{id} read / write
GET/PUT/DELETE /v1/admin/building-schematics/{id} read / write
GET/POST /v1/admin/world-objects read / write
GET/PATCH/DELETE /v1/admin/world-objects/{id} read / write

See 21 world content schemas and flatland-admin capabilities.

5.6 curl examples

# Register
curl -s -X POST http://127.0.0.1:7380/v1/auth/register \
  -H 'content-type: application/json' \
  -d '{"email":"you@example.com","password":"hunter2isok","display_name":"You"}' | jq

# Login
TOKEN=$(curl -s -X POST http://127.0.0.1:7380/v1/auth/login \
  -H 'content-type: application/json' \
  -d '{"email":"you@example.com","password":"hunter2isok"}' | jq -r '.data.session_token')

# Me (session)
curl -s http://127.0.0.1:7380/v1/me -H "Authorization: Bearer $TOKEN" | jq

# Create API token
API=$(curl -s -X POST http://127.0.0.1:7380/v1/me/tokens \
  -H "Authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{"label":"ci-bot","scopes":["play","read"]}' | jq -r '.data.token')

# Me (API token with read scope)
curl -s http://127.0.0.1:7380/v1/me -H "Authorization: Bearer $API" | jq

6. Game server (flatland-server)

TCP postcard protocol on :7373. Authenticated play validates Hello via control plane when FLATLAND_CONTROL_PLANE_URL is set.

export FLATLAND_CONTROL_PLANE_URL=http://127.0.0.1:7380
cargo run -p flatland-server
flatland auth login --email you@example.com --password '…'
cargo run -p flatland

Solo dev without accounts: flatland --local.


7. flatland-admin CLI

Agent-friendly world content management. All subcommands support --json.

flatland-admin capabilities
flatland-admin schema list
flatland-admin schema show segment
flatland-admin segment validate assets/world/segments/starter-plains.yaml
flatland-admin segment upsert --file assets/world/segments/starter-plains.yaml

Auth: FLATLAND_API_TOKEN (write scope), session file from flatland auth login, or FLATLAND_SESSION_TOKEN.


8. Postgres deployment

Environment Approach
Local docker compose up -d (see repo docker-compose.yml)
Hosted Neon, Supabase, Railway — set DATABASE_URL only
CI tests DATABASE_URL + REDIS_URL service containers

Migrations live in migrations/; applied automatically on control-plane startup.


9. Makefile targets

make db-up          # start Postgres + Redis
make db-down        # stop containers
make db-logs        # follow container logs
make control-plane  # run flatland-control-plane
make build          # cargo build --workspace
make test           # cargo test --workspace

Update this doc when new CLI subcommands or HTTP routes ship.