1use std::fs;
2use std::path::Path;
3
4use anyhow::Result;
5use owo_colors::OwoColorize;
6
7pub fn install_hook(root: &Path, min_score: u32) -> Result<()> {
11 let hooks_dir = root.join(".git").join("hooks");
12 if !hooks_dir.exists() {
13 anyhow::bail!("Not a git repository (no .git/hooks). Run `git init` first.");
14 }
15
16 let hook_path = hooks_dir.join("pre-commit");
17 let script = generate_hook_script(min_score);
18 fs::write(&hook_path, script)?;
19
20 #[cfg(unix)]
21 {
22 use std::os::unix::fs::PermissionsExt;
23 fs::set_permissions(&hook_path, fs::Permissions::from_mode(0o755))?;
24 }
25
26 println!("{}", "Pre-commit hook installed!".green().bold());
27 println!(" Path: {}", hook_path.display());
28 println!(" Min score: {min_score}");
29 println!();
30 println!("Commits will be blocked if claude-native score drops below {min_score}.");
31 Ok(())
32}
33
34pub fn print_precommit_config() {
36 println!("Add to .pre-commit-config.yaml:");
37 println!();
38 println!(" - repo: local");
39 println!(" hooks:");
40 println!(" - id: claude-native");
41 println!(" name: Claude Native Score Check");
42 println!(" entry: claude-native");
43 println!(" language: system");
44 println!(" pass_filenames: false");
45 println!(" always_run: true");
46}
47
48fn generate_hook_script(min_score: u32) -> String {
51 format!(
52 r#"#!/bin/sh
53# claude-native pre-commit hook
54# Blocks commits if score drops below {min_score}
55
56if ! command -v claude-native &> /dev/null; then
57 echo "claude-native not found. Install: cargo install claude-native"
58 exit 0
59fi
60
61SCORE=$(claude-native -o json 2>/dev/null | grep '"score"' | head -1 | sed 's/[^0-9.]//g' | cut -d. -f1)
62
63if [ -z "$SCORE" ]; then
64 echo "claude-native: could not determine score, skipping check"
65 exit 0
66fi
67
68if [ "$SCORE" -lt {min_score} ]; then
69 echo ""
70 echo "claude-native: score $SCORE is below minimum {min_score}"
71 echo "Run 'claude-native' to see suggestions, or 'claude-native --fix' to auto-repair."
72 echo ""
73 exit 1
74fi
75
76echo "claude-native: score $SCORE (>= {min_score}) OK"
77exit 0
78"#
79 )
80}