The dev CLI's self-host instance is meant to be persistent (it lives until down), but up wiped the data dir on every boot, so a connected MCP client's dynamic OAuth registration died on each restart and the client then failed with invalid_client until it re-registered. Make up persist the data dir by default and add --fresh to opt into a clean slate. The vitest globalsetup is unaffected: it calls bootSelfhost directly with fresh defaulted on, so suite runs stay hermetic.
Unified · Split
| @@ -1,6 +1,6 @@ | |||
| 1 | // The e2e dev CLI: the same primitives scenarios use, interactive. | 1 | // The e2e dev CLI: the same primitives scenarios use, interactive. |
| 2 | // | 2 | // |
| 3 | // bun scripts/cli.ts up selfhost [--share] [--keep-data] | 3 | // bun scripts/cli.ts up selfhost [--share] [--fresh] |
| 4 | // bun scripts/cli.ts up cloud [--share] | 4 | // bun scripts/cli.ts up cloud [--share] |
| 5 | // bun scripts/cli.ts status | 5 | // bun scripts/cli.ts status |
| 6 | // bun scripts/cli.ts identity <target> [--no-org] | 6 | // bun scripts/cli.ts identity <target> [--no-org] |
| @@ -204,7 +204,12 @@ const run = async (target: "selfhost" | "cloud", flags: ReadonlySet<string>) => · 197 unmodified lines | |||
| 204 | webBaseUrl: baseUrl, | 204 | webBaseUrl: baseUrl, |
| 205 | admin, | 205 | admin, |
| 206 | host: share ? "0.0.0.0" : undefined, | 206 | host: share ? "0.0.0.0" : undefined, |
| 207 | fresh: !flags.has("--keep-data"), | 207 | // A dev-CLI instance is persistent by design (see selfhost.boot.ts): its |
| 208 | // data dir, including registered MCP OAuth clients, survives a restart so | ||
| 209 | // a connected client does not have to re-register every bounce. Opt into a | ||
| 210 | // clean slate with --fresh; the vitest globalsetup stays hermetic on its | ||
| 211 | // own (it calls bootSelfhost with fresh defaulted on). | ||
| 212 | fresh: flags.has("--fresh"), | ||
| 208 | logFile, | 213 | logFile, |
| 209 | }); | 214 | }); |
| 210 | teardown = async () => { | 215 | teardown = async () => { |
| @@ -500,9 +505,11 @@ const logs = (targetName: string) => { · 289 unmodified lines | |||
| 500 | 505 | ||
| 501 | const HELP = `e2e dev CLI — the scenario primitives, interactive (see e2e/AGENTS.md) | 506 | const HELP = `e2e dev CLI — the scenario primitives, interactive (see e2e/AGENTS.md) |
| 502 | 507 | ||
| 503 | up <target> [--share] boot selfhost|cloud; stays up until \`down\`. | 508 | up <target> [--share] [--fresh] boot selfhost|cloud; stays up until \`down\`. |
| 504 | --share = reachable over the tailnet | 509 | --share = reachable over the tailnet |
| 505 | (cloud --share fronts app+WorkOS with tailscale HTTPS) | 510 | (cloud --share fronts app+WorkOS with tailscale HTTPS) |
| 511 | --fresh = wipe the data dir first (default: persist, | ||
| 512 | so MCP OAuth client registrations survive a restart) | ||
| 506 | status list running instances | 513 | status list running instances |
| 507 | identity <target> [--no-org] mint a fresh identity (headers/cookies/creds) | 514 | identity <target> [--no-org] mint a fresh identity (headers/cookies/creds) |
| 508 | api <target> <group.endpoint> [json] typed API call as a fresh identity | 515 | api <target> <group.endpoint> [json] typed API call as a fresh identity |