use std::path::Path;
use recall_hooks::{exit, settings};
use crate::project;
pub fn run(path: Option<&Path>) -> anyhow::Result<i32> {
let root = match path {
Some(p) => p.to_path_buf(),
None => match project::git_root() {
Some(root) => root,
None => anyhow::bail!(
"not inside a git repository — run this from the project you want to sync"
),
},
};
let settings_path = root.join(".claude").join("settings.json");
if settings::wire_file(&settings_path)? {
println!("recall: wired hooks into {}", settings_path.display());
print_commit_hint(&root);
} else {
println!(
"recall: already wired, nothing to change ({})",
settings_path.display()
);
}
warn_about_unset_variables(&root);
Ok(exit::OK)
}
fn print_commit_hint(root: &Path) {
println!(
"
Next: review and commit the change, so fresh clones and cloud sessions
pick it up too — that's what makes this work without per-machine setup.
git -C {0} diff .claude/settings.json
git -C {0} add .claude/settings.json && git -C {0} commit -m \"Enable Recall memory sync\"",
root.display()
);
}
fn warn_about_unset_variables(root: &Path) {
let cfg = project::resolve_at(root.to_path_buf()).config();
if !cfg.url.is_empty() && !cfg.token.is_empty() {
return;
}
println!();
if cfg.url.is_empty() {
println!(" ! RECALL_URL is not set — not in this shell, nor in any settings file");
}
if cfg.token.is_empty() {
println!(" ! RECALL_TOKEN is not set — not in this shell, nor in any settings file");
}
println!(
"
Add these to your shell profile (~/.zshrc, ~/.bashrc) before sync works:
export RECALL_URL=\"https://your-recall-host\"
export RECALL_TOKEN=\"<your token>\"
See docs/reference/token-setup.md for generating the token, and for the extra
variables a claude.ai cloud environment needs."
);
}