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 | 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 | 4 | // bun scripts/cli.ts up cloud [--share] |
| 5 | 5 | // bun scripts/cli.ts status |
| 6 | 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 | 204 | webBaseUrl: baseUrl, |
| 205 | 205 | admin, |
| 206 | 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 | 213 | logFile, |
| 209 | 214 | }); |
| 210 | 215 | teardown = async () => { |
| @@ -500,9 +505,11 @@ const logs = (targetName: string) => { · 289 unmodified lines | ||
| 500 | 505 | |
| 501 | 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 | 509 | --share = reachable over the tailnet |
| 505 | 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 | 513 | status list running instances |
| 507 | 514 | identity <target> [--no-org] mint a fresh identity (headers/cookies/creds) |
| 508 | 515 | api <target> <group.endpoint> [json] typed API call as a fresh identity |