Claude Code Hooks and Scheduled Routines: Handing Off the Start Button
Everything you've built so far, CLAUDE.md, skills, subagents, shares one thing in common: you had to type something to start it. Open a session and CLAUDE.md gets read. Type a slash command and a skill runs. Ask for a delegation and a subagent moves. Automatic as it sounds, the start button was always in a human's hands. Last lesson got you as far as splitting work off to run elsewhere. Today's about letting go of that start button itself. Just here for the automation, not the theory? This lesson alone covers it. If you found this lesson searching for a result rather than the word "hook," that's already covered in Lesson 1, so let's go straight to the result here.
- Hook
A hook is a custom shell command that runs automatically at a specific point in Claude Code's lifecycle. It fires on a defined event, after editing a file, when opening a new session, when sending a notification, so a specific action always happens instead of Claude deciding case by case whether to run it.
What a hook is: a command that runs on an event
The official docs currently list more than 30 hook events. You don't need to memorize all of them, just get a feel for the handful that come up most.
| Event | Fires when | Common use |
|---|---|---|
SessionStart | A session starts fresh or resumes | Running checks or loading context every time you start |
PostToolUse | Right after a tool call succeeds | Auto-cleanup after editing a file |
Notification | Claude Code sends a notification | A desktop alert while it's waiting for input |
Stop | Claude finishes a response | Checking the result at the end of every turn |
This is a list that grows and shifts release to release. This lesson reflects what the official docs showed as of August 22, 2026, so if you're reading it much later, check the current event list against the docs again.
Where you register a hook decides its scope, the same logic as CLAUDE.md and skill locations.
| Location | Scope | Shared? |
|---|---|---|
~/.claude/settings.json | Every project of yours | No, this computer only |
.claude/settings.json | This project only | Yes, shared with the team through version control |
.claude/settings.local.json | This project only | No, gitignored |
Under each event, matcher narrows the scope further. Add matcher: "Edit|Write" under PostToolUse, for example, and the hook only fires when a file-editing tool runs, staying quiet for Bash or Read.
Setting up one hook
This blog's own repository has a real SessionStart hook wired into its .claude/settings.json.
{
"hooks": {
"SessionStart": [
{
"hooks": [
{ "type": "command", "command": "node scripts/handoff.mjs --hook", "timeout": 15 },
{ "type": "command", "command": "node scripts/i18n-sync.mjs --changed --hook", "timeout": 20 }
]
}
]
}
}With matcher left empty, both scripts run for every case that fires SessionStart: opening a session fresh, resuming one, or running /clear or /compact. One checks whether a different working directory has left a handoff note for this repository; the other checks whether the Korean and English editions have drifted out of structural sync. Both only check, they don't touch any files, so even a misfire doesn't delete or break anything.
A hook you're setting up for the first time is safer starting in a spot like this. The official docs' own first walkthrough is similar: a hook that sends a desktop notification while Claude is waiting for input. Open ~/.claude/settings.json (a personal setting, so it won't touch any other project) and add this.
{
"hooks": {
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code is waiting for input\" with title \"Claude Code\"'"
}
]
}
]
}
}This is a macOS example; Windows and Linux each use a different notification command. The exact commands for each platform are laid out in the official docs linked under Sources below.
~/.claude/settings.json, then type /hooks and confirm the new hook you just registered shows up under Notification. This menu is view-only, you can't edit from here, editing means reopening the settings JSON or asking Claude to do it. Next, give Claude a task that needs permission and switch to a different window. If a desktop notification shows up, you've completed this lesson.What a schedule is: automation that runs at a set time
If a hook is "when something happens," a schedule is "at a time I set." Claude Code offers scheduling three ways, and each comes with different conditions. The interval and plan values in the table are as of August 2026.
| Cloud routines | Desktop scheduled tasks | /loop | |
|---|---|---|---|
| Where it runs | Anthropic-managed cloud | Your computer (desktop app) | Your computer (current session) |
| Runs with your computer off | Yes | No | No |
| Access to local files | No (repository is freshly cloned every run) | Yes | Yes |
| Minimum interval | 1 hour | 1 minute | 1 minute |
| Plan requirement | Pro, Max, Team, or Enterprise as of August 2026 (not available on Free) | None, desktop app required | Only while the session stays open |
Want a report draft to pop up automatically at 9 a.m. on the first of every month, like this track's running scenario? Cloud routines are the right fit, since they run on Anthropic's cloud even with your computer off. Type /schedule in your terminal and describe it in plain language.
/schedule Draft the monthly report with report-researcher and monthly-report-draft at 9 a.m. on the first of every monthClaude asks you to confirm the recurrence, the repository, and the prompt, then saves it to your account. The official docs note that cloud routines are still in research preview, so behavior and limits may change, and that they run fully autonomously, with no permission-mode picker and no approval prompts mid-run. If /schedule isn't showing up in your command list, you might be signed in with an API key or organization authentication instead. This command only appears when you're signed in with a claude.ai subscription account.
If the material your report draft depends on lives on your own computer rather than in a repository, the situation changes. Cloud routines clone the repository fresh every run, so they can't touch local files at all. That's when you'd use the desktop app's scheduled tasks instead. From the sidebar, go to Routines and pick Local to create a scheduled task that runs directly on your computer, with the minimum interval down to 1 minute. It only runs while the desktop app is open and your computer is awake, though. A run missed while your computer was asleep gets caught up just once, the most recent one within the last 7 days, when the app reopens (as of August 2026). Miss six days of a daily job and it runs exactly once, the moment it wakes up.
If all you want is a short, tight repeat of a few minutes inside a session that's already open, /loop is the lighter option. It only runs while the session stays open and ends the moment you close it, but if it's still active when you reopen the session with --resume, it picks back up right where it left off. Choosing between the three comes down to two questions: does it need to run with your computer off, and does it need to touch files on your own computer. There's no combination where both are true.
Anything that runs on its own needs a safety net
Cloud routines' own documentation states this plainly: "runs as a full autonomous Claude Code cloud session. There's no permission mode picker, and no approval prompts during execution." Running without a person watching means you have to narrow, ahead of time, what it's even allowed to do. You choose repositories yourself when you set up a routine, but every connector already linked to your account gets included by default. The official docs recommend keeping only what a routine actually needs, for both repositories and connectors, and dropping the rest.
Hooks carry a similar trap. You can build a PermissionRequest hook that auto-approves permission prompts, and leave matcher empty or set it too broadly, like .*, and every permission prompt, file writes and shell commands included, gets silently auto-approved. The official docs explicitly warn to keep this matcher as narrow as possible. Desktop scheduled tasks' "always allow" option works the same way. Approve it once, and every run after that goes through without asking, so it's worth occasionally checking the details page to see exactly which tools you've auto-approved.
Which narrows down to one principle: automate up through the draft, but not the last, hard-to-undo step, publishing, sending, paying. This track's running scenario is built the same way. What shows up automatically on the first of every month is a report draft, not the email that actually goes out to the client. Leaving a spot where a person checks and presses the final button is the safer call.
My own first automation wasn't a hook in a settings file either. It was a relay chain built inside a skill. While bundling content marketing prep into a skill, I chained the steps together so that finishing one step moves straight to the next, and hitting a snag partway sends it back to redo the earlier step, letting the whole thing run untouched until a finished result comes out. The idea itself, do this the moment that finishes, is exactly the same as a hook. Only the location is different.
- A hook runs when a set event fires; a schedule runs at a set time, with no one around. Event names can grow release to release, this lesson reflects what the docs showed as of August 22, 2026
- Register hooks in the
hooksblock ofsettings.json; location (home/project/local) decides scope, andmatchernarrows it further - Scheduling comes in three forms: cloud routines, desktop scheduled tasks, and
/loop. Need it to run with your computer off? Cloud routines (Pro plan or higher as of August 2026). Need it to touch local files? Desktop scheduled tasks - Cloud routines run fully autonomously with no permission prompts, so choose repositories carefully and keep only the connectors a routine actually needs, since every linked connector is included by default
- Don't automate the last, hard-to-undo step, publishing, sending, paying. Leave that for a person to check
Frequently asked questions
What events does Claude Code support for hooks?
As of August 2026, the official docs list more than 30 registered events. The most common ones are SessionStart, which fires when you open a session; PostToolUse, right after a tool call succeeds; Notification, when Claude Code sends a notification; and Stop, when a response finishes. Event names can grow or change release to release, so it's safer to check the current list against the official docs.
What's the difference between a hook and a scheduled routine?
A hook runs alongside a specific event, like editing a file or starting a session. A schedule runs itself at a set time, regardless of any event. Hooks register in settings.json and work inside the session that's currently open; scheduling uses a separate execution path entirely, cloud routines, desktop scheduled tasks, or /loop.
Can I use Claude Code automation on the free plan?
Hooks work regardless of plan, all you need is the settings file. Scheduling depends on which kind. Desktop scheduled tasks and /loop have no separate plan requirement, but cloud routines, which run even with your computer off, are only supported on Pro, Max, Team, and Enterprise plans as of August 2026, not on Free.
What happens to a scheduled task if I turn my computer off?
Depends on which kind. Desktop scheduled tasks only run while the app is open and your computer is awake, and a run missed while it was asleep gets caught up just once, the most recent one within the last 7 days, when the app reopens (as of August 2026). If it needs to run even with your computer fully off, use cloud routines, which run on Anthropic-managed cloud instead.
Can hooks or schedules be risky?
Yes, running without anyone watching means a wide approval scope is genuinely risky. Cloud routines run fully autonomously with no permission prompts at all, and a hook's auto-approval matcher set too broadly silently approves everything, including file writes and shell commands. That's why it's safer to automate only up through the draft and leave the last, hard-to-undo step, publishing, sending, paying, for a person to check.
Sources (5)Expand to see all sources
- Claude Docs, "Automate workflows with hooks": hook definition, the full event list (SessionStart, PostToolUse, Notification, Stop, and around 30 more) and when each fires, the notification-hook walkthrough (with the macOS osascript example), narrowing scope with matcher, the scope table by settings location, PermissionRequest auto-approval and the warning to keep matcher narrow (checked 2026-08-22)
- Claude Docs, "Hooks reference": the full event schema and the matcher target field for each event (checked 2026-08-22)
- Claude Docs, "Automate tasks with routines": cloud routine definition, research-preview notice, the three trigger types (schedule, API, GitHub), the Pro/Max/Team/Enterprise plan requirement, the explicit fully-autonomous statement (no permission prompts), /schedule CLI usage and the claude.ai subscription sign-in requirement, the 1-hour minimum interval for scheduled triggers (checked 2026-08-22)
- Claude Docs, "Schedule recurring tasks in Claude Code Desktop": desktop scheduled task definition, the comparison table across cloud, desktop, and /loop scheduling (run location, computer requirement, local file access, minimum interval), the requirement that the app be open and the computer awake, the 7-day most-recent-run catch-up rule (checked 2026-08-22)
- Verified locally (the link points to the official doc it was checked against): This repository's actual SessionStart hook in .claude/settings.json (node scripts/handoff.mjs --hook, node scripts/i18n-sync.mjs --changed --hook), confirmed locally; Claude Code version 2.1.239 (checked 2026-08-22)