The periodic Claude-mode re-check (setInterval 8s) called
setClaudeMode(false) on plain/codex surfaces, which ran
claudeRenderer.clear() unconditionally. clear() empties the shared
output element (this.el), blanking live terminal/codex content until
the next repaint — perceived as text fading out then back every 8s.
- app.js: remove the 8s claude re-check interval
- terminal-view.js: only clear the renderer on an actual mode
transition (changed), so redundant setClaudeMode/setCodexMode(false)
no longer wipes the shared output
- index.html: bump terminal-view.js v12, app.js v21
Verified deterministically in Playwright: pre-fix the output wiped
48->0 ~350ms after each 8s /api/claude-surfaces fetch; post-fix 18s
window shows 0 fetches and content intact.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Scrolling:
- Fix snap-back race: render() read a stale autoScroll cache (updated only
on async scroll events), yanking scrolled-up users back to the bottom
during live output. Now measure the real bottom position from the DOM at
render time and gate auto-follow on an explicit autoScroll flag.
- Restore scroll-to-top history loading; add a wheel-up handler so desktop
(no touch, screen fits viewport → no scroll room → no scroll event) can
still load scrollback. Resume live updates on scroll-to-bottom.
- Remove the auto-load-when-fits path that permanently froze live updates.
- terminal-container: touch-action pan-y, overflow-y scroll, overscroll
contain; drop terminal-output min-height:100%; desktop app-container
explicit 100dvh height.
- gestures.js touchmove → passive (let Safari composite child scroll).
Claude-mode detection:
- Match node-wrapped `claude` processes (check all ps args tokens).
- Enumerate ALL workspaces via `cmux tree --all`, not just the active
window that the workspace.list socket returns.
- Don't cache empty results; keep last-known-good to survive transient
ps/socket failures. Periodic client-side re-check.
Misc:
- Desktop: Enter sends, Shift/Cmd+Enter newline (mobile unchanged).
- Keyboard area touch-action:none (no vertical drift), key row pan-x.
- claude-parser _stripAnsi also strips C0/C1 control chars.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Send button:
- submitText() sends text without trailing "\n", then a discrete Enter
key event after 100ms. cmux delivers send_text as a bracketed paste,
so a trailing newline became a literal newline in the Claude/Codex
input box instead of submitting — this required a second (empty)
press to actually send. Now one press = the full type-then-Enter
sequence. Fixes Codex always needing two presses and Claude 4+ line
messages not sending / rendering mid-state.
- data-text shortcut keys now type then send Enter separately
- mousedown.preventDefault keeps soft keyboard up so first tap submits
- Remove IME composition Enter handler (textarea Enter = newline now)
Codex view:
- New codex-parser.js / codex-renderer.js for OpenAI Codex CLI surfaces
- /api/codex-surfaces endpoint; generalize surface-ref lookup into
_getSurfaceRefsForProcess() (claude + codex)
- app.js updateCodexMode(), terminal.setCodexMode(), codex-mode body
class (mutually exclusive with claude-mode)
Claude mode:
- Auto-load scrollback when content fits the viewport
- Trim claude-keyboard.js scaffolding; parser/renderer/CSS tweaks
Bump virtual-keyboard.js?v=9 cache-bust.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Auto-request scrollback history when user scrolls to top of terminal
- Preserve scroll position when prepending scrollback content
- Add files/prepublishOnly to package.json for npm install -g support
- Suppress url.parse() deprecation warning from Express internals
- Fix reconnect: re-subscribe to surface after auth-ok on reconnect
- Improve iOS background recovery with visibility API + elapsed check
- Harden ANSI stripping to handle OSC and other escape sequences
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Claude Code parsed view with block-based rendering (prompt, tool-use,
tool-result, code, diff, table, selection options, status bar)
- Add session status dots in sidebar and top bar (idle=yellow, working=green
with pulse animation) parsed from terminal title characters
- Differentiate active input prompt vs previous submitted prompts with
distinct background colors
- Fix Korean IME composition issue (last character on next line on Enter)
- Fix CSP inline script violation by moving to external sw-unregister.js
- Add per-block DOM diffing to prevent layout shifts on re-render
- Strip box-drawing borders from tool-result blocks for stable layout
- Add ngrok tunnel support, replace qrcode with qrcode-terminal
- Add Claude-specific keyboard action bar with mode toggle and shortcuts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full project including 12 UX improvements: wider gesture edge zone (50px),
prefers-reduced-motion support, additional shortcut keys (^A ^E ^R ^W ^U) and
PageDown, Escape to close sidebar, haptic feedback, key repeat for arrow keys,
sidebar loading/empty state, login loading state, reconnect status indicator,
terminal dim on disconnect, QR modal focus management, and desktop keyboard toggle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>