on main help sign in
fix: removed the hardcode codex and claude form ssh.sh
518ca14robcholz
src/config.rs+2−2
@@ -81,11 +81,11 @@ fn default_mounts() -> Vec<String> {
81 let mut mounts = Vec::new();
81 let mut mounts = Vec::new();
82 let codex_host = home.join(".codex");
82 let codex_host = home.join(".codex");
83 if codex_host.exists() {
83 if codex_host.exists() {
84− mounts.push("~/.codex:/usr/local/codex:read-write".to_string());
84+ mounts.push("~/.codex:/home/vibecoder/.codex:read-write".to_string());
85 }
85 }
86 let claude_host = home.join(".claude");
86 let claude_host = home.join(".claude");
87 if claude_host.exists() {
87 if claude_host.exists() {
88− mounts.push("~/.claude:/usr/local/claude:read-write".to_string());
88+ mounts.push("~/.claude:/home/vibecoder/.claude:read-write".to_string());
89 }
89 }
90 mounts
90 mounts
91}
91}
src/explain.rs+34−6
@@ -12,8 +12,9 @@ pub fn build_mount_rows(
12) -> Result<Vec<tui::MountListRow>, Box<dyn Error + Send + Sync>> {
12) -> Result<Vec<tui::MountListRow>, Box<dyn Error + Send + Sync>> {
13 let mut rows = Vec::new();
13 let mut rows = Vec::new();
14 rows.extend(default_mounts(cwd)?);
14 rows.extend(default_mounts(cwd)?);
15+ let guest_home = resolve_guest_home(cwd)?;
15 for spec in &config.box_cfg.mounts {
16 for spec in &config.box_cfg.mounts {
16− rows.push(parse_mount_spec(cwd, spec, false)?);
17+ rows.push(parse_mount_spec(cwd, spec, false, &guest_home)?);
17 }
18 }
18 Ok(rows)
19 Ok(rows)
19}
20}
@@ -75,6 +76,7 @@ fn parse_mount_spec(
75 cwd: &Path,
76 cwd: &Path,
76 spec: &str,
77 spec: &str,
77 default_mount: bool,
78 default_mount: bool,
79+ guest_home: &str,
78) -> Result<tui::MountListRow, Box<dyn Error + Send + Sync>> {
80) -> Result<tui::MountListRow, Box<dyn Error + Send + Sync>> {
79 let parts: Vec<&str> = spec.split(':').collect();
81 let parts: Vec<&str> = spec.split(':').collect();
80 if parts.len() < 2 || parts.len() > 3 {
82 if parts.len() < 2 || parts.len() > 3 {
@@ -99,11 +101,7 @@ fn parse_mount_spec(
99 };
101 };
100
102
101 let host_display = display_host_spec(cwd, host_part);
103 let host_display = display_host_spec(cwd, host_part);
102− let guest_display = if Path::new(guest_part).is_absolute() {
104+ let guest_display = resolve_guest_display(guest_part, guest_home);
103− guest_part.to_string()
104− } else {
105− format!("/root/{guest_part}")
106− };
107 Ok(tui::MountListRow {
105 Ok(tui::MountListRow {
108 host: host_display,
106 host: host_display,
109 guest: guest_display,
107 guest: guest_display,
@@ -128,6 +126,36 @@ fn display_host_spec(cwd: &Path, host: &str) -> String {
128 }
126 }
129}
127}
130
128
129+fn resolve_guest_home(cwd: &Path) -> Result<String, Box<dyn Error + Send + Sync>> {
130+ let instance_dir = cwd.join(session_manager::INSTANCE_DIR_NAME);
131+ if let Ok(Some(user)) = instance::read_instance_ssh_user(&instance_dir) {
132+ return Ok(format!("/home/{user}"));
133+ }
134+ Ok(format!("/home/{}", instance::DEFAULT_SSH_USER))
135+}
136+
137+fn resolve_guest_display(guest: &str, guest_home: &str) -> String {
138+ if guest == "~" {
139+ return "~".to_string();
140+ }
141+ if let Some(stripped) = guest.strip_prefix("~/") {
142+ return format!("~/{stripped}");
143+ }
144+ if Path::new(guest).is_absolute() {
145+ if let Ok(stripped) = Path::new(guest).strip_prefix(guest_home) {
146+ if stripped.components().next().is_none() {
147+ "~".to_string()
148+ } else {
149+ format!("~/{}", stripped.display())
150+ }
151+ } else {
152+ guest.to_string()
153+ }
154+ } else {
155+ format!("/root/{guest}")
156+ }
157+}
158+
131fn display_path(path: &Path) -> String {
159fn display_path(path: &Path) -> String {
132 let Ok(home) = env::var("HOME") else {
160 let Ok(home) = env::var("HOME") else {
133 return path.display().to_string();
161 return path.display().to_string();
src/instance.rs+10−1
@@ -27,7 +27,7 @@ use crate::{
27
27
28const SSH_KEY_NAME: &str = "ssh_key";
28const SSH_KEY_NAME: &str = "ssh_key";
29pub(crate) const SERIAL_LOG_NAME: &str = "serial.log";
29pub(crate) const SERIAL_LOG_NAME: &str = "serial.log";
30−const DEFAULT_SSH_USER: &str = "vibecoder";
30+pub(crate) const DEFAULT_SSH_USER: &str = "vibecoder";
31const SSH_CONNECT_RETRIES: usize = 30;
31const SSH_CONNECT_RETRIES: usize = 30;
32const SSH_CONNECT_DELAY_MS: u64 = 500;
32const SSH_CONNECT_DELAY_MS: u64 = 500;
33const SSH_SETUP_SCRIPT: &str = include_str!("ssh.sh");
33const SSH_SETUP_SCRIPT: &str = include_str!("ssh.sh");
@@ -181,6 +181,15 @@ pub fn read_instance_vm_ip(
181 Ok(config.and_then(|cfg| cfg.vm_ipv4))
181 Ok(config.and_then(|cfg| cfg.vm_ipv4))
182}
182}
183
183
184+pub fn read_instance_ssh_user(
185+ instance_dir: &Path,
186+) -> Result<Option<String>, Box<dyn std::error::Error>> {
187+ let config = read_instance_config(instance_dir)?;
188+ Ok(config
189+ .map(|cfg| cfg.ssh_user)
190+ .filter(|user| !user.trim().is_empty()))
191+}
192+
184pub fn touch_last_active(instance_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
193pub fn touch_last_active(instance_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
185 let mut config = load_or_create_instance_config(instance_dir)?;
194 let mut config = load_or_create_instance_config(instance_dir)?;
186 let now = OffsetDateTime::now_utc().format(&Rfc3339)?;
195 let now = OffsetDateTime::now_utc().format(&Rfc3339)?;
src/ssh.sh−9
@@ -63,19 +63,10 @@ fi
63install -d -m 700 -o "$SSH_USER" -g "$SSH_USER" "/home/${SSH_USER}/.ssh"
63install -d -m 700 -o "$SSH_USER" -g "$SSH_USER" "/home/${SSH_USER}/.ssh"
64install -m 600 -o "$SSH_USER" -g "$SSH_USER" "$KEY_PATH" "/home/${SSH_USER}/.ssh/authorized_keys"
64install -m 600 -o "$SSH_USER" -g "$SSH_USER" "$KEY_PATH" "/home/${SSH_USER}/.ssh/authorized_keys"
65
65
66−# Ensure codex/claude are visible in the user's HOME
67USER_HOME="$(getent passwd "$SSH_USER" | cut -d: -f6 2>/dev/null || true)"
66USER_HOME="$(getent passwd "$SSH_USER" | cut -d: -f6 2>/dev/null || true)"
68if [ -z "$USER_HOME" ]; then
67if [ -z "$USER_HOME" ]; then
69 USER_HOME="/home/${SSH_USER}"
68 USER_HOME="/home/${SSH_USER}"
70fi
69fi
71−install -d -m 755 /usr/local/codex /usr/local/claude
72−if [ ! -e "${USER_HOME}/.codex" ]; then
73− ln -s /usr/local/codex "${USER_HOME}/.codex"
74−fi
75−if [ ! -e "${USER_HOME}/.claude" ]; then
76− ln -s /usr/local/claude "${USER_HOME}/.claude"
77−fi
78−chown -h "${SSH_USER}:${SSH_USER}" "${USER_HOME}/.codex" "${USER_HOME}/.claude" 2>/dev/null || true
79
70
80# Vibebox shell commands
71# Vibebox shell commands
81install -d -m 755 /etc/profile.d
72install -d -m 755 /etc/profile.d
vibebox.toml+2−2
@@ -2,8 +2,8 @@
2cpu_count = 2
2cpu_count = 2
3ram_mb = 2048
3ram_mb = 2048
4mounts = [
4mounts = [
5− "~/.codex:/usr/local/codex:read-write",
5+ "~/.codex:~/.codex:read-write",
6− "~/.claude:/usr/local/claude:read-write",
6+ "~/.claude:~/.claude:read-write",
7]
7]
8
8
9[supervisor]
9[supervisor]