Skip to main content

Farmslot monorepo example

Farmslot dogfoods on itself: this repository is both the framework and a first-party project (farmslot-farm). The example shows how pool slots, project hooks, prepare profiles, and optional worktrees fit together in practice — without a separate "companion farm" or parallel naming scheme.

What you are modeling

LayerFile / conceptRole
Poolpool/<machine>.jsonMachines, slots, ports, optional simulators, tmux sessions
Projectprojects/farmslot-farm/project.jsonHooks, prepare profiles, fixtures, recipe wiring for Command Center + Companion
OperatorMain clone or worktree checkoutWhere agents edit code; each slot points at one checkout

Unified slot rule

All first-party slots share one pattern:

  • Worktree path: farmslot-{n} (e.g. farmslot-1, farmslot-2) — not farmslot-companion-*
  • Platform: cli (gateway is the default stack)
  • Companion / simulator: optional resources.ios-sim; booted only when a prepare profile needs mobile proof
  • Cross-surface tickets: one slot, sandbox-companion — gateway + Metro + sim on demand

Companion is a surface (prepare profile + validation step), not a separate pool farm.

Local demo (fastest path)

The committed demo pool is pool/farmslot-demo.json. Installed gateways hide it by default (fresh installs only see their own machine's slots; set FARMSLOT_DEMO_POOL=1 to load it) — scripts/dev.sh keeps it visible:

bash scripts/dev.sh

Open http://localhost:7777. Slot demo-ff-1 uses project: farmslot-farm, platform: cli, and the repo root as its checkout. This is enough to explore Command Center, dispatch preview, and the scripted-runner validation path described in Local demo and CLI.

The same pool file also documents demo-ff-2 — disabled by default — with optional ios-sim and a second gateway port. Enable it when you want to practice companion-warm or sandbox-companion locally without a private machine pool:

{
"id": "demo-ff-2",
"enabled": false,
"platform": "cli",
"resources": {
"dev-server": { "port": 7779, "cdp_port": 9325 },
"ios-sim": { "simulator": "fs-demo-2", "headless": true }
}
}

Isolated worktree (how real slots work)

Production-style slots point each agent at its own checkout and port block:

{
"id": "workstation-ff-2",
"project": "farmslot-farm",
"platform": "cli",
"repo": "~/dev/farmslot-wt/farmslot-2",
"session": "ff-2",
"resources": {
"dev-server": { "port": 8809, "cdp_port": 9324 },
"ios-sim": { "simulator": "fs-2", "headless": true }
}
}
FieldMeaning
platform: cliDefault prepare is gateway-only (sandbox)
dev-server.portThis checkout's gateway WebSocket/HTTP port
ios-simOptional; idle until companion-warm, companion-full, or sandbox-companion
cdp_portCommand Center recipe / CDP probes for this slot (when configured)

Simulator names align with slot index (fs-2 for farmslot-2), not a parallel companion namespace.

Prepare profiles on farmslot-farm

Defined in projects/farmslot-farm/project.json under prepare.profiles:

ProfileWhen to useWhat boots
sandboxGateway / Command Center workGateway on slot port
attachGateway already runningHealth check only
typecheckStatic verification, no gateway lifecycleTypecheck hooks
companion-warmMobile-only proofMetro + dev client (+ sim when configured)
companion-fullNative drift / cold companion buildNative rebuild then warm
sandbox-companionOne ticket spans CC + CompanionGateway, then companion warm on same checkout

CLI examples (replace slot id with yours):

farmslot slot prepare workstation-ff-2 --prepare-profile sandbox
farmslot slot prepare workstation-ff-2 --prepare-profile sandbox-companion
farmslot slot prepare workstation-ff-2 --prepare-profile companion-warm

See Prepare lifecycle for phase ordering and fallbacks.

Dispatch fit for multi-surface work

When ticket metadata mentions Command Center and Companion, the gateway profile-fit suggestion should prefer sandbox-companion on the dispatch slot — validation steps for CDP, gateway RPC, and companion recipe all target that slot.

Operator override always wins: if you already set prepareProfile, the gate does not replace it.

Two improvement paths while building Farmslot

PathUse whenRecordProve
Agent-directFramework bug; repro is a unit test or local commandGitHub issue (dogfood label)PR + yarn typecheck + targeted tests
Run-mediatedNeeds slot, worker, recipe, device, or publication gateIssue + run.createRecipe artifacts + gate invariants

While the framework is still moving quickly, framework fixes usually land via agent-direct work on an isolated worktree branch. Product dogfood (demo banners, cross-surface evidence) uses run-mediated dispatch on a configured slot once stabilization checklist items are green.

Recipe and evidence

First-party recipes live under docs/examples/recipes/farmslot/. Task runs invoke:

bash projects/farmslot-farm/setup/validate-recipe.sh \
--recipe <path-to-recipe.json> \
--artifacts-dir <task>/artifacts/recipe-run \
--gateway-port <slot-port> \
--slot-id <slot-id>

Companion iOS proof adds --platform ios, --simulator <name>, and Metro derived from the gateway port (typically gateway + 70).