Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5976,6 +5976,12 @@ struct ContentView: View {
panel.allowsMultipleSelection = false
panel.title = String(localized: "panel.openFolder.title", defaultValue: "Open Folder")
panel.prompt = String(localized: "panel.openFolder.prompt", defaultValue: "Open")
if let workspace = tabManager.selectedWorkspace {
let directory = workspace.currentDirectory.trimmingCharacters(in: .whitespacesAndNewlines)
if !directory.isEmpty, FileManager.default.fileExists(atPath: directory) {
panel.directoryURL = URL(fileURLWithPath: directory, isDirectory: true)
Comment on lines +5981 to +5982

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 Verify path is a directory, not just that it exists

FileManager.default.fileExists(atPath:) returns true for both files and directories. If workspace.currentDirectory ever resolves to a file path (e.g., due to a stale workspace record), the URL would still be set as isDirectory: true and passed to NSOpenPanel.directoryURL. Using the isDirectory: variant explicitly confirms the path is a directory before using it:

Suggested change
if !directory.isEmpty, FileManager.default.fileExists(atPath: directory) {
panel.directoryURL = URL(fileURLWithPath: directory, isDirectory: true)
if !directory.isEmpty, FileManager.default.fileExists(atPath: directory, isDirectory: &isDir), isDir.boolValue {

Full suggestion (requires adding var isDir: ObjCBool = false before the check):

if let workspace = tabManager.selectedWorkspace {
    let directory = workspace.currentDirectory.trimmingCharacters(in: .whitespacesAndNewlines)
    var isDir: ObjCBool = false
    if !directory.isEmpty, FileManager.default.fileExists(atPath: directory, isDirectory: &isDir), isDir.boolValue {
        panel.directoryURL = URL(fileURLWithPath: directory, isDirectory: true)
    }
}

Same pattern applies to the equivalent block in Sources/cmuxApp.swift.

}
}
if panel.runModal() == .OK, let url = panel.url {
tabManager.addWorkspace(workingDirectory: url.path)
}
Expand Down
6 changes: 6 additions & 0 deletions Sources/cmuxApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,12 @@ struct cmuxApp: App {
panel.allowsMultipleSelection = false
panel.title = String(localized: "menu.file.openFolder.panelTitle", defaultValue: "Open Folder")
panel.prompt = String(localized: "menu.file.openFolder.panelPrompt", defaultValue: "Open")
if let workspace = activeTabManager.selectedWorkspace {
let directory = workspace.currentDirectory.trimmingCharacters(in: .whitespacesAndNewlines)
if !directory.isEmpty, FileManager.default.fileExists(atPath: directory) {
panel.directoryURL = URL(fileURLWithPath: directory, isDirectory: true)
}
}
Comment on lines +596 to +601

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether `currentDirectory` is guaranteed to always be a directory.
# Expected: assignments/initialization sites should only use directory sources
# (workspace roots, cwd, validated directory paths).

rg -n --type swift -C4 '\b(var|let)\s+currentDirectory\b'
rg -n --type swift -C4 '\bcurrentDirectory\s*='
rg -n --type swift -C4 '\bcurrentDirectory\b.*(URL|path|cwd|workingDirectory)'

Repository: manaflow-ai/cmux

Length of output: 10968


Ensure panel.directoryURL is set only for actual directories.

At Line 598, the code checks only path existence. If workspace.currentDirectory is a file path, Line 599 still forces a directory URL and can open from an unexpected location instead of falling back to default behavior.

Proposed fix
                     if let workspace = activeTabManager.selectedWorkspace {
                         let directory = workspace.currentDirectory.trimmingCharacters(in: .whitespacesAndNewlines)
-                        if !directory.isEmpty, FileManager.default.fileExists(atPath: directory) {
+                        var isDirectory: ObjCBool = false
+                        if !directory.isEmpty,
+                           FileManager.default.fileExists(atPath: directory, isDirectory: &isDirectory),
+                           isDirectory.boolValue {
                             panel.directoryURL = URL(fileURLWithPath: directory, isDirectory: true)
                         }
                     }
📝 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
if let workspace = activeTabManager.selectedWorkspace {
let directory = workspace.currentDirectory.trimmingCharacters(in: .whitespacesAndNewlines)
if !directory.isEmpty, FileManager.default.fileExists(atPath: directory) {
panel.directoryURL = URL(fileURLWithPath: directory, isDirectory: true)
}
}
if let workspace = activeTabManager.selectedWorkspace {
let directory = workspace.currentDirectory.trimmingCharacters(in: .whitespacesAndNewlines)
var isDirectory: ObjCBool = false
if !directory.isEmpty,
FileManager.default.fileExists(atPath: directory, isDirectory: &isDirectory),
isDirectory.boolValue {
panel.directoryURL = URL(fileURLWithPath: directory, isDirectory: true)
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/cmuxApp.swift` around lines 596 - 601, The code sets
panel.directoryURL whenever the path exists but doesn't ensure it's a directory;
update the check around activeTabManager.selectedWorkspace ->
workspace.currentDirectory so you only set panel.directoryURL when the path both
exists and is a directory (use
FileManager.default.fileExists(atPath:isDirectory:) or equivalent to test
isDirectory and only assign to panel.directoryURL when isDirectory is true),
otherwise leave panel.directoryURL unset to allow default behavior.

if panel.runModal() == .OK, let url = panel.url {
if let appDelegate = AppDelegate.shared {
if appDelegate.addWorkspaceInPreferredMainWindow(
Expand Down
31 changes: 0 additions & 31 deletions docs/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,37 +54,6 @@ cmux notify --title "Done" --tab 0 --panel 1

## Integration Examples

### Claude Code Hooks

Add to `~/.claude/settings.json`:

```json
{
"hooks": {
"Notification": [
{
"matcher": "idle_prompt",
"hooks": [
{
"type": "command",
"command": "command -v cmux &>/dev/null && cmux notify --title 'Claude Code' --body 'Waiting for input' || osascript -e 'display notification \"Waiting for input\" with title \"Claude Code\"'"
}
]
},
{
"matcher": "permission_prompt",
"hooks": [
{
"type": "command",
"command": "command -v cmux &>/dev/null && cmux notify --title 'Claude Code' --subtitle 'Permission' --body 'Approval needed' || osascript -e 'display notification \"Approval needed\" with title \"Claude Code\"'"
}
]
}
]
}
}
```

### OpenAI Codex

Add to `~/.codex/config.toml`:
Expand Down