- Updated hook option rendering to support description modes for full text, bounded rows, or hidden detail output.
- Adjusted compact-mode row budgeting so list height is based on labels, preventing a single description from consuming the visible budget.
- Added pre-wrapping with ellipsis truncation for selected option descriptions and updated overflow tests to validate the collapsed label-first behavior.
When OTEL_EXPORTER_OTLP_ENDPOINT (or _TRACES_ENDPOINT) is set, register a
global OTLP/proto TracerProvider and switch on the agent loop's telemetry
so its invoke_agent / chat / execute_tool spans reach a collector instead
of a no-op tracer. Honors the standard OTEL_* env contract
(OTEL_SERVICE_NAME, OTEL_SDK_DISABLED, OTEL_TRACES_EXPORTER=none) and the
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT capture toggle; no-op
when no endpoint is configured.
Uses the exporter-trace-otlp-proto 2.x line, which exports cleanly under
Bun (the 1.x line deadlocks). Adds a flushTelemetryExport() helper and a
periodic + signal-driven flush so long-lived processes surface spans.
This makes the existing telemetry usable from hosts that spawn omp as a
child process (e.g. an ACP harness), where an in-process provider
registered by the parent can't reach the child process.
Per review on #1715: the cap fed gamma-encoded luma into the WCAG contrast formula, so the >=3:1 target wasn't real (light-poimandres #340df2 was ~2.5:1 actual). Split the color helpers into colorLuma (perceptual, for light/dark classification — unchanged behavior) and relativeLuminance (WCAG-linearized sRGB, for contrast ratios). Session accents are now sized, and tests asserted, against relativeLuminance, so >=3:1 holds against the actual surface. Theme keeps luma for isLight/isLightTheme and exposes the WCAG status-line luminance for the cap.
Per review on #1715: the light-theme cap was a fixed absolute luminance (0.2) tuned for near-white backgrounds. On a mid-light shipped theme like light-poimandres (statusLineBg #7390aa, luminance ~0.55) that still left accents at only ~1.8-2.4:1. Theme now exposes statusLineLuminance + accentSurfaceLuminance; getSessionAccentHex takes the surface luminance and caps the accent to guarantee >=3:1 (WCAG AA large) against the actual surface, so near-white and mid-light light themes are both legible. Tests assert contrast across light + mid-light surfaces.
Per review on #1715: theme color values may be a 256-color palette index (colorValueSchema = string | number), so a custom theme can set a light statusLineBg numerically (e.g. 15 = white). bgIsLight only handled hex strings and returned false for numbers, routing those light themes through the dark-accent path and reintroducing the unreadable accent. Add paletteLuminance (0-15 xterm defaults, 16-231 color cube, 232-255 grayscale) and a colorLuminance(string|number) dispatcher; route bgIsLight and isLightTheme through it. Tests added.
Per review on #1715 (nits 3 & 4): the BT.709 relative-luminance + #rrggbb parsing was duplicated three ways (session-color relativeLuminance, theme bgIsLight, isLightTheme), and each rejected #rgb shorthand via length !== 7 — so a custom theme using shorthand backgrounds silently kept the washed-out accent. Lift it into utils/color.ts hexLuminance() (accepts #rgb and #rrggbb), route all three call sites through it, and add tests.
Per review on #1715: Theme.isLight drove accent darkening from userMessageBg, but the accents render on the status line / editor chrome. Themes that style the chat bubble darker than the status line (e.g. built-in porcelain: userMessageBg #5070a0, statusLineBg #f8f9fc) misclassified, leaving the bright dark-theme accent on a light status line. Derive isLight from statusLineBg; add a regression test over porcelain / light-catppuccin / dark-catppuccin.
The status line session_name (plus editor border / gap fill) colors itself with a per-session accent hashed from the name via hslToHex(hue, 0.9, 0.72). The fixed lightness is tuned for dark backgrounds; on light themes high-luminance hues (yellow/lime/cyan) render near-invisible (~1.3:1 contrast). statusLine.sessionAccent (#918) only gates the border/gap fill, not the segment text, so there was no way to make the title legible on a light theme.
Add Theme.isLight (from userMessageBg luminance) and make getSessionAccentHex bisect lightness to cap perceived luminance on light themes, keeping the per-session hue while staying readable. Pass theme.isLight at all four accent call sites; add a unit test.
Refs #918, #680.
- Add CMUX_SURFACE_ID env var fallback to getTerminalId() so cmux
surfaces get a stable terminal identifier alongside kitty/tmux.
Enables per-surface session breadcrumbs for omp -c in cmux.
- Update tip text to mention cmux alongside kitty/tmux.
- Tracked the latest in-flight preview diff recompute in ToolExecutionComponent and exposed it through a new whenPreviewSettled method.
- Updated component paths that trigger preview recomputation to retain the returned promise instead of fire-and-forget calls.
- Updated the streaming preview height test to await settled diff recomputation before assertions, eliminating requestRender race-based flakes.
- Added `Settings.reloadForCwd` to mutate the live instance in place, so `/move` and cross-project resume pick up the destination project's `.claude/settings.yml` and path-scoped `enabledModels`/`disabledProviders`.
- Wired `reloadForCwd` into `applyCwdChange` (interactive mode) and the `--resume` startup path so settings always follow the active working directory.
- Added tests covering path-scoped re-resolution, no-op on same directory, and disk-backed project layer load/drop.
- Enabled resume picker to preload sessions and toggle folder/all scope with Tab.
- Enabled resume flow to fall back to all-project sessions and switch cwd on resume.
- Added centralized applyCwdChange to refresh caches, commands, and UI after cwd updates.
- Updated session restoration to adopt restored session cwd and sessionDir when present.
- Fixed `session_id` never being created or populated; every history row had `NULL` for session.
- Added schema migration (`ALTER TABLE history ADD COLUMN session_id`) for pre-existing databases.
- Wired interactive mode to call `setSessionResolver(...)` so prompts are stamped with the active session at submission time.
- Re-enabled session ranking in `--resume` and in-session pickers via `matchingSessionIds()`, merging fuzzy and prompt-history signals.
Filtered the logout selector to credentials that /logout can actually remove and reported ambient env/config auth when direct logout cannot clear it. Added selector coverage for env-only OpenCode providers.\n\nFixes #1658
When the autocomplete popup is visible, ESC unconditionally falls through
to the editor base class so it can dismiss the popup. Only an ESC with no
popup visible reaches onEscape and routes to the global interrupt handler.
Removed the shouldBypassAutocompleteOnEscape callback that paved over the
popup-dismissal path whenever the agent was busy (streaming, bash, /btw,
auto-compaction, etc.) — that is precisely the moment the user is most
likely to hit ESC while the popup is open, and dismissing-then-aborting in
one keystroke is a footgun, not a feature. Two-press semantics now match
the standard TUI/IDE pattern: first ESC closes the popup, second ESC
aborts.
Tests cover both branches in custom-editor-keybindings.test.ts and the
input-controller escape suite no longer asserts the dead callback.
Fixes#1655
Applied tasks.todoClearDelay to the interactive Todos panel without mutating the session todo history used by the model.
Added regression coverage for instant, delayed, and disabled auto-clear behavior.
Fixes#1644
- Tool execution now renders every 16ms and advances spinner glyphs only every 80ms using a tracked last-advance timestamp.
- Output block shimmer ticks were reduced to 16ms so border-frame updates align with the 60fps cadence for smoother animation.
Avoided the forced teardown repaint during interactive shutdown so disposed UI state cannot clear the viewport before Bash resumes.
Moved TUI stop cursor placement to the first row after short rendered content without adding a blank line.
Fixes#1620
Enable eager native scrollback rebuild mode while assistant text is actively streaming so reflowed Markdown rows do not leave stale duplicated tails in WSL/Windows Terminal scrollback.\n\nFixes #1615
When Zed provisions MCP servers through `session/new.mcpServers`, the
ACP agent
correctly connects to them and registers their tools via
`refreshMCPTools`, but
the tools were never activated. `refreshMCPTools` builds the next
active tool
set from `getSelectedMCPToolNames()`, which — with discovery disabled —
returns
only MCP tools already in the active set. Since ACP sessions start with
no MCP
tools, this created a circular deadlock: tools could only become active
if they
were already active.
Added an optional `{ activateAll?: boolean }` parameter to
`refreshMCPTools`.
When true, every newly registered tool is force-activated regardless of
prior
selection. `AcpAgent#configureMcpServers` passes `activateAll: true` on
both
call sites so client-provisioned tools are immediately usable.
A stdio MCP server that completes the initialize + tools/list handshake and then exits cleanly will fire `transport.onClose` on every clean exit, and the old `MCPManager.reconnectServer` path spawned again unconditionally. A misconfigured PHP-shebang MCP (e.g. Laravel Boost in a non-Laravel project) hit this loop and forked 66 487 `php84` processes parented directly to the agent's `bun` PID until macOS force-rebooted.
Add a per-server sliding-window circuit breaker: at most 5 reconnect attempts per 30 s window. The transport `onClose` callback and the per-tool-call retry in `tool-bridge` are subject to the breaker; `/mcp reconnect` passes `{ manual: true }` to reset the window so users can recover after fixing the underlying misconfiguration. Stale `onClose` is detached when the breaker trips so a late EOF event cannot re-arm the loop.
Defended by `mcp-reconnect-storm.test.ts`: a Bun stdio fixture answers the handshake and exits, then asserts the spawn count stays at ≤ 10 (was 127 without the fix).
Fixes#1592
- Add new keybinding `app.clipboard.pasteTextRaw` with Ctrl+Shift+V / Alt+Shift+V defaults
- Implement `readTextFromClipboard()` utility supporting macOS, Windows, Linux (Wayland/X11), and Termux
- Integrate raw paste handler into CustomEditor and InputController
- Text is inserted without formatting collapse to preserve whitespace and newlines
- Dropped `summarizeShakeRegions`, the shake-summary prompt, and related types.
- Removed `shake-summary` compaction strategy and `providers.shakeSummaryModel` setting.
- Migrated existing `shake-summary` configs to plain `shake` on load.
- Simplified `/shake` to `elide` and `images` modes only.
- Updated toggleToolOutputExpansion to pass allowUnknownViewportMutation when requesting render.
- Added a test that verifies tool output toggling sets expansion state and calls requestRender with the new flag.
- Documented the Ctrl+O POSIX tool-result expansion scrollback fix in the changelog.
- Added a post-dispatch refresh hook to recompute foreground tool render mode after key turn/tool events.
- Computed whether any non-background pending tool is active and toggled eager native scrollback rebuild accordingly.
- Added a regression test confirming eager rebuild is enabled while foreground tools are pending and disabled when none remain.
- Preserved hidden tmux overlays in live viewport while keeping native scrollback intact during forced renders.
- Adjusted forced-render handling so pure appends preserve full scrollback and return viewport repaint on equal-size diffs.
- Capped streaming edit diff previews to a fixed trailing window and reported hidden hunk counts.
- Updated tmux and regression tests to validate hidden overlays, nativeText frame sources, and scrollback retention.
- Removed stream preview height tracking and simplified tool call rendering to always invalidate the content box.
- Replaced composed keyword decorators in `CustomEditor.decorateText` with `highlightMagicKeywords`.
- Adjusted `UserMessageComponent` rendering to use `highlightMagicKeywords` with `keywordReset` for consistent foreground.
- Added `highlightMagicKeywords(text: string, resetTo?: string): string` and chained ultrathink, orchestrate, workflow glow.
- Updated ultrathink, orchestrate, and workflow matching to lowercase whitespace-delimited patterns with prose-only checks.
- Added `maskNonProse` and `keywordInProse` to skip fenced/inline code and HTML/XML segments while highlighting keywords.
- Added `KeywordHighlighter` with optional `resetTo`, and updated gradient highlighting to use masked match slicing.
- Added +Nk/+Nm turn-budget parsing with whitespace-boundary matching, multipliers, and hard `!` indicator.
- Added per-turn budget lifecycle plus APIs (`getTurnBudget`, `recordEvalSubagentUsage`) and hard-cap checks in eval runs.
- Added hard budget observability in eval preludes and docs by exposing `budget.hard` and documenting ceiling modes.
- Fixed streaming preview stutter with max-row tracking and padding, with tests for preview height and budget parsing.
- Replaced ad-hoc ANSI/VT stripping regexes with `stripVTControlCharacters` in status text handling and related tests.
- Updated status footer rendering to truncate using `truncateToWidth` and visible width after VT stripping.
- Extended tui cursor handling and rendering to strip markers from all lines and fit repaint/append-tail lines to width.
- Expanded deterministic render tests with overlay-aware assertions and recorded the truncation/cursor-marker behavior in changelogs.
- Added fuzzy token matching in agent-dashboard, state-manager, and tree-selector, replacing lowercased checks.
- Added search-query state and fuzzy-filter helpers to hook, oauth, and user-message selectors for query filtering.
- Updated filtered selectors to render match results, status lines, no-match text, and move selection within results.
- Added `overflowSearch` and filter state to `SelectList`, switching overflowing list matching to fuzzy checks.
- Configured `SelectList` input flow and fixed cancel so Escape/Ctrl+C closes lists when no matches exist.
- Updated changelogs and added tests for fuzzy-filter behavior in hook, oauth, user-message, and list selectors.