During the v1.1.41 upstream merge, several fork features were lost due to incorrect rerere auto-resolution. This plan documents the fixes needed and provides implementation details for another agent.
Problem: The logo.tsx component was updated by upstream to import from @/cli/logo.ts which contains "open code" ASCII art instead of "shuvcode".
Current State:
packages/opencode/src/cli/logo.tscontains upstream's "open code" logopackages/opencode/src/cli/cmd/tui/component/logo.tsximports from@/cli/logo- Home screen shows "open code" instead of "shuvcode"
Pre-merge State (96e1a43c6):
logo.tsxhad inline "shuvcode" ASCII art:
const LOGO_LEFT = [` ▄ `, `█▀▀▀ █▀▀█ █ █ █ █`, `▀▀▀█ █░░█ █░░█ █░░█`, `▀▀▀▀ ▀ ▀ ▀▀▀▀ ▀▀ `]
const LOGO_RIGHT = [` ▄ `, `█▀▀▀ █▀▀█ █▀▀█ █▀▀█`, `█░░░ █░░█ █░░█ █▀▀▀`, `▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀`]Fix Required:
Update packages/opencode/src/cli/logo.ts to contain shuvcode logo:
export const logo = {
left: [` ▄ `, `█▀▀▀ █▀▀█ █ █ █ █`, `▀▀▀█ █░░█ █░░█ █░░█`, `▀▀▀▀ ▀ ▀ ▀▀▀▀ ▀▀ `],
right: [` ▄ `, `█▀▀▀ █▀▀█ █▀▀█ █▀▀█`, `█░░░ █░░█ █░░█ █▀▀▀`, `▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀`],
}
export const marks = "_^~"Note: The upstream version uses shadow markers (_^~) for visual effects. If these don't render correctly with the shuvcode logo, we may need to use the simpler version without markers (replacing _ with space, removing ^ and ~).
Files to modify:
packages/opencode/src/cli/logo.ts
Problem: ANSI output is not rendered in the TUI because the Bash tool output is stripped of ANSI codes before display.
Current State:
ghostty-opentuidependency exists andptyToTextis used inpackages/opencode/src/tool/bash.ts✓- Build step installs native bindings in
packages/opencode/script/build.ts✓ - TUI renders bash output as plain text with
stripAnsiinpackages/opencode/src/cli/cmd/tui/routes/session/index.tsx, so colors are removed
Fix Required:
Implement ANSI-aware rendering for bash tool output in the TUI using ghostty-opentui (as in the prior fork behavior) instead of stripping ANSI.
Implementation Notes:
- Replace
stripAnsiusage inpackages/opencode/src/cli/cmd/tui/routes/session/index.tsx(Bash tool block) with aghostty-opentuirender path (e.g., GhosttyTerminalRenderable) that parses ANSI/VT sequences. - Preserve colors/styles in the TUI while keeping the existing expanded/collapsed view behavior.
- Keep a safe fallback for non-ANSI output (render plain text when no ANSI sequences are present).
- Ensure copy-to-clipboard and transcript export remain readable (plain text is fine).
Verification Steps:
- Confirm
packages/opencode/script/build.tsstill installs ghostty-opentui - Run a bash tool command that emits ANSI (e.g.,
ls --color=alwaysorprintf '\\x1b[31mred\\x1b[0m') - Verify colors render in the TUI without being stripped
Files to check:
packages/opencode/script/build.tspackages/opencode/src/cli/cmd/tui/routes/session/index.tsxpackages/opencode/src/tool/bash.ts
Problem: Spinner customization should work via command palette.
Current State:
- Spinner utility exists at
packages/opencode/src/cli/cmd/tui/util/spinners.ts✓ - Dialog components exist at
packages/opencode/src/cli/cmd/tui/component/dialog-spinner.tsx✓ - Command palette integration in
app.tsxexists ✓ - Sidebar uses
getSpinnerFrame()✓
Verification: The spinner feature appears intact. Verify by:
- Running shuvcode TUI
- Opening command palette (Ctrl+X Ctrl+X)
- Searching for "spinner" - should see "Change spinner style" and "Change spinner speed"
Problem: The double Ctrl+C feature exists but needs a regression test to prevent regressions.
Implementation Required:
Avoid testing Solid .tsx directly. Extract the exit timing logic into a small .ts helper and test that helper.
Suggested structure:
- Add helper
packages/opencode/src/cli/cmd/tui/component/prompt/exit.tsthat encapsulates:- last attempt timestamp tracking
- 2 second window logic
- return value indicating whether to exit or show toast
- Update
packages/opencode/src/cli/cmd/tui/component/prompt/index.tsxto use the helper. - Create test at
packages/opencode/test/cli/tui/double-ctrl-c.test.tsthat verifies:- first call returns "warn"
- second call within 2 seconds returns "exit"
- calls after 2 seconds reset behavior
Files to modify/create:
packages/opencode/src/cli/cmd/tui/component/prompt/exit.tspackages/opencode/src/cli/cmd/tui/component/prompt/index.tsxpackages/opencode/test/cli/tui/double-ctrl-c.test.ts
Problem: The fork still contains a legacy AskQuestion tool, but we should rely exclusively on the upstream-native question tool.
Fix Required: Remove legacy AskQuestion code and any remaining references.
Files to remove/modify:
packages/opencode/src/askquestion/index.tspackages/opencode/src/tool/askquestion.tspackages/opencode/src/tool/askquestion.txtpackages/opencode/src/cli/cmd/tui/ui/dialog-askquestion.tsxpackages/opencode/src/session/index.ts(remove AskQuestion import + cleanup call)packages/app/src/components/askquestion-wizard.tsx
Changes Required:
- Remove AskQuestion tool entry (PR #5958) - fork should use upstream native
questiontool only - Keep Search in messages entry (PR #4898) if code still exists
{
"pr": 4900,
"title": "Double Ctrl+C to exit",
"author": "AmineGuitouni",
"status": "open",
"description": "Require double Ctrl+C within 2 seconds to prevent accidental exits",
"files": ["packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx"],
"criticalCode": [
{
"file": "packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx",
"description": "Exit attempt tracking and tryExit function",
"markers": ["let lastExitAttempt = 0", "async function tryExit()", "now - lastExitAttempt < 2000"]
},
{
"file": "packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx",
"description": "Toast warning on first Ctrl+C",
"markers": ["message: \"Press again to exit\"", "duration: 2000"]
},
{
"file": "packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx",
"description": "Keybind handler calls tryExit instead of exit",
"markers": ["await tryExit()", "keybind.match(\"app_exit\""]
}
],
"testFile": "packages/opencode/test/tui/double-ctrl-c.test.ts"
}{
"pr": 0,
"title": "Shuvcode ASCII logo branding",
"author": "fork",
"status": "fork-only",
"description": "Fork uses 'shuvcode' ASCII art logo on home screen instead of upstream 'opencode' branding",
"files": ["packages/opencode/src/cli/logo.ts", "packages/opencode/src/cli/cmd/tui/component/logo.tsx"],
"criticalCode": [
{
"file": "packages/opencode/src/cli/logo.ts",
"description": "Shuvcode ASCII art - left side shows 'shuv', right side shows 'code'",
"markers": ["█▀▀▀ █▀▀█ █ █ █ █", "▀▀▀█ █░░█ █░░█ █░░█"]
}
]
}Files to modify:
script/sync/fork-features.json
-
Fix shuvcode logo (CRITICAL - user-visible branding)
- Edit
packages/opencode/src/cli/logo.ts
- Edit
-
Add double Ctrl+C regression test
- Create
packages/opencode/src/cli/cmd/tui/component/prompt/exit.ts - Wire helper in
packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx - Create
packages/opencode/test/cli/tui/double-ctrl-c.test.ts - Run the test
- Create
-
Remove legacy AskQuestion tool
- Delete
packages/opencode/src/askquestion/index.ts - Delete
packages/opencode/src/tool/askquestion.ts - Delete
packages/opencode/src/tool/askquestion.txt - Delete
packages/opencode/src/cli/cmd/tui/ui/dialog-askquestion.tsx - Remove AskQuestion cleanup from
packages/opencode/src/session/index.ts - Delete
packages/app/src/components/askquestion-wizard.tsx
- Delete
-
Update fork-features.json
- Enhance Double Ctrl+C entry with criticalCode
- Add shuvcode logo entry
- Remove AskQuestion entry
- Keep Search in messages entry if code still exists
-
Restore ANSI bash output rendering
- Replace
stripAnsirendering in the Bash tool block - Add ANSI-capable rendering path
- Manual TUI verification with a colored command
- Replace
-
Commit and push
- Stage all changes
- Commit with message:
fix: restore shuvcode branding and add fork feature tests
# Run double Ctrl+C test
bun test test/cli/tui/double-ctrl-c.test.ts
# Typecheck
bun turbo typecheck --filter=opencode
# Verify logo change
grep -n "shuvcode\|█▀▀▀ █▀▀█ █ █" packages/opencode/src/cli/logo.ts
# Verify ghostty in build
grep -n "ghostty-opentui" packages/opencode/script/build.ts
# Verify ANSI render path (stripAnsi removed from Bash output)
grep -n "stripAnsi" packages/opencode/src/cli/cmd/tui/routes/session/index.tsxThe last known good state before the v1.1.41 merge:
- Commit:
96e1a43c6 - Can be used to check any file's pre-merge state with:
git show 96e1a43c6:<filepath>