Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 30 additions & 17 deletions src/hooks/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,7 @@ pub fn run(
}

/// Prepare hook directory and return paths (hook_dir, hook_path)
fn prepare_hook_paths() -> Result<(PathBuf, PathBuf)> {
let claude_dir = resolve_claude_dir()?;
fn prepare_hook_paths(claude_dir: &Path) -> Result<(PathBuf, PathBuf)> {
let hook_dir = claude_dir.join("hooks");
fs::create_dir_all(&hook_dir)
.with_context(|| format!("Failed to create hook directory: {}", hook_dir.display()))?;
Expand Down Expand Up @@ -437,8 +436,8 @@ fn prompt_user_consent(settings_path: &Path) -> Result<bool> {
}

/// Print manual instructions for settings.json patching
fn print_manual_instructions(hook_path: &Path, include_opencode: bool) {
println!("\n MANUAL STEP: Add this to ~/.claude/settings.json:");
fn print_manual_instructions(hook_path: &Path, settings_path: &Path, include_opencode: bool) {
println!("\n MANUAL STEP: Add this to {}:", settings_path.display());
println!(" {{");
println!(" \"hooks\": {{ \"PreToolUse\": [{{");
println!(" \"matcher\": \"Bash\",");
Expand Down Expand Up @@ -696,11 +695,11 @@ fn uninstall_codex_at(codex_dir: &Path, verbose: u8) -> Result<Vec<String>> {
/// Handles reading, checking, prompting, merging, backing up, and atomic writing
fn patch_settings_json(
hook_path: &Path,
claude_dir: &Path,
mode: PatchMode,
verbose: u8,
include_opencode: bool,
) -> Result<PatchResult> {
let claude_dir = resolve_claude_dir()?;
let settings_path = claude_dir.join(SETTINGS_JSON);
let hook_command = hook_path
.to_str()
Expand Down Expand Up @@ -732,12 +731,12 @@ fn patch_settings_json(
// Handle mode
match mode {
PatchMode::Skip => {
print_manual_instructions(hook_path, include_opencode);
print_manual_instructions(hook_path, &settings_path, include_opencode);
return Ok(PatchResult::Skipped);
}
PatchMode::Ask => {
if !prompt_user_consent(&settings_path)? {
print_manual_instructions(hook_path, include_opencode);
print_manual_instructions(hook_path, &settings_path, include_opencode);
return Ok(PatchResult::Declined);
}
}
Expand Down Expand Up @@ -902,7 +901,7 @@ fn run_default_mode(
let claude_md_path = claude_dir.join(CLAUDE_MD);

// 1. Prepare hook directory and install hook
let (_hook_dir, hook_path) = prepare_hook_paths()?;
let (_hook_dir, hook_path) = prepare_hook_paths(&claude_dir)?;
let hook_changed = ensure_hook_installed(&hook_path, verbose)?;

// 2. Write RTK.md
Expand Down Expand Up @@ -939,7 +938,13 @@ fn run_default_mode(
}

// 5. Patch settings.json
let patch_result = patch_settings_json(&hook_path, patch_mode, verbose, install_opencode)?;
let patch_result = patch_settings_json(
&hook_path,
&claude_dir,
patch_mode,
verbose,
install_opencode,
)?;

// Report result
match patch_result {
Expand Down Expand Up @@ -1034,14 +1039,16 @@ fn run_hook_only_mode(
verbose: u8,
install_opencode: bool,
) -> Result<()> {
if !global {
eprintln!("[warn] Warning: --hook-only only makes sense with --global");
eprintln!(" For local projects, use default mode or --claude-md");
return Ok(());
}
let claude_dir = if global {
resolve_claude_dir()?
} else {
std::env::current_dir()?.join(".claude")
};

let scope = if global { "global" } else { "project-scoped" };

// Prepare and install hook
let (_hook_dir, hook_path) = prepare_hook_paths()?;
let (_hook_dir, hook_path) = prepare_hook_paths(&claude_dir)?;
let hook_changed = ensure_hook_installed(&hook_path, verbose)?;

let opencode_plugin_path = if install_opencode {
Expand All @@ -1057,7 +1064,7 @@ fn run_hook_only_mode(
} else {
"already up to date"
};
println!("\nRTK hook {} (hook-only mode).\n", hook_status);
println!("\nRTK hook {} (hook-only mode, {}).\n", hook_status, scope);
println!(" Hook: {}", hook_path.display());
if let Some(path) = &opencode_plugin_path {
println!(" OpenCode: {}", path.display());
Expand All @@ -1067,7 +1074,13 @@ fn run_hook_only_mode(
);

// Patch settings.json
let patch_result = patch_settings_json(&hook_path, patch_mode, verbose, install_opencode)?;
let patch_result = patch_settings_json(
&hook_path,
&claude_dir,
patch_mode,
verbose,
install_opencode,
)?;

// Report result
match patch_result {
Expand Down