Repository navigation
Add CmuxExtensionKit sidebar prototypes - #4309
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds CmuxExtensionKit and integrates an extension-sidebar system: new package with models/reducer/renderers, V2 snapshot API, prompt-submitted event publishing and submission timestamps, UI integration (selection, inspector, worktree prototype), example providers, runtime init fixes, tests, localization, and project wiring. ChangesExtension Sidebar Architecture & Integration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (5 errors, 1 warning, 1 inconclusive)
✅ Passed checks (9 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR introduces
Confidence Score: 5/5Safe to merge — all previously flagged blocking, memory, state, and serialization issues have been addressed; no new defects found in the changed paths. Every concrete defect from prior review rounds has a matching fix: the No files require special attention. The Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as VerticalTabsSidebar (MainActor)
participant TM as TabManager
participant WS as Workspace
participant Bus as CmuxEventBus
participant Reducer as CmuxExtensionSidebarReducer
participant Provider as SidebarProvider (e.g. BrowserStack)
participant TC as TerminalController (socket)
UI->>TM: handlePromptSubmit(workspaceId:message:)
TM->>WS: recordSubmittedMessage(message)
WS->>WS: conversationMessagePreview(from:)
WS->>WS: recordConversationMessage(preview)
WS-->>TM: true (messageRecorded)
TM->>Bus: publishWorkspacePromptSubmitted(workspaceId:preview:)
TM->>Bus: publishWorkspaceReordered(workspaceIds:movedIds:pinnedIds:)
Bus-->>UI: extensionSidebarUpdateToken increments (via .onReceive)
UI->>UI: extensionSidebarRenderModel(renderContext:now:)
UI->>Provider: render(snapshot:)
Provider-->>UI: CmuxExtensionSidebarRenderModel
TC->>TC: v2ExtensionSidebarSnapshot (RPC)
TC->>WS: extensionSidebarProjectRootPath (cached, no .git walk)
TC-->>TC: build payload with latestSubmittedMessage/latestSubmittedAt
TC-->>Bus: .ok([...])
note over Reducer: External consumers use Reducer to apply live events
Bus-->>Reducer: CmuxExtensionEventFrame(workspace.prompt.submitted)
Reducer->>Reducer: "guard normalizedPrompt(message_preview) != nil"
Reducer->>Reducer: update latestSubmittedMessage, latestSubmittedAt
Reviews (33): Last reviewed commit: "fix: return browser stack scoped state" | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 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 `@docs/events.md`:
- Line 246: The doc uses the term `sequence` in the event-reduction guidance
while the rest of the stream/event schema uses `seq`; update the wording to use
`seq` consistently (replace `sequence` with `seq` in the guidance referring to
the returned sequence/seq) and verify related references (e.g., the snapshot
that returns `selected_workspace_id`) mention `seq` so clients implement the
correct field name.
In `@Packages/CmuxExtensionKit/Sources/CmuxExtensionKit/CmuxExtensionKit.swift`:
- Around line 1-1268: The file is too large and mixes multiple responsibilities;
split it into focused Swift files: 1) data models & simple types (move
CmuxExtensionLocalizedText, CmuxExtensionJSONValue, CmuxExtensionEventFrame,
CmuxExtensionCommandResult, CmuxClient, CmuxExtensionWorkspaceSnapshot,
CmuxExtensionSidebarSnapshot, CmuxExtensionSidebarEvent,
CmuxExtensionSidebarMutation, CmuxExtensionSidebarRenderText,
CmuxExtensionSidebarRenderModel, CmuxExtensionSidebarRenderSection,
CmuxExtensionSidebarRenderRow, CmuxExtensionSidebarRenderContext,
CmuxExtensionPathFormatter and related small enums/structs), 2) provider
descriptors and provider protocols (move CmuxExtensionSidebarProviderDescriptor,
CmuxExtensionSidebarProviderID, CmuxExtensionSidebarCustomizationMode,
CmuxExtensionSidebarProvider, CmuxExtensionSidebarContextualProvider,
CmuxExtensionWorkspaceRowAccessory/Kind, CmuxExtensionWorkspacePopoverTab), 3)
reducer logic (move CmuxExtensionSidebarReducer and its helpers like
resolvedWorkspaceId and normalizedPrompt), and 4) tree building & rendering
helpers (move CmuxExtensionWorkspaceTreeBuilder,
CmuxExtensionWorkspaceTreeSection, CmuxExtensionWorkspaceTreeProvider and helper
functions like groupSectionTemplate, appendSection, needsAttention,
hasServerSignal, trimmedNonEmpty and the private CmuxExtensionJSONValue uuid
helpers). Ensure each new file keeps original access levels (public) and
imports, update module visibility, preserve Codable/Sendable conformance, run
build/tests, and adjust any internal references/imports if needed so symbols
like CmuxExtensionSidebarReducer.reduce,
CmuxExtensionWorkspaceTreeBuilder.sections,
CmuxExtensionSidebarProviderDescriptor, CmuxClient, and
CmuxExtensionPathFormatter continue to resolve.
- Around line 86-93: The intValue getter currently converts a rounded Double to
Int without bounds checking (in the .number case); add a range check against
Int.min and Int.max (or use Int64 ranges if needed) before calling Int(rounded)
and return nil if the rounded value is outside the representable Int range,
preserving the existing guard behavior for non-integer doubles; update the
.number branch in intValue to validate rounded is finite and within
Int.min...Int.max prior to the Int(rounded) conversion.
In `@Sources/CmuxEventPublishing.swift`:
- Around line 95-99: The event currently emits full prompt text under the
"message" key and reports no redactions; change the payload so the raw "message"
is not published (replace with NSNull() or a constant like "[REDACTED]"),
continue to publish "message_preview" and "message_length" as appropriate, and
update "redacted_fields" to include "message" so consumers know it was redacted;
locate the dictionary construction that sets "message", "message_preview",
"message_length", and "redacted_fields" and modify those entries accordingly.
In `@Sources/ContentView.swift`:
- Around line 10565-10572: Set a stable cmux.* identifier on the newly created
NSWindow and register that identifier with the shared close-shortcut routing so
Cmd+W is handled by the inspector instead of falling through; specifically,
after creating the NSWindow (the variable named window created with
hostingController and stored via controllers[workspace.id]) assign
window.identifier = NSUserInterfaceItemIdentifier("cmux.inspector.<stable-id>")
(use a stable token such as workspace.id) and ensure this identifier is included
in whatever registry/function backs cmuxWindowShouldOwnCloseShortcut so the
inspector window owns the close shortcut when it becomes key.
In `@Sources/GhosttyTerminalView.swift`:
- Around line 2172-2175: Remove the immediate seeding of
lastAppearanceColorScheme so the initial launch scheme isn't treated as
"unchanged"; instead defer syncing the runtime by either (A) leaving
lastAppearanceColorScheme nil/empty so the first call to
synchronizeThemeWithAppearance(...) sees a change and performs a sync, or (B)
explicitly schedule a deferred call (e.g. dispatch to main queue / next runloop)
that invokes ghostty_app_set_color_scheme(initialColorScheme) or calls
synchronizeThemeWithAppearance(initialColorScheme, force: true) after the
singleton's dispatch_once completes; update the code around
lastAppearanceColorScheme, synchronizeThemeWithAppearance(...), and
ghostty_app_set_color_scheme accordingly.
In `@Sources/TerminalController.swift`:
- Around line 4350-4359: The loop calling
FileManager.default.fileExists(atPath:) inside v2MainSync (via
v2ExtensionSidebarProjectRootPath) blocks the main thread; move the project-root
detection off the main thread and/or cache results. Compute project-root paths
asynchronously (e.g., DispatchQueue.global or Task.detached) for each workspace
path or maintain a cache keyed by workspace.path, then build
v2ExtensionSidebarWorkspacePayloads using the precomputed project-root values
and only call v2MainSync to set selectedWorkspaceId and assign the
already-prepared workspaces array; apply the same change for the similar code
referenced around v2MainSync usage at the 4414-4425 region.
- Around line 4393-4396: The sidebar workspace payload mistakenly sets the
"latest_submitted_message" field to workspace.latestConversationMessage
(copy-paste error); update the payload to use the submitted-message property
(e.g., workspace.latestSubmittedMessage) instead, keeping the same v2OrNull
wrapper and timestamp handling pattern used for "latest_conversation_message"
and "latest_submitted_at" so the keys "latest_conversation_message",
"latest_submitted_message", and "latest_submitted_at" reference the correct
workspace properties in TerminalController.swift where the payload is
constructed.
🪄 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: eb60ae81-393c-4091-b46c-fc2d551b0917
📒 Files selected for processing (15)
Packages/CmuxExtensionKit/Package.swiftPackages/CmuxExtensionKit/README.mdPackages/CmuxExtensionKit/Sources/CmuxExtensionKit/CmuxExtensionKit.swiftPackages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swiftResources/Localizable.xcstringsSources/CmuxEventPublishing.swiftSources/ContentView.swiftSources/GhosttyTerminalView.swiftSources/TerminalController.swiftSources/Update/UpdateTitlebarAccessory.swiftSources/Workspace.swiftSources/WorkspacePromptSubmit.swiftcmux.xcodeproj/project.pbxprojcmuxTests/WorkspacePromptSubmitTests.swiftdocs/events.md
There was a problem hiding this comment.
7 issues found across 15 files
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Sources/ContentView.swift`:
- Around line 10582-10669: CmuxExtensionWorktreePrototype and its helpers
(createWorktree, ensureGitRepository, writeSampleDevServerFiles, run,
shellEscaped) are pure Foundation/subprocess logic and should be extracted out
of the UI file; move this enum into a new dedicated Swift source (e.g.,
WorktreeCreation.swift) or into the CmuxExtensionKit package, update any
module/import references and access control as needed, and keep the
public/internal API (createWorktree signature and
CmuxExtensionWorktreeCreationResult) unchanged so callers in the UI continue to
work and the logic becomes independently testable.
- Around line 10087-10099: The ForEach body is calling
extensionWorkspaceSnapshot(for:) per row which causes repeated recomputation on
every render; move snapshot creation to the render/model preparation phase
(e.g., build a [UUID: WorkspaceSnapshot] map keyed by workspaceId from
section.rows) and pass the precomputed snapshot into
CmuxExtensionSidebarWorkspaceRowView instead of calling
extensionWorkspaceSnapshot(for:) inline; update the ForEach to use the map
lookup (using row.workspaceId) and keep other parameters (providerId,
relativeNow, isSelected, onSelect, onOpenWindow) unchanged so the view receives
a precomputed snapshot rather than recalculating each render.
- Around line 10550-10574: controllers never get removed so inspectors leak;
after creating the NSWindow/NSWindowController in
CmuxExtensionSidebarInspectorWindowController.show(workspace:), register a
one-shot observer for NSWindow.willCloseNotification (object: window) that
removes controllers[workspace.id] when the window closes and also removes the
observer token inside the handler to avoid leaking the observer; place the
addObserver call immediately after controller/window creation so the handler can
reference workspace.id and controllers to clean up.
🪄 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: 16080cd9-a56b-46b7-9820-f549a54805a9
📒 Files selected for processing (1)
Sources/ContentView.swift
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Sources/ContentView.swift`:
- Around line 10562-10580: The fast path in show(workspace:) reuses
controllers[workspace.id] but doesn't refresh the window title or hosted SwiftUI
view, causing stale inspector content; update the existing
NSWindowController/NSWindow by setting controller.window?.title =
workspace.title and either replace the contentViewController with a new
NSHostingController(rootView:
CmuxExtensionWorkspaceInspectorView(...).frame(width:620,height:440)) or, if the
current contentViewController is an NSHostingController, set its rootView to the
new CmuxExtensionWorkspaceInspectorView instance and call
window?.setContentSize(NSSize(width:620,height:440)) before making key and
ordering front so the inspector reflects the latest workspace snapshot.
- Around line 10022-10033: extensionSidebarProjectRootPath currently returns the
original rootPath when no .git is found, which lets the UI show “Create
worktree” for non-git folders; change the function
(extensionSidebarProjectRootPath) to return nil when no .git directory is
discovered so the UI will not offer worktree creation for non-repositories, and
mirror the same change in the duplicate implementation around the other
occurrence (lines referenced in review: the second copy at 10616-10631) to
ensure both code paths stop exposing worktree creation for non-git directories.
- Around line 10445-10457: The formatter
CmuxExtensionRelativeTimeFormatter.string(from:to:) uses single keys for
count-based units; change each unit branch (minutes, hours, days, weeks) to use
pluralized localization keys (ICU/.one and .other variants) and pass the numeric
count into the localized formatter instead of embedding the number in the
defaultValue. For example, replace building "\(minutes)m" with a call that looks
up "relativeTime.minutes" as a pluralized key and supplies minutes as the count
(using String.localizedStringWithFormat(NSLocalizedString(...)) or the Swift
String(localized:_) API that accepts arguments) and do the same for hours, days
and weeks in the string(from:to:) function.
- Around line 9390-9400: The menu currently reads only
UserDefaults.standard.string(forKey: defaultsKey) to set each NSMenuItem.state,
which ignores the AppStorage defaultProviderId on first run; update the
comparison in showMenu (where item.state is set) to use the stored value or
fallback to defaultProviderId (e.g. use UserDefaults.standard.string(forKey:
defaultsKey) ?? defaultProviderId) so the provider whose id equals the
AppStorage defaultProviderId is marked .on; keep the rest of the item setup
(title via localizedTitle(for:), action selectProvider(_:), target
CmuxExtensionSidebarMenuTarget.shared, representedObject = descriptor.id)
unchanged.
🪄 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: 18359cf7-0c42-48a7-bbf1-99c79b760259
📒 Files selected for processing (1)
Sources/ContentView.swift
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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/Sources/CmuxExtensionSidebarExamples/DevServerSidebar.swift`:
- Around line 54-62: The hasServerSignal function currently treats any ":" in
workspace.customDescription as a server signal, causing false positives (e.g.,
"feat: ..."); change the detection so a colon only counts when it looks like a
host:port or port indicator — e.g., check description for "server" OR a pattern
like ":\d+" (colon followed by digits) or common URL schemes ("http://",
"https://") or numeric port tokens; update hasServerSignal to use these stricter
checks against trimmed(workspace.customDescription)?.lowercased() so ordinary
labels with colons are not classified as live servers.
In
`@Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/LastPromptSidebar.swift`:
- Around line 46-51: The subtitle fallback in
promptSubtitle(_:CmuxExtensionWorkspaceSnapshot) uses a hardcoded English
string; replace the plain("No prompts yet") with a localized lookup (for example
NSLocalizedString("No prompts yet", comment: "Last prompt sidebar subtitle") or
String(localized: "No prompts yet")) so the UI localizes correctly, and add the
corresponding key/value to your Localizable.strings file; keep the existing
trimmed(workspace.latestSubmittedMessage) behavior and return type
CmuxExtensionSidebarRenderText.plain.
In
`@Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/ProjectWorktreeSidebar.swift`:
- Around line 43-48: The localization key must be stable instead of using the
runtime folder name; update the ExampleSidebarSection creation so the title uses
a constant key like "example.sidebar.group.project" (not
"example.sidebar.group.project.\(title)") and pass the folder display name
(computed by displayName(for:)) as the localized argument; adjust the
ExampleSidebarSection initializer call where id is "project:\(root)" and the
title currently uses localized("example.sidebar.group.project.\(title)", title)
to use localized("example.sidebar.group.project", title) so translation catalogs
remain deterministic.
🪄 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: 7b0d8e6e-5e08-49ff-82a8-3c4c54b61f84
📒 Files selected for processing (7)
Examples/CmuxExtensionSidebarExamples/Package.swiftExamples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/AttentionQueueSidebar.swiftExamples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/DevServerSidebar.swiftExamples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/LastPromptSidebar.swiftExamples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/ProjectWorktreeSidebar.swiftExamples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SidebarExamples.swiftExamples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SuperCompactSidebar.swift
There was a problem hiding this comment.
1 issue found across 7 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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/CmuxExtensionKit.swift`:
- Around line 590-620: The public enum CmuxExtensionWorkspacePopoverTab
currently exposes .pullRequest but treats it as a legacy alias (decodes
"pullRequest" as .browser and encodes .pullRequest as "browser"), which is
misleading; fix by either (A) making .pullRequest round-trippable: add
.pullRequest to the public allCases and update init(from:) and encode(to:) to
preserve and emit .pullRequest when appropriate, or (B) mark .pullRequest as
deprecated/internal and remove it from the public API while keeping a private
decoding fallback for the legacy "pullRequest" string; after choosing, add a
unit test (e.g., testWorkspacePopoverTabRoundTrips_activeCases) that asserts all
active (non-legacy) cases of CmuxExtensionWorkspacePopoverTab round-trip through
JSON encode/decode unchanged.
- Around line 266-270: Replace the unsafe Dictionary(uniqueKeysWithValues:)
build in the .workspacesReordered case with an explicit loop that records the
first appearance of each id (e.g., iterate ids.enumerated() and only set
indexById[id] if not already present) to avoid crashing on duplicates; also
compute originalIndexById from snapshot.workspaces.enumerated() and change the
sorted key to use indexById[id] ?? originalIndexById[id] ?? Int.max so omitted
IDs preserve their original relative order. Add a reducer unit test that
dispatches .workspacesReordered with duplicate IDs and with a partial payload
(omitting some workspace IDs) and asserts the resulting snapshot.workspaces
order matches the expected ordering (first reordered IDs in their first-seen
order, then the omitted workspaces in original order).
In `@Resources/Localizable.xcstrings`:
- Line 112670: The localization key "sidebar.browserStack.demoGroup" currently
contains placeholder text "lmao" for both en and ja; update the value for that
key to the correct user-facing copy (replace "lmao" with the intended English
string and the appropriate Japanese translation) in
Resources/Localizable.xcstrings so the UI does not show placeholder text, and
ensure the "stringUnit" entries for both "en" and "ja" are set to the finalized
translated values.
In `@Sources/ContentView.swift`:
- Around line 10079-10100: The demo group header uses a placeholder fallback
title and a no-op close button; replace the defaultValue "lmao" in the localized
Text (key "sidebar.browserStack.demoGroup") with the correct product copy and
wire the Button's empty action (the Button {} label: { ... } block) to the real
close/collapse behavior (e.g., call the view model method that removes or
collapses the group, such as closeGroup(groupID) or
toggleGroupExpansion(groupID)), or if that behavior isn't implemented yet,
remove or hide the Button (and its .safeHelp) until a proper handler exists so
the UI isn't misleading.
- Around line 10689-11023: Extract the sidebar-related types from
ContentView.swift into their own files: create separate Swift files for
CmuxExtensionSidebarWorkspaceRowView (View), CmuxExtensionRelativeTimeFormatter
(enum/helper), CmuxExtensionWorkspaceInspectorView (View),
CmuxExtensionWorkspaceInspectorBrowserView (NSViewRepresentable),
CmuxExtensionSidebarInspectorWindowController (class, keep `@MainActor`), and the
worktree helpers CmuxExtensionWorktreeCreationResult and
CmuxExtensionWorktreePrototype; preserve their existing access levels,
attributes (e.g., `@MainActor`, `@State`), and logic, add any required imports
(SwiftUI, WebKit, AppKit/Foundation) at the top of each new file, update
references in the project to the moved symbols, and then remove the
corresponding definitions from ContentView.swift so the file size is reduced
without changing behavior.
- Around line 10854-10860: The TextField is updating the bound `address` on
every keystroke which causes `updateNSView` to normalize and load the WKWebView
continuously; introduce a separate committed state (e.g., `committedAddress` or
`committedQuery`) and bind the TextField to the existing `address` while only
calling `CmuxExtensionWorkspaceInspectorBrowserView.normalizedAddress(...)` and
feeding that into the web view from `updateNSView` when the user submits (the
`.onSubmit` handler) or explicitly opens, and mirror that committed state to the
WKWebView load logic (and update any similar logic referenced around lines
10894-10900) so typing does not trigger navigation until commit.
🪄 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: 56945c2b-6c72-4065-8153-9a9ed7584b64
📒 Files selected for processing (6)
Examples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/BrowserStackSidebar.swiftExamples/CmuxExtensionSidebarExamples/Sources/CmuxExtensionSidebarExamples/SidebarExamples.swiftPackages/CmuxExtensionKit/Sources/CmuxExtensionKit/CmuxExtensionKit.swiftPackages/CmuxExtensionKit/Tests/CmuxExtensionKitTests/CmuxExtensionKitTests.swiftResources/Localizable.xcstringsSources/ContentView.swift
There was a problem hiding this comment.
2 issues found across 6 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
2 issues found across 13 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Summary
CmuxExtensionKitas a Swift package for sidebar snapshots, events, reducers, render models, and built-in example providers.workspace.prompt.submittedand exposeextension.sidebar.snapshotso custom sidebars can hydrate from snapshots and stay current from events.Verification
swift test --package-path Packages/CmuxExtensionKitgit diff --checkjq empty Resources/Localizable.xcstrings./scripts/reload.sh --tag extkitDemo videos
/tmp/cloud-extkit-project-tree-live/recording.mov| TLDR: Project-tree sidebar groups workspaces by repo with open/closed folder icons, icon-only plus buttons, and thin row text./tmp/cloud-extkit-last-message-live/recording.mov| TLDR: Last-message sidebar updates from prompt-submit events while the sidebar is open and reorders recent workspaces./tmp/cloud-extkit-super-compact/recording.mov| TLDR: Super-compact sidebar shows a dense workspace list with thin text and stable virtualized rows.Note
Medium Risk
Introduces a new extension-facing API surface and changes workspace event publishing/mapping (
workspace.prompt.submitted, reorder handling), which can affect sidebar state sync and ordering if regressions slip in.Overview
Adds a new Swift package,
CmuxExtensionKit, defining the extension sidebar contract (snapshots, render models, mutations, event frames, and a reducer for applying events to snapshots), plus a smallCmuxExtensionPathFormatterutility.Introduces
CmuxExtensionSidebarExampleswith several sample sidebar providers (project/worktree grouping, attention queue, dev server detection, last prompt recency, super-compact list) and a mutableBrowserStackSidebarthat supports drag-and-drop grouping with per-window JSON state persistence and async state hydration.Updates host event publishing to emit redacted
workspace.prompt.submittedframes and a structuredworkspace.reorderedpayload (including pinned IDs), and stops mirroringworkspace.reorder*socket-v2 calls into domain reorder events. ExpandsLocalizable.xcstringswith new sidebar/provider strings and adds unit tests covering sidebar rendering, persistence/reconciliation, and reducer/event decoding behavior.Reviewed by Cursor Bugbot for commit cafedc2. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Adds
CmuxExtensionKitandCmuxExtensionSidebarExamplesfor custom, switchable sidebars driven by snapshots and live events. Finalizes sidebar snapshot RPC, publishes redactedworkspace.prompt.submitted, unifiesworkspace.reordered(with pinned state), hardens reducers/replay, and scopes BrowserStack state per window so sidebars stay accurate across replays, restarts, and multiple windows.New Features
CmuxExtensionKitwith snapshot/reducer/render APIs, path formatter, and provider descriptors.CmuxExtensionSidebarExamples: attention queue, dev servers, last prompt, project worktrees, super-compact, and a mutable BrowserStack (per-window persisted groups, drag-and-drop, preserved boundary inserts).latestSubmittedAteven when iMessage mode is off.Bug Fixes
extension.sidebar.snapshotRPC/serialization; tightened event sync and out-of-order handling; request snapshot replacement when needed; reduced noisy logs.workspace.prompt.submittedonly on submissions with redacted payloads; gated remote attention rows.workspace.reorderedpublishing across prompt, drag-and-drop, pin toggles, and lifecycle; includepinned_workspace_ids; removed socket mirroring to avoid duplicates; isolated reorder side effects; added tests for reorder paths and BrowserStack DnD.Written for commit cafedc2. Summary will update on new commits. Review in cubic
Summary by CodeRabbit