|
| 1 | +# Testing the Software Factory Locally |
| 2 | + |
| 3 | +This guide walks through running the software factory on your own |
| 4 | +machine, two ways: |
| 5 | + |
| 6 | +1. **Scripted** — the Node orchestrator (`pnpm factory:go`), which |
| 7 | + drives the loop itself using Claude's and opencode's SDKs. |
| 8 | +2. **Umbrella skill** — an interactive Claude Code session that runs |
| 9 | + the whole loop by following `docs/runbook.md`; there is no |
| 10 | + orchestrator process, the agent drives every step. |
| 11 | + |
| 12 | +Pick whichever you want to exercise — the prerequisites are shared. |
| 13 | + |
| 14 | +## Prerequisites |
| 15 | + |
| 16 | +### 1. Download the latest Boxel CLI |
| 17 | + |
| 18 | +The factory and the interactive flow both shell out to the published |
| 19 | +`@cardstack/boxel-cli`. Install (or upgrade) it globally: |
| 20 | + |
| 21 | +```bash |
| 22 | +pnpm i -g @cardstack/boxel-cli@latest |
| 23 | +boxel --version |
| 24 | +``` |
| 25 | + |
| 26 | +`boxel --help` should list `lint`, `parse`, `test`, `realm`, and |
| 27 | +`profile` among the subcommands. If any are missing, you're on an old |
| 28 | +build — re-run the install above. |
| 29 | + |
| 30 | +### 2. Make sure a Boxel profile is selected |
| 31 | + |
| 32 | +Auth comes from the **active** Boxel profile. List your profiles and |
| 33 | +confirm one is marked active: |
| 34 | + |
| 35 | +```bash |
| 36 | +boxel profile list |
| 37 | +``` |
| 38 | + |
| 39 | +If none is active (or the active one points at the wrong realm |
| 40 | +server), add or switch to the right one: |
| 41 | + |
| 42 | +```bash |
| 43 | +# First time — interactive wizard (environment + credentials) |
| 44 | +boxel profile add |
| 45 | + |
| 46 | +# Already have profiles — switch the active one |
| 47 | +boxel profile switch <profile-id> |
| 48 | +``` |
| 49 | + |
| 50 | +Concrete example: |
| 51 | + |
| 52 | +```bash |
| 53 | +boxel profile switch localhost |
| 54 | +``` |
| 55 | + |
| 56 | +### 3. Check out the boxel repo and navigate to the software factory |
| 57 | + |
| 58 | +```bash |
| 59 | +git clone https://github.com/cardstack/boxel.git |
| 60 | +cd boxel/packages/software-factory |
| 61 | +``` |
| 62 | + |
| 63 | +If you already have the repo, just: |
| 64 | + |
| 65 | +```bash |
| 66 | +cd <path-to>/boxel/packages/software-factory |
| 67 | +``` |
| 68 | + |
| 69 | +The realm server at the URL you target must be reachable. If you're |
| 70 | +publishing to **staging or prod**, it's already running — you just |
| 71 | +need a profile whose credentials point at it (see step 2). If you're |
| 72 | +working **locally**, start it yourself with `mise run dev-all` from |
| 73 | +the monorepo root (starts realm server, host app, icons server, |
| 74 | +Postgres, Synapse). |
| 75 | + |
| 76 | +--- |
| 77 | + |
| 78 | +## Section 1 — Running the scripted software factory |
| 79 | + |
| 80 | +This is the Node orchestrator. It owns the loop: it picks the next |
| 81 | +unblocked issue, hands it to the agent (Claude's Agent SDK by default, |
| 82 | +opencode for the OpenRouter backend), runs the validation pipeline, |
| 83 | +and repeats. You run one command and watch it go. |
| 84 | + |
| 85 | +**Generic command:** |
| 86 | + |
| 87 | +```bash |
| 88 | +pnpm factory:go \ |
| 89 | + --brief-url <BRIEF_URL> \ |
| 90 | + --target-realm <TARGET_REALM_URL> \ |
| 91 | + --enable-boxel-ui-discovery \ |
| 92 | + --debug |
| 93 | +``` |
| 94 | + |
| 95 | +- `--brief-url` — the source brief card describing what to build. |
| 96 | +- `--target-realm` — the realm the factory creates and writes to |
| 97 | + (trailing slash, URL form). |
| 98 | +- `--enable-boxel-ui-discovery` — let the agent discover and reuse |
| 99 | + existing boxel-ui components. |
| 100 | +- `--debug` — verbose logs: LLM prompts, tool calls + results, and |
| 101 | + QUnit `console.log` output as tests run. |
| 102 | + |
| 103 | +> **Testing discovery?** `--enable-boxel-ui-discovery` is not on |
| 104 | +> `main` yet — it lives on the |
| 105 | +> `cs-10527-component-specs-for-searchable-reusable-ui-components` |
| 106 | +> branch (CS-10527). Check that branch out before running with the |
| 107 | +> flag, otherwise `factory:go` rejects it as an unknown argument: |
| 108 | +> |
| 109 | +> ```bash |
| 110 | +> git checkout cs-10527-component-specs-for-searchable-reusable-ui-components |
| 111 | +> ``` |
| 112 | +
|
| 113 | +**Concrete example (local):** |
| 114 | +
|
| 115 | +```bash |
| 116 | +pnpm factory:go \ |
| 117 | + --brief-url https://localhost:4201/software-factory/Wiki/sticky-note \ |
| 118 | + --target-realm https://localhost:4201/user/sticky-note/ \ |
| 119 | + --enable-boxel-ui-discovery \ |
| 120 | + --debug |
| 121 | +``` |
| 122 | +
|
| 123 | +**Concrete example (staging):** |
| 124 | + |
| 125 | +Switch to a staging profile first (`boxel profile switch <staging-id>`), |
| 126 | +then point both URLs at `realms-staging.stack.cards`: |
| 127 | + |
| 128 | +```bash |
| 129 | +pnpm factory:go \ |
| 130 | + --brief-url https://realms-staging.stack.cards/software-factory/Wiki/sticky-note \ |
| 131 | + --target-realm https://realms-staging.stack.cards/<your-username>/sticky-note/ \ |
| 132 | + --enable-boxel-ui-discovery \ |
| 133 | + --debug |
| 134 | +``` |
| 135 | + |
| 136 | +A successful run logs the seed issue, then each outer cycle as the |
| 137 | +agent bootstraps the project and works through the implementation |
| 138 | +issues, finishing with `outcome=all_issues_done`. See the README's |
| 139 | +["What to expect on the command line"](../README.md) section for the |
| 140 | +full log shape and the resulting target-realm artifact tree. |
| 141 | + |
| 142 | +**See the result:** open the Boxel host app and navigate to the |
| 143 | +target realm to browse the generated Project, Issues, card |
| 144 | +definitions, instances, and Spec. |
| 145 | + |
| 146 | +- Local: `https://localhost:4200/user/sticky-note/` |
| 147 | +- Staging: `https://boxel-host-staging.stack.cards/<your-username>/sticky-note/` |
| 148 | + |
| 149 | +--- |
| 150 | + |
| 151 | +## Section 2 — Running the factory using the umbrella skill (`runbook.md`) |
| 152 | + |
| 153 | +Here there is **no** orchestrator process. You open an interactive |
| 154 | +Claude Code session from `packages/software-factory/` (so the |
| 155 | +`.claude/skills` symlink is discovered) and give it one instruction; |
| 156 | +the agent follows `docs/runbook.md` end-to-end — bootstrap, per-issue |
| 157 | +implementation, validators, and project completion — in a single loop. |
| 158 | + |
| 159 | +Open the agent and paste the instruction. |
| 160 | + |
| 161 | +**Generic prompt:** |
| 162 | + |
| 163 | +``` |
| 164 | +Run the software factory per docs/runbook.md. |
| 165 | +Brief: <BRIEF_URL> |
| 166 | +Target realm: <TARGET_REALM_URL> |
| 167 | +``` |
| 168 | + |
| 169 | +**Concrete example (local):** |
| 170 | + |
| 171 | +``` |
| 172 | +Run the software factory per docs/runbook.md. |
| 173 | +Brief: https://localhost:4201/software-factory/Wiki/sticky-note |
| 174 | +Target realm: https://localhost:4201/user/sticky-note/ |
| 175 | +``` |
| 176 | + |
| 177 | +**Concrete example (staging):** |
| 178 | + |
| 179 | +With a staging profile selected, point both URLs at |
| 180 | +`realms-staging.stack.cards`: |
| 181 | + |
| 182 | +``` |
| 183 | +Run the software factory per docs/runbook.md. |
| 184 | +Brief: https://realms-staging.stack.cards/software-factory/Wiki/sticky-note |
| 185 | +Target realm: https://realms-staging.stack.cards/<your-username>/sticky-note/ |
| 186 | +``` |
| 187 | + |
| 188 | +> Always include "per docs/runbook.md". Without it, the agent falls |
| 189 | +> back to the SDK-orchestrator path described in this package's |
| 190 | +> `CLAUDE.md` instead of driving the loop itself. |
| 191 | +
|
| 192 | +**See the result:** when the run finishes, open the Boxel host app |
| 193 | +and navigate to the target realm to browse the generated Project, |
| 194 | +Issues, card definitions, instances, and Spec. |
| 195 | + |
| 196 | +- Local: `https://localhost:4200/user/sticky-note/` |
| 197 | +- Staging: `https://boxel-host-staging.stack.cards/<your-username>/sticky-note/` |
| 198 | + |
| 199 | +This is an example of what you should be seeing when you visit the newly created realm: |
| 200 | + |
| 201 | +<img width="1889" height="1176" alt="image" src="https://github.com/user-attachments/assets/0ab22084-94a8-421b-831a-e6f54ec083bb" /> |
| 202 | + |
| 203 | +If you click on Issue Board, you will see that the software factory marked all the tickets as "Done": |
| 204 | + |
| 205 | +<img width="1457" height="957" alt="image" src="https://github.com/user-attachments/assets/92fbbafa-3478-43aa-a93b-48bde4d9ea65" /> |
| 206 | + |
| 207 | + |
| 208 | +For the full breakdown of every step the agent performs, what it |
| 209 | +invokes, and the expected output, see [docs/runbook.md](./runbook.md). |
0 commit comments