Repository navigation
Conversation
|
Someone is attempting to deploy a commit to the Manaflow Team on Vercel. A member of the Team first needs to authorize it. |
|
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 Changesomo-slim Launcher Support
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 21❌ Failed checks (1 warning, 20 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 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: 4/5Safe to merge after adding the two missing xcstrings catalog entries; the core launch, shadow config, shim, and session relay logic is well-structured and covered by tests. The only defect found is that cli.omoSlim.installFailed and cli.omoSlim.noPackageManager are referenced in production Swift but have no entries in Localizable.xcstrings, so every non-English user gets raw English text during plugin installation failures. Everything else — shadow config isolation, JSONC stripping, tmux shim creation, port arbitration, fork/resume/trust wiring, and the remote relay refactor — looks correct and is exercised by the new Go and Swift test suite additions. Resources/Localizable.xcstrings and CLI/cmux.swift (the two missing localized key registrations) Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User
participant cmux CLI
participant runOMOSlim
participant omoSlimEnsurePlugin
participant shimDir as createOMOSlimShimDirectory
participant opencode
User->>cmux CLI: cmux omo-slim [args]
cmux CLI->>runOMOSlim: dispatch
runOMOSlim->>runOMOSlim: resolve opencode executable
runOMOSlim->>omoSlimEnsurePlugin: set up shadow config + install plugin
omoSlimEnsurePlugin->>omoSlimEnsurePlugin: write shadow opencode.json (strip OMO, add slim)
omoSlimEnsurePlugin->>omoSlimEnsurePlugin: symlink user slim JSONC config
omoSlimEnsurePlugin->>omoSlimEnsurePlugin: "configure multiplexer.type=tmux in slim config"
omoSlimEnsurePlugin->>omoSlimEnsurePlugin: "setenv OPENCODE_CONFIG_DIR=shadow"
runOMOSlim->>shimDir: create tmux + terminal-notifier shims
runOMOSlim->>runOMOSlim: configureOMOSlimEnvironment (CMUX_OMO_SLIM_CMUX_BIN, OPENCODE_PORT, OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS)
runOMOSlim->>opencode: execv with --port arg prepended
opencode-->>User: launches with oh-my-opencode-slim plugin active
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User
participant cmux CLI
participant runOMOSlim
participant omoSlimEnsurePlugin
participant shimDir as createOMOSlimShimDirectory
participant opencode
User->>cmux CLI: cmux omo-slim [args]
cmux CLI->>runOMOSlim: dispatch
runOMOSlim->>runOMOSlim: resolve opencode executable
runOMOSlim->>omoSlimEnsurePlugin: set up shadow config + install plugin
omoSlimEnsurePlugin->>omoSlimEnsurePlugin: write shadow opencode.json (strip OMO, add slim)
omoSlimEnsurePlugin->>omoSlimEnsurePlugin: symlink user slim JSONC config
omoSlimEnsurePlugin->>omoSlimEnsurePlugin: "configure multiplexer.type=tmux in slim config"
omoSlimEnsurePlugin->>omoSlimEnsurePlugin: "setenv OPENCODE_CONFIG_DIR=shadow"
runOMOSlim->>shimDir: create tmux + terminal-notifier shims
runOMOSlim->>runOMOSlim: configureOMOSlimEnvironment (CMUX_OMO_SLIM_CMUX_BIN, OPENCODE_PORT, OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS)
runOMOSlim->>opencode: execv with --port arg prepended
opencode-->>User: launches with oh-my-opencode-slim plugin active
Reviews (7): Last reviewed commit: "Merge latest main into omo-slim launcher..." | Re-trigger Greptile |
| "cli.omoSlim.usage": { | ||
| "extractionState": "manual", | ||
| "localizations": { | ||
| "en": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Usage: cmux omo-slim [opencode-args...]\n\nLaunch OpenCode with oh-my-opencode-slim in a cmux-aware environment.\n\noh-my-opencode-slim coordinates background specialist agents. This\ncommand sets up a tmux shim so those agent panes become native cmux\nsplits with sidebar metadata and notifications.\n\nThis command:\n - sets a tmux-like environment so oh-my-opencode-slim uses cmux splits\n - prepends a private tmux shim to PATH\n - forwards all remaining arguments to opencode\n\nExamples:\n cmux omo-slim\n cmux omo-slim --continue\n cmux omo-slim --model zhipu/glm-5.2" | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "使い方: cmux omo-slim [opencode-args...]\n\ncmux 対応の環境で OpenCode と oh-my-opencode-slim を起動します。\n\noh-my-opencode-slim はバックグラウンドの専門エージェントを調整します。\nこのコマンドは tmux shim を設定し、それらのエージェントペインを\nサイドバーのメタデータと通知を備えたネイティブの cmux split に変換します。\n\nこのコマンドは次を行います:\n - oh-my-opencode-slim が cmux の split を使うよう tmux 風の環境を設定\n - 専用の tmux shim を PATH の先頭に追加\n - 残りの引数をそのまま opencode に渡す\n\n例:\n cmux omo-slim\n cmux omo-slim --continue\n cmux omo-slim --model zhipu/glm-5.2" | ||
| } | ||
| } | ||
| } | ||
| }, |
There was a problem hiding this comment.
Missing locale translations in cli.omoSlim.usage
cli.omoSlim.usage is translated into only en and ja, but the immediately adjacent peer key cli.omo.usage also supplies ko and uk entries. The catalog already supports those locales for this type of CLI usage string, so the new key should include all four. Korean and Ukrainian users running cmux omo-slim --help will see the untranslated English fallback instead of their expected locale.
Rule Used: Flag production user-facing text that is not fully... (source)
| private func omoSlimEnsurePlugin(processEnvironment: [String: String]) throws { | ||
| let userDir = omoUserConfigDir() | ||
| let shadowDir = omoSlimShadowConfigDir() | ||
| let fm = FileManager.default | ||
|
|
||
| try fm.createDirectory(at: shadowDir, withIntermediateDirectories: true, attributes: nil) | ||
|
|
||
| let userJsonURL = userDir.appendingPathComponent("opencode.json") | ||
| let shadowJsonURL = shadowDir.appendingPathComponent("opencode.json") | ||
|
|
||
| var config: [String: Any] | ||
| if let data = try? Data(contentsOf: userJsonURL) { | ||
| guard let existing = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { | ||
| throw CLIError(message: "Failed to parse \(userJsonURL.path). Fix the JSON syntax and retry.") | ||
| } | ||
| config = existing | ||
| } else { | ||
| config = [:] | ||
| } |
There was a problem hiding this comment.
Error message exposes internal config file path
userJsonURL.path expands to the full home-directory path (e.g. /Users/alice/.config/opencode/opencode.json), leaking it in a user-facing error. The Go counterpart's test TestOmoEnsurePluginInvalidJSONErrorDoesNotExposeUserPath was written specifically to prevent this — the Swift omo-slim path should follow the same principle.
| private func omoSlimEnsurePlugin(processEnvironment: [String: String]) throws { | |
| let userDir = omoUserConfigDir() | |
| let shadowDir = omoSlimShadowConfigDir() | |
| let fm = FileManager.default | |
| try fm.createDirectory(at: shadowDir, withIntermediateDirectories: true, attributes: nil) | |
| let userJsonURL = userDir.appendingPathComponent("opencode.json") | |
| let shadowJsonURL = shadowDir.appendingPathComponent("opencode.json") | |
| var config: [String: Any] | |
| if let data = try? Data(contentsOf: userJsonURL) { | |
| guard let existing = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { | |
| throw CLIError(message: "Failed to parse \(userJsonURL.path). Fix the JSON syntax and retry.") | |
| } | |
| config = existing | |
| } else { | |
| config = [:] | |
| } | |
| private func omoSlimEnsurePlugin(processEnvironment: [String: String]) throws { | |
| let userDir = omoUserConfigDir() | |
| let shadowDir = omoSlimShadowConfigDir() | |
| let fm = FileManager.default | |
| try fm.createDirectory(at: shadowDir, withIntermediateDirectories: true, attributes: nil) | |
| let userJsonURL = userDir.appendingPathComponent("opencode.json") | |
| let shadowJsonURL = shadowDir.appendingPathComponent("opencode.json") | |
| var config: [String: Any] | |
| if let data = try? Data(contentsOf: userJsonURL) { | |
| guard let existing = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { | |
| throw CLIError(message: "Failed to parse opencode.json in the opencode config directory. Fix the JSON syntax and retry.") | |
| } | |
| config = existing | |
| } else { | |
| config = [:] | |
| } |
| case "omo", "omo-slim": | ||
| let parts = commandParts(executablePath: executablePath, arguments: arguments, fallbackExecutable: "cmux") | ||
| var tail = parts.tail | ||
| let command = launcher ?? "omo" | ||
| if tail.first == command { tail.removeFirst() } | ||
| guard let preserved = AgentLaunchSanitizer.preservedArguments(kind: "opencode", args: tail) else { | ||
| return .resolved(nil) | ||
| } | ||
| return .resolved([parts.executable, command, "--session", sessionId] + preserved) |
There was a problem hiding this comment.
Mixed indentation: tabs inside a spaces-indented file
The new "omo", "omo-slim" case arm (lines 283–291) uses hard tabs, while the rest of AgentResumeArgv.swift and the adjacent "omx", "omc" arm use spaces. This will render oddly in editors and diffs, and may cause a swiftformat / linter failure in CI.
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!
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@daemon/remote/cmd/cmuxd-remote/agent_launch.go`:
- Around line 135-197: runOMOSlimRelay duplicates nearly all of runOMORelay, so
move the shared relay flow into a common helper and parameterize the few
differences to prevent drift. Keep the existing unique pieces configurable via
args like tmuxPathPrefix, cmuxBinEnvVar, termEnvVar, extraEnv, the plugin setup
function, and the error-message prefix, and reuse the same port-handling logic
from the relay helper instead of copying it. Update runOMOSlimRelay to delegate
to the shared helper while preserving its current opencode/plugin behavior.
In `@Sources/ContentView.swift`:
- Around line 5592-5594: Parenthesize the boolean group in the ternary within
the snapshot launcher support check so the condition is clearly treated as one
expression before the `?` branch. Update the logic around the
`snapshot.launchCommand?.launcher` comparisons and `isRemoteTerminal` in
`ContentView` to match the intended grouping used by
`AgentForkSupport.supportsFork`, improving readability and reducing the chance
of future edits changing the ternary binding.
🪄 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: 6677be95-16e0-49b5-8c0c-ac365b79e03f
📒 Files selected for processing (19)
CLI/CMUXCLI+CommandSuggestions.swiftCLI/CMUXCLI+SessionsListForkDiagnostics.swiftCLI/cmux.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentForkArgv.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchCaptureTrust.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentResumeArgv.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentForkArgvTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchCaptureTrustTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentResumeArgvTests.swiftResources/Localizable.xcstringsSources/AgentForkSupport.swiftSources/ContentView.swiftSources/RestorableAgentSession.swiftSources/TaskManagerTypes.swiftSources/TextBoxAgentDetection.swiftdaemon/remote/cmd/cmuxd-remote/agent_launch.godaemon/remote/cmd/cmuxd-remote/agent_launch_test.godaemon/remote/cmd/cmuxd-remote/cli.go
7c82bab to
acbc7b2
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@daemon/remote/cmd/cmuxd-remote/agent_launch.go`:
- Around line 172-174: The default OPENCODE_PORT initialization in
agent_launch.go currently hardcodes the same port for both relays, so update the
startup path in the relevant launch logic to avoid sharing 4096 between omo and
omo-slim. Adjust the code around the OPENCODE_PORT environment setup in the
agent launch flow so omo-slim uses a distinct default port or an ephemeral
fallback, while preserving the existing behavior for omo. Use the surrounding
symbols in this file that perform relay startup and env setup to locate the
right place.
In `@Sources/AgentForkSupport.swift`:
- Around line 303-305: The omo-family launcher check is duplicated with
hardcoded string literals, which creates multiple sources of truth for the same
launcher set. Update the `snapshot.launchCommand?.launcher` check in
`AgentForkSupport` to use the canonical launcher-kind helper from
`AgentLaunchCaptureTrust` (for example, `launcherDescribesKind(..., kind:
"opencode")`) or another shared accessor instead of repeating `"omo"`,
`"omo-slim"`, and `"omos"`. Make the same shared-source change at the other call
sites so all fork-support logic relies on `wrapperLaunchersByKind` /
`nativeProcessAliasesByKind` rather than local lists.
🪄 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: 02faba01-699e-45a6-9a4d-3f30f138549c
📒 Files selected for processing (19)
CLI/CMUXCLI+CommandSuggestions.swiftCLI/CMUXCLI+SessionsListForkDiagnostics.swiftCLI/cmux.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentForkArgv.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchCaptureTrust.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentResumeArgv.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentForkArgvTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchCaptureTrustTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentResumeArgvTests.swiftResources/Localizable.xcstringsSources/AgentForkSupport.swiftSources/ContentView.swiftSources/RestorableAgentSession.swiftSources/TaskManagerTypes.swiftSources/TextBoxAgentDetection.swiftdaemon/remote/cmd/cmuxd-remote/agent_launch.godaemon/remote/cmd/cmuxd-remote/agent_launch_test.godaemon/remote/cmd/cmuxd-remote/cli.go
00521f8 to
30a17b3
Compare
| guard let openCodeExecutablePath = resolveOpenCodeExecutable(searchPath: launcherEnvironment["PATH"]) else { | ||
| throw CLIError(message: missingProviderExecutableMessage( | ||
| displayName: "OpenCode", | ||
| executableName: "opencode" | ||
| )) | ||
| } | ||
| launcherEnvironment["PATH"] = providerExecutableSearchPath( | ||
| searchPath: launcherEnvironment["PATH"], | ||
| includingExecutableAt: openCodeExecutablePath | ||
| ) | ||
|
|
||
| try omoSlimEnsurePlugin(processEnvironment: launcherEnvironment) |
There was a problem hiding this comment.
This is inconsistent with the fix applied to
runOMO in this same PR. runOMO was changed to the generic "Required agent executable not found. Install the agent CLI and retry." precisely to avoid exposing the upstream vendor name ("OpenCode") and executable name ("opencode") in a user-visible error. runOMOSlim uses the old missingProviderExecutableMessage path, so this error still leaks implementation details to the user.
| guard let openCodeExecutablePath = resolveOpenCodeExecutable(searchPath: launcherEnvironment["PATH"]) else { | |
| throw CLIError(message: missingProviderExecutableMessage( | |
| displayName: "OpenCode", | |
| executableName: "opencode" | |
| )) | |
| } | |
| launcherEnvironment["PATH"] = providerExecutableSearchPath( | |
| searchPath: launcherEnvironment["PATH"], | |
| includingExecutableAt: openCodeExecutablePath | |
| ) | |
| try omoSlimEnsurePlugin(processEnvironment: launcherEnvironment) | |
| guard let openCodeExecutablePath = resolveOpenCodeExecutable(searchPath: launcherEnvironment["PATH"]) else { | |
| throw CLIError(message: "Required agent executable not found. Install the agent CLI and retry.") | |
| } | |
| launcherEnvironment["PATH"] = providerExecutableSearchPath( | |
| searchPath: launcherEnvironment["PATH"], | |
| includingExecutableAt: openCodeExecutablePath | |
| ) | |
| try omoSlimEnsurePlugin(processEnvironment: launcherEnvironment) |
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!
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Sources/RestorableAgentSession.swift (1)
432-444: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFourth hardcoded copy of the omo-family launcher list.
openCodeVersionProbenow independently lists"omo", "omo-slim", "omos"to skip the version probe, mirroring the same set already owned byAgentLaunchCaptureTrust.wrapperLaunchersByKind["opencode"]. As per path instructions ("flag... more than one disagreeing source of truth for the same fact"), consider checkingAgentLaunchCaptureTrust.launcherDescribesKind(launchCommand?.launcher, kind: "opencode")here as well so all four call sites (this one,AgentForkSupport.swift,ContentView.swift, and the CLI diagnostics file) stay in sync automatically.🤖 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/RestorableAgentSession.swift` around lines 432 - 444, openCodeVersionProbe currently hardcodes the omo-family launcher names, creating a duplicate source of truth for the opencode launcher set. Update this switch to rely on AgentLaunchCaptureTrust.launcherDescribesKind(launchCommand?.launcher, kind: "opencode") instead of matching "omo", "omo-slim", and "omos" directly, so the version-probe skip logic stays aligned with the existing wrapperLaunchersByKind definition and the other call sites remain in sync.Source: Path instructions
🤖 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 `@CLI/CMUXCLI`+SessionsListForkDiagnostics.swift:
- Line 367: The omo-family launcher check is duplicated across multiple places
and should use one shared source of truth. Extract the launcher aliases into a
shared Set<String> constant such as OMOFamilyLaunchers, then update the
launchCommand checks in CMUXCLI+SessionsListForkDiagnostics and the related
identity checks in AgentForkSupport and RestorableAgentSession to use that
constant instead of repeated string comparisons. Keep the behavior identical
while centralizing the launcher detection logic.
---
Outside diff comments:
In `@Sources/RestorableAgentSession.swift`:
- Around line 432-444: openCodeVersionProbe currently hardcodes the omo-family
launcher names, creating a duplicate source of truth for the opencode launcher
set. Update this switch to rely on
AgentLaunchCaptureTrust.launcherDescribesKind(launchCommand?.launcher, kind:
"opencode") instead of matching "omo", "omo-slim", and "omos" directly, so the
version-probe skip logic stays aligned with the existing wrapperLaunchersByKind
definition and the other call sites remain in sync.
🪄 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: ac462bec-dd32-4a89-9698-2e2241ec063a
📒 Files selected for processing (19)
CLI/CMUXCLI+CommandSuggestions.swiftCLI/CMUXCLI+SessionsListForkDiagnostics.swiftCLI/cmux.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentForkArgv.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchCaptureTrust.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentResumeArgv.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentForkArgvTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchCaptureTrustTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentResumeArgvTests.swiftResources/Localizable.xcstringsSources/AgentForkSupport.swiftSources/ContentView.swiftSources/RestorableAgentSession.swiftSources/TaskManagerTypes.swiftSources/TextBoxAgentDetection.swiftdaemon/remote/cmd/cmuxd-remote/agent_launch.godaemon/remote/cmd/cmuxd-remote/agent_launch_test.godaemon/remote/cmd/cmuxd-remote/cli.go
| return (true, "available") | ||
| } | ||
| if launchCommand?.launcher == "omo" { | ||
| if launchCommand?.launcher == "omo" || launchCommand?.launcher == "omo-slim" || launchCommand?.launcher == "omos" { |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Consider extracting the omo-family launcher set into a shared constant.
The launcher == "omo" || launcher == "omo-slim" || launcher == "omos" pattern is now duplicated across at least AgentForkSupport.swift, RestorableAgentSession.swift, and this file. A single shared Set<String> constant (e.g., OMOFamilyLaunchers) would serve as the authoritative source and prevent future drift when a new alias is added to one location but not all.
As per coding guidelines, the same behavior should not be wired separately through multiple surfaces instead of one shared path. As per path instructions, correctness-critical identity detection should use a reliable, structured source of truth rather than scattered heuristics.
♻️ Suggested shared constant
// In a shared location, e.g. CMUXAgentLaunch or a common constants file:
static let omoFamilyLaunchers: Set<String> = ["omo", "omo-slim", "omos"]
// Then at each call site:
- if launchCommand?.launcher == "omo" || launchCommand?.launcher == "omo-slim" || launchCommand?.launcher == "omos" {
+ if let launcher = launchCommand?.launcher, Self.omoFamilyLaunchers.contains(launcher) {
return (true, "available")
}🤖 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 `@CLI/CMUXCLI`+SessionsListForkDiagnostics.swift at line 367, The omo-family
launcher check is duplicated across multiple places and should use one shared
source of truth. Extract the launcher aliases into a shared Set<String> constant
such as OMOFamilyLaunchers, then update the launchCommand checks in
CMUXCLI+SessionsListForkDiagnostics and the related identity checks in
AgentForkSupport and RestorableAgentSession to use that constant instead of
repeated string comparisons. Keep the behavior identical while centralizing the
launcher detection logic.
Sources: Coding guidelines, Path instructions
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Sources/RestorableAgentSession.swift (1)
432-444: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winConsider routing through the canonical launcher-kind helper here too.
This switch adds
"omo-slim"to a fourth independent enumeration of the omo/omo-slim/omos triplet (alongsideAgentForkSupport.swift,ContentView.swift, andCLI/CMUXCLI+SessionsListForkDiagnostics.swift). The behavior is correct, but centralizing viaAgentLaunchCaptureTrust's launcher-kind helper would prevent a future omo variant from being missed in one of these spots.Based on path instructions ("Apply
.github/review-bot-rules/reliability-single-source-of-truth.md... flag... more than one disagreeing source of truth for the same fact").🤖 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/RestorableAgentSession.swift` around lines 432 - 444, The launcher check in openCodeVersionProbe is duplicating the omo/omo-slim/omos classification and can drift from the other call sites. Update this switch to route through AgentLaunchCaptureTrust’s canonical launcher-kind helper instead of matching launcher strings directly, and keep the existing nil behavior for the omo family and omx/omc while letting the helper be the single source of truth.Source: Path instructions
♻️ Duplicate comments (1)
CLI/CMUXCLI+SessionsListForkDiagnostics.swift (1)
367-367: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winDuplicate concern: omo-family launcher set should be shared.
This was already flagged in a prior review comment (c9acb673). The
launcher == "omo" || launcher == "omo-slim" || launcher == "omos"pattern remains duplicated acrossAgentForkSupport.swift,RestorableAgentSession.swift, and this file. Extracting a sharedSet<String>constant would prevent future drift when a new alias is added to one location but not all.As per coding guidelines, the same behavior should not be wired separately through multiple surfaces instead of one shared path. As per path instructions, correctness-critical identity detection should use a reliable, structured source of truth rather than scattered heuristics.
🤖 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 `@CLI/CMUXCLI`+SessionsListForkDiagnostics.swift at line 367, The omo-family launcher check is duplicated across multiple places and should be centralized into one shared source of truth. Replace the repeated `launcher == "omo" || launcher == "omo-slim" || launcher == "omos"` logic with a shared `Set<String>` constant or helper used by `AgentForkSupport`, `RestorableAgentSession`, and `CMUXCLI+SessionsListForkDiagnostics` so all identity checks stay consistent and future aliases only need to be updated once.Sources: Coding guidelines, Path instructions, Learnings
🤖 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 `@daemon/remote/cmd/cmuxd-remote/agent_launch_test.go`:
- Around line 65-84: The test
TestOmoSlimEnsurePluginConfiguresShadowTmuxMultiplexer mutates the process
environment by calling omoSlimEnsurePlugin and then asserting
OPENCODE_CONFIG_DIR, so it can leak state into later tests. Update the test to
register and restore OPENCODE_CONFIG_DIR with t.Setenv before invoking
omoSlimEnsurePlugin, using the same shadow directory from omoSlimShadowConfigDir
to keep the environment isolated for the rest of the package tests.
In `@daemon/remote/cmd/cmuxd-remote/agent_launch.go`:
- Around line 891-897: configureOMOSlimPlugin currently ignores failures when
replacing the symlink, marshaling slimConfig, or writing the slim JSON, so make
those operations return errors instead of being silently skipped. In the
needsWrite block, handle the Readlink/Remove path carefully, capture and
propagate any json.MarshalIndent and os.WriteFile errors, and ensure the
function returns a failure when updating oh-my-opencode-slim.json does not
complete successfully. Use the existing configureOMOSlimPlugin flow and
configPath/muxConfig handling to locate the fix.
- Around line 145-153: The OPENCODE_PORT setup in agent_launch.go is using the
default port even when openCodeRelayLaunchArgs preserves an explicit --port
value. Update the launch flow around openCodeRelayLaunchArgs and
resolveNodeScriptExec to derive the effective port from the passed args first
(including both --port and --port= forms), then fall back to the existing
OPENCODE_PORT env var, and only then to openCodeRelayDefaultPort so the
environment matches the launched process.
---
Outside diff comments:
In `@Sources/RestorableAgentSession.swift`:
- Around line 432-444: The launcher check in openCodeVersionProbe is duplicating
the omo/omo-slim/omos classification and can drift from the other call sites.
Update this switch to route through AgentLaunchCaptureTrust’s canonical
launcher-kind helper instead of matching launcher strings directly, and keep the
existing nil behavior for the omo family and omx/omc while letting the helper be
the single source of truth.
---
Duplicate comments:
In `@CLI/CMUXCLI`+SessionsListForkDiagnostics.swift:
- Line 367: The omo-family launcher check is duplicated across multiple places
and should be centralized into one shared source of truth. Replace the repeated
`launcher == "omo" || launcher == "omo-slim" || launcher == "omos"` logic with a
shared `Set<String>` constant or helper used by `AgentForkSupport`,
`RestorableAgentSession`, and `CMUXCLI+SessionsListForkDiagnostics` so all
identity checks stay consistent and future aliases only need to be updated once.
🪄 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: 02062a05-d25c-49d8-ac11-2e45caf0fcb3
📒 Files selected for processing (19)
CLI/CMUXCLI+CommandSuggestions.swiftCLI/CMUXCLI+SessionsListForkDiagnostics.swiftCLI/cmux.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentForkArgv.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchCaptureTrust.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentResumeArgv.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentForkArgvTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchCaptureTrustTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentResumeArgvTests.swiftResources/Localizable.xcstringsSources/AgentForkSupport.swiftSources/ContentView.swiftSources/RestorableAgentSession.swiftSources/TaskManagerTypes.swiftSources/TextBoxAgentDetection.swiftdaemon/remote/cmd/cmuxd-remote/agent_launch.godaemon/remote/cmd/cmuxd-remote/agent_launch_test.godaemon/remote/cmd/cmuxd-remote/cli.go
30a17b3 to
c60b081
Compare
c60b081 to
c300f6d
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (3)
daemon/remote/cmd/cmuxd-remote/agent_launch.go (2)
145-153: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
OPENCODE_PORTstill diverges from an explicit--port.When the user passes
--port 5010withOPENCODE_PORTunset, Line 147 exports the variant default (e.g.4097) whileopenCodeRelayLaunchArgspreserves5010, so plugin/background code reads a different port than the launched OpenCode process. Derive the effective port fromargsfirst, then the env var, then the default.🤖 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 `@daemon/remote/cmd/cmuxd-remote/agent_launch.go` around lines 145 - 153, The port selection in agent_launch.go is inconsistent because OPENCODE_PORT is being set from cfg.defaultPort before the explicit --port value is considered, while openCodeRelayLaunchArgs uses the user-provided port. Update the launch flow in the agent launch path so the effective port is resolved from args first, then the existing OPENCODE_PORT, then the default, and use that same resolved value both for setting OPENCODE_PORT and for building launchArgs via openCodeRelayLaunchArgs so the relay and launched process stay in sync.
891-897: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winPropagate slim config write failures.
configureOMOSlimPluginstill ignores errors fromos.Remove,json.MarshalIndent, andos.WriteFile, so it can report success while leavingoh-my-opencode-slim.jsonwithout the requiredmultiplexer.type = "tmux"config.🛡️ Proposed fix
if needsWrite { slimConfig["multiplexer"] = muxConfig if target, err := os.Readlink(configPath); err == nil && target != "" { - os.Remove(configPath) + if err := os.Remove(configPath); err != nil { + return fmt.Errorf("replace symlinked omo-slim config: %w", err) + } } - data, _ := json.MarshalIndent(slimConfig, "", " ") - os.WriteFile(configPath, data, 0644) + data, err := json.MarshalIndent(slimConfig, "", " ") + if err != nil { + return fmt.Errorf("marshal omo-slim config: %w", err) + } + if err := os.WriteFile(configPath, data, 0644); err != nil { + return fmt.Errorf("write omo-slim config: %w", err) + } }🤖 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 `@daemon/remote/cmd/cmuxd-remote/agent_launch.go` around lines 891 - 897, The configureOMOSlimPlugin flow is swallowing failures from os.Remove, json.MarshalIndent, and os.WriteFile, so update the needsWrite branch to handle and return these errors instead of ignoring them. Use the existing configPath, slimConfig, and muxConfig logic in configureOMOSlimPlugin, and make sure any failure while removing the old file, marshaling the updated config, or writing oh-my-opencode-slim.json is propagated back to the caller so the tmux multiplexer setting is not reported as applied unless it was actually persisted.daemon/remote/cmd/cmuxd-remote/agent_launch_test.go (1)
65-119: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRestore
OPENCODE_CONFIG_DIRafter this test.
omoSlimEnsurePluginmutates the process env viaos.Setenv("OPENCODE_CONFIG_DIR", ...), so this test can leak that value into later package tests. Register it witht.Setenv("OPENCODE_CONFIG_DIR", "")before invoking the helper so it is restored on cleanup.🤖 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 `@daemon/remote/cmd/cmuxd-remote/agent_launch_test.go` around lines 65 - 119, This test leaks the OPENCODE_CONFIG_DIR process environment because omoSlimEnsurePlugin sets it internally and it is never restored. In TestOmoSlimEnsurePluginConfiguresShadowTmuxMultiplexer, register OPENCODE_CONFIG_DIR with t.Setenv before calling omoSlimEnsurePlugin so cleanup resets it automatically, keeping later tests isolated; use the existing omoSlimEnsurePlugin and omoSlimShadowConfigDir symbols to locate the setup.
🤖 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 `@CLI/cmux.swift`:
- Around line 22449-22456: The parse-failure message in the config-loading
branch is inconsistent with the genericized `omoEnsurePlugin` message because it
still interpolates `userJsonURL.path`. Update the `JSONSerialization` failure
path in this config parsing logic to match the same generic `"Failed to parse
launcher config. Fix the JSON syntax and retry."` wording used by
`omoEnsurePlugin`, keeping the message consistent across both code paths.
- Around line 15502-15523: The top-level help output in usage() is missing the
new omo-slim/omos launcher even though the subcommand help exists in the
cmux.swift switch. Update the main usage list to include a matching entry for
omo-slim and its alias omos alongside the existing omo, omx, and omc entries so
cmux --help surfaces the new command; use the existing usage() function and the
new case label strings as the identifiers to locate the right spot.
In `@Sources/TaskManagerTypes.swift`:
- Around line 578-581: The TaskManagerTypes launcher detection entry is missing
the literal "omo-slim" token in argumentNeedles, so add it alongside the
existing opencode/omo aliases in the same initializer to keep indirect
invocation detection consistent with directBasenames and the claude/omc pattern.
---
Duplicate comments:
In `@daemon/remote/cmd/cmuxd-remote/agent_launch_test.go`:
- Around line 65-119: This test leaks the OPENCODE_CONFIG_DIR process
environment because omoSlimEnsurePlugin sets it internally and it is never
restored. In TestOmoSlimEnsurePluginConfiguresShadowTmuxMultiplexer, register
OPENCODE_CONFIG_DIR with t.Setenv before calling omoSlimEnsurePlugin so cleanup
resets it automatically, keeping later tests isolated; use the existing
omoSlimEnsurePlugin and omoSlimShadowConfigDir symbols to locate the setup.
In `@daemon/remote/cmd/cmuxd-remote/agent_launch.go`:
- Around line 145-153: The port selection in agent_launch.go is inconsistent
because OPENCODE_PORT is being set from cfg.defaultPort before the explicit
--port value is considered, while openCodeRelayLaunchArgs uses the user-provided
port. Update the launch flow in the agent launch path so the effective port is
resolved from args first, then the existing OPENCODE_PORT, then the default, and
use that same resolved value both for setting OPENCODE_PORT and for building
launchArgs via openCodeRelayLaunchArgs so the relay and launched process stay in
sync.
- Around line 891-897: The configureOMOSlimPlugin flow is swallowing failures
from os.Remove, json.MarshalIndent, and os.WriteFile, so update the needsWrite
branch to handle and return these errors instead of ignoring them. Use the
existing configPath, slimConfig, and muxConfig logic in configureOMOSlimPlugin,
and make sure any failure while removing the old file, marshaling the updated
config, or writing oh-my-opencode-slim.json is propagated back to the caller so
the tmux multiplexer setting is not reported as applied unless it was actually
persisted.
🪄 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: 60b3fa14-f02e-4e0f-816f-f05ac83b5f62
📒 Files selected for processing (19)
CLI/CMUXCLI+CommandSuggestions.swiftCLI/CMUXCLI+SessionsListForkDiagnostics.swiftCLI/cmux.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentForkArgv.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchCaptureTrust.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swiftPackages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentResumeArgv.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentForkArgvTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchCaptureTrustTests.swiftPackages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentResumeArgvTests.swiftResources/Localizable.xcstringsSources/AgentForkSupport.swiftSources/ContentView.swiftSources/RestorableAgentSession.swiftSources/TaskManagerTypes.swiftSources/TextBoxAgentDetection.swiftdaemon/remote/cmd/cmuxd-remote/agent_launch.godaemon/remote/cmd/cmuxd-remote/agent_launch_test.godaemon/remote/cmd/cmuxd-remote/cli.go
c300f6d to
b74e2c9
Compare
…nd help - TaskManagerTypes: add the literal 'omo-slim' token to argumentNeedles so the slim launcher is detected when invoked indirectly (matching the claude entry which lists its 'omc' alias). - cmux.swift usage(): list 'omo-slim (alias: omos)' in the top-level command list so 'cmux --help' surfaces the new launcher.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a809253. Configure here.
| installedLabel: "oh-my-opencode-slim plugin installed", | ||
| installFailLabel: "failed to install oh-my-opencode-slim", | ||
| }) | ||
| } |
There was a problem hiding this comment.
Remote slim omits session plugin
Medium Severity
macOS omoSlimEnsurePlugin writes plugins/cmux-session.js into the slim shadow config, but remote omoSlimEnsurePlugin only uses ensureOpencodePlugin and never creates that file. Remote cmux omo-slim / cmux omos therefore miss the cmux OpenCode session bridge that the local launcher installs.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit a809253. Configure here.
|
Superseded by #8165. OMO Slim 2.2.x now provides native cmux pane integration, so the replacement PR removes the tmux shim and shadow-config approach while retaining first-class launcher, remote, resume, fork, and agent-detection support. |


Summary
cmux omo-slimandcmux omosas OpenCode launchers for oh-my-opencode-slimoh-my-opencode-slim, background subagents, andmultiplexer.type = "tmux"terminal-notifiercalls throughcmux notify, matching the existing OMO integrationVerification
go test ./cmd/cmuxd-remotefromdaemon/remotegit diff --checkpython3 -m json.tool Resources/Localizable.xcstringsswiftc -parseon all modified Swift filesNot run
swift testforPackages/macOS/CMUXAgentLaunchbecause this machine's CommandLineTools SwiftPM manifest link fails with an undefinedPackageDescription.Packagesymbol./scripts/reload.sh --tag omo-slimbecause this machine is missingzig(brew install zig)Note
Medium Risk
Touches agent launch, shadow config/plugin install, and session restore/fork across local CLI, app UI, and remote daemon; misconfiguration could break OpenCode sessions or mix OMO vs slim plugins.
Overview
Adds
cmux omo-slimand theomosalias to launch OpenCode with oh-my-opencode-slim in a cmux-aware setup: tmux shims route specialist panes to native splits,terminal-notifiergoes throughcmux notify, andOPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTSis enabled with a default port of 4097.A dedicated shadow OpenCode config installs
oh-my-opencode-slim, strips full OMO plugin entries, appliesmultiplexer.type = tmux(with layout defaults), and can read user JSONC slim config. Shared OMO install helpers are generalized (plugin name, manifest, JSON comment stripping).Resume, fork, and trust paths treat
omo,omo-slim, andomosas OpenCode session wrappers viaAgentLaunchCaptureTrust.launcherIsOpenCodeSessionWrapper, so fork support skips direct OpenCode version probes. The same launchers are wired through agent detection, task manager, CLI suggestions, localization, and the remotecmuxd-remoterelay (refactoredrunOpenCodeRelayfor OMO vs slim).Reviewed by Cursor Bugbot for commit a809253. Bugbot is set up for automated code reviews on this repo. Configure here.