Claude Code Hooks Tutorial: Run It Unattended Overnight (13

Claude Code can run for eight hours overnight without you babysitting it — but only if you wire up hooks. And almost nobody shows you this part. If you're using Claude Code for real work and you're still watching the terminal like a hawk because you don't trust it near production, you already know the pain. In the next 13 minutes I'll show you the exact five-hook event system, the settings.json config, and three bash scripts I run on my own home server. Most tutorials stop at slash commands and subagents. Hooks are the 90% they skip — the layer that lets you log, block, or trigger anything Claude does. By the end you'll have a copy-paste blueprint for unattended runs. I'm Lazar, I build automation systems for clients daily, and this is the config I actually trust. Let's start where every tutorial ends.
Here's the situation almost every solopreneur and small team hits the moment they try to use Claude Code for real work. You open the terminal, you give it a task, and for the first ten minutes it's magic. Then you walk away to make coffee, come back, and Claude has rewritten a file you didn't want touched, run a git command you didn't approve, or burned through tokens on a tangent. So now you sit there. You watch every tool call. You approve every edit. And the productivity gain you were promised quietly disappears, because a senior person is now babysitting an AI instead of doing senior work. This is the exact problem clients bring to me. They say, we tried Claude Code, it's powerful, but we can't leave it alone with our repo. And they're right not to. Out of the box, Claude Code has no audit trail you can actually trust. No external notifications. No automatic guardrails against destructive commands. The slash commands tutorials show you, the subagents everyone's hyping, the MCP servers in every thumbnail — none of that solves the trust problem. They make Claude more capable. They don't make it more accountable. The piece that does is hooks. And hooks are barely covered anywhere, which is wild, because they are the single feature that turns Claude Code from a coding assistant into an auditable autonomous worker. So let me walk you through it the way I'd walk a client through it. There are five hook events you need to know. PreToolUse fires before Claude runs any tool — a bash command, a file edit, a web fetch, anything. This is your blocker. You can inspect what Claude is about to do and return a non-zero exit code to stop it cold. PostToolUse fires right after the tool runs, with the result. This is your logger and your notifier. UserPromptSubmit fires when you send a new prompt — useful for injecting context or stamping every session with metadata. Notification fires when Claude wants your attention, like when it's waiting for approval. And Stop fires when the session ends — this is your reporting hook, your commit hook, your cleanup. Five events. That's it. Everything you need to wrap Claude in a layer of observability lives in those five. Now here's the part people miss. You don't configure hooks in code. You configure them in a single settings.json file in your project's .claude directory. The structure is simple. You declare a hooks object. Inside it, you list the event name. Inside that, you give a matcher — which tool or pattern triggers it — and a command, which is just a shell command. That shell command can be anything. A one-liner. A bash script. A Python file. A curl to an external API. Claude pipes the tool call data into that command as JSON on stdin, and the exit code of your script decides what happens next. Zero means proceed. Non-zero on a PreToolUse blocks the action. That's the whole mental model. Let me show you the three hooks I actually run, because theory is cheap. Hook one is a PreToolUse blocker. It reads the incoming JSON, checks if the command contains rm dash rf, force pushes, drops a database table, or pushes directly to main. If it matches any of those, the script exits with code two, prints an error message, and Claude is forced to rethink. About forty lines of bash. It has saved me from at least three near-disasters when I left long-running sessions going. Hook two is a PostToolUse logger. Every time Claude edits a file, this hook fires. It grabs the file path, the diff size, a timestamp, and pipes it into a local SQLite audit table. Then it sends a one-line summary to a Telegram bot. So while I'm away from my desk, my phone buzzes — Claude just modified payment-handler.ts, thirty-two lines changed. If I see something I don't like, I open the terminal and stop the session. If I don't, I keep doing my actual work. That single hook is the difference between trusting Claude with eight hours of autonomous work and not. Hook three is the Stop hook. When Claude finishes the session, this script runs the test suite, runs the linter, and if everything passes it creates a git commit with a summary of what was done. Then it sends me a full report — files changed, tests passing, time elapsed, tokens used. I wake up, check my phone, see the summary, and either merge or roll back. Claude reports for duty when the shift is over. The whole config is about a hundred lines total across settings.json and three bash scripts. No external dependencies beyond curl and sqlite, both of which are already on any Linux box or WSL setup. You can adapt it to Slack, Discord, email, a webhook into your own dashboard — the shell is the universal interface, which is exactly why hooks are so powerful. Let me show you what this actually looks like running. I kick off a session, give Claude a refactoring task that touches about twelve files, and walk away. Within seconds my phone starts buzzing with PostToolUse notifications. Each one tells me which file, how big the change, what tool was used. Halfway through, Claude tries to run a database migration command. The PreToolUse hook catches it, blocks it, and Claude pivots to ask me instead. Forty minutes later, the session ends. Stop hook fires. Tests run green, commit gets created, summary lands on my phone. I never opened the terminal. That is the actual productivity gain everyone was promised and almost nobody is delivering, because they skipped hooks. One thing to watch out for. Hooks run with the full permissions of your user, so write them defensively. Quote your variables. Validate the JSON input. Don't pipe untrusted strings into eval. Treat them like cron jobs, because that's effectively what they are — small scripts running on automated triggers. And test each hook in isolation before chaining them. If your PostToolUse logger has a bug, it can slow Claude to a crawl, because every single tool call is waiting for your script to exit. Keep them fast. Under two hundred milliseconds is a good target. If you need heavy processing, fire and forget — background the work and return immediately. That's the system. Five events, one config file, a handful of bash scripts, and suddenly Claude Code is something you can actually leave running while you sleep, while you take calls, while you do the work only you can do.
Want more like this?
I publish practical AI automation, GenAI engineering, and faceless content workflows on YouTube every week.
Subscribe to bizflowai.io on YouTube — never miss a new tutorial.
Planning an AI automation project or need a second opinion on your architecture?
Connect with me on LinkedIn — Lazar Milicevic, GenAI Engineer & bizflowai.io Founder.
Visit bizflowai.io for our services, case studies, and AI consulting.