Code blocks should keep the richer Shiki rendering in modern WebUI while avoiding the old WebKit startup crash path by loading Shiki lazily and falling back to Prism only when the runtime cannot safely parse or execute it.
Constraint: Issue #461 is triggered by older Safari/WebKit parsing modern RegExp syntax during startup.
Rejected: Replace Shiki entirely with Prism | visual quality regressed for normal WebUI usage.
Confidence: high
Scope-risk: moderate
Directive: Keep Shiki out of the startup path unless macOS 12 WebView compatibility is re-verified.
Tested: cd desktop && bun run test -- --run src/components/chat/CodeViewer.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: Real WebUI smoke on http://127.0.0.1:1420/ verified six code blocks rendered with data-highlight-engine=shiki.
Not-tested: Physical macOS 12 WebView runtime.
Related: https://github.com/NanmiCoder/cc-haha/issues/461
The desktop app was still falling back to raw text in release builds for some
fenced code blocks, which left bash snippets visually wrong and too heavy for
chat use. This change switches the Shiki path to the JavaScript regex engine,
restores tighter code-block defaults for chat, and bumps the desktop app
version to 0.1.4 for the release artifacts.
Constraint: The packaged Tauri app must render markdown code blocks consistently without relying on WebView WASM behavior
Constraint: Chat code blocks should stay compact and should not show line numbers unless a caller explicitly requests them
Rejected: Keep tuning fallback-only CSS | did not address the packaged highlighter path failing to initialize
Rejected: Leave line numbers on by default | too noisy for assistant replies and bash snippets
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If code blocks regress again, inspect the highlighter engine path before adjusting chat spacing CSS
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test CodeViewer.test.tsx MarkdownRenderer.test.tsx Sidebar.test.tsx
Tested: cd desktop && bun run build:macos-arm64
Not-tested: Windows packaged build after the engine switch
This introduces a persisted light/dark appearance setting, maps the desktop shell onto semantic theme tokens, and reworks the highest-traffic chat/settings surfaces so the new dark mode is usable without regressing the original light theme.
The same pass tightens markdown rendering for chat replies by improving inline code, table overflow handling, and safe external-link behavior so dark-mode content stays legible in real conversations.
Constraint: Preserve the existing light theme while adding a user-selectable dark theme in Settings > General
Constraint: Avoid introducing new dependencies for styling or markdown handling
Rejected: Replacing the light palette with a single dual-purpose palette | would risk broad visual regressions across the existing desktop UI
Rejected: Implementing dark mode only for shell chrome | leaves chat markdown, diffs, and permission flows visually broken
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: New desktop UI should use semantic theme variables instead of hard-coded color literals so both themes stay aligned
Tested: bun run lint; bun run test; bun run build; browser review of theme switching, provider/permission states, and chat surfaces
Not-tested: Prototype-style pages with remaining hard-coded colors (scheduled/session control mock surfaces) were not fully normalized in this change
Replace prism-react-renderer with shiki/react-shiki in CodeViewer for
dramatically better tokenization (50+ TextMate scopes vs ~15 Prism tokens).
Custom warm-code theme with improved comment contrast (#5C6B7A, ~5:1 ratio)
and warm off-white background (#FDFCF9). Update DiffViewer to use matching
warm color palette with CSS variables instead of hardcoded GitHub colors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- StreamingIndicator now only shows during 'tool_executing' state
(ThinkingBlock already animates during 'thinking')
- Plain text code blocks force dark color (#24292f) instead of prism's
default faded gray which was invisible on our beige background
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- highlightAuto was misdetecting plain text (file trees, command output) as
code and applying wrong syntax colors (red keywords, green tags, etc.)
- Now only highlights when language is explicitly specified and known to hljs
- Code blocks without a specified language render as clean plain text
- Line numbers hidden for plain text blocks (only shown for actual code)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The desktop app now keeps the composer stable while turns are active,
reduces low-signal tool noise in the transcript, restores project context
under the composer after session creation, and relies on the CLI's own
permission requests instead of injecting broader desktop-side Bash asks.
This also brings in the supporting desktop app source tree and the server
routes/session metadata needed for git info, filesystem browsing, session
resume, slash commands, and SDK-backed permission bridging so the UI can
operate as a coherent feature instead of a partial patch.
Constraint: Desktop transcript needs to stay usable during long multi-tool sessions without hiding file-change diffs
Constraint: Permission prompts must mirror CLI behavior closely enough that read-only commands do not get desktop-only prompts
Rejected: Keep rendering Read/Bash bodies inline | too noisy and unlike the intended transcript model
Rejected: Commit only the touched desktop files | would leave the newly introduced desktop app incomplete in git history
Confidence: medium
Scope-risk: broad
Reversibility: messy
Directive: Treat non-writing tools as summary-first transcript events; do not re-expand them by default without validating the UX against long sessions
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test -- --run
Tested: bun test src/server/__tests__/conversations.test.ts
Not-tested: Manual visual regression against the exact screenshots in a live desktop session
Not-tested: Full root TypeScript check (repository still has unrelated extracted-native parse failures)