CONTEXT ENGINEERING · SPECIALIST 4

Automate recurring work

Turn a procedure you've done twice by hand into a skill, then wire one hook so it never gets skipped.

Behrad Mirafshar

Behrad Mirafshar

Founder, Bonanza Design
|

September 18, 2026

9 min read

Completing Context Engineering for Claude Code means Core 1–3 plus the takeover test. This module is optional, for one specific situation: a procedure in your own project that you have now done by hand at least twice.

You end with a skill that encodes the procedure, and a hook that checks it never gets skipped — the same shape as the updating-claude-md skill you already ran in Core 2, whose own build is the worked example below.

01

The lessons

In order. Skill or command first, since the wrong choice there makes everything after it harder than it needs to be.

  1. Skills versus custom commands versus Projects

    A custom command inserts text you already wrote. It adds no new ability, and Claude can't choose to use it — you have to type it. A skill loads by its own description, so Claude picks it up on its own when the situation matches. A Project bundles instructions and files for one workspace, with no pickup logic at all. If the thing you're automating should just happen when the situation calls for it, it's a skill.

  2. Where skills live: user, project, public

    A user-level skill lives in your home folder and follows you into every project. A project-level skill ships inside the repo, so anyone who clones it gets it too. A public skill or plugin comes from someone else's marketplace listing — same shape, different trust level.

  3. Plugins and reviewing before you install

    A plugin bundles skills, commands and hooks someone else wrote. A hook runs shell commands on your machine with your session's permissions the moment it fires — read the SKILL.md and every hook script before you install, the same way you'd read a package before adding it as a dependency.

  4. Hooks: the nine events you will actually use

    Claude Code has more than 30 hook events, and the list grows with each release. Nine of them cover almost every hook worth writing, from the moment a session starts to the moment it ends. Run /hooks in your own session for the full current list. Pick the event that matches when the thing should happen, not the event that happens to be running when you write the hook.

  5. Wiring a hook in settings.json

    Registering a hook is a few lines in settings.json: which event, which command to run, an optional timeout. Nothing runs until the wiring exists — the skill and the hook script are inert on their own.

  6. Bonus: how updating-claude-md was built

    The skill from Core 2 that already keeps your CLAUDE.md current wasn't handed to you finished. It was built test-first, it failed once in a documented way, and the fix is below — the real build-along, not a description of one.

Hooks: the nine events you will actually use

Every hook you'll ever write fires on one of these. Pick the event that matches when the thing should happen.

EventFires when
SessionStartA new session begins.
UserPromptSubmitYou submit a prompt, before Claude reads it.
PreToolUseBefore a tool call runs. Can block it.
PostToolUseAfter a tool call finishes.
PermissionRequestClaude Code needs your permission for something.
NotificationClaude Code shows a notification, e.g. a permission prompt.
StopThe main reply finishes.
TaskCompletedA background task finishes.
SessionEndA session ends — the one this page's build-along uses.
The nine hook events worth knowing first, and the one this page's build-along wires. Run /hooks for the full list in your version.

We cover what a skill actually is, and where it fits next to a custom command, in more depth on the Claude Skills page.

02

The assignment

This one runs on your own project. There's no reference-project snapshot for specialists — your repeated procedure stands in for the “add a competitor” step Move from idea to evidence shipped a working page from.

Starts from

Your own finished core project, where "add a competitor" (or your project's equivalent recurring step) has now been done twice by hand.

Required output

A skill encoding that procedure, plus one hook.

Passes when

The skill runs on a third instance and produces the same shape as the two you did by hand. The hook fires at the moment you claimed it would, verified in its log.

03

The Claude Code skill, the hook, the wiring

This example adapts the updating-claude-md skill from Core 2, its hook and its wiring, in the order you build them: skill first, then the hook that runs it, then the wiring that fires the hook. A reader who writes the hook first has nothing to point it at. Project details use a fictional reading-list app.

1. The skill — how
SKILL.md (excerpt)
1---
2name: updating-claude-md
3description: Use when a session is about to end, when CLAUDE.md has no
4 last_updated marker, or when files, dev-docs or sessions may have changed
5 since CLAUDE.md was last updated.
6---
7
8# Updating CLAUDE.md
9
10## Overview
11
12CLAUDE.md loads into every session, so it holds the gist of the project and
13says where the detail lives. The detail stays in its own folder. A marker in
14the frontmatter records when CLAUDE.md was last brought up to date, so each
15run only has to look at what changed since then.
16
17Write straight to CLAUDE.md. This runs before a session ends, so there is no
18one to approve a draft.
19
20## The shape CLAUDE.md always has
21
22```markdown
23---
24last_updated: 2026-09-14T16:40
25---
26# <Project name>
27
28## Overview
29What it is and who it is for, in 2 to 3 lines.
30
31## Active work
32- `dev-docs/2026_09_12-PROGRESS-pt1-Reading_List_App.md`: Build a
33 reading-list app that saves books and tracks reading progress.
34```
35
36## Common mistakes
37
38| Mistake | Fix |
39|---|---|
40| Progress numbers or "status as of" lines in CLAUDE.md | Active work lists the dev-doc file name and its gist |
41| Field lists, API tables, long explanations copied in | One line and the path of the file that holds them |
42| Marker left unchanged | The marker moves every time, even when nothing else changed |
43| Only the latest dev-doc read | Every dev-doc not DONE appears in Active work |
44| Hand-written guardrails dropped while restructuring | They stay; only their placement changes |
2. The hook — when

Fires on SessionEnd. The four guards are annotated inline — each one is a real failure the hook had to be corrected for. It uses your configured permissions. Test the skill interactively first and allow only the tools it needs; a background run cannot ask you to approve a blocked action. Check its log for failures.

~/.claude/hooks/claude-md-update.sh
1#!/usr/bin/env bash
2# SessionEnd hook: when a session ends on purpose in a project that has a
3# CLAUDE.md, spawn a headless Claude that runs the updating-claude-md skill.
4# Never blocks the exit.
5LOG="$HOME/.claude/claude-md-update.log"
6[[ "${CLAUDE_MD_UPDATER:-}" == "1" ]] && exit 0 # guard 1 — don't recurse
7IN=$(cat 2>/dev/null || true)
8command -v jq >/dev/null || exit 0
9reason=$(jq -r '.reason // ""' <<<"$IN")
10sid=$(jq -r '.session_id // ""' <<<"$IN")
11cwd=$(jq -r '.cwd // ""' <<<"$IN")
12case "$reason" in prompt_input_exit|logout) ;; *) exit 0 ;; esac # guard 2 — only deliberate exits
13[[ -z "$cwd" || "$cwd" == "$HOME" || "$cwd" == *"/.claude/plugins/"* ]] && exit 0 # guard 3a
14[[ -f "$cwd/CLAUDE.md" ]] || exit 0 # guard 3b — only projects that already have a CLAUDE.md
15lock="$HOME/.claude/claude-md-update.lock.$(printf '%s' "$cwd" | md5 -q)"
16mkdir "$lock" 2>/dev/null || exit 0 # guard 4 — one updater per project at a time
17echo "$(date '+%F %T') start cwd=$cwd sid=$sid" >> "$LOG"
18(
19 cd "$cwd" && CLAUDE_MD_UPDATER=1 claude -p --model sonnet \
20 --permission-mode acceptEdits \
21 "Use the updating-claude-md skill now and update CLAUDE.md. Do not ask questions." \
22 >> "$LOG" 2>&1
23 echo "$(date '+%F %T') done cwd=$cwd rc=$?" >> "$LOG"
24 rmdir "$lock" 2>/dev/null
25) </dev/null >/dev/null 2>&1 &
26disown
27exit 0

The four guards

  1. Don't recurse.

    The Claude the hook spawns also ends a session, which would fire the hook again, forever. An environment variable set only inside the spawned run breaks the loop.

  2. Only deliberate exits.

    Matches prompt_input_exit and logout specifically. A crash shouldn't trigger a rewrite of a file nobody was ready to have touched.

  3. Only projects that already have a CLAUDE.md.

    Skips the home directory and plugin folders, and skips any project that hasn't been introduced to the skill yet — the hook maintains a file, it doesn't create the first one.

  4. One at a time.

    A lock keyed on the project's path stops two sessions closing at once from overwriting each other's update.

3. The wiring — who does it

Three lines in settings.json register the script against the event. Nothing runs until this exists — the skill and the hook script are inert on their own.

settings.json (excerpt)
"SessionEnd": [
  { "hooks": [{ "type": "command", "command": "~/.claude/hooks/claude-md-update.sh" }] }
]

A hook is when. A skill is how. claude -p is who does it — a second, headless Claude in the background, so you're never waiting.

Skills and hooks are one way to wire a tool to Claude. When the choice is between that and a direct API call, see MCP or a single API call.

04

The method correcting itself

This is the skill's own documented failure, from when it was first built and tested — not a hypothetical. The first baseline run wrote progress numbers straight into CLAUDE.md, where they went stale the moment the numbers changed.

Before
CLAUDE.md
## Active work

- pt1-Reading_List_App: Book search working. 3 of 5 tests
  passing as of 2026-09-12. Reading-progress filter still failing —
  investigating filter state, ~60% done overall.

Every session that opened this file after that point read a number that was already wrong. The fix wasn't a longer file — it was a rule: point-in-time progress belongs in the dev-doc it describes, never in CLAUDE.md itself. That rule is now the first row of the skill's own Common mistakes table, above.

After
CLAUDE.md
## Active work

- `dev-docs/2026_09_12-PROGRESS-pt1-Reading_List_App.md`: Build a
  reading-list app that saves books and tracks reading progress.

Gist in CLAUDE.md, detail in the file it points to — that's the difference between instructions that stay useful and instructions nobody reads.

05

Turn a job you repeat into a skill

A blank skill file to fill in, plus a one-page card of the nine hook events you will actually use, so the skill runs without you starting it.

  • A blank skill file and a hooks cheat sheet

    Fill in the blanks to turn a job you repeat into a skill, then pick the moment it should fire from the nine most useful events on the card.

    A procedure in a document

    “At the end of a session, update the project notes: read the work records, keep the gist, leave the detail in its own file.”

    It only works when someone remembers to open the document, and Claude cannot pick it up on its own.

    The same procedure as a skill

    SKILL.md, plus the line that fires it

    A skill is how · a hook is when

    The description line
    “Use when a session is about to end, or when files may have changed since the notes were last updated.” Claude reads that line and picks the skill up without being told.
    The steps
    Read the marker, collect what changed since, write the gist into the notes, move the marker.
    The hook
    Three lines in settings.json fire it the moment a session ends, in the background, so nobody waits.
    The guards
    Do not fire on a crash, do not run twice at once, skip folders with no notes, and never let the spawned session trigger itself.
Verify your email once to unlock these and every other material across the course.
06

FAQ

Want your own recurring work automated, not just read about?

A working session that turns your team's repeated procedures into skills and hooks.

The course

Core modules first. Specialists are optional — take the one that matches your work.

  1. Core 1

    Stop Claude guessing

    Turn a vague idea into a brief Claude can build from: facts, assumptions marked as assumptions, agreed success criteria.

  2. Core 2

    Stop starting over

    Set up project memory so a fresh session, or a teammate, can pick the work up from the files alone.

  3. Core 3

    Move from idea to evidence

    The route from brief to reviewed change: research, one shared page, a prototype, a plan, a small build, a second opinion.

  4. Specialist 4

    Automate recurring work

    Encode a procedure you repeat as a skill, and fire it automatically with a hook.

    You are here
  5. Specialist 5

    Build in parallel

    Run two pieces of work at once without them blocking each other, then review how they fit together.

  6. Specialist 6

    Run research you can trace

    Research where every claim traces back to a saved source, and gaps are marked instead of filled in.

  7. Standalone

    MCP or a single API call

    A judgment call on two axes: what it costs you in context window, and how much access it opens.

Behrad Mirafshar
About the Author

Behrad Mirafshar

Founder, Bonanza Design

Founder of Bonanza Design. Builds operating brains for companies in the AI knowledge crisis. Multi-week engagements, run on the client's infrastructure, owned by the client.

Connect on LinkedIn