Skip to content

Add Claude Code hook integration for command suggestions#9

Merged
philpennock merged 7 commits into
mainfrom
claude/add-tool-check-command-gKuRj
Apr 13, 2026
Merged

Add Claude Code hook integration for command suggestions#9
philpennock merged 7 commits into
mainfrom
claude/add-tool-check-command-gKuRj

Conversation

@philpennock
Copy link
Copy Markdown
Member

Summary

This PR adds a new aifr hook check-command subcommand that integrates with Claude Code's PreToolUse hook system. It analyzes shell commands and suggests aifr alternatives when applicable, allowing users to leverage aifr's access controls instead of running raw shell commands.

Key Changes

  • New hook command group (cmd/aifr/cmd_hook.go): Top-level command for AI agent integrations
  • New hook check-command subcommand (cmd/aifr/cmd_hook_checkcommand.go): Reads Claude Code hook payloads from stdin and outputs hook responses
  • Command analysis engine (internal/hookcmd/suggest.go): Analyzes shell commands and generates aifr suggestions for:
    • File operations: cat, head, tail, ls, find, stat, diff
    • Text search: grep, egrep, fgrep, rg
    • File inspection: wc, hexdump, xxd, od
    • Checksums: sha256sum, sha1sum, md5sum, shasum, sha384sum, sha512sum
    • Stream editing: sed -n (read-only patterns)
    • Version control: git log, git diff
  • Shell parsing utilities (internal/hookcmd/shellparse.go): Robust tokenization and operator detection that handles:
    • Single and double quoted strings
    • Backslash escaping
    • Shell operators (pipes, chains, subshells)
    • Environment variable prefixes
    • Path-based command names
  • Hook protocol implementation (internal/hookcmd/hookcmd.go): Parses Claude Code hook payloads and generates compliant responses
  • Comprehensive test coverage: Unit tests for all parsing, suggestion, and integration logic

Implementation Details

  • Commands with shell operators (pipes, chains, subshells) are skipped to avoid unsafe transformations
  • Suggestions only apply to read-only operations; write operations like sed 's/foo/bar/' are not suggested
  • Shell quoting is applied intelligently to preserve special characters in file paths
  • The hook response denies the Bash call and provides the aifr alternative in the reason field
  • Silent exit (no output) when no suggestion applies, allowing the original command to proceed

https://claude.ai/code/session_017inmawi6PUgMy9zSu6EXKv

claude added 7 commits April 10, 2026 01:57
Adds a new `aifr hook` parent command with a `check-command` sub-command
designed for use as a Claude Code PreToolUse hook. When configured for
the Bash tool matcher, it reads the hook payload from stdin, analyzes
the shell command, and denies it with an aifr alternative suggestion
when the operation can be safely handled by aifr.

Recognized commands: cat, head, tail, grep/rg, find, ls, wc, stat,
diff, sed -n, sha256sum/md5sum/sha1sum, hexdump/xxd, git log, git diff.

Complex commands (pipes, chains, subshells) are passed through silently.

The `hook` parent command is extensible for future hook integrations.

https://claude.ai/code/session_017inmawi6PUgMy9zSu6EXKv
Verifies that a piped command (git log --oneline | head -n 10) passes
through CheckCommand without generating a suggestion, confirming the
full wiring from JSON input through shell operator detection.

https://claude.ai/code/session_017inmawi6PUgMy9zSu6EXKv
Pipelines ending in | head -n N or | tail -n N are now recognized and
mapped to the appropriate aifr limit parameter per command:
  - cat file | head -n N  →  aifr read --lines=1:N file
  - git log | head -n N   →  aifr log --max-count=N
  - grep pat . | head -N  →  aifr search --max-matches=N pat .
  - find/ls | head -N     →  --limit=N

Suggestions now carry MCP tool metadata (tool name + args). When --mcp
is set or an aifr MCP server is detected in .mcp.json / $AIFR_MCP,
the deny reason references the MCP tool call instead of a CLI command.

https://claude.ai/code/session_017inmawi6PUgMy9zSu6EXKv
Use a proper shell parser (mvdan/sh) instead of hand-rolled tokenize,
splitPipeline, and hasShellOperators functions. The AST-based approach
correctly handles all quoting variants, redirections (excluded from args
automatically), environment variable prefixes (in CallExpr.Assigns),
and pipeline detection via BinaryCmd nodes.

https://claude.ai/code/session_017inmawi6PUgMy9zSu6EXKv
The end-to-end pipeline test now checks that the deny reason actually
mentions "aifr log" / "aifr_log" and "max-count" / "max_count", matching
what the comment promised.

https://claude.ai/code/session_017inmawi6PUgMy9zSu6EXKv
Pipelines ending in sed -n 'N,Mp' or sed -n 'Np' are now recognized
as pipeline modifiers. For cat, this maps directly to aifr read --lines:

  cat file | sed -n '50,100p'  →  aifr read --lines=50:100 file
  cat file | sed -n '42p'      →  aifr read --lines=42:42 file

When the sed range starts at line 1, it normalizes to HeadLines so
commands with head-style limits (find --limit, search --max-matches,
log --max-count) also benefit.

https://claude.ai/code/session_017inmawi6PUgMy9zSu6EXKv
@philpennock philpennock merged commit 900a9fd into main Apr 13, 2026
6 checks passed
@philpennock philpennock deleted the claude/add-tool-check-command-gKuRj branch April 13, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants