feat: UX parity with Claude Code (5 improvements)#19360
Closed
johnnykang101 wants to merge 68 commits intoanomalyco:devfrom
Closed
feat: UX parity with Claude Code (5 improvements)#19360johnnykang101 wants to merge 68 commits intoanomalyco:devfrom
johnnykang101 wants to merge 68 commits intoanomalyco:devfrom
Conversation
- Add 9Router as a named ProviderID in schema.ts (9router) - Add 9Router to popularProviders list in use-providers.ts - New DialogConnect9Router: pre-filled form (baseURL + JWT token) with Claude Sonnet/Opus/Haiku defaults via openai-compatible SDK - Update DialogSelectProvider: 9Router appears as a static "popular" entry with a "Local" tag, routes to the dedicated connect dialog - New DialogOnboarding: welcome wizard shown on first launch when no providers are connected; leads directly to provider selection - OnboardingCheck in RouterRoot: detects zero connected providers on mount and shows the onboarding dialog (localStorage-gated) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove API key field entirely. 9Router is a local container that doesn't require auth — connection is just a baseURL. A dummy apiKey is set in options only to satisfy the openai-compatible SDK constructor. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fetch /v1/models from the running 9Router container, show a checklist of available models (all selected by default), and register only the ones the user picks. Includes select/deselect all toggle and a count summary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Single button now tests the connection and fetches models in one step. On success: green dot + "Connected — N models available" + checklist. On failure: red dot + inline error message. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add useGlobalSync import to app.tsx (used in OnboardingCheck) - Explicitly type all new Set() calls as Set<string> to satisfy TypeScript inference in dialog-connect-9router.tsx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Interactive terminal wizard (opencode onboard) for first-run setup. Supports 9Router (URL + model picker) and API key providers (Anthropic, OpenAI, OpenRouter, Google). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
If enabled_providers exists in config, 9router was being filtered out. Now onboard adds it to the list automatically. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CI: typecheck on every PR targeting main - CD: auto-release on merge to main with semver bump and release notes - feat commits → minor bump - fix/chore → patch bump - breaking change → major bump Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Syncs anomalyco/opencode dev → our dev branch every Monday at 6am UTC. - Clean merge: auto-pushes to dev - Conflicts: opens a PR for manual resolution Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…isions Tags now follow cb-vX.Y.Z pattern (e.g. cb-v0.1.0) so they never conflict with upstream anomalyco/opencode tags (v0.0.45, v1.4.0, etc). Release titles display as 'CoBuilder vX.Y.Z' for clarity. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CLI command renamed from opencode → cobuilder - package.json version reset to 0.1.1 (CoBuilder versioning) - build.ts: output binary named cobuilder, uploads to cb-vX.Y.Z tags - cd.yml: builds platform binaries (linux/darwin/windows x64/arm64) and attaches them to each release - install.sh: one-line curl install with platform detection, PATH setup, and automatic onboarding Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces --generate-notes (PR-only) with categorized commit log. Notes are grouped into Features / Bug Fixes / Maintenance sections and link Full Changelog between our own cb-v* tags only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Strip conventional commit prefixes from user-visible notes - Capitalize entries automatically - Sections: Added / Fixed / Changed / Security / Breaking Changes - Include release date in header - Full Changelog link scoped to cb-v* tags only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Security layers added (TypeScript/Bun adaptations): - SSRF protection: blocks cloud metadata, private IPs, localhost by default - Prompt injection scanner: detects override/jailbreak/exfil patterns - Path traversal prevention: canonicalize + base-escape detection - Token bucket rate limiter: per-key cost-aware limiting - Merkle-chained audit log: tamper-evident append-only event log - HTTP security headers: CSP, HSTS, X-Frame, X-Content-Type CI hardened with: - Lint job - Dependency audit (bun audit) - Secret scanning (TruffleHog --only-verified) - SAST (CodeQL for TypeScript) - Unit tests (bun test) with security module coverage Inspired by OpenFang's 16-layer defense-in-depth architecture. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
build.ts uses 'gh release upload cb-vX.Y.Z' which requires the release to already exist. Previously we created it after the build — reversed order. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Persist active session to checkpoint.json on each user message. On next launch, detect interrupted sessions and offer to resume. Checkpoint clears on clean exit (code 0) so it only exists after crashes. Inspired by Claude Code's auto-dream session continuity pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Script.version fetches from opencode-ai npm registry (unavailable for our fork) and falls back to '0.0.0-main-timestamp'. This caused 'gh release upload cb-v0.0.0-main-...' to target a non-existent release. Now pass COBUILDER_RELEASE_TAG=cb-vX.Y.Z from CD workflow so build.ts uploads to the correct release tag regardless of Script.version. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inspired by Claude Code's auto-dream memory consolidation:
- SQLite FTS5 memory store: per-session summaries indexed for search
- Deterministic summarization: extracts user requests + tool actions
- Memory injection: top 3-5 relevant past sessions prepended to system prompt
- Lifecycle hook: auto-summarize when session is archived/closed
- Project-scoped: memories are per working directory
Memory hierarchy:
Working memory (context window)
→ Session memory (SQLite messages, persisted)
→ Long-term memory (FTS5-searchable summaries, injected at next start)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ll guide Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lanations Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… avatar style Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the >_ terminal box with the pixel-art Jindo mascot, clipped to the same rounded square with a gradient border that ties into the CoBuilder wordmark. README updated to use a single unified logo image. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(04-01): add Step N of 4 progress prefixes to onboarding wizard
- Step 1 of 4 — Choose your provider (before provider select)
- Step 2 of 4 — Security modules (was: Security modules — configure which are active)
- Step 3 of 4 — Workflow plugins (optional) (was: Workflow plugins — install methodology tooling)
- Step 4 of 4 — Recommended tools (optional) (was: Recommended tools — extend CoBuilder)
* feat(04-03): background update download with persistent badge
- Replace confirm-dialog+exit flow with silent background download
- Add pendingUpdate signal set on successful upgrade
- Show toast on download start and completion
- Show persistent badge 'Update vX.Y.Z ready — restart to apply' at top
- Remove exit() call after update — user stays in app
* chore(04-03): remove unused DialogAlert and DialogConfirm imports
* feat(04-02): add first-run hint block to TUI home screen
- Added Show block with 3 contextual hints beneath the prompt
- Hints only visible when isFirstTimeUser() (zero sessions)
- Uses theme.primary for bullet markers and theme.text for emphasis
- Existing Tips component untouched
* docs(04-03): complete non-disruptive update flow plan
- 04-03-SUMMARY.md created
- STATE.md updated to phase 4, plan 3 complete
* feat(04-02): add Getting Started panel to Web home screen
- Replaced minimal empty state with numbered 3-step Getting Started panel
- Step numbers use rounded circles with bg-surface-raised-base
- Added home.gettingStarted.{title,step1,step2,step3} i18n keys
- All 5 locale files updated: en, es, zh, zht, no
* feat(04-01): enhance ConnectionError with elapsed timer and actionable guidance
- Add elapsedSeconds signal incremented every second in existing retry interval
- Replace static 'Retrying...' with 'Retrying... Ns' via app.server.retryElapsed key
- Add serverUrl memo extracting http.url from current server connection
- Show 'Try running: cobuilder serve' when no URL is known
- Show 'Check that the server is running at <url>' when URL is known
- Add app.server.retryElapsed, hint.serve, hint.url keys to all 17 locale files
- Fix HttpBase type error: use current.http.url (string) not current.http
* docs(04-02): complete first-run guidance plan
- Add 04-02-SUMMARY.md with task commits and deviation notes
- Update STATE.md: plan 02 complete, deferred issues logged
* docs(04-01): complete onboarding-progress and connection-error-elapsed plan
- 04-01-SUMMARY.md: step progress + ConnectionError elapsed timer
- STATE.md: updated stopped_at, added 2 decisions
* docs: mark Phase 4 UI/UX Polish II complete with verification
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: commit planning artifacts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Renames packages/opencode/bin/opencode → bin/cobuilder
- Updates bin wrapper: .cobuilder cache, cobuilder- asset prefix, cobuilder binary name
- Updates package.json bin field: ./bin/opencode → ./bin/cobuilder
- Fixes install.sh: opencode-${PLATFORM}-${ARCH} → cobuilder-${PLATFORM}-${ARCH}
- Adds `cobuilder` script to root package.json for `bun run cobuilder`
Without this, `cobuilder install` downloaded the right file but unpacked
looking for an `opencode` binary — and the install script was fetching
opencode-* asset names that no longer exist.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The security headers middleware called Config.get() after next(), but early TUI worker requests arrive before the instance AsyncLocalStorage context is initialised, causing an UnknownError crash on every startup. Fix: wrap in try/catch and apply headers unconditionally when config is not yet available — which is the secure default. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…target After renaming the binary prefix from "opencode" to "cobuilder", the target string was no longer replaced correctly since pkg.name is still "opencode". Bun requires compile targets to start with "bun-", so cobuilder-linux-arm64 caused a TypeError and broke every CD build. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When the script is piped (curl | bash), stdin is a pipe not a TTY, so @clack/prompts can't read arrow keys — they print as raw escape sequences. Redirect stdin from /dev/tty when available so interactive onboarding works seamlessly from the one-liner install command. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- bin/cobuilder: OPENCODE_BIN_PATH → COBUILDER_BIN_PATH env var - pr.ts: spawn cobuilder binary instead of opencode (runtime fix) - uninstall.ts: brew/choco/scoop package names, intro/outro text - run.ts/worker.ts/plugin/index.ts/server.ts: default auth username Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…repos gsd-workflow, ralph-loop-workflow, and gstack-workflow repos do not exist under CobuilderLabs. Keeping them caused a confusing git clone failure. Users should provide a full GitHub URL until real workflow repos are published. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Repo now exists at https://github.com/CobuilderLabs/gsd-workflow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mirrors how Claude Code installs skills — clones the repo and drops command markdown files into ~/.config/opencode/commands/<skill>/ so they are available as /<skill>:<command> slash commands. Usage: cobuilder skills install gsd Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Neither repo uses a compatible command structure for CoBuilder skills. Only GSD (CobuilderLabs/gsd-workflow) is installable. Remove the others to avoid offering options that would silently fail. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CoBuilder's AI was checking ~/.claude/skills/ when asked about installed tools. Add installedCommands() to SystemPrompt so the AI knows commands live at ~/.config/opencode/commands/ and can correctly report what's installed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…so binaries show proper semver Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ing latest CD creates the release before uploading binaries, so the "latest" tag can briefly have no assets. Walk up to 10 recent releases and pick the newest one that actually has the expected asset file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oaded Prevents the "latest" tag from pointing to an empty release during the build window. Also adds branch protection context for PRs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nd release HTTP HEAD probing is unreliable (GitHub uses 301/302/other codes). Query each release's asset list via the API to reliably find the newest non-draft release that has the expected binary for the user's platform. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevents electron-builder from auto-publishing in CI (it detects CI env and tries to publish, failing without GH_TOKEN). The explicit gh release upload step handles all artifact publishing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…x makes this reliable The CD pipeline now publishes releases only after all binaries are uploaded (draft → publish on success). No scanning needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TUI (app.tsx) uses React JSX but react was missing from the package dependencies, causing 'Cannot find module react/jsx-dev-runtime' on bun run. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
/dev/tty may exist as a device node in containers but fail to open. Use a subshell exec test to confirm it's accessible before using it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(exec </dev/tty) leaks bash errors; { true </dev/tty; } 2>/dev/null
cleanly tests if the device can be opened without any output.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
true </dev/tty passes even when the device is non-functional because the open() syscall succeeds but reads fail. stty requires an actual terminal and correctly fails in headless containers, falling through to the manual instructions path. Also adds test-e2e.sh: install → version → commands → skills → uninstall → reinstall Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
#18) * fix(onboard): replace multi-select model input with single select Users select one default model during onboard — they can switch to any other model from the same provider inside the app. The comma-separated number input was confusing and unnecessary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(onboard): restore security step, single-select model, fix instance crash - Remove Config.get() call that crashed with "No context found for instance" during onboarding (instance ALS not initialized in CLI context) - Replace comma-separated multi-select model input with single select - Restore security modules step (inline, no missing module deps) - Move prompts.outro to main handler after all steps complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tips): rebrand all opencode references to cobuilder Replace opencode CLI commands, /opencode slash commands, OpenCode product name, and .opencode/ config paths with their cobuilder equivalents. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(system-prompt): tell model not to use which/shell to check for skills Skills are CoBuilder-native and accessed via the skill tool, not system binaries. Without this hint models run `which gsd` and report it as not installed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(system-prompt): list installed skills in env block Adds 'Installed skills: gsd:plan-phase, ...' to the <env> section so the model knows upfront what skills are available without needing to run which/command -v shell checks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(e2e): validate all onboard wizard selections — providers + security modules Step 8 now covers both wizard steps: - Step 1: all 5 providers (Anthropic, OpenAI, OpenRouter, Google, 9Router) - Step 2: all 6 security modules — each individually disabled, all disabled, and combined provider+security state Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(prompt): rebrand OpenCode→CoBuilder, add mandatory GSD workflow CoBuilder is the product name throughout the system prompt. Added mandatory GSD section so the model proactively routes non-trivial tasks through the structured workflow without user having to ask. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(prompt): broaden CoBuilder identity beyond coding agent CoBuilder builds software, products, automations, content, plans, and more — not just code. Update system prompt to reflect this. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(prompt): rebrand all model prompts — CoBuilder is a general AI agent Update all 6 remaining prompt files (default, gemini, gpt, beast, trinity, codex) to use CoBuilder identity and broaden scope beyond software engineering to "build anything". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add --autopilot flag to auto-approve all permission requests Adds `cobuilder --autopilot` (or env var COBUILDER_AUTOPILOT=1) which skips permission confirmation prompts — useful for CI, scripts, and non-interactive runs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tui,prompt): cleaner tool output + autonomous GSD behavior - TUI: show only first input value (truncated to 60 chars) instead of dumping all key=value pairs for generic/MCP tool calls - Prompt: remove gsd:do/sub-skill references that caused double skill load; instruct model to complete full GSD flow autonomously without asking follow-up questions when intent is clear Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tui): show autopilot badge in prompt mode line When --autopilot is active, displays "autopilot ·" in warning color next to the agent name in the prompt area so the user can see at a glance that permission prompts are being auto-approved. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(provider): strip trailing assistant messages for Claude models claude-sonnet-4-6 and newer Claude models reject requests where the last message is an assistant role ("assistant message prefill"). Strip any trailing assistant messages before sending to Anthropic/Claude endpoints. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…g instance context (#19) The security headers middleware called Config.get() after next(), but early TUI worker requests arrive before the instance AsyncLocalStorage context is initialised, causing an UnknownError crash on every startup. Fix: wrap in try/catch and apply headers unconditionally when config is not yet available — which is the secure default. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Open edit tool parts expanded by default (matches Claude Code behavior) - Open diffs collapsible by default after each completed turn - Add contextual bottom HUD showing shortcuts below the prompt input (idle: '/ commands · @ mention', streaming: 'Esc · to stop') - Improve interrupt discoverability by surfacing Esc hint during generation - Add per-turn token/cost display after each assistant response
Contributor
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
Author
|
Wrong repo — PR created in CobuilderLabs/opencode instead. |
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
Closes the UX gap between CoBuilder and Claude Code across 5 targeted improvements, all additive and non-breaking.
Changes
packages/app/src/context/settings.tsxpackages/ui/src/components/session-turn.tsx/ commands · @ mention, streaming showsEsc · to stoppackages/app/src/pages/session/composer/session-composer-region.tsxEschint is now surfaced in the HUD during generation (Esc already worked; this makes it discoverable)packages/app/src/i18n/en.ts↑ 1.2K ↓ 3.4K tokens · ~$0.0041shown after each completed assistant turnpackages/ui/src/components/session-turn.tsxNotes
AssistantMessage.tokensand.cost— no backend changesaria-hiddenandpointer-events-none— purely informational, no interaction requiredPlanning artifacts
.planning/phases/ux-parity/CONTEXT.md.planning/phases/ux-parity/PLAN.md