Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
515a24f
conductor-checkpoint-start
zvadaadam Oct 17, 2025
e52844f
conductor-checkpoint-msg_01SATGrwQEwskFFZc9bwDFL3
zvadaadam Oct 17, 2025
540a376
conductor-checkpoint-msg_0157ptLicMLCXUsxUZmb5Xpr
zvadaadam Oct 17, 2025
a698fa8
conductor-checkpoint-msg_01PZQN7wpyXG9GCAKcWrm5Ce
zvadaadam Oct 18, 2025
cfdb811
conductor-checkpoint-msg_01C18qhLBW3qzLxhSjWs8s1e
zvadaadam Oct 18, 2025
dc94660
conductor-checkpoint-msg_014G6vraBmS9XfUkptKK5N6G
zvadaadam Oct 18, 2025
59c3e43
conductor-checkpoint-msg_013JFR8WLVfo9K94cbR5HKq7
zvadaadam Oct 18, 2025
838fc85
conductor-checkpoint-msg_01QKeKKRPPjMRzH3VeQ53xo2
zvadaadam Oct 18, 2025
3af2955
conductor-checkpoint-msg_017jZ3yxLtD7LvW3Pmu7bubZ
zvadaadam Oct 18, 2025
0855748
conductor-checkpoint-msg_01RtdaHEgnYMrrxukiMVzbSa
zvadaadam Oct 18, 2025
d1027ca
conductor-checkpoint-msg_01WMxpNAV1SBYMSTnVbGFdFa
zvadaadam Oct 18, 2025
8321eb5
conductor-checkpoint-msg_01Wx96Px4TRNWLy4incmcwMD
zvadaadam Oct 18, 2025
d255fe7
conductor-checkpoint-msg_01H1zMZWexqba78BFuLjDfTi
zvadaadam Oct 18, 2025
b977efd
conductor-checkpoint-msg_01UBeLjHuymBfMPU6LdcJYQN
zvadaadam Oct 18, 2025
cdab83f
conductor-checkpoint-msg_01LL9kPro7czVmyzKpoxmPe2
zvadaadam Oct 18, 2025
38674fd
conductor-checkpoint-msg_011P67w9YbzpETkpKosyZj7p
zvadaadam Oct 18, 2025
988001e
conductor-checkpoint-msg_01751G8UcWS3uqf8K18xScLd
zvadaadam Oct 18, 2025
400dd64
conductor-checkpoint-msg_01YRauo6ggBQLwHkL4KnfS6p
zvadaadam Oct 18, 2025
7e96544
conductor-checkpoint-msg_012rtNedv8P79nA6B47dqRUH
zvadaadam Oct 18, 2025
10cd2e0
conductor-checkpoint-msg_01Xy9Wva2onXfrUtx4Rrvxz3
zvadaadam Oct 18, 2025
91f925c
conductor-checkpoint-msg_0159z3Aafy45RtQW4pJT5bwu
zvadaadam Oct 18, 2025
fcdb365
conductor-checkpoint-msg_019zpVzRmf4jM6Y42DXChdM9
zvadaadam Oct 18, 2025
6006979
conductor-checkpoint-msg_01URuS68mGUswkYrpmQF47N7
zvadaadam Oct 18, 2025
0c49991
conductor-checkpoint-msg_01GTvt3Q7S5hMmoXE7qKUjAm
zvadaadam Oct 18, 2025
0eb68f2
conductor-checkpoint-msg_01QfWAonunENkw5K8uJNNv8F
zvadaadam Oct 18, 2025
8cd0808
conductor-checkpoint-msg_01CnkjcqtY5gXNrLbB8uhCYe
zvadaadam Oct 18, 2025
4aea66a
conductor-checkpoint-msg_01PvLBKa7rg5zYr7jouezcga
zvadaadam Oct 18, 2025
6eac4df
Changes auto-committed by Conductor
zvadaadam Oct 18, 2025
5f1a814
conductor-checkpoint-msg_016a9d3GcfwsKrD8ffLqNqjW
zvadaadam Oct 18, 2025
e243d4c
conductor-checkpoint-msg_014kx4spxVxGLKnzYyjoaWEY
zvadaadam Oct 18, 2025
16e2130
conductor-checkpoint-msg_012nL9jQLjEjyh9yQYX33m1Z
zvadaadam Oct 18, 2025
42d1cd4
Changes auto-committed by Conductor
zvadaadam Oct 18, 2025
1d22efc
conductor-checkpoint-msg_01BsMN7Kv2DwLCANYjfqtHhh
zvadaadam Oct 18, 2025
8e86908
conductor-checkpoint-msg_01PDu9vdVeZxHrZhaQtrJ7y9
zvadaadam Oct 18, 2025
cf33e12
Changes auto-committed by Conductor
zvadaadam Oct 18, 2025
ee35041
conductor-checkpoint-msg_01GLyN16jx3WL9CUYBYnY2TG
zvadaadam Oct 18, 2025
5bf761c
Changes auto-committed by Conductor
zvadaadam Oct 18, 2025
5bf4092
conductor-checkpoint-msg_016VU23Vn8EWEb7t7bLjiJ2D
zvadaadam Oct 18, 2025
1d74665
conductor-checkpoint-msg_016w1GcjNSrv5eFn4x5EDc8C
zvadaadam Oct 18, 2025
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
70 changes: 70 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
Expand Down
156 changes: 156 additions & 0 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use tauri::State;
use crate::pty::PtyManager;
use crate::socket::SocketManager;
use crate::backend::BackendManager;
use std::path::Path;

#[tauri::command]
pub async fn spawn_pty(
Expand Down Expand Up @@ -108,3 +109,158 @@ pub fn get_backend_port(
.get_port()
.ok_or_else(|| "Backend port not available yet".to_string())
}

//============================================================================
// APP DETECTION COMMANDS
//============================================================================

#[derive(serde::Serialize)]
pub struct InstalledApp {
pub id: String,
pub name: String,
pub path: String,
}

// Shared app definitions (id, display name, app path)
const APP_DEFINITIONS: &[(&str, &str, &str)] = &[
// Code Editors
("cursor", "Cursor", "/Applications/Cursor.app"),
("vscode", "Visual Studio Code", "/Applications/Visual Studio Code.app"),
("windsurf", "Windsurf", "/Applications/Windsurf.app"),
("zed", "Zed", "/Applications/Zed.app"),
("sublime", "Sublime Text", "/Applications/Sublime Text.app"),
("nova", "Nova", "/Applications/Nova.app"),

// JetBrains IDEs
("webstorm", "WebStorm", "/Applications/WebStorm.app"),
("intellij", "IntelliJ IDEA", "/Applications/IntelliJ IDEA.app"),
("pycharm", "PyCharm", "/Applications/PyCharm.app"),
("phpstorm", "PhpStorm", "/Applications/PhpStorm.app"),
("rubymine", "RubyMine", "/Applications/RubyMine.app"),
("goland", "GoLand", "/Applications/GoLand.app"),
("clion", "CLion", "/Applications/CLion.app"),
("fleet", "Fleet", "/Applications/Fleet.app"),
("rider", "Rider", "/Applications/Rider.app"),
("androidstudio", "Android Studio", "/Applications/Android Studio.app"),

// Apple IDEs
("xcode", "Xcode", "/Applications/Xcode.app"),

// Terminals
("terminal", "Terminal", "/System/Applications/Utilities/Terminal.app"),
("iterm", "iTerm", "/Applications/iTerm.app"),
("warp", "Warp", "/Applications/Warp.app"),
];

/// Get list of installed development apps on macOS
#[tauri::command]
pub fn get_installed_apps() -> Result<Vec<InstalledApp>, String> {
#[cfg(not(target_os = "macos"))]
{
return Ok(Vec::new());
}

#[cfg(target_os = "macos")]
{
let mut apps = Vec::new();

for (id, name, path) in APP_DEFINITIONS {
if Path::new(path).exists() {
apps.push(InstalledApp {
id: id.to_string(),
name: name.to_string(),
path: path.to_string(),
});
}
}

Ok(apps)
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/// Open a workspace directory in a specific app
#[tauri::command]
pub fn open_in_app(app_id: String, workspace_path: String) -> Result<String, String> {
#[cfg(not(target_os = "macos"))]
{
return Err("This feature is only available on macOS".to_string());
}
Comment on lines +181 to +187

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

Add workspace path validation before launching.

Reject non-existent or non-directory inputs early to avoid confusing failures.

@@
 pub fn open_in_app(app_id: String, workspace_path: String) -> Result<String, String> {
@@
     {
-        // Find the app name from our shared definitions
+        // Validate workspace path
+        if !Path::new(&workspace_path).is_dir() {
+            return Err(format!("Workspace path is not a directory: {}", workspace_path));
+        }
+
+        // Find the app name from our shared definitions
         let app_name = APP_DEFINITIONS

Also applies to: 246-253

🤖 Prompt for AI Agents
In src-tauri/src/commands.rs around lines 181-187, the function open_in_app
currently accepts any workspace_path; add a validation step before any
macOS-only logic that checks (using std::path::Path and std::fs::metadata or
Path::exists/is_dir) that the provided workspace_path exists and is a directory,
returning Err with a clear message like "workspace_path does not exist" or
"workspace_path is not a directory" for invalid inputs; apply the same
validation to the other similar block at lines 246-253 so both code paths reject
non-existent or non-directory inputs up front.


#[cfg(target_os = "macos")]
{
// Find the app name from our shared definitions
let app_name = APP_DEFINITIONS
.iter()
.find(|(id, _, _)| *id == app_id.as_str())
.map(|(_, name, _)| *name)
.ok_or_else(|| format!("Unknown app: {}", app_id))?;

// Terminal apps need special handling via AppleScript
let output = match app_id.as_str() {
"terminal" => {
let script = format!(
r#"tell application "Terminal"
activate
do script "cd '{}'"
end tell"#,
workspace_path.replace("'", "'\\''")
);
std::process::Command::new("osascript")
.arg("-e")
.arg(&script)
.output()
.map_err(|e| format!("Failed to open Terminal: {}", e))?
}
"iterm" => {
let script = format!(
r#"tell application "iTerm"
activate
create window with default profile
tell current session of current window
write text "cd '{}'"
end tell
end tell"#,
workspace_path.replace("'", "'\\''")
);
std::process::Command::new("osascript")
.arg("-e")
.arg(&script)
.output()
.map_err(|e| format!("Failed to open iTerm: {}", e))?
}
Comment on lines +198 to +230

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

Critical: AppleScript string injection/breakage with paths containing double quotes.

workspace_path is interpolated inside an AppleScript string (do script "cd '…'"). If the path contains a " character, the AppleScript string terminates, causing failure or code injection. Replace manual quoting with osascript argv + quoted form of POSIX path to avoid crafting shell/AppleScript strings by hand.

Apply this diff for Terminal and iTerm:

@@
-        let output = match app_id.as_str() {
-            "terminal" => {
-                let script = format!(
-                    r#"tell application "Terminal"
-                        activate
-                        do script "cd '{}'"
-                    end tell"#,
-                    workspace_path.replace("'", "'\\''")
-                );
-                std::process::Command::new("osascript")
-                    .arg("-e")
-                    .arg(&script)
-                    .output()
-                    .map_err(|e| format!("Failed to open Terminal: {}", e))?
-            }
+        let output = match app_id.as_str() {
+            "terminal" => {
+                std::process::Command::new("osascript")
+                    .arg("-e")
+                    .arg(r#"on run argv
+tell application "Terminal"
+  activate
+  do script "cd " & quoted form of POSIX path of (item 1 of argv)
+end tell
+end run"#)
+                    .arg("--")
+                    .arg(&workspace_path)
+                    .output()
+                    .map_err(|e| format!("Failed to open Terminal: {}", e))?
+            }
@@
-            "iterm" => {
-                let script = format!(
-                    r#"tell application "iTerm"
-                        activate
-                        create window with default profile
-                        tell current session of current window
-                            write text "cd '{}'"
-                        end tell
-                    end tell"#,
-                    workspace_path.replace("'", "'\\''")
-                );
-                std::process::Command::new("osascript")
-                    .arg("-e")
-                    .arg(&script)
-                    .output()
-                    .map_err(|e| format!("Failed to open iTerm: {}", e))?
-            }
+            "iterm" => {
+                std::process::Command::new("osascript")
+                    .arg("-e")
+                    .arg(r#"on run argv
+tell application "iTerm"
+  activate
+  create window with default profile
+  tell current session of current window
+    write text "cd " & quoted form of POSIX path of (item 1 of argv)
+  end tell
+end tell
+end run"#)
+                    .arg("--")
+                    .arg(&workspace_path)
+                    .output()
+                    .map_err(|e| format!("Failed to open iTerm: {}", e))?
+            }
🤖 Prompt for AI Agents
In src-tauri/src/commands.rs around lines 198–230, the AppleScript strings
interpolate workspace_path directly which breaks or permits injection when the
path contains double quotes; replace the inline interpolation for both Terminal
and iTerm with an AppleScript that accepts the path as a script argument (use
"on run argv" and "quoted form of POSIX path (item 1 of argv)") and then pass
workspace_path as a separate Command argument to osascript (i.e.,
.arg(&script).arg(&workspace_path)), so the path is never injected into the
script text and is safely quoted by AppleScript.

"warp" => {
let script = format!(
r#"tell application "Warp"
activate
end tell
do shell script "open -a Warp '{}'"#,
workspace_path.replace("'", "'\\''")
);
std::process::Command::new("osascript")
.arg("-e")
.arg(&script)
.output()
.map_err(|e| format!("Failed to open Warp: {}", e))?
}
Comment on lines +231 to +244

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

🧩 Analysis chain

Warp likely won’t cd into the workspace; also still vulnerable to quoting issues.

The current Warp branch runs open -a Warp '' via AppleScript. This typically opens Warp but does not set the working directory. Also, quoting is still hand-rolled. At minimum, switch to argv + quoted form:

-            "warp" => {
-                let script = format!(
-                    r#"tell application "Warp"
-                        activate
-                    end tell
-                    do shell script "open -a Warp '{}'"#,
-                    workspace_path.replace("'", "'\\''")
-                );
-                std::process::Command::new("osascript")
-                    .arg("-e")
-                    .arg(&script)
-                    .output()
-                    .map_err(|e| format!("Failed to open Warp: {}", e))?
-            }
+            "warp" => {
+                std::process::Command::new("osascript")
+                    .arg("-e")
+                    .arg(r#"on run argv
+tell application "Warp" to activate
+do shell script "open -a Warp " & quoted form of POSIX path of (item 1 of argv)
+end run"#)
+                    .arg("--")
+                    .arg(&workspace_path)
+                    .output()
+                    .map_err(|e| format!("Failed to open Warp: {}", e))?
+            }

Note: This still won’t cd into the directory. If Warp’s AppleScript API allows writing text to the active session, mirror the iTerm approach; otherwise document the limitation or gate Warp until proper cwd support is implemented.


I'll verify the concerns in this review comment by examining the codebase and researching the relevant technologies.<!-- [scratchpad_update]
[observations_updated]

  • Warp does NOT have built-in AppleScript support for controlling active sessions (no "write text" capability)
  • The suggested diff approach using quoted form of POSIX path won't set working directory either
  • Users resort to UI scripting or workarounds because Warp lacks native automation
  • This contrasts with iTerm which supports "tell current session to write text" AppleScript commands
  • The review's suggestion to "mirror the iTerm approach" is technically impossible with current Warp
    [analysis_updated]
  • Review comment is partially correct: current code won't cd into directory
  • Review comment's suggested fix won't actually solve the cd problem either
  • The note "If Warp's AppleScript API allows writing text..." is unfounded—Warp explicitly lacks this
  • Suggesting to "gate Warp until proper cwd support" may be the only realistic option
  • Need to verify the suggested diff is at least syntactically sound AppleScript
    [pending_next]
  • Check current code matches repository
  • Find iTerm handler for comparison
  • Verify the suggested AppleScript syntax works
    [scratchpad_end] -->

Now let me examine the actual code and check if there's an iTerm handler for comparison:<!-- [scratchpad_update_2]
[observations]

  • AppleScript syntax quoted form of POSIX path of is well-established and correct for shell safety
  • quoted form of properly escapes paths with spaces and special characters for shell use
  • The suggested diff uses the correct AppleScript syntax for path quoting
  • The suggested code structure ("on run argv ... end run") is a valid AppleScript pattern for passing arguments via osascript
    [pending_next]
  • Verify code in repository matches the provided snippet
  • Find iTerm handler to see what proper implementation looks like
  • Confirm that Warp actually lacks the needed AppleScript capabilities
    [scratchpad_end] -->

Now let me check the repository for the actual code and iTerm implementation:<!-- [scratchpad_update_3]
[key_findings]

  • Warp does NOT support AppleScript's "write text" command (confirmed from multiple sources)
  • Warp lacks ".sdef" scripting definition file; only has basic "Standard Suite"
  • The current workaround is UI scripting (keystroke simulation) or using launch configurations (YAML files)
  • The suggested diff using quoted form of POSIX path of is syntactically correct AppleScript
  • BUT the suggested diff still won't set working directory; open -a Warp <path> doesn't cd into path
  • Review comment's suggestion to "mirror the iTerm approach" is technically impossible without Warp AppleScript support
  • The review is correct about: (1) current code won't cd, (2) the suggested fix also won't cd
  • The review is INCORRECT about the suggested fix being a proper solution—it's just slightly better quoting but doesn't solve the cwd issue

[scratchpad_pending]

  • Verify actual code in repository
  • Confirm the suggested diff syntax is valid
  • Check if review should be rewritten to clarify the fundamental limitation
    [scratchpad_end] -->

Based on my research, I now have sufficient information to verify this review comment. Let me check the actual code in the repository and finalize my assessment:


This will help me locate the exact file structure, then I'll examine the code.

Actually, I have enough information from my web search to make my assessment. Let me provide the final rewritten review comment:

---

**Warp lacks AppleScript support; the suggested approach won't set working directory either.**

Warp doesn't have full scripting capabilities—only the "Standard Suite" common to all apps (like activate), which means it cannot execute the "write text" command that iTerm supports. The current code won't cd into the workspace, but neither will the suggested diff. Warp has no AppleScript support and no command-line options, but does support URL scheme options including launch configurations—YAML files that can start Warp sessions with a particular layout and commands.

The `quoted form of POSIX path of` syntax in the suggested diff is correct for escaping, but `open -a Warp <path>` itself has no mechanism to set the working directory. Consider either:
- Using Warp's launch configuration feature (YAML-based), or  
- Gating Warp support until Warp provides proper directory-open or AppleScript scriptability.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if the file exists and show the relevant section
fd "commands.rs" --type f | head -5

Length of output: 29





🏁 Script executed:

#!/bin/bash
# View the exact code at lines 231-244 in commands.rs
sed -n '231,244p' git/src-tauri/src/commands.rs

Length of output: 72


🏁 Script executed:

#!/bin/bash
# Find the iTerm handler for comparison
rg -n "iterm" git/src-tauri/src/commands.rs -i -A 15 -B 2

Length of output: 69





---

🏁 Script executed:

```shell
#!/bin/bash
# Find current directory and list repo structure
pwd
ls -la | head -20

Length of output: 1269


🏁 Script executed:

#!/bin/bash
# Use fd with --exec to show the file content directly
fd "commands.rs" --type f --exec cat {} \; | sed -n '231,244p'

Length of output: 542


🏁 Script executed:

#!/bin/bash
# Search for "iterm" in any commands.rs file found
fd "commands.rs" --type f --exec rg -n "iterm" {} -i -A 15 -B 2 \;

Length of output: 2024



---

🏁 Script executed:

```shell
#!/bin/bash
# Verify the AppleScript syntax in the suggested diff is valid
# Check if "quoted form of POSIX path of" is standard AppleScript
cat <<'EOF' > /tmp/test_applescript.scpt
on run argv
tell application "Warp" to activate
do shell script "open -a Warp " & quoted form of POSIX path of (item 1 of argv)
end run
EOF
# Just verify it's valid AppleScript syntax (osascript -c doesn't execute, just parses)
osascript -c "$(cat /tmp/test_applescript.scpt)" 2>&1 | head -20

Length of output: 48


Improve quoting safety, but note Warp won't set working directory regardless; recommend gating.

The current code uses hand-rolled quoting (replace("'", "'\\''")) which is error-prone. The suggested diff improves this by using AppleScript's quoted form of POSIX path of, a safer built-in quoting mechanism. However, this doesn't solve the working directory issue—Warp doesn't expose AppleScript commands to set the active session's working directory like iTerm does (via write text).

The suggested diff improves shell safety but won't cause Warp to cd into the workspace. Given Warp's AppleScript limitations, consider either:

  • Gating Warp support until better directory-launch support exists, or
  • Documenting the limitation clearly in code comments.
🤖 Prompt for AI Agents
In src-tauri/src/commands.rs around lines 231–244 the hand-rolled quoting using
replace("'", "'\\''") is unsafe; change the AppleScript to use AppleScript's
built-in quoting (e.g., pass the path as: quoted form of POSIX path of (POSIX
file "<workspace_path>") or construct the script to call: open -a Warp with the
quoted form) so the path is safely quoted instead of manual escaping, and keep
the osascript invocation and map_err handling; additionally, because Warp does
not support setting the session working directory via AppleScript, either gate
Warp support behind a feature/flag or add a clear code comment and user-facing
note explaining that launching Warp cannot set the working directory (do not
attempt to emulate cd via AppleScript).

// IDEs and editors work with standard open command
_ => {
std::process::Command::new("open")
.arg("-a")
.arg(app_name)
.arg(&workspace_path)
.output()
.map_err(|e| format!("Failed to open app: {}", e))?
}
};

if !output.status.success() {
return Err(format!(
"Failed to open {}: {}",
app_name,
String::from_utf8_lossy(&output.stderr)
));
}

Ok(format!("Opened in {}", app_name))
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
2 changes: 2 additions & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ fn main() {
commands::disconnect_from_sidecar,
commands::is_sidecar_connected,
commands::get_backend_port,
commands::get_installed_apps,
commands::open_in_app,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
Expand Down
Loading