Skip to content

Expose stable window title templates - #6059

Merged
austinywang merged 14 commits into
mainfrom
issue-6045-stable-window-id
Jun 13, 2026
Merged

austinywang merged 14 commits into
mainfrom
issue-6045-stable-window-id

Conversation

@austinywang

@austinywang austinywang commented Jun 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #6045.

This adds an opt-in app.windowTitleTemplate setting for the macOS NSWindow.title, so users can expose a stable per-window token for AX/title-based tiling window managers without changing the default title behavior.

Default behavior is unchanged: when app.windowTitleTemplate is unset or blank, cmux keeps using the active workspace/current-directory title exactly as before.

Configuration

Example ~/.config/cmux/cmux.json:

{
  "app": {
    "windowTitleTemplate": "[cmux:{windowToken}] {activeWorkspace}"
  }
}

Supported placeholders:

  • {windowId}: full persisted per-window UUID, lowercased
  • {windowToken}: first 8 characters of the persisted window UUID
  • {activeWorkspace}: active workspace title, falling back to the default cmux title when blank
  • {activeDirectory}: active workspace current directory
  • {defaultTitle}: title cmux would have used without a template
  • {appName}: cmux

Unknown placeholders remain literal, and replacement is non-recursive.

Tiling WM Usage

With the template above, a restored window title includes a stable token such as [cmux:abcd1234]. AeroSpace/yabai users can match the title with a regex substring like:

\[cmux:abcd1234\]

The token comes from the existing persisted SessionWindowSnapshot.windowId, so restored macOS windows keep the same matchable token across relaunches.

Testing

No local tests, local builds, xcodebuild, or reload.sh were run per instruction.

Static/no-build validation run before push:

  • scripts/normalize-pbxproj.py
  • scripts/check-pbxproj.sh
  • scripts/lint-pbxproj-test-wiring.sh
  • jq empty web/messages/*.json web/data/cmux.schema.json
  • localization key-presence check for docs.configuration.schemaDescriptions.app.windowTitleTemplate across all 20 web/messages/*.json files
  • git diff --check
  • git diff --cached --check for merge resolutions

CI is being used as the required build/test gate.

Demo Video

Not recorded yet. The local dev build and launch are intentionally deferred until all required CI checks are green and the user explicitly asks to launch the tagged app.

Summary by CodeRabbit

  • New Features

    • Add customizable window title templates (app.windowTitleTemplate) with placeholders ({windowId}, {windowToken}, {activeWorkspace}, {activeDirectory}, {defaultTitle}, {appName}); blank preserves existing title. Titles refresh automatically when settings or active directory change.
  • Documentation

    • Add docs, schema, examples and translations for the new setting; guidance for using stable window tokens.
  • Tests

    • Add tests for template resolution, unknown-placeholder preservation, blank-disable behavior, and settings integration.

@vercel

vercel Bot commented Jun 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jun 13, 2026 7:38pm
cmux-staging Building Building Preview, Comment Jun 13, 2026 7:38pm

@coderabbitai

coderabbitai Bot commented Jun 13, 2026 •

Copy link
Copy Markdown

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

Adds a WindowTitleTemplate type and Defaults key, registers and parses app.windowTitleTemplate, exposes a stable per-window UUID on TabManager, assigns/reuses window IDs in creation/registration, resolves configured title templates for window chrome with trimming/fallback, refreshes titles after config reloads, and wires tests, build, schema, docs, and localizations.

Changes

Window Title Template Feature

Layer / File(s) Summary
Template model and defaults
Sources/App/WindowTitleTemplate.swift, Packages/CmuxSettings/Sources/CmuxSettings/Keys/AppCatalogSection.swift, Sources/CmuxSettingsJSONPathSupport.swift, Sources/KeyboardShortcutSettingsFileStore+Template.swift, Sources/KeyboardShortcutSettingsFileStore.swift
Adds WindowTitleTemplate type, Defaults key app.windowTitleTemplate, registers the JSON path, includes the default template in generated templates, and parses app.windowTitleTemplate when importing settings.
TabManager: windowId and title resolution
Sources/TabManager.swift, Sources/TabManager+WindowTitle.swift
Adds TabManager.windowId, observers for directory and Defaults changes, new refresh/update helpers, and template-driven title computation with trimming and default fallbacks.
AppDelegate window identity helpers
Sources/AppDelegate+WindowIdentity.swift
Adds @MainActor helpers to resolve windows by UUID, choose/validate preferred startup UUIDs, and refresh window titles across tracked main windows.
Window creation and consistent windowId assignment
Sources/AppDelegate.swift
Exposes startupSessionSnapshot read access, threads preferredWindowId into createMainWindow(...), validates/reuses or generates UUIDs, assigns tabManager.windowId across registration and test seams, removes/refactors resolved-window helpers, and triggers title refresh after config reload.
Tests
cmuxTests/WindowTitleTemplateTests.swift
Adds unit and integration tests covering placeholder resolution, blank-value disabling, nested-placeholder safety, settings-file import persistence, and an NSWindow/TabManager title-update integration test.
Config docs, schema, and localization
docs/configuration.md, web/data/cmux.schema.json, web/app/[locale]/docs/configuration/page.tsx, web/messages/*
Documents app.windowTitleTemplate, adds schema entry and web example, and provides localized schema-description strings across message catalogs.
Build system integration
cmux.xcodeproj/project.pbxproj
Adds new source and test file references and PBX entries so the new files compile and tests run.

🎯 3 (Moderate) | ⏱️ ~25 minutes

"I thumped a template in the night,
an ID to hold the window tight—
tokens trimmed and placeholders hugged,
now tilers find their windows snug." 🐇✨


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
Cmux No Hacky Sleeps ❌ Error PR adds new shell script scripts/download-with-retry.sh containing sleep "$sleep_seconds" between curl retries; violates runtime-no-hacky-sleeps fixed-delay/retry guidance. Remove fixed sleep backoff. Use bounded curl retries/connect-timeouts (or a cancellation-aware retry abstraction) and rely on observable completion signals/exit codes instead of wall-clock waits.
Cmux Swift File And Package Boundaries ❌ Error WindowTitleTemplate is pure, unit-testable placeholder resolution (imports Foundation only) living in app target root Sources/App/WindowTitleTemplate*.swift, which the rule says should be behind... Extract WindowTitleTemplate + WindowTitleTemplateContext into a new SwiftPM package (Foundation-only), move/duplicate its unit tests there, and keep only TabManager/AppKit glue in the app target.
Docstring Coverage ⚠️ Warning Docstring coverage is 5.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (18 passed)
Check name Status Explanation
Title check ✅ Passed The title "Expose stable window title templates" clearly describes the main change: adding a new window title templating feature that exposes stable per-window tokens.
Description check ✅ Passed The PR description provides a clear summary of changes, configuration example, supported placeholders, testing approach, and usage guidance. It mostly covers the template structure though testing section states no local tests were run.
Linked Issues check ✅ Passed The PR successfully addresses issue #6045 by implementing a configurable window title template feature with a stable windowToken placeholder, enabling tiling window manager integration as requested.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the window title template feature (configuration, template resolution, window ID tracking, settings integration) and documentation/localization updates. No unrelated changes detected.
Cmux Swift Actor Isolation ✅ Passed TabManager & AppDelegate are @MainActor; NotificationCenter observers use queue .main + MainActor.assumeIsolated before refreshWindowTitle (NSWindow.title). New WindowTitleTemplate/Context are Send...
Cmux Swift Blocking Runtime ✅ Passed Searched PR #6059 Swift diffs for DispatchSemaphore/semaphore.wait/Task.sleep/DispatchQueue.main.sync/NSLock/timers/polling; none present, so no blocking runtime sync added.
Cmux Expensive Synchronous Load ✅ Passed RestorableAgentSessionIndex.load() is only used as a cached nil-coalescing fallback in @MainActor TabManager/Workspace close, or inside SharedLiveAgentIndex Task.detached reload.
Cmux Cache Substitution Correctness ✅ Passed Snapshot/history reads prefer cached context.window but cold-fallback via windowForMainWindowId(NSApp.windows by cmux.main.) and reindexing; agent-index cache falls back to RestorableAgentSes...
Cmux Algorithmic Complexity ✅ Passed Template resolution uses 6 fixed replacements and a single linear scan of the template; window-title refresh iterates mainWindowContexts/tabs linearly (no nested full-collection scans, sorts, or re...
Cmux Swift Concurrency ✅ Passed New/added window-title template Swift files and PR-related title/notification helpers contain no DispatchQueue.global/.async, Task {, Combine, or completion-handler patterns; added NotificationCent...
Cmux Swift @Concurrent ✅ Passed Checked Swift files added/updated for this PR; found no nonisolated async declarations lacking @concurrent and no invalid @concurrent usage in diff scope.
Cmux Swift Logging ✅ Passed PR diff (plain=1) contains no added/changed print/debugPrint/dump/NSLog or Logger constant declarations; added invalid-setting diagnostics use cmuxSettingsFileStoreLogger.warning with privacy masking.
Cmux User-Facing Error Privacy ✅ Passed PR code adds windowTitleTemplate parsing/modeling; no NSAlert/user-facing error copy added. Any invalid-setting logging masks values via privacy .private(mask: .hash), so no raw templates/tokens leak.
Cmux Full Internationalization ✅ Passed Confirmed web/i18n/routing.ts has 20 locales and each web/messages/*.json contains docs.configuration.schemaDescriptions.app.windowTitleTemplate with non-empty, non-English translations; new Swift...
Cmux Swiftui State Layout ✅ Passed Verified Swift files involved in the change: WindowTitleTemplate/TabManager+WindowTitle add no SwiftUI/ObservableObject/@Published/GeometryReader; TabManager adds plain windowId (not @Published) an...
Cmux Architecture Rethink ✅ Passed Inspected WindowTitleTemplate, TabManager+WindowTitle, AppDelegate+WindowIdentity: deterministic placeholder resolution with no locks/sleeps/polling. TabManager’s new NotificationCenter observers r...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR only adds window-title templating/refresh; new files set existing NSWindow.title and AppDelegate close routing still uses cmuxWindowShouldOwnCloseShortcut (no Cmd+W/aux-window bypass).
Cmux Source Artifacts ✅ Passed Rules flag logs/caches/tmp/DerivedData/artifacts. PR files changed are only Swift/JSON/MD/TSX/pbxproj; web diff contains no such artifact paths or extensions.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-6045-stable-window-id

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 and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 13, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds an opt-in app.windowTitleTemplate setting that lets users embed a stable per-window token (drawn from the persisted SessionWindowSnapshot.windowId) into NSWindow.title, enabling reliable AX/title-based tiling-WM rules without changing the default title behavior. All three issues from the prior review round (missing locale translations, untrimmed return value, off-main notification queue) are resolved.

  • WindowTitleTemplate / WindowTitleTemplateContext implement non-recursive {placeholder} substitution as small, Sendable value types with their own test suite; the template is re-evaluated from UserDefaults on every title refresh, keeping the hot path simple with no extra caching layer.
  • TabManager gains a windowId: UUID? set by AppDelegate at registration time, a new workspaceCurrentDirectoryDidChange observer (delivered on queue: .main), and proper removeObserver cleanup in deinit for all observers.
  • AppDelegate+WindowIdentity extracts window-lookup helpers and seeds the initial non-restore window with its persisted UUID so the token remains stable across relaunches.

Confidence Score: 5/5

Safe to merge; the change is purely additive, default behavior is unchanged, and all prior review findings are resolved.

The feature is opt-in and fully isolated behind the blank-default guard in WindowTitleTemplate.configured(). The three issues flagged in the previous review round are all corrected. The only remaining item is a formatting inconsistency on one line in the settings parser, which has no behavioral impact.

Sources/KeyboardShortcutSettingsFileStore.swift — the windowTitleTemplate parsing block is compressed to a single long line, unlike every other parser in that function.

Important Files Changed

Filename Overview
Sources/App/WindowTitleTemplate.swift New struct implementing non-recursive {placeholder} substitution. Sendable, Equatable, well-tested; windowToken correctly takes first 8 hex chars of the UUID string.
Sources/App/WindowTitleTemplateContext.swift Trivial value-type context bag; Sendable and Equatable, no issues.
Sources/TabManager+WindowTitle.swift Title-rendering extracted into a clean extension. The previous trimmedResolvedTitle / queue: .main findings are resolved; windowTitle(for:) guards on nil windowId and falls back to the default title correctly.
Sources/TabManager.swift Adds windowId: UUID? property, a new workspaceCurrentDirectoryDidChange observer on queue: .main, refreshWindowTitle() call on settings change, and removeObserver cleanup in deinit; all correct.
Sources/AppDelegate+WindowIdentity.swift Extracts window-lookup helpers and adds refreshWindowTitlesAcrossMainWindows() with per-TabManager deduplication; also seeds the initial window's preferred UUID from the startup snapshot for stable tokens across relaunches.
Sources/KeyboardShortcutSettingsFileStore.swift Adds windowTitleTemplate parsing; logic is correct and matches workspaceInheritWorkingDirectory semantics, but the block is compressed to a single long line, unlike every other if-else if parser in the same function.
cmuxTests/WindowTitleTemplateTests.swift Covers placeholder resolution, unknown-placeholder preservation, blank-disabled behavior, settings-store wiring, and the directory-change → title-refresh path; good coverage.

Sequence Diagram

sequenceDiagram
    participant WS as Workspace
    participant NC as NotificationCenter
    participant TM as TabManager
    participant WTT as WindowTitleTemplate
    participant UD as UserDefaults
    participant WIN as NSWindow

    WS->>NC: post(.workspaceCurrentDirectoryDidChange, userInfo:[workspaceId:])
    NC->>TM: closure (queue: .main)
    TM->>TM: workspaceCurrentDirectoryDidChange(workspaceId:)
    TM->>TM: "guard workspaceId == selectedTabId"
    TM->>WTT: configured() → reads UserDefaults
    UD-->>WTT: rawValue string
    WTT-->>TM: WindowTitleTemplate?
    TM->>WTT: resolved(context: WindowTitleTemplateContext)
    WTT-->>TM: final title string
    TM->>WIN: "title = trimmedResolvedTitle"

    Note over TM,UD: On settings reload, AppDelegate calls refreshWindowTitlesAcrossMainWindows() which fans out to each unique TabManager
Loading

Reviews (8): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread web/messages/en.json Outdated
Comment thread Sources/TabManager.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/TabManager.swift`:
- Around line 6811-6812: The code trims resolvedTitle into trimmedResolvedTitle
but still returns resolvedTitle, allowing leading/trailing whitespace to leak
into NSWindow.title; update the return in the method that computes the window
title to return trimmedResolvedTitle.isEmpty ? defaultTitle :
trimmedResolvedTitle (use trimmedResolvedTitle in the non-empty case instead of
resolvedTitle) so the trimmed result is applied to NSWindow.title.

In `@web/data/cmux.schema.json`:
- Around line 269-274: Update the fallback wording for the windowTitleTemplate
property so both schema and locale match the actual behavior: in
web/data/cmux.schema.json (lines 269-274) revise the "description" for
"windowTitleTemplate" to state that a blank value preserves the existing default
title (which may include the current directory) rather than only the
"active-workspace title", and keep the list of supported placeholders unchanged;
in web/messages/en.json (lines 866-869) make the mirror change to the English
help text so it also says a blank value preserves the existing default
title/current-directory fallback instead of implying it only uses the
active-workspace title.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a09b546a-bfc6-46bc-9851-56f75222a83c

📥 Commits

Reviewing files that changed from the base of the PR and between 0b82dfe and 2426c8d.

📒 Files selected for processing (14)
  • Packages/CmuxSettings/Sources/CmuxSettings/Keys/AppCatalogSection.swift
  • Sources/App/WindowTitleTemplate.swift
  • Sources/AppDelegate.swift
  • Sources/CmuxSettingsJSONPathSupport.swift
  • Sources/KeyboardShortcutSettingsFileStore+Template.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/TabManager.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/WindowTitleTemplateTests.swift
  • docs/configuration.md
  • web/app/[locale]/docs/configuration/page.tsx
  • web/data/cmux.schema.json
  • web/messages/en.json
  • web/messages/ja.json

Comment thread Sources/TabManager.swift Outdated
Comment thread web/data/cmux.schema.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Sources/TabManager.swift (2)

3786-3803: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mirror PR-tracker cleanup in every workspace-removal path.

closeWorkspace(_:) tears down both sidebarGitMetadataService and pullRequestProbing, but detachWorkspace(tabId:) and restoreSessionSnapshot(_:) now only clear the git-probe side. After a window move or full session restore, this TabManager can keep polling orphaned workspace/panel IDs until deinit, which is the kind of entrypoint drift the repo explicitly tries to avoid. As per coding guidelines, shared behavior exposed through multiple entrypoints should use one shared action/model path and verify every entrypoint that invokes it.

Also applies to: 8098-8102

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/TabManager.swift` around lines 3786 - 3803, detachWorkspace(tabId:)
and restoreSessionSnapshot(_:) only clear sidebarGitMetadataService but not
pullRequestProbing, causing orphaned polling; extract or reuse a shared teardown
action (e.g. teardownProbesForWorkspace(workspaceId: UUID) or reuse the same
helper closeWorkspaceDidTearDownProbes) and call it from detachWorkspace(tabId:)
and restoreSessionSnapshot(_:) so both
sidebarGitMetadataService.clearWorkspaceGitProbes(workspaceId:) and
pullRequestProbing.clearProbes(forWorkspaceId:) (or the existing method used by
closeWorkspace(_:)) are invoked for the removed workspace, leaving other
teardown steps (groupId=nil, unwireClosedBrowserTracking,
recentlyClosedBrowsers.removeSnapshots, owningTabManager=nil) unchanged.

Source: Coding guidelines


1149-1202: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Extract the new sidebar-git / welcome lifecycle code instead of growing TabManager.swift further.

These additions push even more unrelated behavior into an already 8k+ line file that is simultaneously doing workspace lifecycle, window integration, session restore, UI-test harnessing, and now sidebar-git composition plus welcome-command readiness. Please move the new subsystem wiring/helpers into dedicated Sources/ files before adding more here. As per coding guidelines, production Swift files over 800 lines and mixed-responsibility files should be split rather than expanded further.

Also applies to: 1792-1850

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/TabManager.swift` around lines 1149 - 1202, This large
TabManager.swift init block that constructs SidebarGitMetadataService,
PullRequestProbeService/PullRequestPollService, sharedWorkspaceGitProbeLimiter,
and wires attach(host:) (symbols: SidebarGitMetadataService,
PullRequestProbeService, PullRequestPollService, sharedWorkspaceGitProbeLimiter,
sidebarGitMetadataService, pullRequestProbing, attach(host:)) should be
extracted into a dedicated small composition/coordinator type (e.g.
SidebarGitCoordinator) in its own source file: move the creation of
pullRequestProbeService, pullRequestPollService, the SidebarGitMetadataService
instantiation, and the probeLimiter defaulting logic into that coordinator,
implement a simple API (init(...) and attachHost(_ host: SidebarGitHosting) or
similar) and have TabManager only create the coordinator and call its
attachHost(self) and store only the minimal seam(s) (or forward calls). Replace
the large init wiring in TabManager with a 1–2 line creation/forward to the new
coordinator, keeping all behavior identical (preserve debugLog lambda,
defaulting to Self.sharedWorkspaceGitProbeLimiter, and types used), and move any
welcome/ready-to-run helper logic related to sidebar-git into the same new file
or a separate small helper to keep TabManager under the 800-line,
single-responsibility limit.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/AppDelegate.swift`:
- Line 1053: startupSessionSnapshot is mutable outside its intended owner;
restrict mutation to AppDelegate by changing its declaration in AppDelegate from
"var startupSessionSnapshot: AppSessionSnapshot?" to "private(set) var
startupSessionSnapshot: AppSessionSnapshot?" (or make it private and add a
public read-only accessor property) so only AppDelegate can write it while
AppDelegate+WindowIdentity.swift can continue to read it; update any call sites
that attempt to mutate it outside AppDelegate (if any) to use an AppDelegate
method instead.

In `@web/messages/uk.json`:
- Line 767: Update the Ukrainian string for the "windowTitleTemplate" key to
replace the awkward phrase "відступом до поточного каталогу" with wording that
clearly means “fallback to the current directory” (for example, "поверненням до
поточного каталогу" or "з використанням поточного каталогу як запасного
варіанта"); keep the rest of the sentence unchanged so the full value still
lists supported placeholders and context.

---

Outside diff comments:
In `@Sources/TabManager.swift`:
- Around line 3786-3803: detachWorkspace(tabId:) and restoreSessionSnapshot(_:)
only clear sidebarGitMetadataService but not pullRequestProbing, causing
orphaned polling; extract or reuse a shared teardown action (e.g.
teardownProbesForWorkspace(workspaceId: UUID) or reuse the same helper
closeWorkspaceDidTearDownProbes) and call it from detachWorkspace(tabId:) and
restoreSessionSnapshot(_:) so both
sidebarGitMetadataService.clearWorkspaceGitProbes(workspaceId:) and
pullRequestProbing.clearProbes(forWorkspaceId:) (or the existing method used by
closeWorkspace(_:)) are invoked for the removed workspace, leaving other
teardown steps (groupId=nil, unwireClosedBrowserTracking,
recentlyClosedBrowsers.removeSnapshots, owningTabManager=nil) unchanged.
- Around line 1149-1202: This large TabManager.swift init block that constructs
SidebarGitMetadataService, PullRequestProbeService/PullRequestPollService,
sharedWorkspaceGitProbeLimiter, and wires attach(host:) (symbols:
SidebarGitMetadataService, PullRequestProbeService, PullRequestPollService,
sharedWorkspaceGitProbeLimiter, sidebarGitMetadataService, pullRequestProbing,
attach(host:)) should be extracted into a dedicated small
composition/coordinator type (e.g. SidebarGitCoordinator) in its own source
file: move the creation of pullRequestProbeService, pullRequestPollService, the
SidebarGitMetadataService instantiation, and the probeLimiter defaulting logic
into that coordinator, implement a simple API (init(...) and attachHost(_ host:
SidebarGitHosting) or similar) and have TabManager only create the coordinator
and call its attachHost(self) and store only the minimal seam(s) (or forward
calls). Replace the large init wiring in TabManager with a 1–2 line
creation/forward to the new coordinator, keeping all behavior identical
(preserve debugLog lambda, defaulting to Self.sharedWorkspaceGitProbeLimiter,
and types used), and move any welcome/ready-to-run helper logic related to
sidebar-git into the same new file or a separate small helper to keep TabManager
under the 800-line, single-responsibility limit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 68df73fa-a7a4-40cd-92a8-2513c07ad07e

📥 Commits

Reviewing files that changed from the base of the PR and between 2426c8d and f3d894c.

📒 Files selected for processing (27)
  • Sources/AppDelegate+WindowIdentity.swift
  • Sources/AppDelegate.swift
  • Sources/KeyboardShortcutSettingsFileStore.swift
  • Sources/TabManager+WindowTitle.swift
  • Sources/TabManager.swift
  • cmux.xcodeproj/project.pbxproj
  • web/data/cmux.schema.json
  • web/messages/ar.json
  • web/messages/bs.json
  • web/messages/da.json
  • web/messages/de.json
  • web/messages/en.json
  • web/messages/es.json
  • web/messages/fr.json
  • web/messages/it.json
  • web/messages/ja.json
  • web/messages/km.json
  • web/messages/ko.json
  • web/messages/no.json
  • web/messages/pl.json
  • web/messages/pt-BR.json
  • web/messages/ru.json
  • web/messages/th.json
  • web/messages/tr.json
  • web/messages/uk.json
  • web/messages/zh-CN.json
  • web/messages/zh-TW.json

Comment thread Sources/AppDelegate.swift Outdated
Comment thread web/messages/uk.json Outdated
Comment thread Sources/TabManager.swift
@austinywang
austinywang merged commit 410bd8e into main Jun 13, 2026
24 checks passed
hhsw2015 pushed a commit to hhsw2015/cmux that referenced this pull request Jun 14, 2026
PRs included:
- AppDelegate decomposition: CmuxSession session-snapshot repository (manaflow-ai#6030)
- Fix Cmd+T cwd after session restore (manaflow-ai#6055)
- Speed up iOS terminal scroll rendering (manaflow-ai#6035)
- Preserve Pi sessions across workspace restore (manaflow-ai#5607)
- Scope Biome checks to maintained JS sources (manaflow-ai#6008)
- Fix manaflow-ai#5917: restore OSC 11 pane-local backgrounds (manaflow-ai#5997)
- Expose stable window title templates (manaflow-ai#6059)
- Honor macos-option-as-alt left/right
- Fix macOS 27 SF Symbol rasterization crash (manaflow-ai#5999)
- CmuxRemote* family: extract Workspace remote/cloud-VM connectivity
- Fix iOS workspace swipe-delete confirmation crash (manaflow-ai#6051)
- TabManager decomposition Wave 3+4 sub-models
- Sidebar row cleanups: branchless frame anchor
- CmuxIPCService: extract AppDelegate multi-window CLI routing
- CmuxSidebarGit: extract TabManager git-metadata + PR-polling subsystem
- CmuxTerminalCore: extract terminal core leaf

Fork-side adjustments:
- ghostty submodule: cherry-pick mouse-modifier-state fix onto our renderer-realized branch
- Workspace.swift: take theirs (upstream extracted ~7700 lines into CmuxCore.Remote/CmuxRemoteSession packages); restore fork's renameTopLevelLayoutTabContaining/closeTopLevelLayoutTabContaining + surfaceTmuxClientTTYNames + WorkspaceLayoutTab integration
- TabManager.swift: take theirs; re-add static allocatePortOrdinal()
- BrowserPanelView, RenderableSystemSymbol: keep fork's cmuxSymbolPixelSize extension on top of upstream's cmuxSymbolRasterSize
- Add CmuxWorkspaces / CMUXSessionDaemon / CmuxCommandPalette imports to TerminalController, Workspace, SessionPersistence
- Sources/Workspace+P43Stubs.swift: thin shims for SplitEqualizer, WorkspaceRemoteSessionController.PortScanKickReason, WorkspaceGroupNewWorkspacePlacementSettings (legacy types fork TC still calls; replace with package APIs in P44+)
- Sources/GhosttySurfaceSizeDeferralReason.swift: restore fork-only enum (deleted by upstream)
- Sources/StableLayout/SessionBlueprintExportAction.swift: parked debug action (depends on legacy SessionPersistenceStore, gone)
- Sources/GhosttyTerminalView.swift: stub ghostty_surface_select_cursor_line_compat (needs zig 0.15.2 xcframework rebuild)
- pbxproj: keep-both, drop stale ProcessPipeReader/SplitEqualizer/Panels/BrowserProxyEndpoint refs, fix SurfaceHibernationPolicy UUID collision
- Drop fork's WorkspaceRemoteConfiguration.swift + WorkspaceRemoteSSHBatchCommandBuilder.swift (extracted to CmuxCore package)

This branch was successfully deployed

1 active deployment
Preview – cmux — dc6048fc Deployed Jun 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose stable per-window identifier in macOS window title for tiling WM integration

1 participant