lean_ctx/core/editor_registry/
paths.rs1use std::path::{Path, PathBuf};
2
3pub fn zed_settings_path(home: &std::path::Path) -> PathBuf {
4 if cfg!(target_os = "macos") {
5 home.join("Library/Application Support/Zed/settings.json")
6 } else {
7 home.join(".config/zed/settings.json")
8 }
9}
10
11pub fn zed_config_dir(home: &std::path::Path) -> PathBuf {
12 if cfg!(target_os = "macos") {
13 home.join("Library/Application Support/Zed")
14 } else {
15 home.join(".config/zed")
16 }
17}
18
19pub fn vscode_mcp_path() -> PathBuf {
20 if let Some(home) = dirs::home_dir() {
21 #[cfg(target_os = "macos")]
22 {
23 return home.join("Library/Application Support/Code/User/mcp.json");
24 }
25 #[cfg(target_os = "linux")]
26 {
27 return resolve_vscode_global_storage(&home, "User/mcp.json");
28 }
29 #[cfg(target_os = "windows")]
30 {
31 if let Ok(appdata) = std::env::var("APPDATA") {
32 return PathBuf::from(appdata).join("Code/User/mcp.json");
33 }
34 }
35 #[allow(unreachable_code)]
36 home.join(".config/Code/User/mcp.json")
37 } else {
38 PathBuf::from("/nonexistent")
39 }
40}
41
42pub fn vscode_insiders_mcp_path() -> PathBuf {
51 let Some(home) = dirs::home_dir() else {
52 return PathBuf::from("/nonexistent");
53 };
54 #[cfg(target_os = "macos")]
55 {
56 home.join("Library/Application Support/Code - Insiders/User/mcp.json")
57 }
58 #[cfg(target_os = "windows")]
59 {
60 if let Ok(appdata) = std::env::var("APPDATA") {
61 return PathBuf::from(appdata).join("Code - Insiders/User/mcp.json");
62 }
63 home.join("AppData/Roaming/Code - Insiders/User/mcp.json")
64 }
65 #[cfg(not(any(target_os = "macos", target_os = "windows")))]
66 {
67 home.join(".config/Code - Insiders/User/mcp.json")
68 }
69}
70
71pub fn qoder_mcp_path(home: &Path) -> PathBuf {
72 #[cfg(target_os = "windows")]
73 {
74 if let Ok(appdata) = std::env::var("APPDATA") {
75 return PathBuf::from(appdata)
76 .join("Qoder")
77 .join("SharedClientCache")
78 .join("mcp.json");
79 }
80 }
81 home.join(".qoder").join("mcp.json")
82}
83
84#[cfg(target_os = "macos")]
85pub fn qoder_mcp_paths(home: &Path) -> Vec<PathBuf> {
86 let mut paths = vec![qoder_mcp_path(home)];
87 paths.push(home.join("Library/Application Support/Qoder/User/mcp.json"));
88 paths.push(home.join("Library/Application Support/Qoder/SharedClientCache/mcp.json"));
89 paths
90}
91
92#[cfg(not(target_os = "macos"))]
93pub fn qoder_mcp_paths(home: &Path) -> Vec<PathBuf> {
94 vec![qoder_mcp_path(home)]
95}
96
97#[allow(unreachable_code)]
98pub fn cline_mcp_path() -> PathBuf {
99 #[cfg(target_os = "windows")]
100 {
101 if let Ok(appdata) = std::env::var("APPDATA") {
102 return PathBuf::from(appdata).join(
103 "Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json",
104 );
105 }
106 return PathBuf::from("/nonexistent");
107 }
108
109 let Some(home) = dirs::home_dir() else {
110 return PathBuf::from("/nonexistent");
111 };
112 #[cfg(target_os = "macos")]
113 {
114 return home.join("Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json");
115 }
116 #[cfg(target_os = "linux")]
117 {
118 let suffix = "User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json";
119 return resolve_vscode_global_storage(&home, suffix);
120 }
121 PathBuf::from("/nonexistent")
122}
123
124#[allow(unreachable_code)]
125pub fn roo_mcp_path() -> PathBuf {
126 #[cfg(target_os = "windows")]
127 {
128 if let Ok(appdata) = std::env::var("APPDATA") {
129 return PathBuf::from(appdata)
130 .join("Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json");
131 }
132 return PathBuf::from("/nonexistent");
133 }
134
135 let Some(home) = dirs::home_dir() else {
136 return PathBuf::from("/nonexistent");
137 };
138 #[cfg(target_os = "macos")]
139 {
140 return home.join("Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json");
141 }
142 #[cfg(target_os = "linux")]
143 {
144 let suffix =
145 "User/globalStorage/rooveterinaryinc.roo-cline/settings/cline_mcp_settings.json";
146 return resolve_vscode_global_storage(&home, suffix);
147 }
148 PathBuf::from("/nonexistent")
149}
150
151#[cfg(target_os = "linux")]
159fn resolve_vscode_global_storage(home: &Path, suffix: &str) -> PathBuf {
160 const CANDIDATES: &[&str] = &[
161 ".config/VSCodium",
162 ".config/Code - OSS",
163 ".config/Code",
164 ".config/Code - Insiders",
165 ".vscode-server/data",
166 ];
167 for base in CANDIDATES {
168 let path = home.join(base);
169 if path.exists() {
170 return path.join(suffix);
171 }
172 }
173 home.join(".config/Code").join(suffix)
174}
175
176pub fn qoder_settings_path(home: &Path) -> PathBuf {
177 #[cfg(target_os = "windows")]
178 {
179 if let Ok(appdata) = std::env::var("APPDATA") {
180 return PathBuf::from(appdata)
181 .join("Qoder")
182 .join("SharedClientCache")
183 .join("mcp.json");
184 }
185 }
186 home.join(".qoder/mcp.json")
187}
188
189pub fn qoder_all_mcp_paths(home: &Path) -> Vec<PathBuf> {
190 let paths = vec![qoder_settings_path(home)];
191 #[cfg(target_os = "macos")]
192 let paths = {
193 let mut paths = paths;
194 paths.push(home.join("Library/Application Support/Qoder/User/mcp.json"));
195 paths.push(home.join("Library/Application Support/Qoder/SharedClientCache/mcp.json"));
196 paths
197 };
198 paths
199}
200
201pub fn qoderwork_mcp_path(home: &Path) -> PathBuf {
202 home.join(".qoderwork/mcp.json")
203}
204
205pub fn qodercli_settings_path(home: &Path) -> PathBuf {
210 home.join(".qoder/settings.json")
211}
212
213pub fn claude_mcp_json_path(home: &Path) -> PathBuf {
214 if let Ok(dir) = std::env::var("CLAUDE_CONFIG_DIR") {
215 let dir = dir.trim();
216 if !dir.is_empty() {
217 return PathBuf::from(dir).join(".claude.json");
218 }
219 }
220 home.join(".claude.json")
221}
222
223pub fn claude_state_dir(home: &Path) -> PathBuf {
224 if let Ok(dir) = std::env::var("CLAUDE_CONFIG_DIR") {
225 let dir = dir.trim();
226 if !dir.is_empty() {
227 return PathBuf::from(dir);
228 }
229 }
230 home.join(".claude")
231}
232
233pub fn claude_rules_dir(home: &Path) -> PathBuf {
234 claude_state_dir(home).join("rules")
235}
236
237pub fn codebuddy_mcp_json_path(home: &Path) -> PathBuf {
238 codebuddy_state_dir(home).join("mcp.json")
239}
240
241pub fn codebuddy_state_dir(home: &Path) -> PathBuf {
242 if let Ok(dir) = std::env::var("CODEBUDDY_CONFIG_DIR") {
243 let dir = dir.trim();
244 if !dir.is_empty() {
245 return PathBuf::from(dir);
246 }
247 }
248 home.join(".codebuddy")
249}
250
251pub fn codebuddy_rules_dir(home: &Path) -> PathBuf {
252 codebuddy_state_dir(home).join("rules")
253}
254
255pub fn augment_cli_settings_path(home: &Path) -> PathBuf {
256 home.join(".augment/settings.json")
257}
258
259pub fn augment_vscode_mcp_path(home: &Path) -> PathBuf {
269 const TAIL: &str = "globalStorage/augment.vscode-augment/augment-global-state/mcpServers.json";
270
271 #[cfg(target_os = "macos")]
272 {
273 return home
274 .join("Library/Application Support/Code/User")
275 .join(TAIL);
276 }
277 #[cfg(target_os = "linux")]
278 {
279 for path in [
280 ".config/Code/User",
281 ".config/Code - Insiders/User",
282 ".vscode-server/data/User",
283 ] {
284 let full_path = home.join(path).join(TAIL);
285 if full_path.exists() {
286 return full_path;
287 }
288 }
289 return home.join(".config/Code/User").join(TAIL);
291 }
292 #[cfg(target_os = "windows")]
293 {
294 if let Ok(appdata) = std::env::var("APPDATA") {
295 return PathBuf::from(appdata).join("Code/User").join(TAIL);
296 }
297 }
298 #[allow(unreachable_code)]
299 home.join(".config/Code/User").join(TAIL)
300}
301
302pub fn vibe_config_path(home: &Path) -> PathBuf {
303 home.join(".vibe/config.toml")
304}
305
306pub fn detect_vibe_path(home: &Path) -> PathBuf {
307 let vibe_dir = home.join(".vibe");
308 if vibe_dir.exists() {
309 return vibe_dir;
310 }
311 PathBuf::from("/nonexistent")
312}
313
314#[cfg(test)]
315mod augment_tests {
316 use super::*;
317
318 #[test]
319 fn augment_cli_settings_path_is_under_dot_augment() {
320 let home = Path::new("/home/tester");
321 assert_eq!(
322 augment_cli_settings_path(home),
323 home.join(".augment").join("settings.json")
324 );
325 }
326
327 #[test]
328 #[cfg(target_os = "linux")]
329 fn augment_vscode_mcp_path_uses_linux_globalstorage() {
330 let home = Path::new("/home/tester");
331 assert_eq!(
332 augment_vscode_mcp_path(home),
333 home.join(".config/Code/User/globalStorage/augment.vscode-augment/augment-global-state/mcpServers.json")
334 );
335 }
336
337 #[test]
338 #[cfg(target_os = "macos")]
339 fn augment_vscode_mcp_path_uses_macos_application_support() {
340 let home = Path::new("/Users/tester");
341 assert_eq!(
342 augment_vscode_mcp_path(home),
343 home.join("Library/Application Support/Code/User/globalStorage/augment.vscode-augment/augment-global-state/mcpServers.json")
344 );
345 }
346
347 #[test]
353 #[cfg(target_os = "windows")]
354 fn augment_vscode_mcp_path_ends_with_globalstorage_tail() {
355 let home = Path::new("C:/Users/tester");
356 let path = augment_vscode_mcp_path(home);
357 let s = path.to_string_lossy().replace('\\', "/");
358 assert!(
359 s.ends_with(
360 "Code/User/globalStorage/augment.vscode-augment/augment-global-state/mcpServers.json"
361 ),
362 "unexpected windows path: {s}"
363 );
364 }
365}
366
367#[cfg(test)]
368mod qodercli_tests {
369 use super::*;
370
371 #[test]
372 fn qodercli_settings_path_uses_shared_qoder_settings_file() {
373 let home = Path::new("/home/tester");
374 assert_eq!(
375 qodercli_settings_path(home),
376 home.join(".qoder/settings.json")
377 );
378 }
379
380 #[test]
381 fn qodercli_settings_path_is_distinct_from_qoder_ide_mcp_path() {
382 let home = Path::new("/home/tester");
383 assert_ne!(qodercli_settings_path(home), qoder_mcp_path(home));
384 }
385
386 #[test]
387 fn qodercli_settings_path_is_distinct_from_qoderwork_path() {
388 let home = Path::new("/home/tester");
389 assert_ne!(qodercli_settings_path(home), qoderwork_mcp_path(home));
390 }
391}
392
393#[cfg(all(test, target_os = "macos"))]
394mod tests {
395 use super::*;
396
397 #[test]
398 #[cfg(target_os = "macos")]
399 fn qoder_mcp_paths_include_macos_user_and_shared_cache_locations() {
400 let home = Path::new("/Users/tester");
401 let paths = qoder_mcp_paths(home);
402
403 assert_eq!(
404 paths,
405 vec![
406 home.join(".qoder/mcp.json"),
407 home.join("Library/Application Support/Qoder/User/mcp.json"),
408 home.join("Library/Application Support/Qoder/SharedClientCache/mcp.json"),
409 ]
410 );
411 }
412}