Skip to content

feat(runtime): stamp the host terminal theme on headless mobile tabs - #10419

Draft
bbingz wants to merge 4 commits into
stablyai:mainfrom
bbingz:feat/headless-mobile-terminal-theme
Draft

bbingz wants to merge 4 commits into
stablyai:mainfrom
bbingz:feat/headless-mobile-terminal-theme

Conversation

@bbingz

@bbingz bbingz commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

A phone paired to orca serve or an SSH host can receive the host's configured terminal palette even when no desktop renderer is running. Main stamps the existing optional terminalTheme field on all three terminal-tab builders: persisted-session hydration, PTY-backed rescue/split publication, and phone-initiated terminal creation. A runtime without a settings store still omits the field.

Main and renderer share the palette resolver, including custom themes, color overrides, background/cursor opacity and the current minimum-contrast setting. The main-process resolver treats a system theme as dark because it has no matchMedia; an explicit light setting stays light. Consequently, a main-generated tab can differ from a desktop whose OS currently prefers light. There is no new RPC, stream opcode, or required client field; older hosts retain the client's existing fallback.

This remains a draft stacked on #10421 at a1dcff2cab9a16c6511c25179d3f5a376c6df67c. Review #10421 first; this commit adds the headless publication and shared resolution. Its unique delta now spans 12 files because the runtime and graph-sync modules have since been split. The inherited mobile picker remains dark-mode-only, with the light slot stored for later integration.

Testing and review

At 4a33ca211c0011ad43b77616b2dd09fe2ad8b8aa, independent verification passed 1,445 tests across 22 files, with 1 existing skipped test. This includes the three host builders, no-store omission, settings-based palette resolution, overrides/opacity, existing renderer contrast tests, the runtime service suite, and terminal snapshot preservation/reconciliation. CLI, Node and Web TypeScript checks (--composite false), changed-file lint/format and diff whitespace passed. No existing test assertion was removed or weakened.

Independent Cursor review passed for this exact SHA (spec-compliance PASS; quality APPROVED). Native iOS/Android rendering, complete Expo bundling/mobile app typecheck, live paired-host/SSH and desktop-system-light smoke, packaging and the full repository suite were not run. These unit tests do not establish live settings propagation to an already-published phone session or native rendering. Manual integration remains unchecked; this is not a ready-for-merge claim.

AI disclosure

Cursor ported the original stack to the current runtime modules. Codex independently checked the original seven-file stack delta, source and affected tests. The shared catalog and picker validation belong to the separately reviewed parent #10421.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Centralizes built-in terminal theme catalogs and shared appearance resolution in shared modules. Adds custom theme selection, fallback handling, color normalization, opacity conversion, and catalog validation. Updates renderer theme consumers and mobile synchronization to use the shared resolver. Extends headless mobile runtime terminal tabs with host-derived themes across hydrated, persisted, live PTY-backed, and phone-created terminals, with tests covering system preferences, overrides, opacity, missing settings, and prototype-safe catalog lookup.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description provides detailed scope, implementation context, testing results, limitations, and AI disclosure. However, it does not follow the required template and omits required sections such as … Update the description to use the repository template. Add ELI5, What Changed, Why, Linked Issue with a valid issue reference, Visual Proof with attachments or exactly N/A plus a reason, Testing checkboxes, Review, Agent skill upstream boun…
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the primary change: applying the host terminal theme to headless mobile terminal tabs.
Full details: Description check

Explanation

The description provides detailed scope, implementation context, testing results, limitations, and AI disclosure. However, it does not follow the required template and omits required sections such as Visual Proof or an exact N/A explanation, the required Linked Issue format, and the checklist sections.

Resolution

Update the description to use the repository template. Add ELI5, What Changed, Why, Linked Issue with a valid issue reference, Visual Proof with attachments or exactly N/A plus a reason, Testing checkboxes, Review, Agent skill upstream boundary, Notes, and the full Checklist.

  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AmethystLiang
AmethystLiang requested a review from OrcaWin July 24, 2026 16:48
@bbingz
bbingz force-pushed the feat/headless-mobile-terminal-theme branch from 60d19d2 to 5bde200 Compare July 25, 2026 04:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 08dc2af8-461a-4d96-90c1-4163957b991f

📥 Commits

Reviewing files that changed from the base of the PR and between 60d19d26409d85953522a7d67c40345acf7b847f and 5bde2002215c08bd035007d32b779e1293b7842d.

📒 Files selected for processing (25)
  • mobile/src/components/NewWorkspaceFab.tsx
  • mobile/src/theme/mobile-theme-palette.test.ts
  • mobile/src/theme/mobile-theme.ts
  • mobile/src/theme/themed-style-factories.test.ts
  • mobile/src/theme/unthemed-color-imports.test.ts
  • src/main/runtime/headless-mobile-terminal-theme.test.ts
  • src/main/runtime/orca-runtime.ts
  • src/renderer/src/lib/terminal-contrast-correction.test.ts
  • src/renderer/src/lib/terminal-theme.ts
  • src/renderer/src/lib/terminal-themes-data.ts
  • src/renderer/src/lib/terminal-themes/types.ts
  • src/renderer/src/runtime/sync-runtime-graph.ts
  • src/shared/runtime-mobile-terminal-theme.test.ts
  • src/shared/runtime-mobile-terminal-theme.ts
  • src/shared/terminal-theme-resolution.ts
  • src/shared/terminal-themes/catalog-merge.ts
  • src/shared/terminal-themes/classic.ts
  • src/shared/terminal-themes/defaults.ts
  • src/shared/terminal-themes/index.ts
  • src/shared/terminal-themes/popular-dark-core.ts
  • src/shared/terminal-themes/popular-dark-extended.ts
  • src/shared/terminal-themes/popular-dark.ts
  • src/shared/terminal-themes/popular-light.ts
  • src/shared/terminal-themes/terminal-theme-catalog.test.ts
  • src/shared/terminal-themes/types.ts
💤 Files with no reviewable changes (2)
  • src/renderer/src/lib/terminal-themes-data.ts
  • src/renderer/src/lib/terminal-themes/types.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • src/shared/terminal-themes/terminal-theme-catalog.test.ts
  • src/shared/terminal-themes/catalog-merge.ts
  • src/shared/terminal-themes/types.ts
  • src/shared/terminal-themes/popular-dark-core.ts
  • src/shared/terminal-themes/popular-dark.ts
  • src/shared/runtime-mobile-terminal-theme.test.ts
  • src/shared/terminal-themes/classic.ts
  • src/shared/terminal-themes/defaults.ts
  • src/shared/terminal-themes/popular-dark-extended.ts
  • src/renderer/src/lib/terminal-contrast-correction.test.ts
  • src/main/runtime/orca-runtime.ts
  • src/shared/terminal-themes/index.ts
  • src/shared/runtime-mobile-terminal-theme.ts
  • src/shared/terminal-theme-resolution.ts
  • src/shared/terminal-themes/popular-light.ts
  • src/main/runtime/headless-mobile-terminal-theme.test.ts
  • src/renderer/src/runtime/sync-runtime-graph.ts
  • src/renderer/src/lib/terminal-theme.ts

Comment thread mobile/src/theme/mobile-theme.ts Resolved
@bbingz
bbingz force-pushed the feat/headless-mobile-terminal-theme branch 2 times, most recently from 3e42457 to 0ec4d3b Compare July 25, 2026 09:04
@bbingz

bbingz commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main via updated #10418 tip (a69838ef4).

CodeRabbit notes about ThemeColors duplicate / empty themed-style factory registry target files that are not in this PR (later stack).

@bbingz

bbingz commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

Catch-up rebase onto refreshed #10418 tip on latest main (no content change).

@bbingz
bbingz force-pushed the feat/headless-mobile-terminal-theme branch from a269a90 to f21603b Compare July 25, 2026 10:13
@bbingz

bbingz commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

Catch-up rebase onto latest main via refreshed #10418 (no content change).

@nwparker nwparker added the enhancement New feature or request label Jul 27, 2026
@bbingz
bbingz force-pushed the feat/headless-mobile-terminal-theme branch 2 times, most recently from 7992064 to 786d75c Compare July 29, 2026 06:41
@greptile-apps

greptile-apps Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR publishes the host's terminal theme to all three headless mobile tab builders in the main process, closing a gap where paired phones on orca serve or SSH always rendered the phone's hardcoded fallback palette regardless of what the host had configured. The shared projection logic (resolveEffectiveTerminalAppearance, theme catalog, helpers) is extracted from the renderer into src/shared/ so main and renderer produce identical theme shapes from the same code, eliminating future drift.

  • Three builders patched, not one: publishPtyBackedMobileSessionTerminal, buildHeadlessMobileSessionTerminalTabs, and createHeadlessMobileSessionTerminal all stamp terminalTheme; the snapshot merge keeps the first tab per key, so any unstamped builder would permanently leave panes on the fallback palette.
  • Strictly additive on the wire: terminalTheme was already an optional field that mobile clients handle; no protocol bump is needed, and older phones ignore the new field transparently.
  • Known limitation acknowledged: main has no matchMedia, so theme: 'system' resolves to dark everywhere in the main process — the same bias the renderer uses when matchMedia is absent, and explicitly flagged in the PR description and code comments.

Confidence Score: 5/5

Safe to merge. The change is strictly additive on the wire, and all three tab builders are correctly stamped with no behavioural regressions for existing clients.

The core logic (theme resolution, opacity conversion, string-only wire filtering) is a clean extraction of already-shipped renderer code into src/shared/, with no algorithmic changes. All three tab builders are covered, the snapshot-merge first-tab-wins invariant is respected, and the null-prototype catalog map plus Object.hasOwn guards prevent prototype-key lookup. The hardcoded dark bias for systemPrefersDark in main is intentional and well-documented. Sixteen new targeted tests and the existing 62-test suite all pass. No protocol changes, no capability negotiation, no new RPCs.

Files Needing Attention: No files require special attention. The most critical path — the three builders in orca-runtime.ts — is straightforward and well-covered by tests.

Important Files Changed

Filename Overview
src/shared/runtime-mobile-terminal-theme.ts New shared projection function. Correctly handles null/undefined settings, applies color overrides and opacity in the right order, strips non-string values before sending over the wire, and defaults terminalUseSeparateLightTheme absent to true to match the shipped GlobalSettings default.
src/shared/terminal-theme-resolution.ts Logic extracted verbatim from the renderer's terminal-theme.ts into shared. systemPrefersDark parameter is now required (no DOM default), keeping the module import-safe for main and Metro. No behavioural changes to the resolver itself.
src/main/runtime/orca-runtime.ts Adds resolveHostMobileTerminalTheme() private helper (hardcoded dark bias, well-commented) and stamps terminalTheme on all three RuntimeMobileSessionTerminalTab construction sites. Optional chaining on this.store?.getSettings?.() correctly keeps store-less instantiation working.
src/shared/terminal-themes/index.ts Catalog relocated to shared. getBuiltinTerminalThemePalette uses Object.hasOwn on a null-prototype map, making prototype-key lookup impossible. BUILTIN_TERMINAL_THEME_NAMES is computed once at module load from the same map.
src/shared/terminal-themes/catalog-merge.ts Null-prototype accumulator (Object.create(null)) replaces plain {}, preventing __proto__/constructor keys from shadowing Object.prototype. Object.hasOwn replaces Object.prototype.hasOwnProperty.call for consistency.
src/renderer/src/lib/terminal-theme.ts Renderer module now re-exports the shared resolver and constants; removed duplicated logic. getBuiltinTheme is a thin wrapper over getBuiltinTerminalThemePalette. Return type changed from ITheme to TerminalColorOverrides — PR reports typechecks pass.
src/renderer/src/runtime/sync-runtime-graph.ts Replaces local resolveMobileTerminalTheme(state, prefersDark) with the shared resolveRuntimeMobileTerminalTheme(state.settings, prefersDark). The null-settings guard in the shared function is equivalent to the removed early-return in the old local helper.
src/main/runtime/headless-mobile-terminal-theme.test.ts New test file covering all three builders via the internal type alias. Exercises dark/light/system themes, opacity conversion, store-less instantiation, and palette stamping for each builder path.
src/shared/runtime-mobile-terminal-theme.test.ts Unit tests for the shared projection. Covers null/undefined settings, system-mode resolution, absent terminalUseSeparateLightTheme defaulting, 3-digit hex expansion, non-string value stripping, and unknown-theme fallback.
src/shared/terminal-themes/terminal-theme-catalog.test.ts Validates catalog size (30 entries), sort order, default name stability, own-property-only lookup, and that every palette has exactly the 22 keys the mobile WebView whitelists.

Sequence Diagram

sequenceDiagram
    participant Phone as Mobile Client
    participant Main as Main Process (orca-runtime.ts)
    participant Shared as src/shared/runtime-mobile-terminal-theme.ts
    participant Catalog as src/shared/terminal-themes/index.ts
    participant Store as RuntimeStore (GlobalSettings)

    Phone->>Main: connect (headless / SSH)

    Note over Main: Three tab-builder paths
    Main->>Main: resolveHostMobileTerminalTheme()
    Main->>Shared: "resolveRuntimeMobileTerminalTheme(settings, systemPrefersDark=true)"
    Shared->>Store: getSettings()
    Shared->>Shared: resolveEffectiveTerminalAppearance(settings, dark)
    Shared->>Catalog: getBuiltinTerminalThemePalette(themeName)
    Catalog-->>Shared: "TerminalColorOverrides | null"
    Shared->>Shared: apply terminalColorOverrides + opacity
    Shared-->>Main: "RuntimeMobileTerminalTheme { mode, theme }"

    Main->>Main: "build RuntimeMobileSessionTerminalTab { terminalTheme }"
    Main->>Phone: publish tab snapshot (with terminalTheme stamped)
    Phone->>Phone: render terminal with host palette
Loading

Reviews (2): Last reviewed commit: "docs(runtime): correct the mobile termin..." | Re-trigger Greptile

@bbingz
bbingz force-pushed the feat/headless-mobile-terminal-theme branch 2 times, most recently from 2e4fba5 to 7eefa59 Compare August 6, 2026 02:01
@bbingz
bbingz marked this pull request as draft August 11, 2026 07:49
@bbingz

bbingz commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Queue hygiene (contributor): converting this PR to draft.

It is not superseded by main — still a valid product stack — but at +hundreds–thousands of lines it sits behind a large campaign backlog and is unlikely to get review soon. Draft reduces noise for maintainers.

If product wants this stack prioritized, say so and we will mark ready again / rebase.

@bbingz

bbingz commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Relationship note — this PR sits on top of #10421.

Its 31 files are a strict subset of the 37 here; the six that are genuinely mine are terminal-theme-resolution.ts, runtime-mobile-terminal-theme.ts (+ test), orca-runtime.ts, headless-mobile-terminal-theme.test.ts, and sync-runtime-graph.ts.

Intended order: land #10421 first, then I'll rebase this down to those six files so it reviews as a small headless-only change. Flagging it so neither of you reviews the shared relocation twice.

@bbingz
bbingz force-pushed the feat/headless-mobile-terminal-theme branch from 7eefa59 to 4a33ca2 Compare September 8, 2026 22:53
@bbingz bbingz changed the title feat(main): publish the host terminal theme to headless mobile tabs feat(runtime): stamp the host terminal theme on headless mobile tabs Sep 8, 2026
bbingz and others added 4 commits September 20, 2026 19:22
Co-authored-by: Cursor <cursoragent@cursor.com>
A phone paired to orca serve or SSH never sees the renderer, so main now
resolves the host palette (dark-biased, no matchMedia) and stamps it on
the three tab builders. The renderer sync path delegates to the same
shared resolver so attached and headless hosts cannot diverge.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bbingz
bbingz force-pushed the feat/headless-mobile-terminal-theme branch from 4a33ca2 to 7e0a040 Compare September 20, 2026 11:32

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants