From 0f31b429ad7a9bf8ff62ef49bd93e0b92e0fcc7e Mon Sep 17 00:00:00 2001 From: Ethan Date: Tue, 10 Mar 2026 08:29:48 -0700 Subject: [PATCH 1/5] fix: correct VS Code --remote argument format for Remote SSH The path must be a separate argument, not concatenated with the host. `code --remote ssh-remote+HOST /path` instead of `--remote=ssh-remote+HOST/path`. Co-Authored-By: Claude Opus 4.6 --- src/cli/code.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cli/code.rs b/src/cli/code.rs index 347ea94..d41b432 100644 --- a/src/cli/code.rs +++ b/src/cli/code.rs @@ -199,9 +199,11 @@ fn launch_editor(editor: &str, ssh_host: &str, path: &str) -> Result<()> { println!("Opening {editor} → {ssh_host}:{path}"); - let remote_arg = format!("--remote=ssh-remote+{ssh_host}{path}"); + let remote_arg = format!("ssh-remote+{ssh_host}"); let status = std::process::Command::new(editor) + .arg("--remote") .arg(&remote_arg) + .arg(path) .status() .map_err(|e| anyhow::anyhow!("Failed to launch {editor}: {e}"))?; From 4a58b72e920c9457433dbdba2ab590b93e6adb0c Mon Sep 17 00:00:00 2001 From: Ethan Date: Tue, 10 Mar 2026 08:35:53 -0700 Subject: [PATCH 2/5] fix: rewrite Lima SSH Host line to match devbox host alias Lima outputs `Host lima-devbox-` but VS Code connects to `devbox-`. The mismatch caused "Could not resolve hostname" errors. Co-Authored-By: Claude Opus 4.6 --- src/cli/code.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/cli/code.rs b/src/cli/code.rs index d41b432..a2e6cb4 100644 --- a/src/cli/code.rs +++ b/src/cli/code.rs @@ -67,7 +67,9 @@ async fn open_via_lima( ); } - let ssh_config = result.stdout.trim().to_string(); + // Lima's output has its own Host line (e.g. "Host lima-devbox-test2"). + // Replace it with our ssh_host so VS Code can find the right config entry. + let ssh_config = rewrite_ssh_host(ssh_host, result.stdout.trim()); write_ssh_config(ssh_host, &ssh_config)?; launch_editor(editor, ssh_host, path) @@ -139,6 +141,21 @@ fn extract_incus_ip(json_output: &str) -> Result { bail!("Could not find IP address for Incus VM. Is it running?") } +/// Replace the `Host` line in an SSH config block with our desired host alias. +fn rewrite_ssh_host(desired_host: &str, config: &str) -> String { + config + .lines() + .map(|line| { + if line.trim_start().starts_with("Host ") { + format!("Host {desired_host}") + } else { + line.to_string() + } + }) + .collect::>() + .join("\n") +} + /// Write or update an SSH config block in ~/.ssh/config for the devbox host. fn write_ssh_config(host: &str, config_block: &str) -> Result<()> { let home = dirs::home_dir().ok_or_else(|| anyhow::anyhow!("Cannot determine home directory"))?; From 9c6bc493a4b4f6c87e42d4e33f1e0c42138d5bd0 Mon Sep 17 00:00:00 2001 From: Ethan Date: Tue, 10 Mar 2026 08:38:17 -0700 Subject: [PATCH 3/5] fix: enable nix-ld for VS Code Server / Cursor compatibility on NixOS NixOS can't run dynamically linked executables out of the box. programs.nix-ld provides the ld-linux shim so VS Code Remote SSH, Cursor, and similar tools can download and run their server binaries. Co-Authored-By: Claude Opus 4.6 --- nix/devbox-module.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nix/devbox-module.nix b/nix/devbox-module.nix index 97eb73f..597fe71 100644 --- a/nix/devbox-module.nix +++ b/nix/devbox-module.nix @@ -50,6 +50,11 @@ in { virtualisation.docker.enable = lib.mkDefault (sets.container or false); services.tailscale.enable = lib.mkDefault (sets.network or false); + # ── Dynamic linker compat ───────────────────────── + # Required for VS Code Server, Cursor, and other dynamically linked + # binaries that expect a standard FHS layout (ld-linux, libc, etc.). + programs.nix-ld.enable = true; + # ── Shell ────────────────────────────────────────── programs.zsh.enable = true; security.sudo.wheelNeedsPassword = lib.mkDefault false; From d5907d2e3e76c408361d146af5f4e5535e8c30aa Mon Sep 17 00:00:00 2001 From: Ethan Date: Tue, 10 Mar 2026 08:41:57 -0700 Subject: [PATCH 4/5] fix: refresh overlay layer before opening editor to avoid stale file handles Host-side changes cause stale inodes in the overlay cache. Refreshing before launching VS Code/Cursor ensures a clean view of the workspace. Co-Authored-By: Claude Opus 4.6 --- src/cli/code.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cli/code.rs b/src/cli/code.rs index a2e6cb4..98d7714 100644 --- a/src/cli/code.rs +++ b/src/cli/code.rs @@ -4,6 +4,7 @@ use clap::Args; use crate::runtime::cmd::run_cmd; use crate::runtime::SandboxStatus; use crate::sandbox::SandboxManager; +use crate::sandbox::overlay; #[derive(Args, Debug)] pub struct CodeArgs { @@ -36,6 +37,14 @@ pub async fn run(args: CodeArgs, manager: &SandboxManager) -> Result<()> { SandboxStatus::Unknown(s) => bail!("Sandbox '{name}' is in unknown state: {s}"), } + // Refresh overlay before opening editor to avoid stale file handles + if state.mount_mode != "writable" { + println!("Refreshing overlay layer..."); + if let Err(e) = overlay::refresh(runtime.as_ref(), &name).await { + eprintln!("Warning: overlay refresh failed: {e}"); + } + } + let vm_name = format!("devbox-{name}"); let ssh_host = format!("devbox-{name}"); From bc93d34547a749970e8cf18d68adf5a51637e329 Mon Sep 17 00:00:00 2001 From: Ethan Date: Tue, 10 Mar 2026 08:44:07 -0700 Subject: [PATCH 5/5] docs: add IDE Integration section for devbox code command Documents VS Code, Cursor, and Windsurf support via Remote SSH. Adds devbox code to the commands table. Co-Authored-By: Claude Opus 4.6 --- README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.md b/README.md index d2983c7..0708e95 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,29 @@ ssh yourserver -t "devbox shell --name shared-api" --- +## IDE Integration + +Use your local VS Code, Cursor, or Windsurf to edit code inside the sandbox — full IntelliSense, extensions, and debugging, all running in the isolated VM. + +```bash +devbox code # Open VS Code into the sandbox +devbox code --editor cursor # Use Cursor instead +devbox code --editor windsurf # Use Windsurf +devbox code myapp # Open a specific sandbox +devbox code --path /workspace/src # Open a specific directory +``` + +Devbox automatically: +1. Configures `~/.ssh/config` for the sandbox VM +2. Refreshes the overlay layer (clears stale file handles) +3. Launches the editor with Remote SSH pointed at `/workspace` + +Works with any editor that supports [Remote SSH](https://code.visualstudio.com/docs/remote/ssh) — VS Code, Cursor, Windsurf, and others. + +> **NixOS compatibility:** Devbox enables `nix-ld` in the VM so VS Code Server and other dynamically linked binaries run without issues. + +--- + ## Quick Start ### Prerequisites @@ -309,6 +332,7 @@ All layer operations are also available in the **DevBox Management Panel** insid | `devbox destroy` | Remove a sandbox | | `devbox list` | List all sandboxes | | `devbox status` | Show detailed sandbox status | +| `devbox code` | Open VS Code / Cursor into sandbox via Remote SSH | | `devbox use ` | Switch sandbox to current directory | | `devbox upgrade --tools ` | Add tools to a running sandbox | | `devbox packages` | Open TUI package manager |