feat(opencode): add /experimental slash command to enable experimental flags#14515
feat(opencode): add /experimental slash command to enable experimental flags#14515aravhawk wants to merge 5 commits intoanomalyco:devfrom
Conversation
Carl-Bowen
left a comment
There was a problem hiding this comment.
Some strong code, couldn't find much to touch on but hope this helps.
| import { Flag } from "@/flag/flag" | ||
|
|
||
| function esc(value: string) { | ||
| return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") |
There was a problem hiding this comment.
Have a consts file that includes named consts for these regexes for readability and import them in.
| const clean = trimmed.startsWith("export ") ? trimmed.slice(7).trim() : trimmed | ||
| const index = clean.indexOf("=") | ||
| if (index <= 0) return result | ||
| result[clean.slice(0, index).trim()] = clean.slice(index + 1).trim() |
There was a problem hiding this comment.
This is basically a homemade dotenv parser. It’s going to break on:
- quoted values
- values with = inside them
- inline comments
- escaped stuff
We really shouldn’t be parsing .env ourselves. That’s user config. If we corrupt it, that’s a bad day.
Would strongly prefer using a real dotenv parser instead of rolling our own.
| const [text, { refetch }] = createResource( | ||
| file, | ||
| (target) => { | ||
| return Bun.file(target).text().catch(() => "") |
There was a problem hiding this comment.
This just swallows errors and pretends the file is empty.
If the file exists but has permissions issues or some other problem, we’ll just overwrite it with a new one. That’s kind of scary.
At least surface a toast or log something meaningful here...
| } | ||
|
|
||
| const output = edit(text() ?? "", flag.key, value) | ||
| const saved = await Bun.write(file(), output) |
There was a problem hiding this comment.
This isn’t atomic. If the process crashes mid-write, we could corrupt .env?
Would be safer to write to a temp file and rename 🤔
Maybe not critical, but since this is config mutation, it matters.
| const vars = createMemo(() => parse(text() ?? "")) | ||
| const flags = createMemo(() => { | ||
| const entries = Object.entries(Flag.types) | ||
| .filter(([key]) => key.includes("EXPERIMENTAL")) |
There was a problem hiding this comment.
From a DRY perspective...
You duplicate flag discovery logic.
You're basically discovering experimental flags in two different ways and merging them.
This logic probably belongs in one place — ideally inside Flag itself.
Instead of:
const flags = createMemo(() => { ... })You could have:
Flag.getExperimental()Then this component just consumes it.
That removes duplication and centralises flag knowledge.
|
Would this cover experinental variables set in opencode.json like BTW, idk why there are two sets of experimental variables, the ones in config file and the flags |
Dialog: safer .env handling, atomic writes, and centralized experimental flags
|
Addressed @ConsultantCarl's feedback |
This command only targets environment-based experimental flags (via So it won’t cover config-based experimental options in We currently have both because they serve different purposes:
|
|
@aravhawk |
replace the dotenv parser dependency in the tui experimental dialog with a local parser. this avoids missing-package failures during sdk build, typecheck, and unit jobs in ci.
Carl-Bowen
left a comment
There was a problem hiding this comment.
Looks good. Annoying I don't have permittance to approve, but if I did I would.
Issue for this PR
Closes #7717
Type of change
What does this PR do?
Adds a built-in
/experimentalslash command in the TUI so users can quickly enable experimental flags without manually editing env files.Changes:
/experimentalin built-in TUI commands.Experimental flagsdialog that:KEY=true..env./experimentalin TUI docs.Why this works:
.envupdate logic replaces existing lines (includingexport KEY=...) or appends when missing.How did you verify your code works?
bun run --cwd packages/opencode typecheck(pass).bun run --cwd packages/web build(pass).Screenshots / recordings
/experimentalappears in autocomplete):Checklist