| Crates.io | claude-hook-advisor |
| lib.rs | claude-hook-advisor |
| version | 0.2.1 |
| created_at | 2025-07-22 13:34:11.236088+00 |
| updated_at | 2025-11-11 12:27:40.838782+00 |
| description | A Claude Code hook that provides intelligent command suggestions and semantic directory aliasing for enhanced AI-assisted development workflows |
| homepage | https://github.com/sirmews/claude-hook-advisor |
| repository | https://github.com/sirmews/claude-hook-advisor |
| max_upload_size | |
| id | 1763530 |
| size | 231,882 |
A Rust CLI tool that integrates with Claude Code using a triple-hook architecture to provide intelligent command suggestions and semantic directory aliasing. Enhance your development workflow with automatic command mapping and natural language directory references.
Once installed, claude-hook-advisor works invisibly in your Claude Code conversations:
You type: "What files are in my docs?" Claude responds: "I'll check what files are in your docs directory at /Users/you/Documents/Documentation."
Behind the scenes, you'll see:
<user-prompt-submit-hook>Directory reference 'docs' resolved to: /Users/you/Documents/Documentation</user-prompt-submit-hook>
You type: "Check the project_docs for API documentation"
Claude automatically knows: Uses /Users/you/Documents/Documentation/my-project/ without you typing the full path
Claude tries to run: npm install
Tool intervenes: Suggests bun install based on your configuration
Claude automatically runs: bun install with no manual intervention
You see: Claude seamlessly uses your preferred tools without you having to correct it every time.
.claude-hook-advisor.toml fileInstall directly from crates.io using cargo:
cargo install claude-hook-advisor
This installs the binary to ~/.cargo/bin/claude-hook-advisor (make sure ~/.cargo/bin is in your PATH).
git clone https://github.com/sirmews/claude-hook-advisor.git
cd claude-hook-advisor
make install
# Install the binary
cargo install claude-hook-advisor
# Automatically install hooks into Claude Code (creates backups)
claude-hook-advisor --install-hooks
# Remove hooks if needed (with backup)
claude-hook-advisor --uninstall-hooks
Edit your .claude-hook-advisor.toml file to set up directory aliases:
# Semantic directory aliases - use natural language!
[semantic_directories]
"project docs" = "~/Documents/Documentation/my-project"
"central docs" = "~/Documents/Documentation"
"claude docs" = "~/Documents/Documentation/claude"
"test data" = "~/Documents/test-data"
Pro tip: Use quoted, space-separated aliases for natural conversation:
"project docs""test data"Create a .claude-hook-advisor.toml file in your project root:
# Command mappings
[commands]
npm = "bun"
yarn = "bun"
npx = "bunx"
curl = "wget --verbose"
# Semantic directory aliases - natural language
[semantic_directories]
"project docs" = "~/Documents/Documentation/my-project"
"central docs" = "~/Documents/Documentation"
"claude docs" = "~/Documents/Documentation/claude"
Track all commands Claude runs to a SQLite database:
[command_history]
enabled = true
log_file = "~/.claude-hook-advisor/bash-history.db"
Then view history anytime with: claude-hook-advisor --history
See the Command History Tracking section for full details.
Node.js project (prefer bun):
[commands]
npm = "bun"
yarn = "bun"
npx = "bunx"
Python project (prefer uv):
[commands]
pip = "uv pip"
"pip install" = "uv add"
General preferences:
[commands]
curl = "wget --verbose"
cat = "bat"
ls = "eza"
claude-hook-advisor --install-hooks
This automatically configures all three hooks:
If you prefer manual setup, add to your .claude/settings.json:
{
"hooks": {
"PreToolUse": { "Bash": "claude-hook-advisor --hook" },
"UserPromptSubmit": { ".*": "claude-hook-advisor --hook" },
"PostToolUse": { "Bash": "claude-hook-advisor --hook" }
}
}
Note: This assumes claude-hook-advisor is in your PATH. After cargo install, the binary is typically located at ~/.cargo/bin/claude-hook-advisor.
The Flow:
.claude-hook-advisor.toml from the current directorynpm matches npm install but not npx npm or my-npm-tool)Behind the Scenes:
// Simplified code flow
let config = load_config(".claude-hook-advisor.toml")?;
let command = parse_bash_command(&hook_input.tool_input.command);
if let Some(replacement) = config.commands.get(&command.base_command) {
return Ok(HookResponse::Block {
reason: format!("Command '{}' is mapped to '{}'", command.base_command, replacement),
suggested_command: command.replace_base_with(replacement),
});
}
What makes it smart:
npm install → bun install, but npx npm is unchanged)npm won't match npm-check or my-npm-tool)git rm won't trigger an rm mapping)npm install --save → bun install --save)The Flow:
Behind the Scenes:
// Pattern detection
let patterns = [
r"\b(docs|documentation)\b",
r"\bproject[_\s]docs?\b",
r"\bcentral[_\s]docs?\b"
];
// Tilde expansion
let resolved = expand_tilde(path_template)?;
// Security canonicalization
let canonical = fs::canonicalize(&resolved)?;
What makes it secure:
../../../etc/passwd attacksThe Flow:
Behind the Scenes:
// Success/failure tracking
match hook_data.tool_response.exit_code {
0 => log::info!("Command '{}' succeeded", command),
code => log::warn!("Command '{}' failed (exit: {})", command, code),
}
Future possibilities:
Track every Bash command Claude runs in a SQLite database. Commands executed by Claude don't show up in your shell's history, but now you can retrieve them anytime.
1. Install/Update the binary:
If you just cloned or pulled the latest code:
cargo install --path .
If you installed from crates.io, the feature is already available in v0.2.0+.
2. Enable command history:
Edit your .claude-hook-advisor.toml and add:
[command_history]
enabled = true
log_file = "~/.claude-hook-advisor/bash-history.db"
Or if you don't have a config file yet, run:
claude-hook-advisor --install
This creates a config file with command history as a commented example you can uncomment.
3. That's it!
The PostToolUse hook (already installed if you ran --install before) will automatically start logging commands. No restart needed!
Show recent commands:
claude-hook-advisor --history
Show last 50 commands:
claude-hook-advisor --history --limit 50
Show only failed commands:
claude-hook-advisor --history --failures
Show git commands only:
claude-hook-advisor --history --pattern git
Show commands from a specific session:
claude-hook-advisor --history --session abc123
Each command record includes:
Command History (5 records)
================================================================================
2025-11-10T14:30:22Z ✓
Command: git status
CWD: /home/user/my-project
Session: abc123-def456
2025-11-10T14:30:25Z ✓
Command: cargo test
CWD: /home/user/my-project
Session: abc123-def456
2025-11-10T14:30:30Z ✗ (exit: 1)
Command: npm test
CWD: /home/user/my-project
Session: abc123-def456
Here's what an actual conversation looks like with claude-hook-advisor working:
🗣️ You: "What files are in my docs?"
🤖 Claude: "⏺ I'll check what files are in your docs directory at /Users/you/Documents/Documentation."
Behind the scenes:
[DEBUG] UserPromptSubmit hook triggered
[DEBUG] Pattern matched: 'docs' -> '~/Documents/Documentation'
[DEBUG] Path resolved: /Users/you/Documents/Documentation
Hook message in Claude:
<user-prompt-submit-hook>Directory reference 'docs' resolved to: /Users/you/Documents/Documentation</user-prompt-submit-hook>
🗣️ You: "Install the dependencies for this project"
🤖 Claude: "I'll install the dependencies using npm install."
(Claude attempts: npm install)
Hook intercepts:
{
"decision": "block",
"reason": "Command 'npm' is mapped to 'bun' instead",
"suggested_command": "bun install"
}
🤖 Claude: "I'll use bun install instead based on your project preferences."
(Claude runs: bun install)
Result: Your preferred package manager is used automatically, no manual correction needed!
Directory Resolution:
# Test directory resolution via hook
echo '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check docs directory"}' | claude-hook-advisor --hook
# Expected output:
# Directory reference 'docs' resolved to: /Users/you/Documents/Documentation
*Note: Directory resolution requires the path to exist on your filesystem.*
Hook Simulation:
$ echo '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check the docs directory"}' | claude-hook-advisor --hook
<user-prompt-submit-hook>Directory reference 'docs' resolved to: /Users/you/Documents/Documentation</user-prompt-submit-hook>
$ echo '{"session_id":"test","hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npm install"}}' | claude-hook-advisor --hook
{
"decision": "block",
"reason": "Command 'npm' is mapped to 'bun' instead",
"suggested_command": "bun install"
}
make build # Build in debug mode
make release # Build in release mode
make test # Run tests
make lint # Run clippy linting
make fmt # Format code
make clean # Clean build artifacts
make example-config# Create example config
make run-example # Test with example input
make help # Show all targets
# Run unit tests
make test
# Test with example npm command
make run-example
# Manual testing - Command mapping (PreToolUse)
echo '{"session_id":"test","transcript_path":"","cwd":"","hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"yarn start"}}' | ./target/debug/claude-hook-advisor --hook
# Manual testing - Directory detection (UserPromptSubmit)
echo '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check the docs directory"}' | ./target/debug/claude-hook-advisor --hook
# Manual testing - Analytics (PostToolUse)
echo '{"session_id":"test","hook_event_name":"PostToolUse","tool_name":"Bash","tool_input":{"command":"bun install"},"tool_response":{"exit_code":0}}' | ./target/debug/claude-hook-advisor --hook
# Test directory resolution with existing config
echo '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check the docs directory"}' | ./target/debug/claude-hook-advisor --hook
When claude-hook-advisor is working correctly, you'll see these messages in Claude Code:
Directory Resolution:
<user-prompt-submit-hook>Directory reference 'docs' resolved to: /Users/you/Documents/Documentation</user-prompt-submit-hook>
Command Suggestions:
<pre-tool-use-hook>Command 'npm' mapped to 'bun'. Suggested: bun install</pre-tool-use-hook>
Execution Tracking:
<post-tool-use-hook>Command 'bun install' completed successfully (exit code: 0)</post-tool-use-hook>
Enable detailed logging to see what's happening behind the scenes:
# Add RUST_LOG=debug to your Claude Code settings
{
"hooks": {
"UserPromptSubmit": { ".*": "RUST_LOG=debug claude-hook-advisor --hook" },
"PreToolUse": { "Bash": "RUST_LOG=debug claude-hook-advisor --hook" },
"PostToolUse": { "Bash": "RUST_LOG=debug claude-hook-advisor --hook" }
}
}
Debug output shows:
Problem: No hook messages appear in Claude Code conversations
Solutions:
.claude/settings.json or .claude/settings.local.json:
{
"hooks": {
"UserPromptSubmit": { ".*": "claude-hook-advisor --hook" }
}
}
claude-hook-advisor is in your PATH: which claude-hook-advisorecho '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check docs"}' | claude-hook-advisor --hookProblem: "docs" doesn't resolve to the expected path
Solutions:
ls .claude-hook-advisor.toml[semantic_directories]
docs = "~/Documents/Documentation"
echo '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check docs"}' | claude-hook-advisor --hookls -la .claude-hook-advisor.tomlProblem: npm still runs instead of bun
Solutions:
[commands]
npm = "bun"
echo '{"session_id":"test","hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npm install"}}' | claude-hook-advisor --hooknpm install matches and becomes bun installnpx npm won't match (npm is not the primary command)npm-check won't match (different command)Problem: Hook fails with permission errors
Solutions:
chmod +x ~/.cargo/bin/claude-hook-advisorls -la ~/.cargo/bin/claude-hook-advisor~/.cargo/bin: echo $PATHTest each component individually:
# Test directory resolution via hook
echo '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check docs"}' | claude-hook-advisor --hook
# Test command mapping
echo '{"session_id":"test","hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"npm install"}}' | claude-hook-advisor --hook
# Test user prompt analysis
echo '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check the docs directory"}' | claude-hook-advisor --hook
# Check configuration by testing resolution
echo '{"session_id":"test","hook_event_name":"UserPromptSubmit","prompt":"check docs"}' | claude-hook-advisor --hook
The tool looks for configuration files in this order:
-c/--config flag.claude-hook-advisor.toml in current directorybun instead of npm/yarncurl with wget, cat with bat, etc.This tool is inspired by and similar to:
If you find this tool useful, consider supporting its development: