feat(cli): opt supabase init into the experimental stack via env - #6665
Merged
Merged
Conversation
SUPABASE_EXPERIMENTAL_STACK=1 writes experimental.stack and omits Docker-era default ports so new projects can use the stack without pinning legacy local ports.
Keep the init opt-in docs next to develop's stack targeting section.
Member
Author
|
/ai-review |
Contributor
There was a problem hiding this comment.
🤖 AI Review
Adjudication found eight confirmed concerns and refuted two. Most are documentation, robustness, and coverage issues; the most significant is that persisting the environment opt-in conflicts with the trusted repository convention that environment opt-ins must not write project configuration.
Findings
| Severity | Location | Category | Sources | Claim |
|---|---|---|---|---|
| 🟠 MAJOR | apps/cli/src/commands/init/init.handler.ts:23 |
behavior-regression |
codex | The new init and blank-bootstrap behavior turns a temporary environment override into persistent project configuration, contrary to the trusted repository convention that environment opt-ins do not write project configuration. |
| 🟡 MINOR | apps/cli/src/commands/bootstrap/bootstrap.handler.ts:171 |
error-handling |
claude | Blank bootstrap validates SUPABASE_EXPERIMENTAL_STACK only after creating the work directory, possibly prompting for overwrite, and changing the process working directory. |
| 🟡 MINOR | apps/cli/src/commands/init/SIDE_EFFECTS.md:33 |
documentation |
claude | The init environment-variable table omits SUPABASE_YES even though the handler reads it through resolveYes. |
| 🟡 MINOR | apps/cli/src/commands/init/SIDE_EFFECTS.md:41 |
documentation |
codex | The documented invalid-value condition incorrectly includes an empty SUPABASE_EXPERIMENTAL_STACK value, although the resolver treats an empty value as unset. |
| 🟡 MINOR | apps/cli/src/commands/bootstrap/bootstrap.handler.ts:171 |
test-coverage |
claude | The newly added bootstrap environment-flag wiring has no handler integration coverage for either enabled scaffolding or invalid input. |
| ⚪ NIT | apps/cli/src/shared/init/project-init.templates.ts:496 |
robustness |
claude | The stack template transformation relies on brittle substring replacements, including an analytics port fragment with no section or comment anchor. |
| ⚪ NIT | apps/cli/src/shared/init/project-init.templates.ts:469 |
documentation |
claude | The generated comment describes only top-level start, stop, and status even though experimental.stack also controls numerous local database, migration, storage, seed, and inspection paths. |
| ⚪ NIT | apps/cli/src/commands/bootstrap/SIDE_EFFECTS.md:72 |
formatting |
claude+codex | The newly added SIDE_EFFECTS table rows are not padded consistently with the surrounding aligned Markdown tables. |
Refuted findings (kept for transparency, not posted as review comments)
apps/cli/src/shared/init/project-init.ts:139(api-design): Making experimentalStack optional allows callers to omit an explicit scaffolding decision.
Refuted: Concrete surrounding API behavior establishes false as the intentional default for this opt-in: renderCliConfigTemplate defaults experimentalStack to false at project-init.templates.ts:508-517, and the existing non-production file-mode caller deliberately omits it. Both production handlers pass an explicit value. Optionality therefore encodes the established opt-in default rather than an ambiguous runtime state.apps/cli/src/commands/init/init.handler.ts:25(correctness): An unset environment variable during init --force drops an existing experimental.stack=true setting.
Refuted: The force path intentionally replaces the entire configuration rather than preserving selected existing settings: project-init.ts:296-308 only short-circuits without force and otherwise writes a fresh template, while init/SIDE_EFFECTS.md:92 and stack-commands.md:90-93 explicitly document replacement and the no-environment legacy template. Preserving this one field would conflict with the established force semantics.
Stats
Claude findings: 8 · Codex findings: 3 · Confirmed: 8 · Refuted: 2 · Uncertain: 0
Models: claude-opus-5 + gpt-5.6-sol · Trigger: manual · Workflow run
This review runs once per PR. A maintainer can request another with a /ai-review comment.
Init tests were mutating SUPABASE_EXPERIMENTAL_STACK, which leaked into parallel integration files and could take pull off the mocked pg-delta path.
…writes Validate SUPABASE_EXPERIMENTAL_STACK on the scratch path before mkdir/chdir, cover that in integration tests, and document empty-string fallback.
jgoux
approved these changes
Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SUPABASE_EXPERIMENTAL_STACK=1 supabase initwrites[experimental] stack = trueand omits Docker-era default ports so the new stack is not pinned to legacy local listeners.0keeps the established Go-parity template. Invalid values fail closed. Blanksupabase bootstrapuses the same scaffold.