Skip to content

Organize extension SDK boundaries - #5085

Merged
azooz2003-bit merged 10 commits into
mainfrom
feat-extension-sdk-organization
Jun 2, 2026
Merged

azooz2003-bit merged 10 commits into
mainfrom
feat-extension-sdk-organization

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jun 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Split legacy in-process sidebar provider/render APIs into CmuxSidebarProviderKit so CmuxExtensionKit stays focused on extension-author APIs.
  • Mark host transport and legacy host action APIs behind SPI, add typed sidebar host helpers, and tighten snapshot scope filtering.
  • Add a stub agent sidebar extension package as a clean SDK-consumer proof and update sample docs/projects.

Verification

  • swift test --package-path Packages/CmuxExtensionKit --scratch-path /tmp/cmux-sdk-proof-kit
  • swift build --package-path Packages/CmuxSidebarProviderKit --scratch-path /tmp/cmux-sdk-proof-provider2
  • swift test --package-path Packages/CMUXExtensionClient --scratch-path /tmp/cmux-sdk-proof-client2
  • swift test --package-path Examples/CmuxExtensionSidebarExamples --scratch-path /tmp/cmux-sdk-proof-sidebar-examples2
  • swift build --package-path Examples/StubAgentSidebarExtension --scratch-path /tmp/cmux-sdk-proof-stub2
  • xcodebuild -quiet -project Examples/TabsVisibleSidebar/TabsVisibleSidebar.xcodeproj -scheme TabsVisibleSidebar -configuration Debug -destination 'platform=macOS,arch=arm64' -derivedDataPath /tmp/cmux-sdk-proof-tabs2 CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO build
  • xcodebuild -quiet -project Examples/SampleSidebarExtensionApp/SampleSidebarExtensionApp.xcodeproj -scheme SampleSidebarExtensionApp -configuration Debug -destination 'platform=macOS,arch=arm64' -derivedDataPath /tmp/cmux-sdk-proof-sample2 CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO build
  • ./scripts/reload.sh --tag ext-sdk --swift-frontend-workaround

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.


Summary by cubic

Split the extension SDK into a clean extension-author API and app-side provider/host layers, and moved the sidebar contract to API v2 with simpler manifests, typed action results, and connection status. Updated examples, added string catalogs, tightened async calls, and introduced a stub agent extension.

  • Refactors

    • Introduced CmuxSidebarProviderKit for in-process providers with typed render models; examples now import it.
    • Replaced CMUXExtensionClient with CMUXExtensionHostSupport (host view + browser presenter); removed discovery/registry/session and tests.
    • Promoted manifest/snapshot to v2: readScopes/actionScopes, CmuxExtensionAPIVersion.sidebarV2, renamed CMUX* → Cmux* (actions, surfaces, XPC codec, validator, extension point), and switched Info.plist key to CmuxSidebarExtensionPointIdentifier; ExtensionKit point is generated at build time.
    • Collapsed base protocols (CmuxExtension, CmuxUIExtension) into CmuxSidebarExtension refining ExtensionKit; action results now use CmuxSidebarActionResult with optional rejectionReason.
  • New Features

    • Added .createWorkspaceWithPath action scope with localized permission copy.
    • Added CmuxSidebarConnectionStatus and async CmuxSidebarHost methods; samples handle status and use String(localized:).
    • Provider kit gained mutations and presentation requests (e.g., moveWorkspace, openWorkspacePopover/window, openURL).
    • Added Examples/StubAgentSidebarExtension and .xcstrings localizations across samples and the Tabs Visible example.

Written for commit fad4790. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added an in-process sidebar provider framework with provider descriptors, richer render models, icons, rows/sections, and presentation types.
    • New provider mutations, presentation requests, and workspace-move support.
  • Improvements

    • Async/typed sidebar host actions and connection status reporting; improved workspace creation (optional path) and richer workspace metadata (branches, ports, unread counts).
    • Example extensions and host integration migrated to the new provider APIs.
  • Documentation

    • Updated samples, README, and localized strings for new APIs.

@vercel

vercel Bot commented Jun 1, 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 2, 2026 3:06pm
cmux-staging Building Building Preview, Comment Jun 2, 2026 3:06pm

@coderabbitai

coderabbitai Bot commented Jun 1, 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 CmuxSidebarProviderKit, renames and SPI-gates many Cmux extension types to a provider model, refactors host transport to async/throws, migrates app UI, examples, and tests to provider contracts, and updates packages, Xcode projects, scripts, and localizations.

Changes

Provider-kit migration and host wiring

Layer / File(s) Summary
Provider kit and public models
Packages/CmuxSidebarProviderKit/*
Adds CmuxSidebarProviderKit manifest and public types: descriptors, snapshots, workspaces, render models, rows/sections, icons, text, mutations, commands, and presentation tabs.
ExtensionKit contracts & validation
Packages/CmuxExtensionKit/*
Renames CMUX→Cmux types (manifest, snapshot, action, surface, workspace, APIVersion), updates manifest shape to readScopes/actionScopes, introduces sidebarV2, adds SPI annotations, and adjusts validation and codec behavior.
Host transport & runtime
Packages/CMUXExtensionHostSupport/*, Packages/CmuxExtensionKit/*
SPI-gates host transport and action/result types, refactors CmuxSidebarHost to async/throws send(_:) plumbing, updates runtime/connection to typed CmuxSidebarConnectionStatus, and adjusts reply/continuation gates.
App UI and main rendering
Sources/ContentView.swift, Sources/*
Switches ContentView and sidebar selection to provider descriptors/existentials, updates render pipeline to consume CmuxSidebarProviderRenderModel/snapshot, and migrates action handling/mutations and drop/move wiring to provider move/mutation types.
Built-in providers & examples
Examples/CmuxExtensionSidebarExamples/*, Examples/*
Migrates all example sidebars (AttentionQueue, BrowserStack, DevServer, LastPrompt, ProjectWorktree, SuperCompact, SidebarExamples) and their tests to use CmuxSidebarProviderKit types and descriptors.
Sample/Stub extensions & host UI
Examples/SampleSidebarExtensionApp/*, Examples/StubAgentSidebarExtension/*, Sources/CMUXInstalledExtensionSidebarHostView.swift
Updates sample extensions to CmuxExtensionManifest/readScopes/actionScopes, connectionStatus API, async host calls; adds StubAgentSidebarExtension; rewires installed-extension host view and XPC host adapter to new types.
Xcode/package/project/scripts/localization
cmux.xcodeproj, cmux.xcworkspace, scripts/*, Resources/*
Rewires Swift package references (CMUXExtensionHostSupport, CmuxSidebarProviderKit), updates build scripts to emit appextensionpoint, removes old appextensionpoint resource, and adds/updates localization keys.

Sequence Diagram(s)

sequenceDiagram
  participant AppUI as App UI
  participant Provider as CmuxSidebarProvider
  participant Host as CmuxSidebarHost
  AppUI->>Provider: render(snapshot: CmuxSidebarProviderSnapshot)
  Provider-->>AppUI: CmuxSidebarProviderRenderModel
  AppUI->>Host: send action (select/create/open) as CmuxSidebarAction
  Host-->>AppUI: CmuxSidebarActionResult or throws CmuxSidebarActionError
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

  • manaflow-ai/cmux-dev-artifacts#1950 — Sidebar rendering and snapshot type changes may relate to failing WorkspaceSidebarScrollUITests.

Possibly related PRs

  • manaflow-ai/cmux#5127 — Modifies ContentView sidebar provider selection/routing; likely overlaps with provider selection changes here.
  • manaflow-ai/cmux#5092 — Also edits Sources/ContentView.swift and provider/extension presentation wiring.
  • manaflow-ai/cmux#5063 — Touches extension-point emission and build-time appextensionpoint scripts and project wiring.

Poem

i’m a rabbit in the tree of code,
i hop from snapshot to provider mode,
descriptors hum and hosts reply,
async tasks leap, errors fly —
sidebars render, packages sing,
a tiny rabbit ships a big spring. 🐇✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-extension-sdk-organization

@greptile-apps

greptile-apps Bot commented Jun 1, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR reorganizes the extension SDK into two clear layers — CmuxExtensionKit for extension authors and a new CmuxSidebarProviderKit for cmux-owned in-process providers — promotes the sidebar contract to API v2, and ships typed async/throwing host helpers with a proper cancellation bridge. It also adds a StubAgentSidebarExtension example and a new .createWorkspaceWithPath action scope.

  • SDK split: CmuxSidebarProviderKit extracts provider/render/section/row/snapshot models out of CmuxExtensionKit; host transport and legacy action APIs are moved behind @_spi(CmuxHostTransport); CmuxSidebarExtensionScene is made internal in favour of the CmuxSidebarExtension protocol default.
  • Async host API: CmuxSidebarHost gains ergonomic async throws helpers backed by CmuxSidebarActionReplyGate (NSLock-guarded) that bridge XPC callbacks to Swift concurrency with cooperative cancellation.
  • Localization gap: Two new permission-UI strings for .createWorkspaceWithPath (sidebar.extensions.actionScope.createWorkspaceWithPath and sidebar.extensions.permission.createWorkspaceWithPath.detail) are added to Resources/Localizable.xcstrings with only en and ja entries; 18 of the 20 catalog locales are missing translations and will fall back to raw key identifiers in the permission popover and access-review sheet.

Confidence Score: 4/5

Safe to merge after adding the 18 missing locale translations for the two new .createWorkspaceWithPath permission strings.

The SDK restructuring, async host API, cancellation bridge, and new package boundaries are all well-implemented. The one issue that needs fixing before ship is the localization gap: the two new permission-UI strings shown to users in the access-review sheet and permissions popover only carry English and Japanese translations, leaving users in all other supported locales with untranslated key identifiers on screen.

Resources/Localizable.xcstrings — the two new createWorkspaceWithPath entries need ar, bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, and zh-Hant translations.

Important Files Changed

Filename Overview
Resources/Localizable.xcstrings Two new permission-UI keys (createWorkspaceWithPath action scope and permission detail) only translated into en and ja; 18 of 20 catalog locales are missing entries.
Sources/CMUXInstalledExtensionSidebarHostView.swift Adds .createWorkspaceWithPath case to two switch blocks that render permission descriptions in the user-facing permission UI; the matching xcstrings keys are only available in en/ja.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarHost.swift New async/throwing public API wrapping callback-based action dispatch; CmuxSidebarActionReplyGate uses NSLock safely to bridge Swift Concurrency with the XPC callback path and handle cancellation without double-resume.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift Renamed types and status handler introduced; lock-guarded connection-generation pattern retained; internally consistent error handling with typed CmuxSidebarConnectionStatus.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarAction.swift Renamed to CmuxSidebarAction, moved behind @_spi(CmuxHostTransport); requiredScopes now correctly returns [.createWorkspace, .createWorkspaceWithPath] for path-based workspace creation.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift Slimmed down to purely wire the connection to the extension; actor isolation is safe — @unchecked Sendable justified by lock-guarded CMUXSidebarExtensionConnection.
scripts/write-sidebar-extension-point.sh Removes private _EXScopeRestriction key from generated .appextensionpoint plist; comment documents the deliberate avoidance of underscored keys; stale-declaration cleanup retained via find -delete.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderSnapshot.swift New in-process provider snapshot model extracting rows from sections; no actor isolation concerns, no blocking primitives.
Packages/CMUXExtensionHostSupport/Sources/CMUXExtensionHostSupport/Hosting/CMUXSidebarExtensionHostView.swift Minimal rename-only change; host view wiring unchanged.

Sequence Diagram

sequenceDiagram
    participant Ext as Extension (@main)
    participant Scene as CmuxSidebarExtensionScene
    participant Runtime as CmuxSidebarExtensionRuntime
    participant Conn as CMUXSidebarExtensionConnection
    participant Host as CmuxSidebarHost (async API)
    participant XPC as XPC / cmux host

    Ext->>Scene: body evaluated
    Scene->>Runtime: "init(sidebarExtension:) @MainActor"
    Runtime->>Conn: init(manifest:onSnapshot:onStatus:)
    XPC-->>Conn: accept(NSXPCConnection)
    Conn-->>Ext: connectionStatusDidChange(.connected)
    XPC-->>Conn: sidebarSnapshotDidChange(payload)
    Conn->>Runtime: "onSnapshot(snapshot) @MainActor"
    Runtime->>Host: CmuxSidebarHost(performCancellableAction:)
    Runtime->>Ext: update(context: CmuxSidebarContext)
    Ext->>Host: selectWorkspace(id) async throws
    Host->>Conn: perform(action, reply:)
    Conn->>XPC: performSidebarAction(payload, reply:)
    XPC-->>Conn: reply(resultPayload, nil)
    Conn->>Host: reply(CmuxSidebarActionResult)
    Host-->>Ext: returns / throws CmuxSidebarActionError
Loading

Reviews (5): Last reviewed commit: "Document sidebar provider kit models" | Re-trigger Greptile

Comment on lines 57 to 69
return CMUXSidebarSnapshot(
apiVersion: apiVersion,
sequence: sequence,
windowID: windowID,
selectedWorkspaceID: selectedWorkspaceID,
windowID: scopeSet.contains(.workspaceMetadata) ? windowID : nil,
selectedWorkspaceID: scopeSet.contains(.workspaceMetadata) ? selectedWorkspaceID : nil,
grantedReadScopes: scopeSet,
grantedActionScopes: actionScopeSet,
workspaces: workspaces.map { workspace in
scopeSet.contains(.workspaceMetadata)
? workspace.filtered(for: scopeSet)
: CMUXSidebarWorkspace(id: workspace.id, title: workspace.title)
: CMUXSidebarWorkspace(id: workspace.id, title: "")
}
)

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.

P1 workspaceList scope now silently strips workspace titles — breaking change for existing extensions

Before this change, an extension granted only .workspaceList received workspace.title from the snapshot. After it, the title is forcibly cleared to "". Any existing third-party or in-house extension that renders or logs workspace names using only the workspaceList scope will silently show empty strings without any compile-time or runtime error. The README only subtly signals this via "workspace identities and ordering only", which is easy to miss. It would help to add a runtime assertion or debug-only warning when an extension requests workspaceList but not workspaceMetadata, or at minimum document the behavioral break in the migration notes / CHANGELOG before shipping.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 4 to +6
@main
final class SampleSidebarExtension: CmuxSidebarExtension {
@MainActor
final class SampleSidebarExtension: @MainActor CmuxSidebarExtension {

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.

P2 Redundant @MainActor on the protocol conformance — the class declaration already marks every member @MainActor, so the attribute on the inheritance entry is a no-op and could confuse readers or generate a future compiler diagnostic about duplicate actor annotations.

Suggested change
@main
final class SampleSidebarExtension: CmuxSidebarExtension {
@MainActor
final class SampleSidebarExtension: @MainActor CmuxSidebarExtension {
@main
@MainActor
final class SampleSidebarExtension: CmuxSidebarExtension {

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 17 to 18
@_spi(CmuxLegacyHostActions)
public let cmux: CmuxHost

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.

P2 The non-SPI public init eagerly allocates a CmuxHost fallback (inside the SPI init via cmux ?? CmuxHost { ... }) even though callers without @_spi(CmuxLegacyHostActions) can never access context.cmux. The allocation is cheap (it's a struct + closure), but a lazy backing store or an internal Optional<CmuxHost> would make the "this field is inactive in the public API" intent clearer and avoid the unnecessary closure capture.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@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: 1

🤖 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
`@Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Session/CMUXSidebarExtensionSession.swift`:
- Around line 20-21: The `@_spi`(CmuxHostTransport) on the initializer is
redundant because the actor CMUXSidebarExtensionSession is already annotated
with that SPI; remove the annotation from the init declaration (public
init(...)) so the initializer inherits the actor's SPI implicitly, leaving the
actor-level `@_spi`(CmuxHostTransport) only; if you prefer keeping it for explicit
documentation you can alternatively leave a brief comment, but do not duplicate
the attribute on CMUXSidebarExtensionSession.init.
🪄 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: 786bca21-cfbd-4c7d-aabf-0c980d220836

📥 Commits

Reviewing files that changed from the base of the PR and between 33e5294 and eb2aa86.

📒 Files selected for processing (44)
  • Examples/CmuxExtensionSidebarExamples/Package.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/AttentionQueueSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/BrowserStackSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/DevServerSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/LastPromptSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/ProjectWorktreeSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SidebarExamples.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SuperCompactSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/AttentionQueueSidebarTests.swift
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/BrowserStackSidebarTests.swift
  • Examples/SampleSidebarExtensionApp/README.md
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Connection/SidebarConnectionModel.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Extension/SampleSidebarExtension.swift
  • Examples/StubAgentSidebarExtension/Package.swift
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/Resources/Localizable.xcstrings
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/StubAgentSidebarExtension.swift
  • Examples/TabsVisibleSidebar/TabsVisibleSidebar.xcodeproj/project.pbxproj
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Browser/CMUXSidebarExtensionBrowserPresenter.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXInstalledSidebarExtension.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXSidebarExtensionDiscovery.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXExtensionClientError.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRecord.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRegistry.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Session/CMUXSidebarExtensionSession.swift
  • Packages/CMUXExtensionClient/Tests/CMUXExtensionClientTests/CMUXExtensionClientTests.swift
  • Packages/CmuxExtensionKit/README.md
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxHost.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarAction.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarActionCancellation.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarContext.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionScene.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarHost.swift
  • Packages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swift
  • Packages/CmuxSidebarProviderKit/Package.swift
  • Packages/CmuxSidebarProviderKit/README.md
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxExtensionCompatibility.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/HostCompatibility/CmuxExtensionLocalizedText.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/HostCompatibility/CmuxExtensionSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/HostCompatibility/CmuxExtensionSidebarProviderDescriptor.swift
  • Sources/ContentView.swift
  • Sources/ExtensionSidebarWorkspaceRowView.swift
  • cmux.xcodeproj/project.pbxproj
💤 Files with no reviewable changes (1)
  • Examples/TabsVisibleSidebar/TabsVisibleSidebar.xcodeproj/project.pbxproj

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 44 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxHost.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: 9

Caution

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

⚠️ Outside diff range comments (6)
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift (1)

3-23: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Missing Swift-DocC documentation for public types.

Both CmuxSidebarActionResult and CmuxSidebarActionError are public API but lack documentation. Add triple-slash comments describing their purpose and cases.

📝 Proposed documentation
 `@_spi`(CmuxHostTransport)
+/// Result of a sidebar action request sent to the CMUX host.
 public struct CmuxSidebarActionResult: Codable, Equatable, Sendable {
+    /// Whether the host accepted and processed the action.
     public var accepted: Bool
+    /// Optional message describing the result or rejection reason.
     public var message: String?
     ...
 }
 
+/// Errors that can occur when performing a sidebar action.
 public enum CmuxSidebarActionError: Error, Equatable, Sendable {
+    /// The host rejected the action with the given reason.
     case rejected(String)
+    /// The action was cancelled before completion.
     case cancelled
 }
🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`
around lines 3 - 23, Add Swift-DocC triple‑slash documentation comments to the
public types: describe CmuxSidebarActionResult (its role as the result of a
sidebar action, meanings of the accepted Bool, optional message, the static
accepted constant, and the rejected(_:) constructor) and CmuxSidebarActionError
(explain each error case: .rejected(String) with the reason and .cancelled for
user/cancellation). Place the comments immediately above the declarations for
CmuxSidebarActionResult and CmuxSidebarActionError so they appear in generated
docs and Xcode Quick Help.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift (1)

3-5: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Missing safety comment for @unchecked Sendable.

The class is marked @unchecked Sendable but lacks the required safety argument comment. Document why this is safe (e.g., the stored properties and their thread-safety guarantees).

📝 Proposed safety comment
+/// Runtime that bridges a `CmuxSidebarExtension` to the XPC transport.
+///
+/// - Note: `@unchecked Sendable`: `sidebarExtension` is `@MainActor`-isolated and accessed
+///   only via `@MainActor` closures; `connection` is itself `Sendable`.
 final class CmuxSidebarExtensionRuntime<Extension: CmuxSidebarExtension>: `@unchecked` Sendable {

As per coding guidelines: "@unchecked Sendable and nonisolated(unsafe) require comment on declaration explaining safety argument."

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift`
around lines 3 - 5, The declaration of CmuxSidebarExtensionRuntime is marked
`@unchecked` Sendable but lacks the required safety justification comment; add a
brief comment directly above the class declaration explaining why it's safe to
bypass automatic Sendable checking (e.g., that the stored properties
sidebarExtension and connection are themselves thread-safe or only accessed on a
single serial executor, that no mutable shared state is exposed, and any
required synchronization is handled elsewhere), and reference the relevant
symbols (sidebarExtension, connection, and the Extension generic) so reviewers
can verify the safety argument.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift (1)

3-14: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider adding DocC comments for SPI-gated public symbols.

While this type is gated under @_spi(CmuxHostTransport), adding brief documentation (e.g., purpose of snapshot vs dispatch closures) would help host-side consumers understand the contract.

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift`
around lines 3 - 14, The SPI-exposed type CmuxSidebarHostClient lacks DocC
comments explaining its role and the semantics of its closures; add brief
documentation comments to the struct and its public members
(CmuxSidebarHostClient, snapshot, dispatch) describing the host-side purpose of
the client, what snapshot() returns and when it should be called, and what
dispatch(action) does and what CmuxSidebarActionResult represents so consumers
understand the contract and expected behavior.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionScene.swift (2)

27-27: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing safety comment for @unchecked Sendable.

Per coding guidelines, @unchecked Sendable requires a comment explaining the safety argument. Add a comment describing why this type is safe to send across isolation boundaries (e.g., "Runtime handles its own isolation via XPC connection serialization").

As per coding guidelines: "@unchecked Sendable and nonisolated(unsafe) require comment on declaration explaining safety argument; use 'Wraps X; every mutation happens on Y' or 'UserDefaults is thread-safe' pattern."

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionScene.swift`
at line 27, Add a concise safety comment to the SidebarRuntimeBox declaration
explaining why `@unchecked` Sendable is safe: mention the generic type
SidebarRuntimeBox<Extension: CmuxSidebarExtension>, that it conforms to
AnySidebarRuntimeBox, and state the specific isolation guarantee (e.g., "Wraps
Runtime; all mutation happens on the XPC/actor thread and access is serialized
by the runtime's XPC connection") so reviewers can verify thread-safety; place
this comment immediately before the declaration of SidebarRuntimeBox to satisfy
the guideline requiring a safety rationale for `@unchecked` Sendable.

39-39: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing safety comment for @unchecked Sendable.

Same as above—add a brief comment explaining why AnySidebarRuntimeBox is safe to share across isolation domains.

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionScene.swift`
at line 39, Add a brief safety rationale comment explaining why
AnySidebarRuntimeBox is annotated with `@unchecked` Sendable: state which internal
stored properties or captured references are immutable or themselves Sendable
(e.g., immutable closures, value types, or thread-safe objects) and note that no
non-sendable mutable state is accessed across concurrency domains; place this
comment immediately above the declaration of the private class
AnySidebarRuntimeBox to document why it's safe to share across isolation
boundaries.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderLocalizedText.swift (1)

3-11: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider adding DocC comments for public API.

This is a new public type in Packages/. A brief triple-slash comment explaining the intended usage (e.g., "Represents a localizable string with its key and fallback value for sidebar provider rendering") would help extension authors.

As per coding guidelines: "Every public symbol in new Swift packages under Packages/ must be documented with Swift-DocC triple-slash comment at time of writing."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderLocalizedText.swift`
around lines 3 - 11, Add Swift-DocC triple-slash comments to the public type
CmuxSidebarProviderLocalizedText and its public members: document the struct
with a brief summary like "Represents a localizable string with its key and
fallback value for sidebar provider rendering", then add brief comments for the
properties key and defaultValue and the public init describing their purpose and
parameters; ensure every public symbol (CmuxSidebarProviderLocalizedText, key,
defaultValue, init) has a /// comment immediately above it to satisfy the
Packages/ documentation guideline.
🤖 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
`@Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/StubAgentSidebarExtension.swift`:
- Around line 33-35: The click handlers currently swallow failures by using try?
when calling selectWorkspace(workspace.id) and createWorkspace(...); change them
to capture errors and surface user feedback: add an observable errorText (or
reuse existing state) and update the Task blocks to await the call inside a
do/catch that sets errorText on failure and handles
CmuxSidebarActionError.rejected specifically (or use the existing apply helper
pattern shown in Sample/TabsVisible) so users see an error message instead of
silent failure.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift`:
- Around line 3-8: The public API CmuxExtensionManifest and its public
properties (id, displayName, minimumAPIVersion, readScopes, actionScopes) lack
Swift-DocC documentation; add triple-slash (///) doc comments above the struct
declaration and above each public property describing their purpose,
units/format (e.g., id format), semantics (what displayName represents),
expected values/constraints for minimumAPIVersion, and what
readScopes/actionScopes control so the public symbols are documented per package
guidelines.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtension.swift`:
- Around line 5-9: Add Swift-DocC documentation to the public enum
CmuxSidebarConnectionStatus explaining its overall purpose (representing the
sidebar connection state) and document each case (connected, waitingForHost,
error(String)) including what the associated String in error represents and when
waitingForHost applies; place /// comments immediately above the enum and each
case so Xcode/DocC will surface the descriptions.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift`:
- Line 8: The declaration of CMUXSidebarExtensionConnection uses `@unchecked`
Sendable but lacks the required safety comment; add a concise comment on the
class explaining why it's safe to be `@unchecked` Sendable (e.g., state is
protected by an NSLock instance and all non-sendable mutation happens under that
lock, or only immutable/sendable data is shared), and reference the NSLock used
for synchronization (and any other thread-affine or non-sendable members) so
reviewers can verify the safety argument; keep the comment adjacent to the class
declaration containing the `@unchecked` Sendable attribute.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarHost.swift`:
- Around line 140-142: The code uses a fragile literal "Extension action was
cancelled" to detect cancellation (checked against message and thrown as
CmuxSidebarActionError.cancelled); extract that literal into a single shared
constant (e.g., cancellationMessage) in CmuxSidebarHost and replace every
literal comparison/usage (the if message == ... check and the other occurrence
that constructs/returns that text) to use the constant instead; alternatively,
replace the string-based signaling with a structured result or error enum
consistently, but at minimum introduce and reference cancellationMessage
wherever the cancellation text is produced or checked so they cannot drift
independently.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProvider.swift`:
- Around line 3-5: Add Swift-DocC triple-slash documentation to the public
protocol CmuxSidebarProvider and its public member descriptor: write a brief ///
summary above the protocol declaration describing its role and contract
(including that it is Sendable) and add a /// comment for the descriptor
property explaining what the CmuxSidebarProviderDescriptor represents and how
callers should use it; ensure the comments follow the project's DocC style and
appear directly above the protocol and the var descriptor declaration.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift`:
- Around line 3-33: Add Swift-DocC triple-slash documentation for the public
struct and all its public members: document CmuxSidebarProviderDescriptor itself
and its static defaultWorkspacesID and defaultWorkspaces, the properties id,
title, subtitle, systemImageName, isHostProvided, and the public init(...)
initializer; include a short description for each symbol, document parameter
names and meanings for the initializer, and ensure comments follow the
triple-slash format (///) and concise DocC style so the package complies with
the public-symbol documentation guideline.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderModels.swift`:
- Around line 3-6: Public types and protocols in CmuxSidebarProviderModels.swift
lack Swift-DocC triple-slash documentation; add concise one-line DocC summaries
for each public symbol listed (e.g., CmuxSidebarProviderPresentation,
CmuxSidebarProviderWorkspacePopoverTab, CmuxSidebarProviderRelativeDateStyle,
CmuxSidebarProviderIconShape, CmuxSidebarProviderText,
CmuxContextualSidebarProvider, CmuxMutableSidebarProvider,
CmuxSidebarProviderGitBranch) and any other public enums/structs/protocols noted
in the review ranges so they comply with the package guideline; place ///
comments immediately above each declaration with a short descriptive sentence,
and include brief documentation on public protocol methods where applicable.

In `@scripts/write-sidebar-extension-point.sh`:
- Around line 31-37: The generated appextensionpoint plist currently emits only
EXExtensionPointIsPublic and EXPresentsUserInterface at top-level, but
ExtensionKit requires the extension-point identifier to be the top-level key
(e.g., use the POINT_ID variable as the top-level key with the configuration
dict nested under it); update scripts/write-sidebar-extension-point.sh so the
plist root is a dict with a single key of the extension point identifier whose
value is the dict containing EXExtensionPointIsPublic and
EXPresentsUserInterface (and if applicable reintroduce the _EXScopeRestriction
key into that nested dict rather than removing it, or document/justify its
removal to avoid widening attachment scope). Ensure you reference the POINT_ID
variable (or constant used in the script) when emitting the top-level key and
include _EXScopeRestriction back under that nested dict unless you have an
explicit reason to drop it.

---

Outside diff comments:
In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`:
- Around line 3-23: Add Swift-DocC triple‑slash documentation comments to the
public types: describe CmuxSidebarActionResult (its role as the result of a
sidebar action, meanings of the accepted Bool, optional message, the static
accepted constant, and the rejected(_:) constructor) and CmuxSidebarActionError
(explain each error case: .rejected(String) with the reason and .cancelled for
user/cancellation). Place the comments immediately above the declarations for
CmuxSidebarActionResult and CmuxSidebarActionError so they appear in generated
docs and Xcode Quick Help.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift`:
- Around line 3-5: The declaration of CmuxSidebarExtensionRuntime is marked
`@unchecked` Sendable but lacks the required safety justification comment; add a
brief comment directly above the class declaration explaining why it's safe to
bypass automatic Sendable checking (e.g., that the stored properties
sidebarExtension and connection are themselves thread-safe or only accessed on a
single serial executor, that no mutable shared state is exposed, and any
required synchronization is handled elsewhere), and reference the relevant
symbols (sidebarExtension, connection, and the Extension generic) so reviewers
can verify the safety argument.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionScene.swift`:
- Line 27: Add a concise safety comment to the SidebarRuntimeBox declaration
explaining why `@unchecked` Sendable is safe: mention the generic type
SidebarRuntimeBox<Extension: CmuxSidebarExtension>, that it conforms to
AnySidebarRuntimeBox, and state the specific isolation guarantee (e.g., "Wraps
Runtime; all mutation happens on the XPC/actor thread and access is serialized
by the runtime's XPC connection") so reviewers can verify thread-safety; place
this comment immediately before the declaration of SidebarRuntimeBox to satisfy
the guideline requiring a safety rationale for `@unchecked` Sendable.
- Line 39: Add a brief safety rationale comment explaining why
AnySidebarRuntimeBox is annotated with `@unchecked` Sendable: state which internal
stored properties or captured references are immutable or themselves Sendable
(e.g., immutable closures, value types, or thread-safe objects) and note that no
non-sendable mutable state is accessed across concurrency domains; place this
comment immediately above the declaration of the private class
AnySidebarRuntimeBox to document why it's safe to share across isolation
boundaries.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift`:
- Around line 3-14: The SPI-exposed type CmuxSidebarHostClient lacks DocC
comments explaining its role and the semantics of its closures; add brief
documentation comments to the struct and its public members
(CmuxSidebarHostClient, snapshot, dispatch) describing the host-side purpose of
the client, what snapshot() returns and when it should be called, and what
dispatch(action) does and what CmuxSidebarActionResult represents so consumers
understand the contract and expected behavior.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderLocalizedText.swift`:
- Around line 3-11: Add Swift-DocC triple-slash comments to the public type
CmuxSidebarProviderLocalizedText and its public members: document the struct
with a brief summary like "Represents a localizable string with its key and
fallback value for sidebar provider rendering", then add brief comments for the
properties key and defaultValue and the public init describing their purpose and
parameters; ensure every public symbol (CmuxSidebarProviderLocalizedText, key,
defaultValue, init) has a /// comment immediately above it to satisfy the
Packages/ documentation guideline.
🪄 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: e016a4b9-a03d-40d4-8604-ed384dea5ca4

📥 Commits

Reviewing files that changed from the base of the PR and between eb2aa86 and 2bb8686.

📒 Files selected for processing (74)
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/AttentionQueueSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/BrowserStackSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/DevServerSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/LastPromptSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/ProjectWorktreeSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SidebarExamples.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SuperCompactSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/AttentionQueueSidebarTests.swift
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/BrowserStackSidebarTests.swift
  • Examples/SampleSidebarExtensionApp/README.md
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Connection/SidebarConnectionModel.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Extension/SampleSidebarExtension.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Localizable.xcstrings
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Model/SidebarInsightModel.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/UI/SampleSidebarView.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtensionApp/Localizable.xcstrings
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/StubAgentSidebarExtension.swift
  • Examples/TabsVisibleSidebar/TabsVisibleSidebar.xcodeproj/project.pbxproj
  • Examples/TabsVisibleSidebar/TabsVisibleSidebar/Localizable.xcstrings
  • Examples/TabsVisibleSidebar/TabsVisibleSidebarExtension/Localizable.xcstrings
  • Examples/TabsVisibleSidebar/TabsVisibleSidebarExtension/TabsVisibleSidebarExtension.swift
  • Examples/TabsVisibleSidebar/TabsVisibleSidebarExtension/TabsVisibleSidebarView.swift
  • Packages/CMUXExtensionClient/README.md
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXInstalledSidebarExtension.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXSidebarExtensionDiscovery.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXExtensionClientError.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRecord.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRegistry.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Session/CMUXSidebarExtensionSession.swift
  • Packages/CMUXExtensionClient/Tests/CMUXExtensionClientTests/CMUXExtensionClientTests.swift
  • Packages/CMUXExtensionHostSupport/Package.swift
  • Packages/CMUXExtensionHostSupport/README.md
  • Packages/CMUXExtensionHostSupport/Sources/CMUXExtensionHostSupport/Browser/CMUXSidebarExtensionBrowserPresenter.swift
  • Packages/CMUXExtensionHostSupport/Sources/CMUXExtensionHostSupport/Hosting/CMUXSidebarExtensionHostView.swift
  • Packages/CmuxExtensionKit/README.md
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Common/CMUXExtensionAPIVersion.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxHost.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxUIExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionKind.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionScope.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarAction.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionPoint.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSurface.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarWorkspace.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarXPC.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarContext.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionScene.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarHost.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Validation/CMUXExtensionValidationError.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Validation/CMUXExtensionValidator.swift
  • Packages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swift
  • Packages/CmuxSidebarProviderKit/README.md
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderLocalizedText.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderModels.swift
  • Resources/Localizable.xcstrings
  • Resources/com.manaflow.cmux.sidebar.appextensionpoint
  • Sources/CMUXInstalledExtensionSidebarHostView.swift
  • Sources/CMUXSidebarExtensionBrowserPanel.swift
  • Sources/ContentView.swift
  • Sources/ExtensionSidebarWorkspaceRowView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmux.xcworkspace/contents.xcworkspacedata
  • scripts/reload.sh
  • scripts/write-sidebar-extension-point.sh
💤 Files with no reviewable changes (14)
  • Packages/CMUXExtensionClient/README.md
  • Packages/CMUXExtensionClient/Tests/CMUXExtensionClientTests/CMUXExtensionClientTests.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxHost.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionKind.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxUIExtension.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXInstalledSidebarExtension.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXSidebarExtensionDiscovery.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxExtension.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRegistry.swift
  • Resources/com.manaflow.cmux.sidebar.appextensionpoint
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXExtensionClientError.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRecord.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Session/CMUXSidebarExtensionSession.swift
  • Packages/CMUXExtensionHostSupport/Sources/CMUXExtensionHostSupport/Browser/CMUXSidebarExtensionBrowserPresenter.swift

Comment thread Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarHost.swift Outdated
Comment on lines 3 to 6
public enum CmuxSidebarProviderPresentation: String, Codable, Equatable, Sendable {
case tree
case browserStack = "browser-stack"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoff

Missing DocC documentation on public types in models file.

Multiple public enums, structs, and protocols in this file lack Swift-DocC documentation. Key types needing documentation include:

  • CmuxSidebarProviderPresentation
  • CmuxSidebarProviderWorkspacePopoverTab
  • CmuxSidebarProviderRelativeDateStyle
  • CmuxSidebarProviderIconShape
  • CmuxSidebarProviderText
  • CmuxContextualSidebarProvider / CmuxMutableSidebarProvider
  • CmuxSidebarProviderGitBranch

Consider adding at minimum a one-line summary for each public type and protocol method.

As per coding guidelines: "Every public symbol in new Swift packages under Packages/ must be documented with Swift-DocC triple-slash comment at time of writing."

Also applies to: 39-43, 71-73, 75-78, 102-115, 229-238, 280-288

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderModels.swift`
around lines 3 - 6, Public types and protocols in
CmuxSidebarProviderModels.swift lack Swift-DocC triple-slash documentation; add
concise one-line DocC summaries for each public symbol listed (e.g.,
CmuxSidebarProviderPresentation, CmuxSidebarProviderWorkspacePopoverTab,
CmuxSidebarProviderRelativeDateStyle, CmuxSidebarProviderIconShape,
CmuxSidebarProviderText, CmuxContextualSidebarProvider,
CmuxMutableSidebarProvider, CmuxSidebarProviderGitBranch) and any other public
enums/structs/protocols noted in the review ranges so they comply with the
package guideline; place /// comments immediately above each declaration with a
short descriptive sentence, and include brief documentation on public protocol
methods where applicable.

Comment thread scripts/write-sidebar-extension-point.sh

@cubic-dev-ai cubic-dev-ai 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.

8 issues found across 76 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift">

<violation number="1" location="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift:36">
P2: Decoder is not backward-compatible with previous manifest key `requestedScopes`, so older manifests now fail to load.</violation>
</file>

<file name="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionPoint.swift">

<violation number="1" location="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionPoint.swift:20">
P1: Info.plist key string mismatch: the renamed `identifierInfoPlistKey` (`"CmuxSidebarExtensionPointIdentifier"`) does not match the key still declared in `./Resources/Info.plist` (`CMUXSidebarExtensionPointIdentifier`). This causes `Bundle.object(forInfoDictionaryKey:)` to always return nil, silently falling back to `baseIdentifier` and bypassing any build-time override.</violation>
</file>

<file name="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Common/CMUXExtensionAPIVersion.swift">

<violation number="1" location="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Common/CMUXExtensionAPIVersion.swift:3">
P3: File name `CMUXExtensionAPIVersion.swift` no longer matches the renamed struct `CmuxExtensionAPIVersion`. Rename the file to `CmuxExtensionAPIVersion.swift` to follow Swift naming conventions where the file name matches the primary type name.</violation>
</file>

<file name="Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Connection/SidebarConnectionModel.swift">

<violation number="1" location="Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Connection/SidebarConnectionModel.swift:28">
P3: Map known host error strings to localized text instead of displaying raw transport messages.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

/// (via Info.plist variable substitution), so the resolved id lives only in the built
/// bundle, never in tracked source. Absent or empty means "use ``baseIdentifier``".
public static let identifierInfoPlistKey = "CMUXSidebarExtensionPointIdentifier"
public static let identifierInfoPlistKey = "CmuxSidebarExtensionPointIdentifier"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Info.plist key string mismatch: the renamed identifierInfoPlistKey ("CmuxSidebarExtensionPointIdentifier") does not match the key still declared in ./Resources/Info.plist (CMUXSidebarExtensionPointIdentifier). This causes Bundle.object(forInfoDictionaryKey:) to always return nil, silently falling back to baseIdentifier and bypassing any build-time override.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionPoint.swift, line 20:

<comment>Info.plist key string mismatch: the renamed `identifierInfoPlistKey` (`"CmuxSidebarExtensionPointIdentifier"`) does not match the key still declared in `./Resources/Info.plist` (`CMUXSidebarExtensionPointIdentifier`). This causes `Bundle.object(forInfoDictionaryKey:)` to always return nil, silently falling back to `baseIdentifier` and bypassing any build-time override.</comment>

<file context>
@@ -16,7 +17,7 @@ public enum CMUXSidebarExtensionPoint {
     /// (via Info.plist variable substitution), so the resolved id lives only in the built
     /// bundle, never in tracked source. Absent or empty means "use ``baseIdentifier``".
-    public static let identifierInfoPlistKey = "CMUXSidebarExtensionPointIdentifier"
+    public static let identifierInfoPlistKey = "CmuxSidebarExtensionPointIdentifier"
 
     /// Resolves the extension point identifier for a bundle.
</file context>
Suggested change
public static let identifierInfoPlistKey = "CmuxSidebarExtensionPointIdentifier"
public static let identifierInfoPlistKey = "CMUXSidebarExtensionPointIdentifier"

Comment thread scripts/write-sidebar-extension-point.sh Outdated
[CMUXExtensionActionScope].self,
forKey: .requestedActionScopes
minimumAPIVersion = try container.decodeIfPresent(CmuxExtensionAPIVersion.self, forKey: .minimumAPIVersion) ?? .sidebarV1
readScopes = try container.decode([CmuxExtensionScope].self, forKey: .readScopes)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Decoder is not backward-compatible with previous manifest key requestedScopes, so older manifests now fail to load.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift, line 36:

<comment>Decoder is not backward-compatible with previous manifest key `requestedScopes`, so older manifests now fail to load.</comment>

<file context>
@@ -1,65 +1,42 @@
-            [CMUXExtensionActionScope].self,
-            forKey: .requestedActionScopes
+        minimumAPIVersion = try container.decodeIfPresent(CmuxExtensionAPIVersion.self, forKey: .minimumAPIVersion) ?? .sidebarV1
+        readScopes = try container.decode([CmuxExtensionScope].self, forKey: .readScopes)
+        actionScopes = try container.decodeIfPresent(
+            [CmuxExtensionActionScope].self,
</file context>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Resolved by bumping the manifest/snapshot contract to CmuxExtensionAPIVersion.sidebarV2 and removing sidebarV1 from the public SDK default path. We are intentionally not adding requestedScopes/requestedActionScopes aliases because extensions have not shipped publicly yet.

— Claude Code

import Foundation

public struct CMUXExtensionAPIVersion: Codable, Comparable, Equatable, Sendable {
public struct CmuxExtensionAPIVersion: Codable, Comparable, Equatable, Sendable {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: File name CMUXExtensionAPIVersion.swift no longer matches the renamed struct CmuxExtensionAPIVersion. Rename the file to CmuxExtensionAPIVersion.swift to follow Swift naming conventions where the file name matches the primary type name.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Common/CMUXExtensionAPIVersion.swift, line 3:

<comment>File name `CMUXExtensionAPIVersion.swift` no longer matches the renamed struct `CmuxExtensionAPIVersion`. Rename the file to `CmuxExtensionAPIVersion.swift` to follow Swift naming conventions where the file name matches the primary type name.</comment>

<file context>
@@ -1,6 +1,6 @@
 import Foundation
 
-public struct CMUXExtensionAPIVersion: Codable, Comparable, Equatable, Sendable {
+public struct CmuxExtensionAPIVersion: Codable, Comparable, Equatable, Sendable {
     public var major: Int
     public var minor: Int
</file context>

case .waitingForHost:
errorText = String(localized: "sampleSidebar.waitingForHost", defaultValue: "Waiting for cmux")
case .error(let message):
errorText = message

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Map known host error strings to localized text instead of displaying raw transport messages.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Connection/SidebarConnectionModel.swift, line 28:

<comment>Map known host error strings to localized text instead of displaying raw transport messages.</comment>

<file context>
@@ -18,8 +18,15 @@ final class SidebarConnectionModel {
+        case .waitingForHost:
+            errorText = String(localized: "sampleSidebar.waitingForHost", defaultValue: "Waiting for cmux")
+        case .error(let message):
+            errorText = message
+        }
     }
</file context>
Suggested change
errorText = message
errorText = message == "cmux did not send a workspace snapshot"
? String(localized: "sampleSidebar.emptySnapshot", defaultValue: "cmux did not send a workspace snapshot")
: message

Comment thread Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarHost.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: 8

Caution

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

⚠️ Outside diff range comments (2)
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift (1)

4-44: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Split the three public types into their own files and rename to match.

This file declares three public types (CmuxSidebarActionResult, CmuxSidebarActionRejectionReason, CmuxSidebarActionError), and the filename CMUXExtensionActionResult.swift no longer matches any of them after the rename. CmuxSidebarActionRejectionReason and CmuxSidebarActionError are meaningful public types that warrant their own files.

As per coding guidelines: "One major type per file; each struct/class/enum/actor/protocol in public API lives in own file named after type; small helpers and nested types stay with parent."

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`
around lines 4 - 44, This file contains three public API types
(CmuxSidebarActionResult, CmuxSidebarActionRejectionReason,
CmuxSidebarActionError) and must be split so each public type lives in its own
file named after the type; create three files each declaring one of:
CmuxSidebarActionResult, CmuxSidebarActionRejectionReason, and
CmuxSidebarActionError (moving their definitions verbatim), keep any `@_spi` or
access modifiers with the corresponding type, and update/remove the original
CMUXExtensionActionResult.swift so no public type is left in a mismatched file
name.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift (1)

8-26: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Fix potential self-retain cycle + missing @unchecked Sendable justification

  • CmuxSidebarExtensionRuntime’s onSnapshot closure captures transport strongly (transport.perform / transport.refreshSnapshot) while CMUXSidebarExtensionConnection stores onSnapshot/onStatus as let properties; this creates a retain cycle where CMUXSidebarExtensionConnection can keep itself alive, and invalidate() only clears internal connection state (it does not release those handlers).
  • CmuxSidebarExtensionRuntime is @unchecked Sendable without the required safety justification comment.
🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift`
around lines 8 - 26, The onSnapshot closure currently captures transport
strongly (used in transport.perform and transport.refreshSnapshot), creating a
retain cycle because CMUXSidebarExtensionConnection stores the handlers; change
the closure captures to use a weak (or unowned if provably safe) reference to
transport (e.g., [weak transport]) and guard/early-return if transport is nil
before calling perform/refreshSnapshot so handlers don’t retain the connection;
keep invalidate() behavior as-is but ensure handlers can break the cycle. Also
add the required `@unchecked` Sendable justification comment on the
CmuxSidebarExtensionRuntime type explaining why it's safe to mark unchecked
(referencing thread-safety of captured state and that external synchronization
or immutability guarantees are in place).
🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift`:
- Line 3: Add a concise safety-argument comment explaining why using `@unchecked`
Sendable on the CmuxSidebarExtensionRuntime declaration is safe: locate the
class CmuxSidebarExtensionRuntime and append a comment on the same line or
immediately above the declaration that states the invariant (for example, what
internal state is being wrapped and the thread/actor controlling all mutations,
e.g., "Wraps X; all mutations occur on Y/are synchronized by Z"), making clear
there are no data races and why the unchecked annotation is justified.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderMutations.swift`:
- Around line 3-49: Add Swift-DocC triple-slash comments to every public symbol
in this file: document the enum CmuxSidebarProviderPresentationRequest and each
of its cases, the struct CmuxSidebarProviderWorkspaceMove and its initializer
and properties (workspaceId, sourceSectionId, targetSectionId, targetIndex), the
enum CmuxSidebarProviderMutation and each case, the struct
CmuxSidebarProviderCommandResult and its init + ok property, and the protocol
CmuxMutableSidebarProvider and its handle(_:snapshot:) method; ensure each
public type and public member has a brief /// description explaining purpose,
parameters, and return value where applicable to satisfy the package
documentation guideline.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderPresentation.swift`:
- Around line 3-12: Public enums CmuxSidebarProviderPresentation and
CmuxSidebarProviderWorkspacePopoverTab lack Swift-DocC comments; add
triple-slash (///) documentation above each public enum
(CmuxSidebarProviderPresentation, CmuxSidebarProviderWorkspacePopoverTab) and
above each case (tree, browserStack, notes, browser, pullRequest) describing
their purpose and any special semantics (e.g., rawValue "browser-stack"),
example usage or platform scope if relevant, and mark parameters/returns or
remarks only if applicable so the public symbols are fully documented per
package guidelines.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderRenderModel.swift`:
- Around line 3-49: Add Swift-DocC triple-slash comments to all public API in
this file: document the CmuxSidebarProviderRenderModel type and its public init
and stored properties (providerId, snapshotSequence, sections, presentation),
the CmuxSidebarProviderRenderContext type and its public init/now property, the
CmuxContextualSidebarProvider protocol and its render(snapshot:context:)
requirement, and the two public render(...) extension methods on
CmuxSidebarProvider; explicitly note in the documentation for the default
render(snapshot:context:) extension that it intentionally ignores the context
and delegates to render(snapshot:). Ensure each comment is concise, describes
purpose and behavior, and appears immediately above the corresponding public
symbol using triple-slash DocC format.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderRows.swift`:
- Around line 3-101: Public API symbols in CmuxSidebarProviderRows are
undocumented; add Swift-DocC triple-slash comments for all seven public types
and their public members/initializers. Specifically document
CmuxSidebarProviderRowAccessoryKind, CmuxSidebarProviderRowAccessory (and its
init and static inspector), CmuxSidebarProviderRelativeDateStyle,
CmuxSidebarProviderIconShape, CmuxSidebarProviderIcon (and its init),
CmuxSidebarProviderText (document cases and relativeDate property), and
CmuxSidebarProviderRow (and its init and public properties) with concise
summaries, parameter/return tags where applicable, and example/remarks if
helpful to satisfy the package guideline. Ensure every public stored property,
enum case, initializer, and computed property has a triple-slash comment
immediately above it.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderSections.swift`:
- Around line 13-22: The initializer public init(...) has inconsistent optional
defaults: titleText and subtitleText default to nil but subtitle and
projectRootPath are required; update the initializer signature in
CmuxSidebarProviderSections.swift so that subtitle: String? and projectRootPath:
String? also have default values of nil (matching titleText/subtitleText) to
improve ergonomics when calling the init; keep the parameter order and names
(id, title, titleText, subtitle, subtitleText, systemImageName, projectRootPath,
workspaceIds) and adjust any call sites if necessary to rely on the new
defaults.
- Around line 3-48: The two public types CmuxSidebarProviderTreeSection and
CmuxSidebarProviderSection (including their public properties like id, title,
titleText, subtitle, subtitleText, systemImageName, projectRootPath,
workspaceIds, treeSection, rows and their public init initializers) must each be
moved into their own file (one major public type per file) and annotated with
Swift-DocC triple-slash comments; add concise /// documentation for each public
struct, every public property, and the public init parameters describing purpose
and semantics, then split the current file so CmuxSidebarProviderTreeSection is
defined in its own file and CmuxSidebarProviderSection in its own file to
satisfy the one-type-per-file guideline.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderSnapshot.swift`:
- Around line 3-92: Split the three public types into their own files and add
Swift-DocC comments for each public symbol: create
CmuxSidebarProviderSnapshot.swift containing the CmuxSidebarProviderSnapshot
struct and document its properties and init with triple-slash comments; create
CmuxSidebarProviderGitBranch.swift for CmuxSidebarProviderGitBranch and document
branch/isDirty and init; create CmuxSidebarProviderWorkspace.swift for
CmuxSidebarProviderWorkspace and document the struct, all public properties (id,
title, customDescription, isPinned, rootPath, projectRootPath, branchSummary,
remoteDisplayTarget, remoteConnectionState, unreadCount, latestNotificationText,
latestSubmittedMessage, latestSubmittedAt, listeningPorts, pullRequestURLs,
panelDirectories, gitBranches) and its init; ensure file names match the type
names and that each public symbol has a brief Swift-DocC description above it.

---

Outside diff comments:
In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`:
- Around line 4-44: This file contains three public API types
(CmuxSidebarActionResult, CmuxSidebarActionRejectionReason,
CmuxSidebarActionError) and must be split so each public type lives in its own
file named after the type; create three files each declaring one of:
CmuxSidebarActionResult, CmuxSidebarActionRejectionReason, and
CmuxSidebarActionError (moving their definitions verbatim), keep any `@_spi` or
access modifiers with the corresponding type, and update/remove the original
CMUXExtensionActionResult.swift so no public type is left in a mismatched file
name.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift`:
- Around line 8-26: The onSnapshot closure currently captures transport strongly
(used in transport.perform and transport.refreshSnapshot), creating a retain
cycle because CMUXSidebarExtensionConnection stores the handlers; change the
closure captures to use a weak (or unowned if provably safe) reference to
transport (e.g., [weak transport]) and guard/early-return if transport is nil
before calling perform/refreshSnapshot so handlers don’t retain the connection;
keep invalidate() behavior as-is but ensure handlers can break the cycle. Also
add the required `@unchecked` Sendable justification comment on the
CmuxSidebarExtensionRuntime type explaining why it's safe to mark unchecked
(referencing thread-safety of captured state and that external synchronization
or immutability guarantees are in place).
🪄 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: edbbc48c-4ba5-40f6-854f-f2d21df5977d

📥 Commits

Reviewing files that changed from the base of the PR and between 2bb8686 and 4c59be9.

📒 Files selected for processing (11)
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionScene.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarHost.swift
  • Packages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderMutations.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderPresentation.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderRenderModel.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderRows.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderSections.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderSnapshot.swift

Comment on lines +3 to +48
public struct CmuxSidebarProviderTreeSection: Identifiable, Codable, Equatable, Sendable {
public var id: String
public var title: String
public var titleText: CmuxSidebarProviderLocalizedText?
public var subtitle: String?
public var subtitleText: CmuxSidebarProviderLocalizedText?
public var systemImageName: String
public var projectRootPath: String?
public var workspaceIds: [UUID]

public init(
id: String,
title: String,
titleText: CmuxSidebarProviderLocalizedText? = nil,
subtitle: String?,
subtitleText: CmuxSidebarProviderLocalizedText? = nil,
systemImageName: String,
projectRootPath: String?,
workspaceIds: [UUID]
) {
self.id = id
self.title = title
self.titleText = titleText
self.subtitle = subtitle
self.subtitleText = subtitleText
self.systemImageName = systemImageName
self.projectRootPath = projectRootPath
self.workspaceIds = workspaceIds
}
}

public struct CmuxSidebarProviderSection: Identifiable, Codable, Equatable, Sendable {
public var id: String
public var treeSection: CmuxSidebarProviderTreeSection
public var rows: [CmuxSidebarProviderRow]

public init(
id: String,
treeSection: CmuxSidebarProviderTreeSection,
rows: [CmuxSidebarProviderRow]
) {
self.id = id
self.treeSection = treeSection
self.rows = rows
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Document public symbols and split into one file per type.

Two issues for this new-package file:

  • All public symbols (CmuxSidebarProviderTreeSection, CmuxSidebarProviderSection, their properties and initializers) lack Swift-DocC comments.
  • The file declares two major public types.

As per coding guidelines: "Every public symbol in new Swift packages under Packages/ must be documented with Swift-DocC triple-slash comment at time of writing" and "One major type per file; each struct/class/enum/actor/protocol in public API lives in own file named after type."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderSections.swift`
around lines 3 - 48, The two public types CmuxSidebarProviderTreeSection and
CmuxSidebarProviderSection (including their public properties like id, title,
titleText, subtitle, subtitleText, systemImageName, projectRootPath,
workspaceIds, treeSection, rows and their public init initializers) must each be
moved into their own file (one major public type per file) and annotated with
Swift-DocC triple-slash comments; add concise /// documentation for each public
struct, every public property, and the public init parameters describing purpose
and semantics, then split the current file so CmuxSidebarProviderTreeSection is
defined in its own file and CmuxSidebarProviderSection in its own file to
satisfy the one-type-per-file guideline.

Comment on lines +13 to +22
public init(
id: String,
title: String,
titleText: CmuxSidebarProviderLocalizedText? = nil,
subtitle: String?,
subtitleText: CmuxSidebarProviderLocalizedText? = nil,
systemImageName: String,
projectRootPath: String?,
workspaceIds: [UUID]
) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Optional-parameter defaults are inconsistent.

titleText/subtitleText default to nil, but the equally-optional subtitle and projectRootPath require explicit arguments. Consider defaulting them for ergonomic call sites.

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderSections.swift`
around lines 13 - 22, The initializer public init(...) has inconsistent optional
defaults: titleText and subtitleText default to nil but subtitle and
projectRootPath are required; update the initializer signature in
CmuxSidebarProviderSections.swift so that subtitle: String? and projectRootPath:
String? also have default values of nil (matching titleText/subtitleText) to
improve ergonomics when calling the init; keep the parameter order and names
(id, title, titleText, subtitle, subtitleText, systemImageName, projectRootPath,
workspaceIds) and adjust any call sites if necessary to rely on the new
defaults.

Comment on lines +3 to +92
public struct CmuxSidebarProviderSnapshot: Codable, Equatable, Sendable {
public var sequence: UInt64
public var selectedWorkspaceId: UUID?
public var workspaces: [CmuxSidebarProviderWorkspace]
public var windowId: UUID?

public init(
sequence: UInt64,
selectedWorkspaceId: UUID?,
workspaces: [CmuxSidebarProviderWorkspace],
windowId: UUID? = nil
) {
self.sequence = sequence
self.selectedWorkspaceId = selectedWorkspaceId
self.workspaces = workspaces
self.windowId = windowId
}

public var workspaceIds: [UUID] {
workspaces.map(\.id)
}
}

public struct CmuxSidebarProviderGitBranch: Codable, Equatable, Sendable {
public var branch: String
public var isDirty: Bool

public init(branch: String, isDirty: Bool) {
self.branch = branch
self.isDirty = isDirty
}
}

public struct CmuxSidebarProviderWorkspace: Identifiable, Codable, Equatable, Sendable {
public var id: UUID
public var title: String
public var customDescription: String?
public var isPinned: Bool
public var rootPath: String?
public var projectRootPath: String?
public var branchSummary: String?
public var remoteDisplayTarget: String?
public var remoteConnectionState: String?
public var unreadCount: Int
public var latestNotificationText: String?
public var latestSubmittedMessage: String?
public var latestSubmittedAt: Date?
public var listeningPorts: [Int]
public var pullRequestURLs: [String]
public var panelDirectories: [String]
public var gitBranches: [CmuxSidebarProviderGitBranch]

public init(
id: UUID,
title: String,
customDescription: String?,
isPinned: Bool,
rootPath: String?,
projectRootPath: String?,
branchSummary: String?,
remoteDisplayTarget: String?,
remoteConnectionState: String?,
unreadCount: Int,
latestNotificationText: String?,
latestSubmittedMessage: String? = nil,
latestSubmittedAt: Date? = nil,
listeningPorts: [Int],
pullRequestURLs: [String] = [],
panelDirectories: [String] = [],
gitBranches: [CmuxSidebarProviderGitBranch] = []
) {
self.id = id
self.title = title
self.customDescription = customDescription
self.isPinned = isPinned
self.rootPath = rootPath
self.projectRootPath = projectRootPath
self.branchSummary = branchSummary
self.remoteDisplayTarget = remoteDisplayTarget
self.remoteConnectionState = remoteConnectionState
self.unreadCount = unreadCount
self.latestNotificationText = latestNotificationText
self.latestSubmittedMessage = latestSubmittedMessage
self.latestSubmittedAt = latestSubmittedAt
self.listeningPorts = listeningPorts
self.pullRequestURLs = pullRequestURLs
self.panelDirectories = panelDirectories
self.gitBranches = gitBranches
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Document public symbols and split the three types into separate files.

This new-package file declares CmuxSidebarProviderSnapshot, CmuxSidebarProviderGitBranch, and CmuxSidebarProviderWorkspace with no Swift-DocC comments on any public symbol, and bundles three major public types in one file.

As per coding guidelines: "Every public symbol in new Swift packages under Packages/ must be documented with Swift-DocC triple-slash comment at time of writing" and "One major type per file; each struct/class/enum/actor/protocol in public API lives in own file named after type."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderSnapshot.swift`
around lines 3 - 92, Split the three public types into their own files and add
Swift-DocC comments for each public symbol: create
CmuxSidebarProviderSnapshot.swift containing the CmuxSidebarProviderSnapshot
struct and document its properties and init with triple-slash comments; create
CmuxSidebarProviderGitBranch.swift for CmuxSidebarProviderGitBranch and document
branch/isDirty and init; create CmuxSidebarProviderWorkspace.swift for
CmuxSidebarProviderWorkspace and document the struct, all public properties (id,
title, customDescription, isPinned, rootPath, projectRootPath, branchSummary,
remoteDisplayTarget, remoteConnectionState, unreadCount, latestNotificationText,
latestSubmittedMessage, latestSubmittedAt, listeningPorts, pullRequestURLs,
panelDirectories, gitBranches) and its init; ensure file names match the type
names and that each public symbol has a brief Swift-DocC description above it.

@cubic-dev-ai cubic-dev-ai 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.

9 issues found across 26 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderSnapshot.swift">

<violation number="1" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderSnapshot.swift:3">
P3: Public API doc comment still uses legacy `CMUX` branding instead of `Cmux`, creating naming inconsistency in the new SDK surface.</violation>
</file>

<file name="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderPresentationRequest.swift">

<violation number="1" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderPresentationRequest.swift:3">
P3: Doc comments still reference the legacy "CMUX" branding instead of the renamed "Cmux" prefix, inconsistent with the PR's stated global renaming from CMUX* → Cmux*.</violation>

<violation number="2" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderPresentationRequest.swift:10">
P2: `openURL` case uses a bare `String` parameter instead of `URL`, sacrificing compile-time type safety for an API that semantically represents a URL. `URL` is `Codable` in Foundation, so this would not break the enum's `Codable` conformance.</violation>
</file>

<file name="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift">

<violation number="1" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift:25">
P3: The `accessory` init parameter is typed as optional (`CmuxSidebarProviderRowAccessory?`) but lacks a default value of `nil`, unlike the other three optional parameters (`subtitle`, `trailingText`, `leadingIcon`) which all default to `nil`. This forces callers to explicitly pass `nil` even when no accessory is needed, creating unnecessary friction and inconsistency.</violation>
</file>

<file name="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderModel.swift">

<violation number="1" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderModel.swift:6">
P3: Render-model struct uses `var` instead of `let` for its stored properties, which allows external mutation after construction. For a `Sendable` value type that represents an immutable snapshot/emission of provider state, `let` properties better communicate the snapshot semantics and prevent accidental state corruption by consumers.</violation>
</file>

<file name="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProvider+Rendering.swift">

<violation number="1" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProvider+Rendering.swift:18">
P1: The `render(snapshot:context:)` method on `CmuxSidebarProvider` ignores the `context` parameter and creates a static dispatch ambiguity with `CmuxContextualSidebarProvider`. Because this method is NOT a requirement of `CmuxSidebarProvider` (it only exists in the protocol extension), Swift uses static dispatch when calling through a `CmuxSidebarProvider`-typed reference. A caller with a `CmuxSidebarProvider` reference pointing to an object that actually conforms to `CmuxContextualSidebarProvider` will silently get this context-ignoring default instead of the contextual implementation, causing the context (e.g., `context.now` for relative date formatting) to be discarded without warning.</violation>
</file>

<file name="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift">

<violation number="1" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift:16">
P2: `defaultTab` is a required property in the initializer, but its semantics ("popover tab when the accessory opens workspace details") are only meaningful for certain accessory kinds. Currently `CmuxSidebarProviderRowAccessoryKind` has a single case (`.workspaceInspector`), which happens to open workspace details, so this works today. However, as soon as another kind is added (e.g., a direct-action button, a context-menu trigger), callers must supply a meaningless `defaultTab` just to construct the struct. This couples unrelated concerns into a single required parameter.</violation>
</file>

<file name="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIcon.swift">

<violation number="1" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIcon.swift:6">
P2: Icon model allows an empty/unrenderable state: both `systemImageName` and `text` are optional with no guard ensuring at least one is non-nil. Since `leadingIcon` on the row is already `CmuxSidebarProviderIcon?`, a nil icon already means "no icon"; an icon struct with neither field set is a meaningless state that should be prevented at the type level.</violation>

<violation number="2" location="Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIcon.swift:10">
P2: Hex color strings accept any arbitrary `String?` with no format validation, despite being documented as "CSS-style hex string." Invalid values (wrong length, missing `#`, invalid characters) would be silently accepted and could cause rendering failures downstream.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

snapshot: CmuxSidebarProviderSnapshot,
context: CmuxSidebarProviderRenderContext
) -> CmuxSidebarProviderRenderModel {
render(snapshot: snapshot)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: The render(snapshot:context:) method on CmuxSidebarProvider ignores the context parameter and creates a static dispatch ambiguity with CmuxContextualSidebarProvider. Because this method is NOT a requirement of CmuxSidebarProvider (it only exists in the protocol extension), Swift uses static dispatch when calling through a CmuxSidebarProvider-typed reference. A caller with a CmuxSidebarProvider reference pointing to an object that actually conforms to CmuxContextualSidebarProvider will silently get this context-ignoring default instead of the contextual implementation, causing the context (e.g., context.now for relative date formatting) to be discarded without warning.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProvider+Rendering.swift, line 18:

<comment>The `render(snapshot:context:)` method on `CmuxSidebarProvider` ignores the `context` parameter and creates a static dispatch ambiguity with `CmuxContextualSidebarProvider`. Because this method is NOT a requirement of `CmuxSidebarProvider` (it only exists in the protocol extension), Swift uses static dispatch when calling through a `CmuxSidebarProvider`-typed reference. A caller with a `CmuxSidebarProvider` reference pointing to an object that actually conforms to `CmuxContextualSidebarProvider` will silently get this context-ignoring default instead of the contextual implementation, causing the context (e.g., `context.now` for relative date formatting) to be discarded without warning.</comment>

<file context>
@@ -0,0 +1,20 @@
+        snapshot: CmuxSidebarProviderSnapshot,
+        context: CmuxSidebarProviderRenderContext
+    ) -> CmuxSidebarProviderRenderModel {
+        render(snapshot: snapshot)
+    }
+}
</file context>

/// Open a detached workspace window on a preferred tab.
case openWorkspaceWindow(workspaceId: UUID, preferredTab: CmuxSidebarProviderWorkspacePopoverTab)
/// Ask CMUX to open a URL.
case openURL(String)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: openURL case uses a bare String parameter instead of URL, sacrificing compile-time type safety for an API that semantically represents a URL. URL is Codable in Foundation, so this would not break the enum's Codable conformance.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderPresentationRequest.swift, line 10:

<comment>`openURL` case uses a bare `String` parameter instead of `URL`, sacrificing compile-time type safety for an API that semantically represents a URL. `URL` is `Codable` in Foundation, so this would not break the enum's `Codable` conformance.</comment>

<file context>
@@ -0,0 +1,11 @@
+    /// Open a detached workspace window on a preferred tab.
+    case openWorkspaceWindow(workspaceId: UUID, preferredTab: CmuxSidebarProviderWorkspacePopoverTab)
+    /// Ask CMUX to open a URL.
+    case openURL(String)
+}
</file context>

public init(
kind: CmuxSidebarProviderRowAccessoryKind,
systemImageName: String,
defaultTab: CmuxSidebarProviderWorkspacePopoverTab

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: defaultTab is a required property in the initializer, but its semantics ("popover tab when the accessory opens workspace details") are only meaningful for certain accessory kinds. Currently CmuxSidebarProviderRowAccessoryKind has a single case (.workspaceInspector), which happens to open workspace details, so this works today. However, as soon as another kind is added (e.g., a direct-action button, a context-menu trigger), callers must supply a meaningless defaultTab just to construct the struct. This couples unrelated concerns into a single required parameter.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift, line 16:

<comment>`defaultTab` is a required property in the initializer, but its semantics ("popover tab when the accessory opens workspace details") are only meaningful for certain accessory kinds. Currently `CmuxSidebarProviderRowAccessoryKind` has a single case (`.workspaceInspector`), which happens to open workspace details, so this works today. However, as soon as another kind is added (e.g., a direct-action button, a context-menu trigger), callers must supply a meaningless `defaultTab` just to construct the struct. This couples unrelated concerns into a single required parameter.</comment>

<file context>
@@ -0,0 +1,29 @@
+    public init(
+        kind: CmuxSidebarProviderRowAccessoryKind,
+        systemImageName: String,
+        defaultTab: CmuxSidebarProviderWorkspacePopoverTab
+    ) {
+        self.kind = kind
</file context>

/// Optional short text fallback.
public var text: String?
/// Foreground color as a CSS-style hex string.
public var foregroundColorHex: String?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Hex color strings accept any arbitrary String? with no format validation, despite being documented as "CSS-style hex string." Invalid values (wrong length, missing #, invalid characters) would be silently accepted and could cause rendering failures downstream.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIcon.swift, line 10:

<comment>Hex color strings accept any arbitrary `String?` with no format validation, despite being documented as "CSS-style hex string." Invalid values (wrong length, missing `#`, invalid characters) would be silently accepted and could cause rendering failures downstream.</comment>

<file context>
@@ -0,0 +1,30 @@
+    /// Optional short text fallback.
+    public var text: String?
+    /// Foreground color as a CSS-style hex string.
+    public var foregroundColorHex: String?
+    /// Background color as a CSS-style hex string.
+    public var backgroundColorHex: String?
</file context>

/// Icon model for a provider row.
public struct CmuxSidebarProviderIcon: Codable, Equatable, Sendable {
/// Optional SF Symbols name.
public var systemImageName: String?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Icon model allows an empty/unrenderable state: both systemImageName and text are optional with no guard ensuring at least one is non-nil. Since leadingIcon on the row is already CmuxSidebarProviderIcon?, a nil icon already means "no icon"; an icon struct with neither field set is a meaningless state that should be prevented at the type level.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIcon.swift, line 6:

<comment>Icon model allows an empty/unrenderable state: both `systemImageName` and `text` are optional with no guard ensuring at least one is non-nil. Since `leadingIcon` on the row is already `CmuxSidebarProviderIcon?`, a nil icon already means "no icon"; an icon struct with neither field set is a meaningless state that should be prevented at the type level.</comment>

<file context>
@@ -0,0 +1,30 @@
+/// Icon model for a provider row.
+public struct CmuxSidebarProviderIcon: Codable, Equatable, Sendable {
+    /// Optional SF Symbols name.
+    public var systemImageName: String?
+    /// Optional short text fallback.
+    public var text: String?
</file context>

@@ -0,0 +1,31 @@
import Foundation

/// Snapshot of CMUX workspace state consumed by in-process sidebar providers.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Public API doc comment still uses legacy CMUX branding instead of Cmux, creating naming inconsistency in the new SDK surface.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderSnapshot.swift, line 3:

<comment>Public API doc comment still uses legacy `CMUX` branding instead of `Cmux`, creating naming inconsistency in the new SDK surface.</comment>

<file context>
@@ -0,0 +1,31 @@
+import Foundation
+
+/// Snapshot of CMUX workspace state consumed by in-process sidebar providers.
+public struct CmuxSidebarProviderSnapshot: Codable, Equatable, Sendable {
+    /// Monotonic snapshot sequence.
</file context>
Suggested change
/// Snapshot of CMUX workspace state consumed by in-process sidebar providers.
/// Snapshot of Cmux workspace state consumed by in-process sidebar providers.

@@ -0,0 +1,11 @@
import Foundation

/// Presentation command a provider can request from the CMUX sidebar host.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Doc comments still reference the legacy "CMUX" branding instead of the renamed "Cmux" prefix, inconsistent with the PR's stated global renaming from CMUX* → Cmux*.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderPresentationRequest.swift, line 3:

<comment>Doc comments still reference the legacy "CMUX" branding instead of the renamed "Cmux" prefix, inconsistent with the PR's stated global renaming from CMUX* → Cmux*.</comment>

<file context>
@@ -0,0 +1,11 @@
+import Foundation
+
+/// Presentation command a provider can request from the CMUX sidebar host.
+public enum CmuxSidebarProviderPresentationRequest: Codable, Equatable, Sendable {
+    /// Open the workspace popover on a preferred tab.
</file context>
Suggested change
/// Presentation command a provider can request from the CMUX sidebar host.
/// Presentation command a provider can request from the Cmux sidebar host.

id: UUID,
title: String,
workspaceId: UUID,
accessory: CmuxSidebarProviderRowAccessory?,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The accessory init parameter is typed as optional (CmuxSidebarProviderRowAccessory?) but lacks a default value of nil, unlike the other three optional parameters (subtitle, trailingText, leadingIcon) which all default to nil. This forces callers to explicitly pass nil even when no accessory is needed, creating unnecessary friction and inconsistency.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift, line 25:

<comment>The `accessory` init parameter is typed as optional (`CmuxSidebarProviderRowAccessory?`) but lacks a default value of `nil`, unlike the other three optional parameters (`subtitle`, `trailingText`, `leadingIcon`) which all default to `nil`. This forces callers to explicitly pass `nil` even when no accessory is needed, creating unnecessary friction and inconsistency.</comment>

<file context>
@@ -0,0 +1,38 @@
+        id: UUID,
+        title: String,
+        workspaceId: UUID,
+        accessory: CmuxSidebarProviderRowAccessory?,
+        subtitle: CmuxSidebarProviderText? = nil,
+        trailingText: CmuxSidebarProviderText? = nil,
</file context>

/// Complete render model emitted by an in-process sidebar provider.
public struct CmuxSidebarProviderRenderModel: Codable, Equatable, Sendable {
/// Provider id that produced this model.
public var providerId: String

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Render-model struct uses var instead of let for its stored properties, which allows external mutation after construction. For a Sendable value type that represents an immutable snapshot/emission of provider state, let properties better communicate the snapshot semantics and prevent accidental state corruption by consumers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderModel.swift, line 6:

<comment>Render-model struct uses `var` instead of `let` for its stored properties, which allows external mutation after construction. For a `Sendable` value type that represents an immutable snapshot/emission of provider state, `let` properties better communicate the snapshot semantics and prevent accidental state corruption by consumers.</comment>

<file context>
@@ -0,0 +1,26 @@
+/// Complete render model emitted by an in-process sidebar provider.
+public struct CmuxSidebarProviderRenderModel: Codable, Equatable, Sendable {
+    /// Provider id that produced this model.
+    public var providerId: String
+    /// Snapshot sequence this model was rendered from.
+    public var snapshotSequence: UInt64
</file context>

@azooz2003-bit
azooz2003-bit force-pushed the feat-extension-sdk-organization branch from 3c778bf to 8173919 Compare June 2, 2026 14:47

@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: 11

Caution

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

⚠️ Outside diff range comments (4)
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift (1)

37-38: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix missing translations for defaultWorkspaces sidebar provider title/subtitle

defaultWorkspaces uses CmuxSidebarProviderLocalizedText for sidebar.provider.default.title and sidebar.provider.default.subtitle, but in Resources/Localizable.xcstrings those keys are localized only for en and ja while the catalog includes many other supported locales (e.g., fr, de, es, it, zh-Hans, zh-Hant, etc.). This will fall back to English for the other locales, violating the full internationalization rule.

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift`
around lines 37 - 38, The title/subtitle for the defaultWorkspaces provider
(created with CmuxSidebarProviderLocalizedText in
CmuxSidebarProviderDescriptor.swift using keys "sidebar.provider.default.title"
and "sidebar.provider.default.subtitle") are only localized for en/ja; add the
missing translations for all supported locales in
Resources/Localizable.xcstrings (e.g., fr, de, es, it, zh-Hans, zh-Hant, etc.)
so these keys exist in each locale bundle, or update the localization catalog to
include those keys for every supported locale to avoid English fallbacks.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift (1)

3-42: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Expand the DocC on this public tree-section API.

This file adds a public package model, but its docs are still summary-only. The repo rule for Packages/ requires full Swift-DocC coverage for the type, public properties, and init(...), including discussion text and parameter callouts.

As per coding guidelines, "Document every public symbol in new Swift packages under Packages/ with Swift-DocC triple-slash comments at time of writing" and "document enums/inits/properties/methods with meaning and invariants."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift`
around lines 3 - 42, Add full Swift-DocC documentation to the public API:
provide a triple-slash doc comment for the CmuxSidebarProviderTreeSection type
describing its purpose and invariants, then add triple-slash comments for each
public property (id, title, titleText, subtitle, subtitleText, systemImageName,
projectRootPath, workspaceIds) explaining meaning, expected formats (e.g.,
stable id, SF Symbols name), nilability, and any invariants (e.g., workspaceIds
non-empty if representing a workspace). Also document the public init(...) with
a DocC discussion and `@param-style` callouts for each parameter describing
allowed values and behavior (including defaults for optional parameters) and
note thread-safety/Sendable conformance where relevant.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift (1)

101-104: 🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoff

Consider using localized strings for transport error messages.

Multiple hardcoded English strings ("Waiting for cmux", "cmux connection changed", "cmux connection was lost", "cmux did not send a workspace snapshot", etc.) flow through rejection results and may surface in extension UIs.

The downstream sample in SidebarConnectionModel.swift shows these can become errorText. While these are in internal transport code, consider either:

  1. Documenting that host rejection messages are diagnostic-only and extensions should provide their own localized fallback UI, or
  2. Using localized strings with Bundle.module for consistency.

Current sample code handles this appropriately by mapping .rejected(message) to its own localized fallback, so this is not blocking.

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift`
around lines 101 - 104, Replace hardcoded English transport messages (e.g. the
"Waiting for cmux" message passed into deliver(.rejected(message), to: reply)
and other strings used when reporting connection state like in
report(.waitingForHost) or deliver(.rejected(...))) with localized strings from
your package bundle (e.g. use NSLocalizedString or a localized helper that loads
from Bundle.module) so these rejection messages can be localized or documented
as diagnostic-only; update the message creation in
CMUXSidebarExtensionConnection (the spots that call report(.waitingForHost,
ifCurrentGeneration: currentGeneration()) and deliver(.rejected(...), to:
reply)) to fetch a localized string or a clearly documented diagnostic message
provider.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift (1)

37-42: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Hardcoded English string violates localization guidelines.

The cancelled result contains the hardcoded message "Extension action was cancelled" which may surface in extension UIs (see SidebarConnectionModel.swift context showing errorText = message). Per full-internationalization.md, user-facing text must use localized APIs.

Since this is inside a package (not the main app target), you'll need to use the Bundle.module pattern:

📝 Proposed fix
     /// Rejected action result used when the caller cancels an in-flight request.
     public static let cancelled = CmuxSidebarActionResult(
         accepted: false,
-        message: "Extension action was cancelled",
+        message: String(
+            localized: "sidebar.action.cancelled",
+            defaultValue: "Extension action was cancelled",
+            bundle: .module
+        ),
         rejectionReason: .cancelled
     )

You'll also need to add a Localizable.xcstrings resource to the package if one doesn't exist.

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`
around lines 37 - 42, The static constant cancelled on CmuxSidebarActionResult
currently embeds a hardcoded English message; replace the literal "Extension
action was cancelled" with a localized lookup using Bundle.module (e.g.,
NSLocalizedString or String(localized:bundle:)) so the user-facing text comes
from the package resource bundle, and add the corresponding key/value to the
package's Localizable.xcstrings resource; update
CmuxSidebarActionResult.cancelled to call the localization API with
Bundle.module and ensure the Localizable.xcstrings contains the translated
string for that key.
🤖 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
`@Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/SidebarProviderExistentialDispatchTests.swift`:
- Around line 46-52: The test currently loops "for provider in
SidebarExamples.providers where
listingProviderIDs.contains(provider.descriptor.id)" and can vacuously pass if
no providers match; update the test to assert that at least one provider was
exercised by either (a) computing the matchedProviders via
SidebarExamples.providers.filter { listingProviderIDs.contains($0.descriptor.id)
} and XCTAssertGreaterThan(matchedProviders.count, 0) before iterating, or (b)
keep the loop but increment a counter for each iteration and
XCTAssertGreaterThan(counter, 0) after the loop; use the same
provider.descriptor.id and model.sections.flatMap(\\.rows) checks inside the
iteration as-is.
- Around line 1-53: Convert this XCTest-based file to Swift Testing: replace
"import XCTest" with "import Testing", change the XCTestCase class
SidebarProviderExistentialDispatchTests into a Swift Testing suite (e.g.
annotate a struct or enum with `@Suite` and keep the same name), mark the two test
methods testSuperCompactRendersIdenticallyThroughExistential and
testWorkspaceListingProvidersRenderRowsThroughExistential with `@Test`, and
replace XCTAssert* calls with the corresponding `#expect`(...) matchers (e.g.
`#expect`(concreteModel.sections.isEmpty).toBeFalse(),
`#expect`(concreteModel.sections.flatMap(\.rows).count).toEqual(3), and
`#expect`(existentialModel.sections).toEqual(concreteModel.sections); similarly
use `#expect`(...).not.toBeEmpty() or equivalent for the provider loop). Keep
references to SuperCompactSidebar, SidebarExamples.providers,
provider.descriptor.id, and CmuxSidebarProvider render(snapshot:) usage
unchanged except for assertion syntax and suite/test annotations.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderCommandResult.swift`:
- Around line 3-10: The public type CmuxSidebarProviderCommandResult and its
initializer init(ok:) lack complete DocC comments: update the triple-slash docs
for the struct, the public var ok and the public init(ok:) to include a summary
sentence for the type, a clear description of the ok property, and a "-
Parameter ok:" callout that explains what true and false mean for callers (e.g.,
ok == true means CMUX accepted and completed the command; ok == false means the
command was rejected or failed and callers should treat the result as
unsuccessful). Ensure comments are placed immediately above
CmuxSidebarProviderCommandResult, above the ok property, and above init(ok:)
using Swift-DocC triple-slash style.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderWorkspaceMove.swift`:
- Around line 11-24: The public transport type allows negative targetIndex
values which can be decoded or constructed; fix by enforcing a non-negative
invariant at decode-time or via a refined type: add a custom Decodable
init(from:) on CmuxSidebarProviderWorkspaceMove that reads targetIndex and
throws a decoding error if value < 0 (or replace targetIndex with a
NonNegativeInt wrapper type that validates on init/Decodable), and update the
public init/workflow to accept/produce only the validated value so negatives
cannot flow through the API.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift`:
- Around line 3-38: Add full Swift-DocC comments for the public type
CmuxSidebarProviderRow, its public stored properties (id, title, workspaceId,
accessory, subtitle, trailingText, leadingIcon) and the public initializer; for
each symbol use triple-slash comments with a one-sentence summary on the first
line, a blank line, then a short discussion paragraph, and for the init include
a detailed "- Parameter" entry for every parameter (and "- Returns:" only if
applicable) following DocC style; update the existing short summaries above the
struct and above init(...) to the required summary/discussion shape and add
per-parameter callouts to the init signature so the package meets the Packages/
Swift-DocC documentation policy.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift`:
- Around line 3-29: Add full Swift-DocC triple-slash documentation to the public
struct CmuxSidebarProviderRowAccessory, its public stored properties (kind,
systemImageName, defaultTab), the public initializer
(init(kind:systemImageName:defaultTab:)) and the public static inspector
constant: expand the brief summaries into a discussion paragraph describing
purpose and usage, document invariants/behavior, and add - Parameter callouts
for each initializer parameter explaining expected values and effects (e.g.,
what each CmuxSidebarProviderRowAccessoryKind value does, valid systemImageName
expectations, and defaultTab behavior); ensure the inspector constant has its
own summary/discussion noting it is a standard preconfigured accessory.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessoryKind.swift`:
- Around line 3-7: Add full Swift-DocC triple-slash documentation for the
exported enum CmuxSidebarProviderRowAccessoryKind and its public member(s):
document the enum's purpose, when and where clients should use it, any
invariants or expectations (e.g., that it is Codable/Equatable/Sendable and
backed by a String raw value), and describe serialization/compatibility
guarantees; for the case workspaceInspector add a clear sentence about what UI
affordance it represents and any behavior/constraints (for example whether it
always opens the workspace inspector, platform limits, or visibility rules).
Place the comments immediately above the enum declaration and above the case
using triple-slash (///) DocC style so the symbol and member are fully
documented for clients and documentation generation.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderSection.swift`:
- Around line 3-22: Add full Swift-DocC triple-slash documentation to the public
type CmuxSidebarProviderSection, each public property (id, treeSection, rows),
and the public initializer init(id:treeSection:rows:). For each symbol follow
the package guideline: start with a one-sentence summary on the first line, add
a blank /// line, then a short discussion paragraph describing purpose/behavior
and any invariants; for the initializer include a /// - Parameters: block
documenting id, treeSection, and rows. Ensure comments are triple-slash (///)
and placed immediately above the struct, each property, and the initializer so
DocC picks them up.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderGitBranch.swift`:
- Around line 3-15: Add full Swift-DocC triple-slash documentation for the
public symbol CmuxSidebarProviderGitBranch: start with a one-sentence summary on
the first /// line, add a blank /// line, then a short discussion describing the
purpose and usage of this snapshot type; document the stored properties branch
and isDirty with brief descriptions; and add a documented initializer
init(branch:isDirty:) that includes /// - Parameters: with callouts for branch
and isDirty. Ensure every public symbol (struct, properties, and init) uses the
/// pattern and follows the package doc style.

In
`@Packages/CmuxSocketControl/Sources/CmuxSocketControl/SocketControlPasswordStore.swift`:
- Around line 25-28: Replace the hardcoded legacy keychain service/account
strings with the defined constants: use legacyKeychainService and
legacyKeychainAccount wherever the CFDictionary keychain queries are built (the
dictionaries currently containing "com.cmuxterm.app.socket-control" and
"local-socket-password"), including in the migration routine and
deleteLegacyPasswordFromKeychain(); update the query dictionaries to reference
these constants instead of string literals so the service/account names are
maintained in one place.

In `@Sources/ContentView.swift`:
- Around line 10356-10361: The view currently calls GhosttyConfig.load()
synchronously inside the SidebarTabItemSettingsStore initializer which may block
view init; change to construct SidebarTabItemSettingsStore with a fast default
(e.g. a default font size) and remove the synchronous GhosttyConfig.load() call,
then kick off an async load (using SidebarFontSizeProvider.loadFromGhosttyConfig
or a .task/async init helper) to fetch the real value and update the
SidebarTabItemSettingsStore instance when ready; target the
SidebarTabItemSettingsStore creation site and the async loader
SidebarFontSizeProvider.loadFromGhosttyConfig to implement the deferred load and
update logic.

---

Outside diff comments:
In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`:
- Around line 37-42: The static constant cancelled on CmuxSidebarActionResult
currently embeds a hardcoded English message; replace the literal "Extension
action was cancelled" with a localized lookup using Bundle.module (e.g.,
NSLocalizedString or String(localized:bundle:)) so the user-facing text comes
from the package resource bundle, and add the corresponding key/value to the
package's Localizable.xcstrings resource; update
CmuxSidebarActionResult.cancelled to call the localization API with
Bundle.module and ensure the Localizable.xcstrings contains the translated
string for that key.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift`:
- Around line 101-104: Replace hardcoded English transport messages (e.g. the
"Waiting for cmux" message passed into deliver(.rejected(message), to: reply)
and other strings used when reporting connection state like in
report(.waitingForHost) or deliver(.rejected(...))) with localized strings from
your package bundle (e.g. use NSLocalizedString or a localized helper that loads
from Bundle.module) so these rejection messages can be localized or documented
as diagnostic-only; update the message creation in
CMUXSidebarExtensionConnection (the spots that call report(.waitingForHost,
ifCurrentGeneration: currentGeneration()) and deliver(.rejected(...), to:
reply)) to fetch a localized string or a clearly documented diagnostic message
provider.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift`:
- Around line 37-38: The title/subtitle for the defaultWorkspaces provider
(created with CmuxSidebarProviderLocalizedText in
CmuxSidebarProviderDescriptor.swift using keys "sidebar.provider.default.title"
and "sidebar.provider.default.subtitle") are only localized for en/ja; add the
missing translations for all supported locales in
Resources/Localizable.xcstrings (e.g., fr, de, es, it, zh-Hans, zh-Hant, etc.)
so these keys exist in each locale bundle, or update the localization catalog to
include those keys for every supported locale to avoid English fallbacks.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift`:
- Around line 3-42: Add full Swift-DocC documentation to the public API: provide
a triple-slash doc comment for the CmuxSidebarProviderTreeSection type
describing its purpose and invariants, then add triple-slash comments for each
public property (id, title, titleText, subtitle, subtitleText, systemImageName,
projectRootPath, workspaceIds) explaining meaning, expected formats (e.g.,
stable id, SF Symbols name), nilability, and any invariants (e.g., workspaceIds
non-empty if representing a workspace). Also document the public init(...) with
a DocC discussion and `@param-style` callouts for each parameter describing
allowed values and behavior (including defaults for optional parameters) and
note thread-safety/Sendable conformance where relevant.
🪄 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: 4e072668-a9ca-4dc2-a69d-bbc9583bb3cd

📥 Commits

Reviewing files that changed from the base of the PR and between 4c59be9 and 3c778bf.

📒 Files selected for processing (46)
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/SidebarProviderExistentialDispatchTests.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Connection/SidebarConnectionModel.swift
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/Resources/Localizable.xcstrings
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/StubAgentSidebarExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Common/CMUXExtensionAPIVersion.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Validation/CMUXExtensionValidator.swift
  • Packages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderLocalizedText.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIcon.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIconShape.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxMutableSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderCommandResult.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderMutation.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderPresentationRequest.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderWorkspaceMove.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Presentation/CmuxSidebarProviderPresentation.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Presentation/CmuxSidebarProviderWorkspacePopoverTab.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxContextualSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProvider+Rendering.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderContext.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderModel.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessoryKind.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderSection.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderGitBranch.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderSnapshot.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderWorkspace.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Text/CmuxSidebarProviderRelativeDateStyle.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Text/CmuxSidebarProviderText.swift
  • Packages/CmuxSocketControl/Sources/CmuxSocketControl/SocketControlPasswordStore.swift
  • Resources/Localizable.xcstrings
  • Sources/ContentView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmux.xcworkspace/contents.xcworkspacedata
  • scripts/write-sidebar-extension-point.sh
💤 Files with no reviewable changes (2)
  • scripts/write-sidebar-extension-point.sh
  • Resources/Localizable.xcstrings

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 11

Caution

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

⚠️ Outside diff range comments (4)
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift (1)

37-38: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix missing translations for defaultWorkspaces sidebar provider title/subtitle

defaultWorkspaces uses CmuxSidebarProviderLocalizedText for sidebar.provider.default.title and sidebar.provider.default.subtitle, but in Resources/Localizable.xcstrings those keys are localized only for en and ja while the catalog includes many other supported locales (e.g., fr, de, es, it, zh-Hans, zh-Hant, etc.). This will fall back to English for the other locales, violating the full internationalization rule.

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift`
around lines 37 - 38, The title/subtitle for the defaultWorkspaces provider
(created with CmuxSidebarProviderLocalizedText in
CmuxSidebarProviderDescriptor.swift using keys "sidebar.provider.default.title"
and "sidebar.provider.default.subtitle") are only localized for en/ja; add the
missing translations for all supported locales in
Resources/Localizable.xcstrings (e.g., fr, de, es, it, zh-Hans, zh-Hant, etc.)
so these keys exist in each locale bundle, or update the localization catalog to
include those keys for every supported locale to avoid English fallbacks.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift (1)

3-42: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Expand the DocC on this public tree-section API.

This file adds a public package model, but its docs are still summary-only. The repo rule for Packages/ requires full Swift-DocC coverage for the type, public properties, and init(...), including discussion text and parameter callouts.

As per coding guidelines, "Document every public symbol in new Swift packages under Packages/ with Swift-DocC triple-slash comments at time of writing" and "document enums/inits/properties/methods with meaning and invariants."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift`
around lines 3 - 42, Add full Swift-DocC documentation to the public API:
provide a triple-slash doc comment for the CmuxSidebarProviderTreeSection type
describing its purpose and invariants, then add triple-slash comments for each
public property (id, title, titleText, subtitle, subtitleText, systemImageName,
projectRootPath, workspaceIds) explaining meaning, expected formats (e.g.,
stable id, SF Symbols name), nilability, and any invariants (e.g., workspaceIds
non-empty if representing a workspace). Also document the public init(...) with
a DocC discussion and `@param-style` callouts for each parameter describing
allowed values and behavior (including defaults for optional parameters) and
note thread-safety/Sendable conformance where relevant.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift (1)

101-104: 🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoff

Consider using localized strings for transport error messages.

Multiple hardcoded English strings ("Waiting for cmux", "cmux connection changed", "cmux connection was lost", "cmux did not send a workspace snapshot", etc.) flow through rejection results and may surface in extension UIs.

The downstream sample in SidebarConnectionModel.swift shows these can become errorText. While these are in internal transport code, consider either:

  1. Documenting that host rejection messages are diagnostic-only and extensions should provide their own localized fallback UI, or
  2. Using localized strings with Bundle.module for consistency.

Current sample code handles this appropriately by mapping .rejected(message) to its own localized fallback, so this is not blocking.

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift`
around lines 101 - 104, Replace hardcoded English transport messages (e.g. the
"Waiting for cmux" message passed into deliver(.rejected(message), to: reply)
and other strings used when reporting connection state like in
report(.waitingForHost) or deliver(.rejected(...))) with localized strings from
your package bundle (e.g. use NSLocalizedString or a localized helper that loads
from Bundle.module) so these rejection messages can be localized or documented
as diagnostic-only; update the message creation in
CMUXSidebarExtensionConnection (the spots that call report(.waitingForHost,
ifCurrentGeneration: currentGeneration()) and deliver(.rejected(...), to:
reply)) to fetch a localized string or a clearly documented diagnostic message
provider.
Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift (1)

37-42: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Hardcoded English string violates localization guidelines.

The cancelled result contains the hardcoded message "Extension action was cancelled" which may surface in extension UIs (see SidebarConnectionModel.swift context showing errorText = message). Per full-internationalization.md, user-facing text must use localized APIs.

Since this is inside a package (not the main app target), you'll need to use the Bundle.module pattern:

📝 Proposed fix
     /// Rejected action result used when the caller cancels an in-flight request.
     public static let cancelled = CmuxSidebarActionResult(
         accepted: false,
-        message: "Extension action was cancelled",
+        message: String(
+            localized: "sidebar.action.cancelled",
+            defaultValue: "Extension action was cancelled",
+            bundle: .module
+        ),
         rejectionReason: .cancelled
     )

You'll also need to add a Localizable.xcstrings resource to the package if one doesn't exist.

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`
around lines 37 - 42, The static constant cancelled on CmuxSidebarActionResult
currently embeds a hardcoded English message; replace the literal "Extension
action was cancelled" with a localized lookup using Bundle.module (e.g.,
NSLocalizedString or String(localized:bundle:)) so the user-facing text comes
from the package resource bundle, and add the corresponding key/value to the
package's Localizable.xcstrings resource; update
CmuxSidebarActionResult.cancelled to call the localization API with
Bundle.module and ensure the Localizable.xcstrings contains the translated
string for that key.
🤖 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
`@Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/SidebarProviderExistentialDispatchTests.swift`:
- Around line 46-52: The test currently loops "for provider in
SidebarExamples.providers where
listingProviderIDs.contains(provider.descriptor.id)" and can vacuously pass if
no providers match; update the test to assert that at least one provider was
exercised by either (a) computing the matchedProviders via
SidebarExamples.providers.filter { listingProviderIDs.contains($0.descriptor.id)
} and XCTAssertGreaterThan(matchedProviders.count, 0) before iterating, or (b)
keep the loop but increment a counter for each iteration and
XCTAssertGreaterThan(counter, 0) after the loop; use the same
provider.descriptor.id and model.sections.flatMap(\\.rows) checks inside the
iteration as-is.
- Around line 1-53: Convert this XCTest-based file to Swift Testing: replace
"import XCTest" with "import Testing", change the XCTestCase class
SidebarProviderExistentialDispatchTests into a Swift Testing suite (e.g.
annotate a struct or enum with `@Suite` and keep the same name), mark the two test
methods testSuperCompactRendersIdenticallyThroughExistential and
testWorkspaceListingProvidersRenderRowsThroughExistential with `@Test`, and
replace XCTAssert* calls with the corresponding `#expect`(...) matchers (e.g.
`#expect`(concreteModel.sections.isEmpty).toBeFalse(),
`#expect`(concreteModel.sections.flatMap(\.rows).count).toEqual(3), and
`#expect`(existentialModel.sections).toEqual(concreteModel.sections); similarly
use `#expect`(...).not.toBeEmpty() or equivalent for the provider loop). Keep
references to SuperCompactSidebar, SidebarExamples.providers,
provider.descriptor.id, and CmuxSidebarProvider render(snapshot:) usage
unchanged except for assertion syntax and suite/test annotations.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderCommandResult.swift`:
- Around line 3-10: The public type CmuxSidebarProviderCommandResult and its
initializer init(ok:) lack complete DocC comments: update the triple-slash docs
for the struct, the public var ok and the public init(ok:) to include a summary
sentence for the type, a clear description of the ok property, and a "-
Parameter ok:" callout that explains what true and false mean for callers (e.g.,
ok == true means CMUX accepted and completed the command; ok == false means the
command was rejected or failed and callers should treat the result as
unsuccessful). Ensure comments are placed immediately above
CmuxSidebarProviderCommandResult, above the ok property, and above init(ok:)
using Swift-DocC triple-slash style.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderWorkspaceMove.swift`:
- Around line 11-24: The public transport type allows negative targetIndex
values which can be decoded or constructed; fix by enforcing a non-negative
invariant at decode-time or via a refined type: add a custom Decodable
init(from:) on CmuxSidebarProviderWorkspaceMove that reads targetIndex and
throws a decoding error if value < 0 (or replace targetIndex with a
NonNegativeInt wrapper type that validates on init/Decodable), and update the
public init/workflow to accept/produce only the validated value so negatives
cannot flow through the API.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift`:
- Around line 3-38: Add full Swift-DocC comments for the public type
CmuxSidebarProviderRow, its public stored properties (id, title, workspaceId,
accessory, subtitle, trailingText, leadingIcon) and the public initializer; for
each symbol use triple-slash comments with a one-sentence summary on the first
line, a blank line, then a short discussion paragraph, and for the init include
a detailed "- Parameter" entry for every parameter (and "- Returns:" only if
applicable) following DocC style; update the existing short summaries above the
struct and above init(...) to the required summary/discussion shape and add
per-parameter callouts to the init signature so the package meets the Packages/
Swift-DocC documentation policy.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift`:
- Around line 3-29: Add full Swift-DocC triple-slash documentation to the public
struct CmuxSidebarProviderRowAccessory, its public stored properties (kind,
systemImageName, defaultTab), the public initializer
(init(kind:systemImageName:defaultTab:)) and the public static inspector
constant: expand the brief summaries into a discussion paragraph describing
purpose and usage, document invariants/behavior, and add - Parameter callouts
for each initializer parameter explaining expected values and effects (e.g.,
what each CmuxSidebarProviderRowAccessoryKind value does, valid systemImageName
expectations, and defaultTab behavior); ensure the inspector constant has its
own summary/discussion noting it is a standard preconfigured accessory.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessoryKind.swift`:
- Around line 3-7: Add full Swift-DocC triple-slash documentation for the
exported enum CmuxSidebarProviderRowAccessoryKind and its public member(s):
document the enum's purpose, when and where clients should use it, any
invariants or expectations (e.g., that it is Codable/Equatable/Sendable and
backed by a String raw value), and describe serialization/compatibility
guarantees; for the case workspaceInspector add a clear sentence about what UI
affordance it represents and any behavior/constraints (for example whether it
always opens the workspace inspector, platform limits, or visibility rules).
Place the comments immediately above the enum declaration and above the case
using triple-slash (///) DocC style so the symbol and member are fully
documented for clients and documentation generation.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderSection.swift`:
- Around line 3-22: Add full Swift-DocC triple-slash documentation to the public
type CmuxSidebarProviderSection, each public property (id, treeSection, rows),
and the public initializer init(id:treeSection:rows:). For each symbol follow
the package guideline: start with a one-sentence summary on the first line, add
a blank /// line, then a short discussion paragraph describing purpose/behavior
and any invariants; for the initializer include a /// - Parameters: block
documenting id, treeSection, and rows. Ensure comments are triple-slash (///)
and placed immediately above the struct, each property, and the initializer so
DocC picks them up.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderGitBranch.swift`:
- Around line 3-15: Add full Swift-DocC triple-slash documentation for the
public symbol CmuxSidebarProviderGitBranch: start with a one-sentence summary on
the first /// line, add a blank /// line, then a short discussion describing the
purpose and usage of this snapshot type; document the stored properties branch
and isDirty with brief descriptions; and add a documented initializer
init(branch:isDirty:) that includes /// - Parameters: with callouts for branch
and isDirty. Ensure every public symbol (struct, properties, and init) uses the
/// pattern and follows the package doc style.

In
`@Packages/CmuxSocketControl/Sources/CmuxSocketControl/SocketControlPasswordStore.swift`:
- Around line 25-28: Replace the hardcoded legacy keychain service/account
strings with the defined constants: use legacyKeychainService and
legacyKeychainAccount wherever the CFDictionary keychain queries are built (the
dictionaries currently containing "com.cmuxterm.app.socket-control" and
"local-socket-password"), including in the migration routine and
deleteLegacyPasswordFromKeychain(); update the query dictionaries to reference
these constants instead of string literals so the service/account names are
maintained in one place.

In `@Sources/ContentView.swift`:
- Around line 10356-10361: The view currently calls GhosttyConfig.load()
synchronously inside the SidebarTabItemSettingsStore initializer which may block
view init; change to construct SidebarTabItemSettingsStore with a fast default
(e.g. a default font size) and remove the synchronous GhosttyConfig.load() call,
then kick off an async load (using SidebarFontSizeProvider.loadFromGhosttyConfig
or a .task/async init helper) to fetch the real value and update the
SidebarTabItemSettingsStore instance when ready; target the
SidebarTabItemSettingsStore creation site and the async loader
SidebarFontSizeProvider.loadFromGhosttyConfig to implement the deferred load and
update logic.

---

Outside diff comments:
In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`:
- Around line 37-42: The static constant cancelled on CmuxSidebarActionResult
currently embeds a hardcoded English message; replace the literal "Extension
action was cancelled" with a localized lookup using Bundle.module (e.g.,
NSLocalizedString or String(localized:bundle:)) so the user-facing text comes
from the package resource bundle, and add the corresponding key/value to the
package's Localizable.xcstrings resource; update
CmuxSidebarActionResult.cancelled to call the localization API with
Bundle.module and ensure the Localizable.xcstrings contains the translated
string for that key.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift`:
- Around line 101-104: Replace hardcoded English transport messages (e.g. the
"Waiting for cmux" message passed into deliver(.rejected(message), to: reply)
and other strings used when reporting connection state like in
report(.waitingForHost) or deliver(.rejected(...))) with localized strings from
your package bundle (e.g. use NSLocalizedString or a localized helper that loads
from Bundle.module) so these rejection messages can be localized or documented
as diagnostic-only; update the message creation in
CMUXSidebarExtensionConnection (the spots that call report(.waitingForHost,
ifCurrentGeneration: currentGeneration()) and deliver(.rejected(...), to:
reply)) to fetch a localized string or a clearly documented diagnostic message
provider.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift`:
- Around line 37-38: The title/subtitle for the defaultWorkspaces provider
(created with CmuxSidebarProviderLocalizedText in
CmuxSidebarProviderDescriptor.swift using keys "sidebar.provider.default.title"
and "sidebar.provider.default.subtitle") are only localized for en/ja; add the
missing translations for all supported locales in
Resources/Localizable.xcstrings (e.g., fr, de, es, it, zh-Hans, zh-Hant, etc.)
so these keys exist in each locale bundle, or update the localization catalog to
include those keys for every supported locale to avoid English fallbacks.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift`:
- Around line 3-42: Add full Swift-DocC documentation to the public API: provide
a triple-slash doc comment for the CmuxSidebarProviderTreeSection type
describing its purpose and invariants, then add triple-slash comments for each
public property (id, title, titleText, subtitle, subtitleText, systemImageName,
projectRootPath, workspaceIds) explaining meaning, expected formats (e.g.,
stable id, SF Symbols name), nilability, and any invariants (e.g., workspaceIds
non-empty if representing a workspace). Also document the public init(...) with
a DocC discussion and `@param-style` callouts for each parameter describing
allowed values and behavior (including defaults for optional parameters) and
note thread-safety/Sendable conformance where relevant.
🪄 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: 4e072668-a9ca-4dc2-a69d-bbc9583bb3cd

📥 Commits

Reviewing files that changed from the base of the PR and between 4c59be9 and 3c778bf.

📒 Files selected for processing (46)
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/SidebarProviderExistentialDispatchTests.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Connection/SidebarConnectionModel.swift
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/Resources/Localizable.xcstrings
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/StubAgentSidebarExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Common/CMUXExtensionAPIVersion.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Validation/CMUXExtensionValidator.swift
  • Packages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderLocalizedText.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIcon.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIconShape.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxMutableSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderCommandResult.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderMutation.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderPresentationRequest.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderWorkspaceMove.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Presentation/CmuxSidebarProviderPresentation.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Presentation/CmuxSidebarProviderWorkspacePopoverTab.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxContextualSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProvider+Rendering.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderContext.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderModel.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessoryKind.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderSection.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderGitBranch.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderSnapshot.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderWorkspace.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Text/CmuxSidebarProviderRelativeDateStyle.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Text/CmuxSidebarProviderText.swift
  • Packages/CmuxSocketControl/Sources/CmuxSocketControl/SocketControlPasswordStore.swift
  • Resources/Localizable.xcstrings
  • Sources/ContentView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmux.xcworkspace/contents.xcworkspacedata
  • scripts/write-sidebar-extension-point.sh
💤 Files with no reviewable changes (2)
  • scripts/write-sidebar-extension-point.sh
  • Resources/Localizable.xcstrings
🛑 Comments failed to post (11)
Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/SidebarProviderExistentialDispatchTests.swift (2)

1-53: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Convert this new test to Swift Testing.

This is a new, non-UI test file using XCTest. Per the test guidelines, new unit/integration tests must use Swift Testing (import Testing, @Suite, @Test, #expect).

♻️ Proposed conversion to Swift Testing
-import CmuxSidebarProviderKit
-@testable import CmuxExtensionSidebarExamples
-import XCTest
+import CmuxSidebarProviderKit
+import Testing
+@testable import CmuxExtensionSidebarExamples
-final class SidebarProviderExistentialDispatchTests: XCTestCase {
+@Suite struct SidebarProviderExistentialDispatchTests {
     /// Super Compact lists every workspace in a single section, so calling it
     /// through the existential must yield exactly the same rows as the concrete
     /// call — not the empty protocol-extension default.
-    func testSuperCompactRendersIdenticallyThroughExistential() {
+    `@Test` func superCompactRendersIdenticallyThroughExistential() {
         let snapshot = Self.snapshot(workspaceCount: 3)
         let concrete = SuperCompactSidebar()
         let existential: any CmuxSidebarProvider = concrete

         let concreteModel = concrete.render(snapshot: snapshot)
         let existentialModel = existential.render(snapshot: snapshot)

-        XCTAssertFalse(concreteModel.sections.isEmpty, "concrete render should produce a section")
-        XCTAssertEqual(concreteModel.sections.flatMap(\.rows).count, 3)
-        XCTAssertEqual(
-            existentialModel.sections,
-            concreteModel.sections,
-            "render(snapshot:) must dynamic-dispatch through the existential, not the empty default"
-        )
+        `#expect`(!concreteModel.sections.isEmpty, "concrete render should produce a section")
+        `#expect`(concreteModel.sections.flatMap(\.rows).count == 3)
+        `#expect`(
+            existentialModel.sections == concreteModel.sections,
+            "render(snapshot:) must dynamic-dispatch through the existential, not the empty default"
+        )
     }
-    func testWorkspaceListingProvidersRenderRowsThroughExistential() {
+    `@Test` func workspaceListingProvidersRenderRowsThroughExistential() {
         let snapshot = Self.snapshot(workspaceCount: 4)
         ...
         for provider in SidebarExamples.providers where listingProviderIDs.contains(provider.descriptor.id) {
             let model = provider.render(snapshot: snapshot)
-            XCTAssertFalse(
-                model.sections.flatMap(\.rows).isEmpty,
-                "Provider \(provider.descriptor.id) rendered no rows through the existential"
-            )
+            `#expect`(
+                !model.sections.flatMap(\.rows).isEmpty,
+                "Provider \(provider.descriptor.id) rendered no rows through the existential"
+            )
         }
     }

As per coding guidelines: "do not write new tests with import XCTest unless they are UI tests."

🧰 Tools
🪛 SwiftLint (0.63.3)

[Warning] 13-13: Classes should have an explicit deinit method

(required_deinit)

🤖 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
`@Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/SidebarProviderExistentialDispatchTests.swift`
around lines 1 - 53, Convert this XCTest-based file to Swift Testing: replace
"import XCTest" with "import Testing", change the XCTestCase class
SidebarProviderExistentialDispatchTests into a Swift Testing suite (e.g.
annotate a struct or enum with `@Suite` and keep the same name), mark the two test
methods testSuperCompactRendersIdenticallyThroughExistential and
testWorkspaceListingProvidersRenderRowsThroughExistential with `@Test`, and
replace XCTAssert* calls with the corresponding `#expect`(...) matchers (e.g.
`#expect`(concreteModel.sections.isEmpty).toBeFalse(),
`#expect`(concreteModel.sections.flatMap(\.rows).count).toEqual(3), and
`#expect`(existentialModel.sections).toEqual(concreteModel.sections); similarly
use `#expect`(...).not.toBeEmpty() or equivalent for the provider loop). Keep
references to SuperCompactSidebar, SidebarExamples.providers,
provider.descriptor.id, and CmuxSidebarProvider render(snapshot:) usage
unchanged except for assertion syntax and suite/test annotations.

46-52: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Guard against a vacuous pass.

If none of the listingProviderIDs match an actual provider.descriptor.id (e.g., an ID is renamed/typo'd), the where filter yields nothing, the loop body never runs, and the test passes without asserting anything. Assert that the expected number of providers was exercised.

🛡️ Proposed fix
+        var matched = 0
         for provider in SidebarExamples.providers where listingProviderIDs.contains(provider.descriptor.id) {
+            matched += 1
             let model = provider.render(snapshot: snapshot)
             XCTAssertFalse(
                 model.sections.flatMap(\.rows).isEmpty,
                 "Provider \(provider.descriptor.id) rendered no rows through the existential"
             )
         }
+        XCTAssertEqual(matched, listingProviderIDs.count, "expected every listing provider ID to be exercised")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        var matched = 0
        for provider in SidebarExamples.providers where listingProviderIDs.contains(provider.descriptor.id) {
            matched += 1
            let model = provider.render(snapshot: snapshot)
            XCTAssertFalse(
                model.sections.flatMap(\.rows).isEmpty,
                "Provider \(provider.descriptor.id) rendered no rows through the existential"
            )
        }
        XCTAssertEqual(matched, listingProviderIDs.count, "expected every listing provider ID to be exercised")
🤖 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
`@Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/SidebarProviderExistentialDispatchTests.swift`
around lines 46 - 52, The test currently loops "for provider in
SidebarExamples.providers where
listingProviderIDs.contains(provider.descriptor.id)" and can vacuously pass if
no providers match; update the test to assert that at least one provider was
exercised by either (a) computing the matchedProviders via
SidebarExamples.providers.filter { listingProviderIDs.contains($0.descriptor.id)
} and XCTAssertGreaterThan(matchedProviders.count, 0) before iterating, or (b)
keep the loop but increment a counter for each iteration and
XCTAssertGreaterThan(counter, 0) after the loop; use the same
provider.descriptor.id and model.sections.flatMap(\\.rows) checks inside the
iteration as-is.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderCommandResult.swift (1)

3-10: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Complete the DocC for this public package API.

CmuxSidebarProviderCommandResult is a new public package type, but init(ok:) still lacks the required - Parameter ok: callout and the docs do not spell out what ok == false means for callers.

📝 Proposed doc update
 /// Result returned after CMUX handles a provider mutation.
+///
+/// Use this value to distinguish between commands the host completed and
+/// commands it rejected or could not apply.
 public struct CmuxSidebarProviderCommandResult: Codable, Equatable, Sendable {
     /// Whether CMUX accepted and completed the command.
     public var ok: Bool

     /// Creates a command result.
+    ///
+    /// - Parameter ok: `true` when the host accepted and completed the command;
+    ///   otherwise `false`.
     public init(ok: Bool) {
         self.ok = ok
     }
 }

As per coding guidelines, "Document every public symbol in new Swift packages under Packages/ with Swift-DocC triple-slash comments at time of writing" and "use - Parameter name: callouts".

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderCommandResult.swift`
around lines 3 - 10, The public type CmuxSidebarProviderCommandResult and its
initializer init(ok:) lack complete DocC comments: update the triple-slash docs
for the struct, the public var ok and the public init(ok:) to include a summary
sentence for the type, a clear description of the ok property, and a "-
Parameter ok:" callout that explains what true and false mean for callers (e.g.,
ok == true means CMUX accepted and completed the command; ok == false means the
command was rejected or failed and callers should treat the result as
unsuccessful). Ensure comments are placed immediately above
CmuxSidebarProviderCommandResult, above the ok property, and above init(ok:)
using Swift-DocC triple-slash style.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderWorkspaceMove.swift (1)

11-24: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

targetIndex currently allows impossible negative positions.

Because this is a public Codable transport type, Int allows negative indices to be constructed and decoded even if you later add an initializer precondition. Please encode the non-negative invariant in the type itself, or add custom Decodable validation that rejects negatives at the boundary.

🧭 Safer direction
-    public var targetIndex: Int
+    public var targetIndex: UInt

If you need to keep Int for downstream APIs, add a custom init(from:) and fail decoding for values < 0 instead of relying on the memberwise initializer.

As per coding guidelines, "Prefer compile-time invariants to runtime traps; encode 'programmer error' cases in the type system".

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderWorkspaceMove.swift`
around lines 11 - 24, The public transport type allows negative targetIndex
values which can be decoded or constructed; fix by enforcing a non-negative
invariant at decode-time or via a refined type: add a custom Decodable
init(from:) on CmuxSidebarProviderWorkspaceMove that reads targetIndex and
throws a decoding error if value < 0 (or replace targetIndex with a
NonNegativeInt wrapper type that validates on init/Decodable), and update the
public init/workflow to accept/produce only the validated value so negatives
cannot flow through the API.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift (1)

3-38: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Complete the required DocC for this public package API.

The type, its public properties, and init(...) currently only have short summary comments. For new Packages/ public APIs, this repo requires full Swift-DocC coverage, including the summary/discussion shape and - Parameter callouts on the initializer.

As per coding guidelines, "Document every public symbol in new Swift packages under Packages/ with Swift-DocC triple-slash comments at time of writing" and "use one-sentence summary on first line, blank /// line, then discussion" plus - Parameter/- Returns:/- Throws: callouts where applicable.

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift`
around lines 3 - 38, Add full Swift-DocC comments for the public type
CmuxSidebarProviderRow, its public stored properties (id, title, workspaceId,
accessory, subtitle, trailingText, leadingIcon) and the public initializer; for
each symbol use triple-slash comments with a one-sentence summary on the first
line, a blank line, then a short discussion paragraph, and for the init include
a detailed "- Parameter" entry for every parameter (and "- Returns:" only if
applicable) following DocC style; update the existing short summaries above the
struct and above init(...) to the required summary/discussion shape and add
per-parameter callouts to the init signature so the package meets the Packages/
Swift-DocC documentation policy.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift (1)

3-29: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Fill in the package-required DocC for the new public symbols.

CmuxSidebarProviderRowAccessory, its public members, and the initializer are only documented with brief summaries right now. This package rule requires full DocC on new public APIs, including discussion text and initializer parameter callouts.

As per coding guidelines, "Document every public symbol in new Swift packages under Packages/ with Swift-DocC triple-slash comments at time of writing" and "document enums/inits/properties/methods with meaning and invariants; include - Parameter name: callouts."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift`
around lines 3 - 29, Add full Swift-DocC triple-slash documentation to the
public struct CmuxSidebarProviderRowAccessory, its public stored properties
(kind, systemImageName, defaultTab), the public initializer
(init(kind:systemImageName:defaultTab:)) and the public static inspector
constant: expand the brief summaries into a discussion paragraph describing
purpose and usage, document invariants/behavior, and add - Parameter callouts
for each initializer parameter explaining expected values and effects (e.g.,
what each CmuxSidebarProviderRowAccessoryKind value does, valid systemImageName
expectations, and defaultTab behavior); ensure the inspector constant has its
own summary/discussion noting it is a standard preconfigured accessory.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessoryKind.swift (1)

3-7: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add full DocC for this exported enum.

This is a new public package enum, but the docs stop at one-line summaries. The package guideline still requires full Swift-DocC structure for the type and public members.

As per coding guidelines, "Document every public symbol in new Swift packages under Packages/ with Swift-DocC triple-slash comments at time of writing" and "document enums/inits/properties/methods with meaning and invariants."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessoryKind.swift`
around lines 3 - 7, Add full Swift-DocC triple-slash documentation for the
exported enum CmuxSidebarProviderRowAccessoryKind and its public member(s):
document the enum's purpose, when and where clients should use it, any
invariants or expectations (e.g., that it is Codable/Equatable/Sendable and
backed by a String raw value), and describe serialization/compatibility
guarantees; for the case workspaceInspector add a clear sentence about what UI
affordance it represents and any behavior/constraints (for example whether it
always opens the workspace inspector, platform limits, or visibility rules).
Place the comments immediately above the enum declaration and above the case
using triple-slash (///) DocC style so the symbol and member are fully
documented for clients and documentation generation.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderSection.swift (1)

3-22: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Bring this public section model up to the package DocC standard.

The type, properties, and initializer only have terse summaries. New public SwiftPM APIs in Packages/ need full DocC coverage, including discussion text and initializer parameter documentation.

As per coding guidelines, "Document every public symbol in new Swift packages under Packages/ with Swift-DocC triple-slash comments at time of writing" and "use one-sentence summary on first line, blank /// line, then discussion" with parameter callouts where applicable.

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderSection.swift`
around lines 3 - 22, Add full Swift-DocC triple-slash documentation to the
public type CmuxSidebarProviderSection, each public property (id, treeSection,
rows), and the public initializer init(id:treeSection:rows:). For each symbol
follow the package guideline: start with a one-sentence summary on the first
line, add a blank /// line, then a short discussion paragraph describing
purpose/behavior and any invariants; for the initializer include a /// -
Parameters: block documenting id, treeSection, and rows. Ensure comments are
triple-slash (///) and placed immediately above the struct, each property, and
the initializer so DocC picks them up.
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderGitBranch.swift (1)

3-15: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Document this public snapshot type to the package standard.

The current comments are only short summaries. New public SwiftPM symbols in Packages/ need full DocC, and init(branch:isDirty:) should include parameter callouts.

As per coding guidelines, "Document every public symbol in new Swift packages under Packages/ with Swift-DocC triple-slash comments at time of writing" and "use /// doc comments for public symbols with one-sentence summary on first line, blank /// line, then discussion."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderGitBranch.swift`
around lines 3 - 15, Add full Swift-DocC triple-slash documentation for the
public symbol CmuxSidebarProviderGitBranch: start with a one-sentence summary on
the first /// line, add a blank /// line, then a short discussion describing the
purpose and usage of this snapshot type; document the stored properties branch
and isDirty with brief descriptions; and add a documented initializer
init(branch:isDirty:) that includes /// - Parameters: with callouts for branch
and isDirty. Ensure every public symbol (struct, properties, and init) uses the
/// pattern and follows the package doc style.
Packages/CmuxSocketControl/Sources/CmuxSocketControl/SocketControlPasswordStore.swift (1)

25-28: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Use the defined constants instead of hardcoded strings.

Lines 27-28 define legacyKeychainService and legacyKeychainAccount constants, but these are not used. Lines 258-259 and 279-280 hardcode the same string literals in the keychain query dictionaries. This creates a maintenance risk—if the service or account name changes, it must be updated in multiple places.

♻️ Proposed fix
     private static func loadLegacyPasswordFromKeychain() -> String? {
 `#if` canImport(Security)
         let query: [CFString: Any] = [
             kSecClass: kSecClassGenericPassword,
-            kSecAttrService: "com.cmuxterm.app.socket-control",
-            kSecAttrAccount: "local-socket-password",
+            kSecAttrService: legacyKeychainService,
+            kSecAttrAccount: legacyKeychainAccount,
             kSecReturnData: true,
             kSecMatchLimit: kSecMatchLimitOne,
         ]

Apply the same change to deleteLegacyPasswordFromKeychain() at lines 279-280.

🤖 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
`@Packages/CmuxSocketControl/Sources/CmuxSocketControl/SocketControlPasswordStore.swift`
around lines 25 - 28, Replace the hardcoded legacy keychain service/account
strings with the defined constants: use legacyKeychainService and
legacyKeychainAccount wherever the CFDictionary keychain queries are built (the
dictionaries currently containing "com.cmuxterm.app.socket-control" and
"local-socket-password"), including in the migration routine and
deleteLegacyPasswordFromKeychain(); update the query dictionaries to reference
these constants instead of string literals so the service/account names are
maintained in one place.
Sources/ContentView.swift (1)

10356-10361: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Synchronous config load during @StateObject initialization.

GhosttyConfig.load() is called synchronously when the view initializes. If this config load is I/O-bound or slow, it could delay view initialization. The async path via SidebarFontSizeProvider.loadFromGhosttyConfig handles subsequent refreshes, but the initial value blocks here.

If GhosttyConfig.load() is cached or fast in practice, this is acceptable. Otherwise, consider initializing with a default and letting the async refresh populate the actual value.

🧰 Tools
🪛 SwiftLint (0.63.3)

[Warning] 10356-10356: SwiftUI state properties should be private

(private_swiftui_state)


[Warning] 10357-10357: SwiftUI state properties should be private

(private_swiftui_state)

🤖 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/ContentView.swift` around lines 10356 - 10361, The view currently
calls GhosttyConfig.load() synchronously inside the SidebarTabItemSettingsStore
initializer which may block view init; change to construct
SidebarTabItemSettingsStore with a fast default (e.g. a default font size) and
remove the synchronous GhosttyConfig.load() call, then kick off an async load
(using SidebarFontSizeProvider.loadFromGhosttyConfig or a .task/async init
helper) to fetch the real value and update the SidebarTabItemSettingsStore
instance when ready; target the SidebarTabItemSettingsStore creation site and
the async loader SidebarFontSizeProvider.loadFromGhosttyConfig to implement the
deferred load and update logic.

…ganization

# Conflicts:
#	Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/HostCompatibility/CmuxExtensionSidebarProvider.swift
#	Sources/ContentView.swift
#	cmux.xcodeproj/project.pbxproj
coderabbitai[bot]
coderabbitai Bot previously requested changes Jun 2, 2026

@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: 10

Caution

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

⚠️ Outside diff range comments (3)
scripts/reload.sh (1)

787-791: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Replace wall-clock sleeps with state-based synchronization.

reload.sh still waits for build/quit/launch readiness via fixed sleep calls and socket polling in Lines 787, 965-976, and 1064-1102. That makes tagged reloads flaky on slower machines and is explicitly disallowed for runtime/build scripts here. Please switch these paths to waiting on the actual condition with a bounded timeout instead of sleeping and hoping the process state caught up.

As per coding guidelines "fail when the diff violates .github/review-bot-rules/runtime-no-hacky-sleeps.md: fixed sleeps, delayed dispatch, timers, polling, or wall-clock waits used to paper over lifecycle, focus, rendering, socket, process, filesystem, network, teardown, startup, retry, or shared-state races".

Also applies to: 965-976, 1064-1102

🤖 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 `@scripts/reload.sh` around lines 787 - 791, The current reload.sh uses fixed
sleeps and ad-hoc socket polling (e.g., the "sleep 0.2" before checking
$RELOAD_LOG and the later socket/poll blocks) which causes flaky timing; replace
those sleeps/polls with explicit state-based waits with a bounded timeout: wait
for the real condition (xcodebuild process exit/return code or presence of the
completed build marker in $RELOAD_LOG, the target process PID becoming
visible/terminated via ps/pgrep, or the launch socket/file descriptor becoming
ready) using a loop that checks the concrete condition and breaks on success or
after a configured timeout, and fail deterministically on timeout. Update the
blocks that reference $RELOAD_LOG, the socket polling logic, and any retry loops
so they use these condition checks and a clear timeout variable rather than
sleep or fixed delays.
Sources/ExtensionSidebarWorkspaceRowView.swift (1)

124-261: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider renaming internal types for consistency.

The internal types (CmuxExtensionWorkspaceInspectorDraft, CmuxExtensionWorkspaceInspectorView, CmuxExtensionWorkspaceInspectorWindowContentView, CmuxExtensionWorkspaceInspectorBrowserView, CmuxExtensionSidebarInspectorWindowController) retain the CmuxExtension prefix while they now work exclusively with CmuxSidebarProvider* types. For clarity, consider renaming them to use CmuxSidebarProvider or Cmux prefixes instead.

🤖 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/ExtensionSidebarWorkspaceRowView.swift` around lines 124 - 261, The
internal types use the outdated CmuxExtension prefix while they operate on
CmuxSidebarProvider* models; rename CmuxExtensionWorkspaceInspectorDraft,
CmuxExtensionWorkspaceInspectorView,
CmuxExtensionWorkspaceInspectorWindowContentView,
CmuxExtensionWorkspaceInspectorBrowserView, and
CmuxExtensionSidebarInspectorWindowController to use a consistent
CmuxSidebarProvider (or shorter Cmux) prefix (e.g.,
CmuxSidebarProviderWorkspaceInspectorDraft,
CmuxSidebarProviderWorkspaceInspectorView,
CmuxSidebarProviderWorkspaceInspectorWindowContentView,
CmuxSidebarProviderWorkspaceInspectorBrowserView,
CmuxSidebarProviderSidebarInspectorWindowController), and update all
references/usages including the initial(...) factory, the State initialValue,
initializer signatures, binding names ($draft), and any callers to these types
so symbol names remain consistent across the module.
Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/AttentionQueueSidebarTests.swift (1)

3-69: 🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoff

Convert this touched XCTest suite to Swift Testing.

This file is being modified, and the repo convention is to migrate touched XCTest tests in place: XCTestCase → @Suite struct, func testFoo() → @Test func foo(), XCTAssertEqual(a, b) → #expect(a == b), XCTAssertNil(x) → #expect(x == nil), and XCTUnwrap(x) → try #require(x).

As per coding guidelines: "When touching existing XCTest tests, convert in place ... XCTestCase → @Suite struct/final class; func testFoo() → @Test func foo(); XCTAssertEqual(a, b) → #expect(a == b) ... XCTUnwrap(x) → try #require(x)".

🤖 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
`@Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/AttentionQueueSidebarTests.swift`
around lines 3 - 69, Convert the XCTest-based suite to Swift Testing: change
final class AttentionQueueSidebarTests: XCTestCase to `@Suite` struct
AttentionQueueSidebarTests, convert each test method like func
testLocalDisconnectedWorkspaceRemainsQuiet() throws to `@Test` func
localDisconnectedWorkspaceRemainsQuiet() throws (drop the "test" prefix),
replace XCTAssertNil(...) with `#expect`(... == nil), XCTAssertEqual(a, b) with
`#expect`(a == b), and replace try XCTUnwrap(x) with try `#require`(x); keep the
helper workspace(...) function and all usages of CmuxSidebarProviderSnapshot and
AttentionQueueSidebar().render unchanged. Ensure imports and any test attributes
required by Swift Testing are present elsewhere in the file/project.
♻️ Duplicate comments (1)
Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift (1)

23-32: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Inconsistent optional-parameter defaults.

titleText and subtitleText default to nil, but the equally optional subtitle and projectRootPath require explicit arguments. Default them to nil for consistency and ergonomic call sites.

♻️ Proposed fix
     public init(
         id: String,
         title: String,
         titleText: CmuxSidebarProviderLocalizedText? = nil,
-        subtitle: String?,
+        subtitle: String? = nil,
         subtitleText: CmuxSidebarProviderLocalizedText? = nil,
         systemImageName: String,
-        projectRootPath: String?,
+        projectRootPath: String? = nil,
         workspaceIds: [UUID]
     ) {
🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift`
around lines 23 - 32, The initializer for CmuxSidebarProviderTreeSection has
inconsistent optional-parameter defaults; make the optional parameters subtitle
and projectRootPath default to nil like titleText and subtitleText by updating
the CmuxSidebarProviderTreeSection.init signature to use subtitle: String? = nil
and projectRootPath: String? = nil, and then update any call sites that relied
on the previous required arguments to omit those parameters where appropriate.
🤖 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 `@cmux.xcodeproj/project.pbxproj`:
- Around line 1945-1947: cmuxTests is missing the new CmuxSidebarProviderKit
package wiring so test builds will fail when SidebarProviderMenuRegressionTests
imports it; add an XCLocalSwiftPackageReference for the provider and an
XCSwiftPackageProductDependency referencing "CmuxSidebarProviderKit" for the
cmuxTests target, create the corresponding PBXBuildFile entry and include it in
the cmuxTests Frameworks build phase (mirror the entries you added for cmux and
cmux-unit), and ensure the package product dependency is also added to the
cmux-unit/ cmux targets as per the existing pattern used for
CmuxExtensionHostSupport/CmuxExtensionKit.

In
`@Examples/TabsVisibleSidebar/TabsVisibleSidebarExtension/TabsVisibleSidebarExtension.swift`:
- Around line 72-81: The apply(_ operation: ) helper currently treats all errors
the same; add an explicit handler for the cancellation case so stale errorText
is cleared instead of showing the generic denial message. Update the apply
function to catch CmuxSidebarActionError.cancelled (or catch CancellationError
if your code uses standard cancellation) before the generic catch, and set
errorText = nil in that branch; keep the existing catch
CmuxSidebarActionError.rejected(let message) to set the rejection message and
the final generic catch to set the localized "tabsVisible.actionDenied" text.

In `@Packages/CMUXExtensionHostSupport/Package.swift`:
- Around line 18-25: Add a test target to the package and scaffold unit tests
for the host view and browser presenter: update the Package.swift to include a
.testTarget referencing "CMUXExtensionHostSupport" as a dependency, and create a
Tests directory with test files that exercise CMUXSidebarExtensionHostView and
CMUXSidebarExtensionBrowserPresenter behaviors (initialization, state
transitions, and key public methods); ensure tests import CmuxExtensionKit where
needed and cover edge cases for presenter logic and view lifecycle.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift`:
- Line 47: The decoder currently requires readScopes by calling readScopes = try
container.decode([CmuxExtensionScope].self, forKey: .readScopes) in init(from:),
but the public initializer defaults readScopes to [] which makes the key
effectively optional; update init(from:) to use decodeIfPresent for readScopes
and fall back to [] (e.g., readScopes = try
container.decodeIfPresent([CmuxExtensionScope].self, forKey: .readScopes) ?? [])
to match actionScopes and the public init behavior, ensuring round-trip Codable
compatibility for CmuxExtensionManifest.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`:
- Around line 1-5: The file name does not match its public API type: rename the
source file currently named CMUXExtensionActionResult.swift to
CmuxSidebarActionResult.swift and update any imports/targets referring to the
old filename; ensure the primary public type CmuxSidebarActionResult (and
related enums like the rejection-reason and error enums defined in the same
file) remain in this single file so each public API type lives in its own file
named after the type.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionPoint.swift`:
- Line 20: The Info.plist key used by CmuxSidebarExtensionPoint no longer
matches the constant identifierInfoPlistKey
("CmuxSidebarExtensionPointIdentifier"), causing identifier resolution in
CmuxSidebarExtensionPoint.identifier() to miss the override and fall back to
baseIdentifier; fix this by updating Resources/Info.plist to rename the existing
CMUXSidebarExtensionPointIdentifier entry to CmuxSidebarExtensionPointIdentifier
(or revert the constant if you intend to keep the old key) so the
identifierInfoPlistKey lookup in CmuxSidebarExtensionPoint.identifier() reads
the intended override.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift`:
- Around line 3-5: The documentation comment is placed between the attribute and
the type declaration; move the doc comment so it appears immediately before the
`@_spi`(CmuxHostTransport) attribute (i.e., place the doc comment above the
attribute) so tooling sees the doc comment associated with the
CmuxSidebarHostClient struct; update the placement around the
`@_spi`(CmuxHostTransport) and public struct CmuxSidebarHostClient: Sendable
declaration accordingly.

In
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift`:
- Around line 74-82: Add a short clarifying comment near the lossy decoding util
and a note in CMUXSidebarSnapshot explaining the fail-closed, forward-compat
behavior: reference
KeyedDecodingContainer.decodeLossySetIfPresent(Value.Type,forKey:) to state that
unknown scope raw values are dropped (treated as not granted), and mention that
host-side enforcement (in CMUXInstalledExtensionSidebarHostView) will reject
actions unless allowedActionScopes is a superset of action.requiredScopes; also
document the workspaceMetadata-missing behavior in
CMUXSidebarSnapshot.filtered(for:actionScopes:) that causes workspace.title to
be set to an empty string.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxMutableSidebarProvider.swift`:
- Around line 5-9: Update the public protocol requirement declaration for
handle(_:snapshot:) to include DocC callouts: add a one-line summary plus "-
Parameter mutation: CmuxSidebarProviderMutation — description of the mutation
input", "- Parameter snapshot: CmuxSidebarProviderSnapshot — description of the
snapshot input", "- Returns: CmuxSidebarProviderCommandResult — describe what
the result represents", and "- Throws: — describe under what conditions the
method throws"; target the protocol method named handle(_:snapshot:) in
CmuxMutableSidebarProvider and reference the types CmuxSidebarProviderMutation,
CmuxSidebarProviderSnapshot, and CmuxSidebarProviderCommandResult so the
documentation appears for this public symbol.

In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProvider`+Rendering.swift:
- Around line 13-19: The extension-provided render(snapshot:context:) is
currently dropping the context by forwarding to render(snapshot:), so ensure
contextual rendering isn’t lost: change the implementation of
render(snapshot:context:) on CmuxSidebarProvider to detect and call the
contextual implementation when available (i.e., if self conforms to
CmuxContextualSidebarProvider, invoke that provider’s render(snapshot:context:)
using the provided context), otherwise fall back to calling render(snapshot:).
Update the extension containing render(snapshot:context:) (and keep names
render(snapshot:) and render(snapshot:context:) unchanged) so context.now and
other contextual data are preserved for contextual providers.

---

Outside diff comments:
In
`@Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/AttentionQueueSidebarTests.swift`:
- Around line 3-69: Convert the XCTest-based suite to Swift Testing: change
final class AttentionQueueSidebarTests: XCTestCase to `@Suite` struct
AttentionQueueSidebarTests, convert each test method like func
testLocalDisconnectedWorkspaceRemainsQuiet() throws to `@Test` func
localDisconnectedWorkspaceRemainsQuiet() throws (drop the "test" prefix),
replace XCTAssertNil(...) with `#expect`(... == nil), XCTAssertEqual(a, b) with
`#expect`(a == b), and replace try XCTUnwrap(x) with try `#require`(x); keep the
helper workspace(...) function and all usages of CmuxSidebarProviderSnapshot and
AttentionQueueSidebar().render unchanged. Ensure imports and any test attributes
required by Swift Testing are present elsewhere in the file/project.

In `@scripts/reload.sh`:
- Around line 787-791: The current reload.sh uses fixed sleeps and ad-hoc socket
polling (e.g., the "sleep 0.2" before checking $RELOAD_LOG and the later
socket/poll blocks) which causes flaky timing; replace those sleeps/polls with
explicit state-based waits with a bounded timeout: wait for the real condition
(xcodebuild process exit/return code or presence of the completed build marker
in $RELOAD_LOG, the target process PID becoming visible/terminated via ps/pgrep,
or the launch socket/file descriptor becoming ready) using a loop that checks
the concrete condition and breaks on success or after a configured timeout, and
fail deterministically on timeout. Update the blocks that reference $RELOAD_LOG,
the socket polling logic, and any retry loops so they use these condition checks
and a clear timeout variable rather than sleep or fixed delays.

In `@Sources/ExtensionSidebarWorkspaceRowView.swift`:
- Around line 124-261: The internal types use the outdated CmuxExtension prefix
while they operate on CmuxSidebarProvider* models; rename
CmuxExtensionWorkspaceInspectorDraft, CmuxExtensionWorkspaceInspectorView,
CmuxExtensionWorkspaceInspectorWindowContentView,
CmuxExtensionWorkspaceInspectorBrowserView, and
CmuxExtensionSidebarInspectorWindowController to use a consistent
CmuxSidebarProvider (or shorter Cmux) prefix (e.g.,
CmuxSidebarProviderWorkspaceInspectorDraft,
CmuxSidebarProviderWorkspaceInspectorView,
CmuxSidebarProviderWorkspaceInspectorWindowContentView,
CmuxSidebarProviderWorkspaceInspectorBrowserView,
CmuxSidebarProviderSidebarInspectorWindowController), and update all
references/usages including the initial(...) factory, the State initialValue,
initializer signatures, binding names ($draft), and any callers to these types
so symbol names remain consistent across the module.

---

Duplicate comments:
In
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift`:
- Around line 23-32: The initializer for CmuxSidebarProviderTreeSection has
inconsistent optional-parameter defaults; make the optional parameters subtitle
and projectRootPath default to nil like titleText and subtitleText by updating
the CmuxSidebarProviderTreeSection.init signature to use subtitle: String? = nil
and projectRootPath: String? = nil, and then update any call sites that relied
on the previous required arguments to omit those parameters where appropriate.
🪄 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: fd91e3ae-4df0-4398-a5f7-d620421d816a

📥 Commits

Reviewing files that changed from the base of the PR and between 3c778bf and fad4790.

📒 Files selected for processing (108)
  • Examples/CmuxExtensionSidebarExamples/Package.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/AttentionQueueSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/BrowserStackSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/DevServerSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/LastPromptSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/ProjectWorktreeSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SidebarExamples.swift
  • Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SuperCompactSidebar.swift
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/AttentionQueueSidebarTests.swift
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/BrowserStackSidebarTests.swift
  • Examples/CmuxExtensionSidebarExamples/Tests/CmuxExtensionSidebarExamplesTests/SidebarProviderExistentialDispatchTests.swift
  • Examples/SampleSidebarExtensionApp/README.md
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Connection/SidebarConnectionModel.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Extension/SampleSidebarExtension.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Localizable.xcstrings
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/Model/SidebarInsightModel.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtension/UI/SampleSidebarView.swift
  • Examples/SampleSidebarExtensionApp/SampleSidebarExtensionApp/Localizable.xcstrings
  • Examples/StubAgentSidebarExtension/Package.swift
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/Resources/Localizable.xcstrings
  • Examples/StubAgentSidebarExtension/Sources/StubAgentSidebarExtension/StubAgentSidebarExtension.swift
  • Examples/TabsVisibleSidebar/TabsVisibleSidebar.xcodeproj/project.pbxproj
  • Examples/TabsVisibleSidebar/TabsVisibleSidebar/Localizable.xcstrings
  • Examples/TabsVisibleSidebar/TabsVisibleSidebarExtension/Localizable.xcstrings
  • Examples/TabsVisibleSidebar/TabsVisibleSidebarExtension/TabsVisibleSidebarExtension.swift
  • Examples/TabsVisibleSidebar/TabsVisibleSidebarExtension/TabsVisibleSidebarView.swift
  • Packages/CMUXExtensionClient/README.md
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXInstalledSidebarExtension.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXSidebarExtensionDiscovery.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXExtensionClientError.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRecord.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRegistry.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Session/CMUXSidebarExtensionSession.swift
  • Packages/CMUXExtensionClient/Tests/CMUXExtensionClientTests/CMUXExtensionClientTests.swift
  • Packages/CMUXExtensionHostSupport/Package.swift
  • Packages/CMUXExtensionHostSupport/README.md
  • Packages/CMUXExtensionHostSupport/Sources/CMUXExtensionHostSupport/Browser/CMUXSidebarExtensionBrowserPresenter.swift
  • Packages/CMUXExtensionHostSupport/Sources/CMUXExtensionHostSupport/Hosting/CMUXSidebarExtensionHostView.swift
  • Packages/CmuxExtensionKit/README.md
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/CmuxExtensionCompatibility.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Common/CMUXExtensionAPIVersion.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxHost.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxUIExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/HostCompatibility/CmuxExtensionLocalizedText.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/HostCompatibility/CmuxExtensionSidebarProvider.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/HostCompatibility/CmuxExtensionSidebarProviderDescriptor.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionKind.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionScope.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarAction.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionPoint.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSurface.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarWorkspace.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarXPC.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarActionCancellation.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarContext.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionRuntime.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarExtensionScene.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarHost.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Validation/CMUXExtensionValidationError.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Validation/CMUXExtensionValidator.swift
  • Packages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swift
  • Packages/CmuxSidebarProviderKit/Package.swift
  • Packages/CmuxSidebarProviderKit/README.md
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderDescriptor.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/CmuxSidebarProviderLocalizedText.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIcon.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Icons/CmuxSidebarProviderIconShape.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxMutableSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderCommandResult.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderMutation.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderPresentationRequest.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxSidebarProviderWorkspaceMove.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Presentation/CmuxSidebarProviderPresentation.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Presentation/CmuxSidebarProviderWorkspacePopoverTab.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxContextualSidebarProvider.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProvider+Rendering.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderContext.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rendering/CmuxSidebarProviderRenderModel.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRow.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessory.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Rows/CmuxSidebarProviderRowAccessoryKind.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderSection.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Sections/CmuxSidebarProviderTreeSection.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderGitBranch.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderSnapshot.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Snapshot/CmuxSidebarProviderWorkspace.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Text/CmuxSidebarProviderRelativeDateStyle.swift
  • Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Text/CmuxSidebarProviderText.swift
  • Packages/CmuxSocketControl/Sources/CmuxSocketControl/SocketControlPasswordStore.swift
  • Resources/Localizable.xcstrings
  • Resources/com.manaflow.cmux.sidebar.appextensionpoint
  • Sources/CMUXInstalledExtensionSidebarHostView.swift
  • Sources/CMUXSidebarExtensionBrowserPanel.swift
  • Sources/ContentView.swift
  • Sources/ExtensionSidebarWorkspaceRowView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmux.xcworkspace/contents.xcworkspacedata
  • cmuxTests/SidebarProviderMenuRegressionTests.swift
  • scripts/reload.sh
  • scripts/write-sidebar-extension-point.sh
💤 Files with no reviewable changes (18)
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRecord.swift
  • Packages/CMUXExtensionClient/Tests/CMUXExtensionClientTests/CMUXExtensionClientTests.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXInstalledSidebarExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/HostCompatibility/CmuxExtensionSidebarProviderDescriptor.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionKind.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/HostCompatibility/CmuxExtensionLocalizedText.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxHost.swift
  • Resources/com.manaflow.cmux.sidebar.appextensionpoint
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Discovery/CMUXSidebarExtensionDiscovery.swift
  • Packages/CMUXExtensionClient/README.md
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxUIExtension.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/HostCompatibility/CmuxExtensionSidebarProvider.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Session/CMUXSidebarExtensionSession.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXExtensionClientError.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/CmuxExtensionCompatibility.swift
  • Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Extension/CmuxExtension.swift
  • Packages/CMUXExtensionClient/Sources/CMUXExtensionClient/Registry/CMUXSidebarExtensionRegistry.swift
  • Packages/CmuxSocketControl/Sources/CmuxSocketControl/SocketControlPasswordStore.swift

Comment thread cmux.xcodeproj/project.pbxproj
Comment on lines +72 to 81
private func apply(_ operation: () async throws -> Void) async {
do {
try await operation()
errorText = nil
} else {
errorText = result.message ?? String(localized: "tabsVisible.actionDenied", defaultValue: "cmux did not allow that action")
} catch CmuxSidebarActionError.rejected(let message) {
errorText = message
} catch {
errorText = String(localized: "tabsVisible.actionDenied", defaultValue: "cmux did not allow that action")
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle .cancelled explicitly to avoid showing stale error text.

The apply helper currently treats cancellation the same as other errors, setting errorText to "cmux did not allow that action". Cancellation is not an error condition and should clear any existing error text instead. The StubAgentSidebarExtension example handles this correctly by clearing errorText on .cancelled.

🔧 Proposed fix
 private func apply(_ operation: () async throws -> Void) async {
     do {
         try await operation()
         errorText = nil
     } catch CmuxSidebarActionError.rejected(let message) {
         errorText = message
+    } catch CmuxSidebarActionError.cancelled {
+        errorText = nil
     } catch {
         errorText = String(localized: "tabsVisible.actionDenied", defaultValue: "cmux did not allow that action")
     }
 }
🤖 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
`@Examples/TabsVisibleSidebar/TabsVisibleSidebarExtension/TabsVisibleSidebarExtension.swift`
around lines 72 - 81, The apply(_ operation: ) helper currently treats all
errors the same; add an explicit handler for the cancellation case so stale
errorText is cleared instead of showing the generic denial message. Update the
apply function to catch CmuxSidebarActionError.cancelled (or catch
CancellationError if your code uses standard cancellation) before the generic
catch, and set errorText = nil in that branch; keep the existing catch
CmuxSidebarActionError.rejected(let message) to set the rejection message and
the final generic catch to set the localized "tabsVisible.actionDenied" text.

Comment on lines 18 to 25
targets: [
.target(
name: "CMUXExtensionClient",
name: "CMUXExtensionHostSupport",
dependencies: [
.product(name: "CmuxExtensionKit", package: "CmuxExtensionKit"),
]
),
.testTarget(
name: "CMUXExtensionClientTests",
dependencies: ["CMUXExtensionClient"]
),
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check that the source directory exists and has Swift files
fd -t f '\.swift$' 'Packages/CMUXExtensionHostSupport/Sources/CMUXExtensionHostSupport' --exec echo "Found: {}"

# Check if any test files exist under CMUXExtensionHostSupport
fd -t f '\.swift$' 'Packages/CMUXExtensionHostSupport/Tests' --exec echo "Test file: {}" 2>/dev/null || echo "No test directory found"

Repository: manaflow-ai/cmux

Length of output: 326


Add/replace test coverage for CMUXExtensionHostSupport

  • Packages/CMUXExtensionHostSupport/Package.swift defines only a single .target (CMUXExtensionHostSupport) and no .testTarget.
  • The sources exist under Packages/CMUXExtensionHostSupport/Sources/CMUXExtensionHostSupport/ (e.g., Hosting/CMUXSidebarExtensionHostView.swift, Browser/CMUXSidebarExtensionBrowserPresenter.swift), but there is no Packages/CMUXExtensionHostSupport/Tests directory.
  • Consider adding replacement unit tests for the host view and browser presenter logic.
🤖 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 `@Packages/CMUXExtensionHostSupport/Package.swift` around lines 18 - 25, Add a
test target to the package and scaffold unit tests for the host view and browser
presenter: update the Package.swift to include a .testTarget referencing
"CMUXExtensionHostSupport" as a dependency, and create a Tests directory with
test files that exercise CMUXSidebarExtensionHostView and
CMUXSidebarExtensionBrowserPresenter behaviors (initialization, state
transitions, and key public methods); ensure tests import CmuxExtensionKit where
needed and cover edge cases for presenter logic and view lifecycle.

[CMUXExtensionActionScope].self,
forKey: .requestedActionScopes
minimumAPIVersion = try container.decodeIfPresent(CmuxExtensionAPIVersion.self, forKey: .minimumAPIVersion) ?? .sidebarV2
readScopes = try container.decode([CmuxExtensionScope].self, forKey: .readScopes)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Decoding requires readScopes but init defaults it to [].

The initializer defaults readScopes to [], but init(from:) uses decode (not decodeIfPresent), making readScopes a required key when decoding. This asymmetry will cause decode failures for payloads created with the default initializer if they're round-tripped through Codable without explicitly including readScopes.

Consider using decodeIfPresent with a ?? [] fallback for consistency with actionScopes and the public initializer:

🔧 Proposed fix
-        readScopes = try container.decode([CmuxExtensionScope].self, forKey: .readScopes)
+        readScopes = try container.decodeIfPresent([CmuxExtensionScope].self, forKey: .readScopes) ?? []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
readScopes = try container.decode([CmuxExtensionScope].self, forKey: .readScopes)
readScopes = try container.decodeIfPresent([CmuxExtensionScope].self, forKey: .readScopes) ?? []
🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionManifest.swift`
at line 47, The decoder currently requires readScopes by calling readScopes =
try container.decode([CmuxExtensionScope].self, forKey: .readScopes) in
init(from:), but the public initializer defaults readScopes to [] which makes
the key effectively optional; update init(from:) to use decodeIfPresent for
readScopes and fall back to [] (e.g., readScopes = try
container.decodeIfPresent([CmuxExtensionScope].self, forKey: .readScopes) ?? [])
to match actionScopes and the public init behavior, ensuring round-trip Codable
compatibility for CmuxExtensionManifest.

Comment on lines 1 to +5
import Foundation

public struct CMUXExtensionActionResult: Codable, Equatable, Sendable {
@_spi(CmuxHostTransport)
/// Result returned by CMUX for a sidebar host action request.
public struct CmuxSidebarActionResult: Codable, Equatable, Sendable {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Rename the file to match its primary type.

The file is still named CMUXExtensionActionResult.swift but now defines CmuxSidebarActionResult (plus the rejection-reason and error enums). Rename to CmuxSidebarActionResult.swift so the file matches the type it declares.

As per coding guidelines: "each struct, class, enum ... that is part of a public API ... lives in its own file named after the type."

🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXExtensionActionResult.swift`
around lines 1 - 5, The file name does not match its public API type: rename the
source file currently named CMUXExtensionActionResult.swift to
CmuxSidebarActionResult.swift and update any imports/targets referring to the
old filename; ensure the primary public type CmuxSidebarActionResult (and
related enums like the rejection-reason and error enums defined in the same
file) remain in this single file so each public API type lives in its own file
named after the type.

/// (via Info.plist variable substitution), so the resolved id lives only in the built
/// bundle, never in tracked source. Absent or empty means "use ``baseIdentifier``".
public static let identifierInfoPlistKey = "CMUXSidebarExtensionPointIdentifier"
public static let identifierInfoPlistKey = "CmuxSidebarExtensionPointIdentifier"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if extension point generation scripts reference the new key name
rg -n 'CmuxSidebarExtensionPointIdentifier|CMUXSidebarExtensionPointIdentifier' --type sh --type swift -g '!*.swift.gyb'

Repository: manaflow-ai/cmux

Length of output: 239


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find any remaining references to the old/new key names across the repo
rg -n 'CMUXSidebarExtensionPointIdentifier|CmuxSidebarExtensionPointIdentifier' --hidden --glob '!.git/*'

echo "---- usage of identifierInfoPlistKey symbol ----"
rg -n 'identifierInfoPlistKey' --hidden --glob '!.git/*'

echo "---- potential Info.plist writers / extension point generation ----"
# Look for files that mention "extension point" and/or the old/new key
rg -n 'extension point|Info\.plist|identifierInfoPlistKey|SidebarExtensionPoint' --hidden --glob '!.git/*' --glob '*.{sh,swift,py,js,ts,mjs,cjs,yml,yaml,json,tml,txt,rb,go,Makefile}'

Repository: manaflow-ai/cmux

Length of output: 14026


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Show the Swift implementation around identifierInfoPlistKey + fallback behavior
sed -n '1,120p' Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionPoint.swift

# 2) Inspect how the base app Info.plist is declared (does it still use the old key?)
sed -n '1,120p' Resources/Info.plist

# 3) Inspect build-time generation script that writes extension point declaration
sed -n '1,120p' scripts/write-sidebar-extension-point.sh

# 4) Inspect reload-extension script notes about baked EXExtensionPointIdentifier
sed -n '1,220p' scripts/reload-extension.sh

# 5) Search scripts for both key names (broader than just sh/swift)
rg -n 'CMUXSidebarExtensionPointIdentifier|CmuxSidebarExtensionPointIdentifier' scripts Resources Packages --hidden --glob '!.git/*'

Repository: manaflow-ai/cmux

Length of output: 16027


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for both key spellings across Info.plist templates/resources and example projects.
rg -n 'CMUXSidebarExtensionPointIdentifier|CmuxSidebarExtensionPointIdentifier' \
  --hidden --glob '!.git/*' \
  --glob '*/Info.plist' --glob '*/Info.plist.*' --glob '*.plist' --glob '*.xib' --glob '*.storyboard' \
  Examples Packages Resources .github scripts --glob '!*swift.gyb' --glob '!*swift.gyb/*' || true

# Find where the host reads the extension point identifier at runtime.
rg -n 'CmuxSidebarExtensionPoint\.identifier(\(|\b)' --hidden --glob '!.git/*' Packages || true

# Inspect host view around the call site.
FILE='Sources/CMUXInstalledExtensionSidebarHostView.swift'
if [ -f "$FILE" ]; then
  sed -n '240,340p' "$FILE"
fi

Repository: manaflow-ai/cmux

Length of output: 3764


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n 'CmuxSidebarExtensionPoint\.identifier\s*\(' --hidden --glob '!.git/*' .
rg -n 'identifierInfoPlistKey|CMUXSidebarExtensionPointIdentifier|CmuxSidebarExtensionPointIdentifier' --hidden --glob '!.git/*' --glob '*.plist' --glob '*.pbxproj' --glob '*.*' \
  Examples Packages Resources scripts .github

# Focus on example extension projects' Info.plist templates
fd -t f -e plist -e plist.in -e xcconfig -e xib -e storyboard Examples Packages Resources scripts .github | head -n 50

Repository: manaflow-ai/cmux

Length of output: 1150


Update Info.plist key to match identifierInfoPlistKey (breaks sidebar extension point resolution)

  • CmuxSidebarExtensionPoint.identifier() now reads identifierInfoPlistKey = "CmuxSidebarExtensionPointIdentifier" and falls back to baseIdentifier when the key is absent/empty.
  • Resources/Info.plist still declares the old key CMUXSidebarExtensionPointIdentifier (set to $(CMUX_SIDEBAR_EXTENSION_POINT_ID)), so the override is never read and tag-scoped point IDs collapse to com.manaflow.cmux.sidebar, leading to extension point mismatches (and old third-party bundles using the old key won’t override either).
  • Rename the key in Resources/Info.plist to CmuxSidebarExtensionPointIdentifier to match the new constant (or revert the constant if the old key must remain supported).
🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionPoint.swift`
at line 20, The Info.plist key used by CmuxSidebarExtensionPoint no longer
matches the constant identifierInfoPlistKey
("CmuxSidebarExtensionPointIdentifier"), causing identifier resolution in
CmuxSidebarExtensionPoint.identifier() to miss the override and fall back to
baseIdentifier; fix this by updating Resources/Info.plist to rename the existing
CMUXSidebarExtensionPointIdentifier entry to CmuxSidebarExtensionPointIdentifier
(or revert the constant if you intend to keep the old key) so the
identifierInfoPlistKey lookup in CmuxSidebarExtensionPoint.identifier() reads
the intended override.

Comment on lines +3 to +5
@_spi(CmuxHostTransport)
/// Host-side callbacks used by the sidebar XPC bridge.
public struct CmuxSidebarHostClient: Sendable {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Doc comment placement after @_spi attribute.

The doc comment on line 4 appears between the @_spi attribute and the struct declaration. While syntactically valid, the conventional placement is before all attributes for better tooling support.

📝 Suggested reordering
+/// Host-side callbacks used by the sidebar XPC bridge.
 `@_spi`(CmuxHostTransport)
-/// Host-side callbacks used by the sidebar XPC bridge.
 public struct CmuxSidebarHostClient: Sendable {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@_spi(CmuxHostTransport)
/// Host-side callbacks used by the sidebar XPC bridge.
public struct CmuxSidebarHostClient: Sendable {
/// Host-side callbacks used by the sidebar XPC bridge.
`@_spi`(CmuxHostTransport)
public struct CmuxSidebarHostClient: Sendable {
🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarHostClient.swift`
around lines 3 - 5, The documentation comment is placed between the attribute
and the type declaration; move the doc comment so it appears immediately before
the `@_spi`(CmuxHostTransport) attribute (i.e., place the doc comment above the
attribute) so tooling sees the doc comment associated with the
CmuxSidebarHostClient struct; update the placement around the
`@_spi`(CmuxHostTransport) and public struct CmuxSidebarHostClient: Sendable
declaration accordingly.

Comment on lines +74 to +82
private extension KeyedDecodingContainer {
func decodeLossySetIfPresent<Value>(
_ type: Value.Type,
forKey key: Key
) throws -> Set<Value> where Value: RawRepresentable, Value.RawValue == String, Value: Hashable {
guard let rawValues = try decodeIfPresent([String].self, forKey: key) else { return [] }
return Set(rawValues.compactMap(type.init(rawValue:)))
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for documentation of the lossy decoding contract and scope versioning strategy
rg -n -C3 --type=swift --type=md 'lossy.*decod|forward.compa|scope.*version|unknown.*scope' Packages/CmuxExtensionKit/

Repository: manaflow-ai/cmux

Length of output: 42


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift"

echo "=== File header/context ==="
# Show first ~120 lines with numbers (avoid huge output)
sed -n '1,140p' "$FILE" | nl -ba

echo "=== Search for decodeLossySetIfPresent usage in repo ==="
rg -n "decodeLossySetIfPresent" .

echo "=== Search for sidebarV1/sidebarV2/apiVersion usage ==="
rg -n "sidebarV1|sidebarV2|apiVersion" Packages/CmuxExtensionKit/Sources

echo "=== Search for scope versioning / grant / permission terms in Swift/MD ==="
rg -n --type=swift --type=md 'scope.*version|lossy|forward compat|unknown.*scope|grant' Packages/CmuxExtensionKit/ .

Repository: manaflow-ai/cmux

Length of output: 149


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift"

echo "=== File context (first 200 lines, numbered) ==="
sed -n '1,200p' "$FILE" | cat -n

echo "=== decodeLossySetIfPresent usage in repo ==="
rg -n --hidden --glob '!**/.build/**' "decodeLossySetIfPresent" .

echo "=== sidebarV1/sidebarV2/apiVersion usage ==="
rg -n --hidden --glob '!**/.build/**' "(sidebarV1|sidebarV2|apiVersion)" Packages/CmuxExtensionKit/Sources

echo "=== docs/contracts mentioning scope versioning / lossy decoding ==="
rg -n --hidden --glob '!**/.build/**' --type=md '(lossy|forward compat|forward-compatible|scope.*version|unknown.*scope|grant)' .

Repository: manaflow-ai/cmux

Length of output: 8615


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Packages/CmuxExtensionKit/README.md: around snapshot contract ==="
# Show around the previously hit line ~113
sed -n '80,170p' Packages/CmuxExtensionKit/README.md | cat -n

echo "=== CMUXExtensionHostSupport README: look for permission/grants/snapshot policy ==="
sed -n '1,220p' Packages/CMUXExtensionHostSupport/README.md | cat -n

echo "=== Search for scope/grant/snapshot filtering docs in CmuxExtensionKit package ==="
rg -n "grantedReadScopes|grantedActionScopes|CmuxExtensionScope|CmuxExtensionActionScope|workspaceMetadata|snapshot" Packages/CmuxExtensionKit/README.md Packages/CmuxExtensionKit/Sources Packages/CMUXExtensionHostSupport/README.md

echo "=== Locate CmuxExtensionScope / CmuxExtensionActionScope definitions ==="
rg -n "enum CmuxExtensionScope|struct CmuxExtensionScope|typealias CmuxExtensionScope|enum CmuxExtensionActionScope|typealias CmuxExtensionActionScope" Packages/CmuxExtensionKit/Sources

echo "=== Show CmuxExtensionScope / CmuxExtensionActionScope source files (line-limited) ==="
# Print matching files with some surrounding context
rg -n "enum CmuxExtensionScope|enum CmuxExtensionActionScope" --files-with-matches Packages/CmuxExtensionKit/Sources | sed -n '1,20p'

Repository: manaflow-ai/cmux

Length of output: 16273


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== CMUXExtensionScope.swift ==="
sed -n '1,200p' Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Manifest/CMUXExtensionScope.swift | cat -n

echo "=== CMUXSidebarContext.swift docs ==="
sed -n '1,120p' Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CmuxSidebarContext.swift | cat -n

echo "=== Search where grantedReadScopes/grantedActionScopes are used ==="
rg -n "grantedReadScopes|grantedActionScopes" Packages/CmuxExtensionKit/Sources | head -n 200

echo "=== Search for forward-compat/lossy/unknown scope wording in README/docs ==="
rg -n --type=swift --type=md '(lossy|forward|compat|unknown.*scope|ignore.*unknown)' Packages/CmuxExtensionKit/README.md Packages/CmuxExtensionKit/Sources Packages/CMUXExtensionHostSupport/README.md | head -n 200

Repository: manaflow-ai/cmux

Length of output: 5334


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== CMUXSidebarExtensionConnection.swift (first 260 lines) ==="
sed -n '1,260p' Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarExtensionConnection.swift | cat -n

echo "=== CMUXExtensionValidator.swift ==="
sed -n '1,220p' Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Validation/CMUXExtensionValidator.swift | cat -n

echo "=== Search Sources for compatibility/lossy/unknown/forward wording ==="
rg -n --hidden --glob '!**/.build/**' '(compatib|lossy|forward|unknown.*scope)' Packages/CmuxExtensionKit/Sources | head -n 200

Repository: manaflow-ai/cmux

Length of output: 14261


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== grantedActionScopes usage across repo ==="
rg -n --hidden --glob '!**/.build/**' "grantedActionScopes" .

echo "=== requiredScopes usage (action gating) ==="
rg -n --hidden --glob '!**/.build/**' "requiredScopes" Packages/CmuxExtensionKit/Sources .

echo "=== Search for rejection / granted scope checks ==="
rg -n --hidden --glob '!**/.build/**' "(grantedActionScopes|grantedReadScopes).*contains|contains.*(grantedActionScopes|grantedReadScopes)|(reject|rejected).*(scope|granted)|requiredScopes.*granted" Packages/CmuxExtensionKit/Sources Packages/CMUXExtensionHostSupport .

Repository: manaflow-ai/cmux

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Inspect action gating in CMUXInstalledExtensionSidebarHostView.swift (around 1284) ==="
HOSTVIEW="Sources/CMUXInstalledExtensionSidebarHostView.swift"
# Print a small window around the known match
start=1250
end=1320
sed -n "${start},${end}p" "$HOSTVIEW" | cat -n

echo "=== CMUXSidebarAction.swift: requiredScopes ==="
ACTIONFILE="Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarAction.swift"
sed -n '1,120p' "$ACTIONFILE" | cat -n

echo "=== Narrow searches for granted/allowed/required scopes (Swift only) ==="
rg -n --type=swift --hidden --glob '!**/.build/**' \
  "(allowedActionScopes|requiredScopes|grantedActionScopes|grantedReadScopes|isSuperset\\(of: action\\.requiredScopes\\))" \
  Packages/CmuxExtensionKit/Sources Sources --max-count=200

echo "=== Search for decodeLossySetIfPresent outside CMUXSidebarSnapshot.swift ==="
rg -n --type=swift --hidden --glob '!**/.build/**' "decodeLossySetIfPresent" Packages/CmuxExtensionKit/Sources --max-count=50

Repository: manaflow-ai/cmux

Length of output: 10849


🏁 Script executed:

#!/bin/bash
set -euo pipefail
TESTFILE="Packages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swift"

echo "=== Search tests for 'lossy' or 'unknown' ==="
rg -n "lossy|unknown|rawValue|compactMap" "$TESTFILE"

echo "=== Show around decoded/grantedActionScopes expectations ==="
# show first 260 lines and then around the lines earlier hit (approx line numbers)
sed -n '1,120p' "$TESTFILE" | cat -n
sed -n '120,260p' "$TESTFILE" | cat -n
sed -n '260,420p' "$TESTFILE" | cat -n

Repository: manaflow-ai/cmux

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

TESTFILE="Packages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swift"

echo "=== test file length ==="
wc -l "$TESTFILE"

echo "=== show beginning (1-120) ==="
sed -n '1,120p' "$TESTFILE" | cat -n

echo "=== show middle (120-240) ==="
sed -n '120,240p' "$TESTFILE" | cat -n

echo "=== show end (240-420) ==="
sed -n '240,420p' "$TESTFILE" | cat -n

Repository: manaflow-ai/cmux

Length of output: 20413


Clarify lossy scope decoding as fail-closed forward-compat behavior

  • decodeLossySetIfPresent in Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift drops unknown scope raw strings via compactMap(type.init(rawValue:)), so older extensions treat newly-added scopes as “not granted” (no permission expansion).
  • Host-side action enforcement in Sources/CMUXInstalledExtensionSidebarHostView.swift rejects any action when allowedActionScopes isn’t a superset of action.requiredScopes, so the worst case is reduced UI/data for older extensions.
  • Add a brief comment/README note calling out this contract, and the workspaceMetadata-missing behavior that sets workspace title to "" in CMUXSidebarSnapshot.filtered(for:actionScopes:).
🤖 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
`@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/Sidebar/CMUXSidebarSnapshot.swift`
around lines 74 - 82, Add a short clarifying comment near the lossy decoding
util and a note in CMUXSidebarSnapshot explaining the fail-closed,
forward-compat behavior: reference
KeyedDecodingContainer.decodeLossySetIfPresent(Value.Type,forKey:) to state that
unknown scope raw values are dropped (treated as not granted), and mention that
host-side enforcement (in CMUXInstalledExtensionSidebarHostView) will reject
actions unless allowedActionScopes is a superset of action.requiredScopes; also
document the workspaceMetadata-missing behavior in
CMUXSidebarSnapshot.filtered(for:actionScopes:) that causes workspace.title to
be set to an empty string.

Comment on lines +5 to +9
/// Handles a mutation against the latest sidebar snapshot.
func handle(
_ mutation: CmuxSidebarProviderMutation,
snapshot: CmuxSidebarProviderSnapshot
) throws -> CmuxSidebarProviderCommandResult

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add - Parameter/- Returns/- Throws DocC callouts to handle(_:snapshot:).

This public protocol requirement takes two parameters, returns a result, and is throws, but only has a one-line summary. Document the mutation/snapshot inputs, the returned result, and the throwing conditions.

📝 Proposed docs
-    /// Handles a mutation against the latest sidebar snapshot.
+    /// Handles a mutation against the latest sidebar snapshot.
+    ///
+    /// - Parameters:
+    ///   - mutation: The mutation the host is requesting.
+    ///   - snapshot: The latest sidebar snapshot the mutation applies to.
+    /// - Returns: The result indicating whether CMUX accepted the command.
+    /// - Throws: An error if the provider cannot apply the mutation.
     func handle(
         _ mutation: CmuxSidebarProviderMutation,
         snapshot: CmuxSidebarProviderSnapshot
     ) throws -> CmuxSidebarProviderCommandResult

As per coding guidelines: "Document every public symbol in new Swift packages under Packages/ ... use - Parameter name:, - Returns:, - Throws: callouts."

🤖 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
`@Packages/CmuxSidebarProviderKit/Sources/CmuxSidebarProviderKit/Mutations/CmuxMutableSidebarProvider.swift`
around lines 5 - 9, Update the public protocol requirement declaration for
handle(_:snapshot:) to include DocC callouts: add a one-line summary plus "-
Parameter mutation: CmuxSidebarProviderMutation — description of the mutation
input", "- Parameter snapshot: CmuxSidebarProviderSnapshot — description of the
snapshot input", "- Returns: CmuxSidebarProviderCommandResult — describe what
the result represents", and "- Throws: — describe under what conditions the
method throws"; target the protocol method named handle(_:snapshot:) in
CmuxMutableSidebarProvider and reference the types CmuxSidebarProviderMutation,
CmuxSidebarProviderSnapshot, and CmuxSidebarProviderCommandResult so the
documentation appears for this public symbol.

@azooz2003-bit
azooz2003-bit dismissed coderabbitai[bot]’s stale review June 2, 2026 15:24

Dismissed for merge: bot review is blocking on broad/nit comments after current-head build and release checks passed; remaining tests job is a stuck runner.

@azooz2003-bit
azooz2003-bit merged commit 1a9bd90 into main Jun 2, 2026
29 of 30 checks passed
@azooz2003-bit
azooz2003-bit deleted the feat-extension-sdk-organization branch June 2, 2026 15:24

This branch was successfully deployed

1 active deployment
Preview – cmux — fad4790b Deployed Jun 2, 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.

1 participant