generated from nhcarrigan/template
fix: read/write global CLAUDE.md via WSL on Windows (#264)
## Summary - `get_global_claude_md` and `save_global_claude_md` were using `dirs::home_dir()` which resolves to the Windows home directory (`C:\Users\accou`) on Windows builds - The actual `~/.claude/CLAUDE.md` lives in the WSL home directory, so the editor was always showing an empty text box and would have written to the wrong location on save - Added `get_global_claude_md_via_wsl()` and `save_global_claude_md_via_wsl()` helpers that shell out to WSL (matching the existing pattern used by `list_skills` and `list_memory_files`) - Both Tauri commands now branch on `cfg!(target_os = "windows")` to use the appropriate path ## Test plan - [ ] Open Settings sidebar on a Windows build — Global Instructions textarea should load the contents of `~/.claude/CLAUDE.md` from WSL - [ ] Edit the content and click Save — verify the WSL file is updated - [ ] Verify Linux/macOS builds are unaffected (native filesystem path unchanged) ✨ This issue was created with help from Hikari~ 🌸 Reviewed-on: #264 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #264.
This commit is contained in:
+81
-17
@@ -2618,37 +2618,101 @@ pub async fn open_binary_file(app: AppHandle, path: String) -> Result<(), String
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read `~/.claude/CLAUDE.md` via WSL (for Windows).
|
||||||
|
/// Returns an empty string if the file does not exist.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
async fn get_global_claude_md_via_wsl() -> Result<String, String> {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
let output = Command::new("wsl")
|
||||||
|
.hide_window()
|
||||||
|
.args(["-e", "bash", "-l", "-c", "cat ~/.claude/CLAUDE.md 2>/dev/null || true"])
|
||||||
|
.output()
|
||||||
|
.map_err(|e| format!("Failed to execute WSL command: {}", e))?;
|
||||||
|
|
||||||
|
Ok(String::from_utf8_lossy(&output.stdout).to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write content to `~/.claude/CLAUDE.md` via WSL (for Windows).
|
||||||
|
/// Creates the file (and `~/.claude/` directory) if they do not exist.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
async fn save_global_claude_md_via_wsl(content: String) -> Result<(), String> {
|
||||||
|
use std::io::Write;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
let mut child = Command::new("wsl")
|
||||||
|
.hide_window()
|
||||||
|
.args([
|
||||||
|
"-e",
|
||||||
|
"bash",
|
||||||
|
"-l",
|
||||||
|
"-c",
|
||||||
|
"mkdir -p ~/.claude && cat > ~/.claude/CLAUDE.md",
|
||||||
|
])
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.map_err(|e| format!("Failed to execute WSL command: {}", e))?;
|
||||||
|
|
||||||
|
if let Some(stdin) = child.stdin.as_mut() {
|
||||||
|
stdin
|
||||||
|
.write_all(content.as_bytes())
|
||||||
|
.map_err(|e| format!("Failed to write content to WSL stdin: {}", e))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = child
|
||||||
|
.wait()
|
||||||
|
.map_err(|e| format!("Failed to wait for WSL command: {}", e))?;
|
||||||
|
|
||||||
|
if !status.success() {
|
||||||
|
return Err("Failed to save CLAUDE.md via WSL".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Read the contents of `~/.claude/CLAUDE.md`.
|
/// Read the contents of `~/.claude/CLAUDE.md`.
|
||||||
/// Returns an empty string if the file does not exist.
|
/// Returns an empty string if the file does not exist.
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn get_global_claude_md() -> Result<String, String> {
|
pub async fn get_global_claude_md() -> Result<String, String> {
|
||||||
let path = dirs::home_dir()
|
#[cfg(target_os = "windows")]
|
||||||
.ok_or_else(|| "Could not determine home directory".to_string())?
|
return get_global_claude_md_via_wsl().await;
|
||||||
.join(".claude")
|
|
||||||
.join("CLAUDE.md");
|
|
||||||
|
|
||||||
if !path.exists() {
|
#[cfg(not(target_os = "windows"))]
|
||||||
return Ok(String::new());
|
{
|
||||||
|
let path = dirs::home_dir()
|
||||||
|
.ok_or_else(|| "Could not determine home directory".to_string())?
|
||||||
|
.join(".claude")
|
||||||
|
.join("CLAUDE.md");
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
return Ok(String::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fs::read_to_string(&path).map_err(|e| format!("Failed to read CLAUDE.md: {}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fs::read_to_string(&path).map_err(|e| format!("Failed to read CLAUDE.md: {}", e))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write content to `~/.claude/CLAUDE.md`.
|
/// Write content to `~/.claude/CLAUDE.md`.
|
||||||
/// Creates the file (and `~/.claude/` directory) if they do not exist.
|
/// Creates the file (and `~/.claude/` directory) if they do not exist.
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn save_global_claude_md(content: String) -> Result<(), String> {
|
pub async fn save_global_claude_md(content: String) -> Result<(), String> {
|
||||||
let claude_dir = dirs::home_dir()
|
#[cfg(target_os = "windows")]
|
||||||
.ok_or_else(|| "Could not determine home directory".to_string())?
|
return save_global_claude_md_via_wsl(content).await;
|
||||||
.join(".claude");
|
|
||||||
|
|
||||||
if !claude_dir.exists() {
|
#[cfg(not(target_os = "windows"))]
|
||||||
std::fs::create_dir_all(&claude_dir)
|
{
|
||||||
.map_err(|e| format!("Failed to create ~/.claude directory: {}", e))?;
|
let claude_dir = dirs::home_dir()
|
||||||
|
.ok_or_else(|| "Could not determine home directory".to_string())?
|
||||||
|
.join(".claude");
|
||||||
|
|
||||||
|
if !claude_dir.exists() {
|
||||||
|
std::fs::create_dir_all(&claude_dir)
|
||||||
|
.map_err(|e| format!("Failed to create ~/.claude directory: {}", e))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = claude_dir.join("CLAUDE.md");
|
||||||
|
std::fs::write(&path, content).map_err(|e| format!("Failed to write CLAUDE.md: {}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = claude_dir.join("CLAUDE.md");
|
|
||||||
std::fs::write(&path, content).map_err(|e| format!("Failed to write CLAUDE.md: {}", e))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Reference in New Issue
Block a user