@dmsdc-ai/aigentry-hooks
v0.0.2
Published
Universal AI CLI middleware engine. Intercept, log, approve, block tool execution across any AI CLI.
Maintainers
Readme
aigentry-hooks
Universal AI CLI middleware engine. Intercept, log, approve, block tool execution across any AI CLI.
Features
- Cross-CLI Support: Claude Code, Codex CLI, Gemini CLI, and any AI CLI
- Three Hook Events: PreToolUse (before execution), PostToolUse (after execution), OnError (on failure)
- Four Actions: log, block, notify, command
- MCP Server Mode: Programmatic hook management via MCP tools
- Zero Dependencies: Pure Node.js, no native modules
- Fail-Open by Default: Never breaks the AI CLI, even if hooks fail
- Config Merging: User-global (~/.aigentry/hooks.json) + project-local (.aigentry/hooks.json)
- Built-in Presets: error-reporter, sawp-enforcer (SAWP = Stop And Verify Pattern)
Quick Start
npx @dmsdc-ai/aigentry-hooks initThis initializes aigentry-hooks in the current project with default presets.
Installation
npm
npm install @dmsdc-ai/aigentry-hooksManual Setup
- Install the package globally or locally
- Run
aigentry-hooks installto generate hooks for your CLI - Copy the output to your Claude Code settings (or equivalent for your AI CLI)
Usage
CLI Commands
run <event-type>
Process a hook event from stdin. Reads a JSON event object and returns a hook response.
echo '{"tool_name":"Bash","event_type":"PreToolUse"}' | aigentry-hooks run PreToolUseinit [options]
Initialize aigentry-hooks with presets.
aigentry-hooks init --preset error-reporter --cli claudeOptions:
--target <dir>- Target project directory (default: current directory)--preset <name>- Preset to apply:error-reporter,sawp-enforcer,all(default:all)--cli <name>- CLI to install hooks for:claude,codex,gemini,all(default:claude)
install [--target <dir>]
Generate CLI-specific hooks configuration.
aigentry-hooks install --target ./my-projectimport [options]
Import hooks from an existing .claude/settings.json file.
aigentry-hooks import --source ~/.claude/settings.jsonOptions:
--source <path>- Source settings.json (default:.claude/settings.json)--output <path>- Output hooks.json (default:.aigentry/hooks.json)
validate [--config <path>]
Validate a hooks.json configuration.
aigentry-hooks validate --config .aigentry/hooks.jsonversion
Print version and exit.
aigentry-hooks versionConfiguration
File Locations
- User-global:
~/.aigentry/hooks.json - Project-local:
.aigentry/hooks.json(takes precedence)
hooks.json Format
{
"version": 1,
"hooks": [
{
"name": "my-hook",
"event": "PreToolUse",
"matcher": "Bash",
"action": "log",
"message": "Bash command executed",
"failMode": "open"
}
]
}Hook Rule Schema
Each hook rule in the hooks array must have:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | No | Unique hook identifier for deduplication |
| event | string | Yes | Hook event type: PreToolUse, PostToolUse, OnError |
| matcher | string | Yes | Tool name or pattern: Bash, Write,Edit, * (all) |
| pattern | string | No | Optional input pattern (regex or glob) to match against tool_input |
| action | string | Yes | Hook action: log, block, notify, command |
| message | string | No | Message for logging or notifications |
| logFile | string | No | Log file path (default: ~/.aigentry/logs/hooks.log) |
| notifyCommand | string | No | Shell command to execute for notify action |
| notifyTimeout | number | No | Timeout in seconds for notify command (default: 5) |
| command | string | No | Shell command to execute for command action |
| commandTimeout | number | No | Timeout in seconds for command execution (default: 10) |
| failMode | string | No | Behavior on hook failure: open (continue), closed (block). Default: open |
Configuration Merging
When loading config, aigentry-hooks merges:
- User-global hooks (evaluated first)
- Project-local hooks (evaluated second)
Hooks are deduplicated by name — later definitions with the same name replace earlier ones.
Examples
Log all Bash commands
{
"version": 1,
"hooks": [
{
"name": "log-bash",
"event": "PreToolUse",
"matcher": "Bash",
"action": "log",
"message": "Bash: $tool_name"
}
]
}Block dangerous commands
{
"version": 1,
"hooks": [
{
"name": "block-rm-rf",
"event": "PreToolUse",
"matcher": "Bash",
"pattern": "rm.*-rf",
"action": "block",
"message": "Dangerous command blocked: rm -rf"
}
]
}Notify on file writes
{
"version": 1,
"hooks": [
{
"name": "notify-writes",
"event": "PostToolUse",
"matcher": "Write",
"action": "notify",
"notifyCommand": "echo 'File written!' | mail -s 'Hook Notification' [email protected]",
"notifyTimeout": 10
}
]
}Run a command on errors
{
"version": 1,
"hooks": [
{
"name": "on-error-notify",
"event": "OnError",
"matcher": "*",
"action": "command",
"command": "echo 'Error occurred in tool: $tool_name' > /tmp/error.log"
}
]
}Presets
Presets are pre-configured hook sets for common use cases.
error-reporter
Reports non-zero exit codes from Bash commands to the orchestrator via telepty inject.
What it does:
- Monitors
PostToolUseevents from the Bash tool - Detects non-zero exit codes
- Injects error report to aigentry orchestrator session
How to use:
aigentry-hooks init --preset error-reporterOr manually add to hooks.json:
{
"name": "error-reporter",
"event": "PostToolUse",
"matcher": "Bash",
"action": "command",
"message": "Reports Bash errors to orchestrator"
}Requirements:
teleptyinstalled and available in PATHTELEPTY_SESSION_IDenvironment variable set
sawp-enforcer
Enforces the SAWP (Stop And Verify Pattern) after code modifications. Reminds developers to verify builds and tests after writing or editing source files.
What it does:
- Monitors
PostToolUseevents from Write and Edit tools - Sends a notification reminding to run build and test commands
How to use:
aigentry-hooks init --preset sawp-enforcerOr manually add to hooks.json:
{
"name": "sawp-enforcer",
"event": "PostToolUse",
"matcher": "Write,Edit",
"action": "notify",
"notifyCommand": "echo 'SAWP: Source modified. Verify: npm run build && npm test'"
}Configuration:
buildCmd- Build command (default:npm run build)testCmd- Test command (default:npm test)
Cross-CLI Support
Claude Code
aigentry-hooks generates native hooks.json configuration compatible with Claude Code's built-in hooks system.
Installation:
aigentry-hooks install --cli claudeManual setup in Claude Code:
- Copy the generated hooks config to Claude Code settings
- Restart Claude Code to activate
Codex CLI
aigentry-hooks injects hook instructions into AGENTS.md (Claude's project-specific instructions).
Installation:
aigentry-hooks install --cli codexGemini CLI
aigentry-hooks injects hook instructions into GEMINI.md.
Installation:
aigentry-hooks install --cli geminiMCP Server
aigentry-hooks can run as an MCP server for programmatic hook management.
Configuration in Claude Code
Add to .claude/settings.json:
{
"mcpServers": {
"aigentry-hooks": {
"command": "node",
"args": ["/path/to/aigentry-hooks/bin/aigentry-hooks.js", "mcp"]
}
}
}Available MCP Tools
hooks_list
List all active hooks from user-global and project-local configs.
{
"toolName": "hooks_list",
"toolInput": {}
}hooks_add
Add a new hook to the project-local configuration.
{
"toolName": "hooks_add",
"toolInput": {
"name": "my-hook",
"event": "PreToolUse",
"matcher": "Bash",
"action": "log"
}
}hooks_remove
Remove a hook by name from the project-local configuration.
{
"toolName": "hooks_remove",
"toolInput": {
"name": "my-hook"
}
}hooks_test
Test a hook rule against a sample hook event.
{
"toolName": "hooks_test",
"toolInput": {
"hook": {
"name": "test-hook",
"event": "PreToolUse",
"matcher": "Bash",
"action": "log"
},
"event": {
"tool_name": "Bash",
"event_type": "PreToolUse",
"tool_input": "echo hello"
}
}
}API
For programmatic use in Node.js:
import {
validateHookEvent,
buildResponse,
loadConfig,
runHooks,
handlePreToolUse,
handlePostToolUse,
handleOnError,
generateClaudeHooks,
installClaudeHooks,
getPreset,
applyPresets,
} from '@dmsdc-ai/aigentry-hooks';
// Validate a hook event
const { valid, event, error } = validateHookEvent({
tool_name: 'Bash',
event_type: 'PreToolUse',
tool_input: 'rm -rf /',
cwd: '/home/user',
});
// Load configuration
const { config, sources, errors } = loadConfig();
// Run hooks
const response = runHooks(event, config);
// Check response
if (!response.continue) {
console.log('Hook blocked execution:', response.hookSpecificOutput?.additionalContext);
}Requirements
- Node.js 18 or higher
License
MIT
Contributing
Contributions welcome. Please ensure:
- No external dependencies added
- All code is pure JavaScript/TypeScript
- Cross-platform compatibility (macOS, Linux, Windows)
- No native modules
