Skip to content

Commit e974d2d

Browse files
committed
feat(agents): introduce PostToolUse hook for Claude Code and Copilot, auto-lint script
1 parent 97d3760 commit e974d2d

4 files changed

Lines changed: 79 additions & 0 deletions

File tree

.claude/hooks/post-edit.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
# Auto-format and lint after file edits.
3+
# Works with both Claude Code (PostToolUse) and GitHub Copilot (postToolUse) hooks.
4+
#
5+
# Input formats:
6+
# Claude Code: {"tool_input": {"file_path": "/path/to/file"}}
7+
# Copilot: {"toolName": "edit", "toolArgs": "{\"path\": \"/path/to/file\"}"}
8+
#
9+
# Exit codes:
10+
# 0 = success (formatting applied silently)
11+
# 2 = lint errors found (fed back to Claude as feedback; ignored by Copilot)
12+
13+
# Parse file path - handles both Claude Code and Copilot input formats
14+
FILE_PATH=$(cat | node -e "
15+
let d='';
16+
process.stdin.on('data',c=>d+=c);
17+
process.stdin.on('end',()=>{
18+
try {
19+
const j=JSON.parse(d);
20+
if (j.tool_input?.file_path) { console.log(j.tool_input.file_path); return; }
21+
if (j.toolArgs) { const a=JSON.parse(j.toolArgs); if (a.path) console.log(a.path); }
22+
} catch {}
23+
})
24+
")
25+
26+
# Skip if no file path or file doesn't exist
27+
[[ -z "$FILE_PATH" || ! -f "$FILE_PATH" ]] && exit 0
28+
29+
# Auto-format with prettier using the project's installed version
30+
npx prettier --write "$FILE_PATH" 2>/dev/null
31+
32+
# Find the nearest package directory with eslint config
33+
SEARCH_DIR=$(dirname "$FILE_PATH")
34+
PACKAGE_DIR=""
35+
while [[ "$SEARCH_DIR" != "/" ]]; do
36+
if [[ -f "$SEARCH_DIR/eslint.config.mjs" ]]; then
37+
PACKAGE_DIR="$SEARCH_DIR"
38+
break
39+
fi
40+
SEARCH_DIR=$(dirname "$SEARCH_DIR")
41+
done
42+
43+
# Run lint from the package directory using the project's lint setup
44+
if [[ -n "$PACKAGE_DIR" ]]; then
45+
LINT_OUTPUT=$(cd "$PACKAGE_DIR" && npm run lint 2>&1)
46+
if [[ $? -ne 0 ]]; then
47+
echo "$LINT_OUTPUT" >&2
48+
exit 2
49+
fi
50+
fi
51+
52+
exit 0

.claude/settings.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"hooks": {
3+
"PostToolUse": [
4+
{
5+
"matcher": "Edit|Write|MultiEdit",
6+
"hooks": [
7+
{
8+
"type": "command",
9+
"command": ".claude/hooks/post-edit.sh"
10+
}
11+
]
12+
}
13+
]
14+
}
15+
}

.github/hooks/hooks.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"version": 1,
3+
"hooks": {
4+
"postToolUse": [
5+
{
6+
"type": "command",
7+
"bash": "bash .claude/hooks/post-edit.sh"
8+
}
9+
]
10+
}
11+
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ tests
2828
automation/run-e2e/ctrf/*.json
2929
.cursor
3030
.windsurf
31+
.claude/settings.local.json

0 commit comments

Comments
 (0)