I automated my entire dev workflow with Claude Code hooks
<p>Most people use Claude Code as a smarter terminal assistant.<br> Type a request, read the response, approve the changes.<br> That's fine, but it leaves a lot of capability on the table.</p> <p>Claude Code has a hook system that wires the AI directly into your existing workflow:<br> your formatter, your test runner, your notification system.<br> We've been running hooks in production-style setups for a few months now<br> and the interaction model genuinely changes when the tool stops being conversational<br> and starts being ambient.</p> <p>Here's what we actually run and why.</p> <h2> What hooks are </h2> <p>Hooks are defined in <code>~/.claude/settings.json</code> under the <code>hooks</code> key.<br> Each hook fires at a lifecycle event and runs a shell command.</p> <p>The four events
Most people use Claude Code as a smarter terminal assistant. Type a request, read the response, approve the changes. That's fine, but it leaves a lot of capability on the table.
Claude Code has a hook system that wires the AI directly into your existing workflow: your formatter, your test runner, your notification system. We've been running hooks in production-style setups for a few months now and the interaction model genuinely changes when the tool stops being conversational and starts being ambient.
Here's what we actually run and why.
What hooks are
Hooks are defined in ~/.claude/settings.json under the hooks key. Each hook fires at a lifecycle event and runs a shell command.
The four events that matter:
-
PreToolUse -- fires before Claude runs a tool (file write, bash command, etc.)
-
PostToolUse -- fires after a tool completes
-
Notification -- fires when Claude sends status updates
-
Stop -- fires when Claude finishes a response
Hooks can be filtered by tool name, so you can target Bash separately from Write and Edit.
The basic structure:
{ "hooks": { "PostToolUse": [ { "matcher": "Write", "hooks": [ { "type": "command", "command": "your-command-here" } ] } ] } }{ "hooks": { "PostToolUse": [ { "matcher": "Write", "hooks": [ { "type": "command", "command": "your-command-here" } ] } ] } }Enter fullscreen mode
Exit fullscreen mode
Hook 1: Auto-format on file write
Every time Claude writes or edits a file, format it immediately. This keeps diffs clean and removes a whole category of review noise.
{ "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "bash -c 'FILE=$(echo $CLAUDE_TOOL_OUTPUT | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"filePath\\\",\\\"\\\"))\" 2>/dev/null); if [ -n \"$FILE\" ]; then case \"$FILE\" in *.rs) cargo fmt -- \"$FILE\" 2>/dev/null;; *.py) ruff format \"$FILE\" 2>/dev/null;; *.ts|*.tsx|*.js) npx prettier --write \"$FILE\" 2>/dev/null;; esac; fi'" } ] } ] } }{ "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "bash -c 'FILE=$(echo $CLAUDE_TOOL_OUTPUT | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"filePath\\\",\\\"\\\"))\" 2>/dev/null); if [ -n \"$FILE\" ]; then case \"$FILE\" in *.rs) cargo fmt -- \"$FILE\" 2>/dev/null;; *.py) ruff format \"$FILE\" 2>/dev/null;; *.ts|*.tsx|*.js) npx prettier --write \"$FILE\" 2>/dev/null;; esac; fi'" } ] } ] } }Enter fullscreen mode
Exit fullscreen mode
The hook reads the file path from the tool output, detects the extension, and runs the right formatter. Silent on error (2>/dev/null) so it doesn't interrupt the session if a formatter isn't installed.
For Rust specifically, we also add a cargo check after writes. This catches type errors while Claude is still in context and can fix them in the same pass:
{ "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "bash -c 'FILE=$(echo $CLAUDE_TOOL_OUTPUT | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"filePath\\\",\\\"\\\"))\" 2>/dev/null); if echo \"$FILE\" | grep -q \"\\.rs$\"; then cargo check 2>&1 | tail -5; fi'" } ] }{ "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "bash -c 'FILE=$(echo $CLAUDE_TOOL_OUTPUT | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"filePath\\\",\\\"\\\"))\" 2>/dev/null); if echo \"$FILE\" | grep -q \"\\.rs$\"; then cargo check 2>&1 | tail -5; fi'" } ] }Enter fullscreen mode
Exit fullscreen mode
Hook 2: Security scan before bash commands
Before Claude runs any shell command, scan for patterns worth flagging: piping to sh/bash from curl, rm -rf without bounds, writes to /etc/.
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "bash -c 'CMD=$(echo $CLAUDE_TOOL_INPUT | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"command\\\",\\\"\\\"))\" 2>/dev/null); RISKY=0; echo \"$CMD\" | grep -qE \"curl.*\\|.*(bash|sh)\" && RISKY=1; echo \"$CMD\" | grep -qE \"rm -rf /[^t]\" && RISKY=1; echo \"$CMD\" | grep -q \"/etc/\" && RISKY=1; if [ $RISKY -eq 1 ]; then echo \"[hook] high-risk command flagged -- review before proceeding\"; fi'" } ] } ] } }{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "bash -c 'CMD=$(echo $CLAUDE_TOOL_INPUT | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"command\\\",\\\"\\\"))\" 2>/dev/null); RISKY=0; echo \"$CMD\" | grep -qE \"curl.*\\|.*(bash|sh)\" && RISKY=1; echo \"$CMD\" | grep -qE \"rm -rf /[^t]\" && RISKY=1; echo \"$CMD\" | grep -q \"/etc/\" && RISKY=1; if [ $RISKY -eq 1 ]; then echo \"[hook] high-risk command flagged -- review before proceeding\"; fi'" } ] } ] } }Enter fullscreen mode
Exit fullscreen mode
This doesn't block the command. It prints a visible warning in the output so you catch it when skimming. We've caught a few genuine mistakes this way -- not AI hallucinations, just cases where a reasonable command had an unexpected side effect in context.
Hook 3: Desktop notification when Claude finishes
Switch to another window during a long task and you lose track of when it's done. The Stop hook fires on response completion.
{ "hooks": { "Stop": [ { "hooks": [ { "type": "command", "command": "notify-send 'Claude Code' 'Done.' --icon=terminal --urgency=low 2>/dev/null || true" } ] } ] } }{ "hooks": { "Stop": [ { "hooks": [ { "type": "command", "command": "notify-send 'Claude Code' 'Done.' --icon=terminal --urgency=low 2>/dev/null || true" } ] } ] } }Enter fullscreen mode
Exit fullscreen mode
On Ubuntu this uses notify-send. On macOS, swap it for osascript -e 'display notification "Done." with title "Claude Code"'.
For remote machines, we send to a Discord webhook instead:
{ "type": "command", "command": "bash -c 'source ~/.secrets; curl -s -X POST \"$DISCORD_WEBHOOK_DEV\" -H \"Content-Type: application/json\" -d \"{\\\"content\\\": \\\"Claude finished a task\\\"}\" > /dev/null'" }{ "type": "command", "command": "bash -c 'source ~/.secrets; curl -s -X POST \"$DISCORD_WEBHOOK_DEV\" -H \"Content-Type: application/json\" -d \"{\\\"content\\\": \\\"Claude finished a task\\\"}\" > /dev/null'" }Enter fullscreen mode
Exit fullscreen mode
Hook 4: Custom status line with git context
The Notification hook fires when Claude sends progress updates (tool names, status messages). We use it to set the terminal title to show current branch and last action:
{ "hooks": { "Notification": [ { "hooks": [ { "type": "command", "command": "bash -c 'BRANCH=$(git branch --show-current 2>/dev/null || echo \"no-git\"); MSG=$(echo $CLAUDE_NOTIFICATION | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"message\\\",\\\"\\\")[:40])\" 2>/dev/null); printf \"\\033]0;claude [%s] %s\\007\" \"$BRANCH\" \"$MSG\"'" } ] } ] } }{ "hooks": { "Notification": [ { "hooks": [ { "type": "command", "command": "bash -c 'BRANCH=$(git branch --show-current 2>/dev/null || echo \"no-git\"); MSG=$(echo $CLAUDE_NOTIFICATION | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"message\\\",\\\"\\\")[:40])\" 2>/dev/null); printf \"\\033]0;claude [%s] %s\\007\" \"$BRANCH\" \"$MSG\"'" } ] } ] } }Enter fullscreen mode
Exit fullscreen mode
The terminal title becomes something like claude [main] Writing src/main.rs. When you have multiple Claude sessions across different projects, this is the only sane way to tell them apart in your taskbar.
Hook 5: Test runner on source file changes
For TDD-style work, tests should run automatically after Claude modifies source files. The tight feedback loop matters: Claude writes code, tests run, Claude sees the result in the same context window and can iterate without prompting.
{ "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "bash -c 'FILE=$(echo $CLAUDE_TOOL_OUTPUT | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"filePath\\\",\\\"\\\"))\" 2>/dev/null); if echo \"$FILE\" | grep -qE \"\\.(rs|py|ts)$\" && ! echo \"$FILE\" | grep -qE \"(test|spec)\"; then echo \"[hook] running tests...\"; if [ -f Cargo.toml ]; then cargo test 2>&1 | tail -10; elif [ -f pyproject.toml ]; then python -m pytest -x -q 2>&1 | tail -10; fi; fi'" } ] } ] } }{ "hooks": { "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "bash -c 'FILE=$(echo $CLAUDE_TOOL_OUTPUT | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get(\\\"filePath\\\",\\\"\\\"))\" 2>/dev/null); if echo \"$FILE\" | grep -qE \"\\.(rs|py|ts)$\" && ! echo \"$FILE\" | grep -qE \"(test|spec)\"; then echo \"[hook] running tests...\"; if [ -f Cargo.toml ]; then cargo test 2>&1 | tail -10; elif [ -f pyproject.toml ]; then python -m pytest -x -q 2>&1 | tail -10; fi; fi'" } ] } ] } }Enter fullscreen mode
Exit fullscreen mode
Skips test files themselves to avoid infinite loops. Detects project type by manifest file. Tails 10 lines so the output stays readable.
Putting it together
The full hooks section in ~/.claude/settings.json:
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [{ "type": "command", "command": "..." }] } ], "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "..." }, { "type": "command", "command": "..." } ] } ], "Notification": [ { "hooks": [{ "type": "command", "command": "..." }] } ], "Stop": [ { "hooks": [{ "type": "command", "command": "..." }] } ] } }{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [{ "type": "command", "command": "..." }] } ], "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "..." }, { "type": "command", "command": "..." } ] } ], "Notification": [ { "hooks": [{ "type": "command", "command": "..." }] } ], "Stop": [ { "hooks": [{ "type": "command", "command": "..." }] } ] } }Enter fullscreen mode
Exit fullscreen mode
Multiple hooks can fire for the same event and run in sequence.
Caveats worth knowing
PreToolUse hooks run synchronously -- a slow pre-hook adds latency before every tool call. Keep them under 100ms or use them sparingly.
PostToolUse hooks run after the tool completes, so slow post-hooks don't block Claude. They just add noise to the output, which is usually fine.
If a hook exits non-zero, Claude sees the output but continues. By default hooks are advisory, not blocking. There's a blocking mode available for PreToolUse, but we haven't needed it -- the warning output is enough.
The hook system is underused because it's not obvious that it exists. Once you wire Claude into your actual toolchain, the conversational back-and-forth collapses into something closer to a fast pair programmer who runs your checks automatically.
The full config is in a public gist at github.com/noxcraftdev if you want a starting point.
Happy coding!*
DEV Community
https://dev.to/noxcraftdev/i-automated-my-entire-dev-workflow-with-claude-code-hooks-2e73Sign in to highlight and annotate this article

Conversation starters
Daily AI Digest
Get the top 5 AI stories delivered to your inbox every morning.
More about
claudemodelavailable
2026 CIO Hall of Fame honorees
The CIO Hall of Fame was created in 1997 to spotlight outstanding IT leaders who had significantly contributed to and profoundly influenced the IT discipline, the use of technology in business and the advancement of the CIO role. Ten years later, in 2007, CIO inducted its second class of honorees into the CIO Hall of Fame during CIO magazine’s 20th anniversary celebration. Now an annual award, presented at the CIO 100 Awards & Conference each August, the CIO Hall of Fame recognizes an elite group of IT leaders. Below are the 222 members of the CIO Hall of Fame, showing the year of their induction and their company affiliation at the time. Class of 2026 Mike Anderson , Chief Digital & Information Officer, Netskope Andrea Ballinger , Chief Information Officer, RPI Dani Brown , SVP & CIO, Whi

2026 US CIO 100 winners: Celebrating IT innovation and leadership
The annual US CIO 100 Awards recognizes CIOs and their organizations for translating technology strategy into measurable business impact at enterprise and public sector scale. This year’s recognized 100 organizations have put technology to use in innovative ways to deliver business value, whether by creating competitive advantage, optimizing business processes, enabling growth, or improving relationships with customers. The award is an acknowledged mark of enterprise IT excellence and leadership. Along with this year’s CIO Hall of Fame inductees , the 2026 CIO 100 US honorees will be recognized at the CIO 100 Awards & Conference taking place August 17-19, 2026, at the Omni PGA Frisco Resort & Spa in Frisco, Texas. The event brings together the most influential CIOs to share how they are na

Scaling a business: A leadership guide for the rest of us
Leadership is changing faster than most organizations can comfortably absorb. In 2026, senior leaders are being measured by a new mix of expectations, sharper accountability for performance, a more vocal and values-driven workforce and rising pressure to protect culture while navigating constant change. These shifts are not theoretical. They are already showing up in how people engage, how boards govern and how executive teams make decisions. At the same time, boards and senior executives are looking at leadership through a more disciplined lens, return on capital invested. Not just “Are we growing,” but “Are we getting more output, more resilience and more customer value from every dollar and every hour we put into the system?” In that context, scaling is not a vanity goal. It is a practi
Knowledge Map
Connected Articles — Knowledge Graph
This article is connected to other articles through shared AI topics and tags.
More in Products
Only 11% of Firms Are Seeing Real AI Returns, Finds KPMG
While business leaders’ enthusiasm for AI appears to be unwavering, only a few are scaling fast enough to turn their spend into real business value, according to new findings from KPMG. Polling more than 2,200 C‑suite and senior execs around the world, the firm’s latest Global AI Pulse report found that business leaders plan to […] The post Only 11% of Firms Are Seeing Real AI Returns, Finds KPMG appeared first on DIGIT .
Databricks Sets Sights on UK Expansion
The investment will allow Databricks to 4x their footprint with a new 137,000 sq ft London HQ. As well as office expansion, the investment will increase job opportunities in the UK. Databricks currently has a team of 500 UK and Ireland employees but this is expected to grow to over 1,000 in the next few […] The post Databricks Sets Sights on UK Expansion appeared first on DIGIT .

2026 US CIO 100 winners: Celebrating IT innovation and leadership
The annual US CIO 100 Awards recognizes CIOs and their organizations for translating technology strategy into measurable business impact at enterprise and public sector scale. This year’s recognized 100 organizations have put technology to use in innovative ways to deliver business value, whether by creating competitive advantage, optimizing business processes, enabling growth, or improving relationships with customers. The award is an acknowledged mark of enterprise IT excellence and leadership. Along with this year’s CIO Hall of Fame inductees , the 2026 CIO 100 US honorees will be recognized at the CIO 100 Awards & Conference taking place August 17-19, 2026, at the Omni PGA Frisco Resort & Spa in Frisco, Texas. The event brings together the most influential CIOs to share how they are na

Discussion
Sign in to join the discussion
No comments yet — be the first to share your thoughts!