1. What the agent calls it
Tommy ran out for coffee, sat back down. He’d already worked it out in his head: event, handler, arrow, a ready-made list of events. All that was left was to find out what that thing was called in his agent.
“It’s called hook,” says Alex. “In plain English, think of it as ‘an auto-action on an event.’ That’s exactly your arrow, only inside a session with the agent: a certain event happened — you sent a request, the agent finished a reply, the agent edits a file — and the attached handler ran on its own. No reminders, no ‘just don’t forget.’ Event happens — action fires, period.”
“So this is not ‘ask the agent to do it.’” Tommy hesitates. “This is… set it up so it does it on its own.”
“Well, there you go.” Alex is pleased. “That’s the same setup seat I was talking about. You hang a hook once — and then it lives without you. The most common first example is that after every edit the code gets combed automatically; you didn’t lift a finger. An hour later you realize you’ve stopped thinking about it altogether. It just does it.”
“Can you be more specific?” Tommy is already trying to picture it. “Where do you configure all this?”
“In the project file, .claude/settings.json.” Alex nods. “You put the event plus the command there, what to run. And to check that the hook is in place, use /hooks right in the session. Remember the essence: hook is an action attached to a session event; it fires on its own — every time, not ‘when you remember.’ You are configuring the agent’s behavior for the first time, not tugging it by the hand for each action.”
2. The log that writes itself
“Enough words,” says Alex. “And you’re not going to poke around in the config by hand — that’s not your job. Just ask the AI agent in plain words, exactly as you stated your spec. Tell it: add a hook.”
Tommy does exactly that — he writes to the agent in an ordinary sentence, the way he’s used to:
Add a hook: on every request I send, append its text with a timestamp to the file requests.log.
The agent doesn’t ask twice — it takes care of it itself. It drops a tiny handler script .claude/hooks/log-prompt.sh next to it and writes the event into .claude/settings.json — that’s where the project settings live. Alex unfolds on the screen what the agent just put there so Tommy can see his spec come to life:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{ "type": "command", "command": ".claude/hooks/log-prompt.sh" }
]
}
]
}
}
“I’ll explain everything now, don’t be scared of the brackets.” Alex breaks it down line by line so Tommy doesn’t drown. “UserPromptSubmit is the event: ‘the user sent a request to the agent,’ exactly the moment you wrote in the spec. Here you don’t even need a filter — there’s only one event, nothing to react to selectively. And command is what to run: start our little script, which will append a line to the log. See? That’s your HOOK_SPEC, only in the agent’s language. Event, action, where to write — all three columns are here.”
Your spec — in the agent’s language. Left — the HOOK_SPEC that Tommy said in words; right — what the agent put into the project: settings.json and the script log-prompt.sh. The EVENT field “I sent a request to the agent” became the UserPromptSubmit event in settings.json. The ACTION field “record the time and the request” became the command that runs the script .claude/hooks/log-prompt.sh, and the script pulls out the request text and the time. The WHERE field “requests.log” became the script line that appends to the file requests.log. You said it in words — the agent translated it into its language; all three fields are there Your spec — in the agent’s language HOOK_SPEC — you said it in words The agent put into the project EVENT ACTION WHERE I sent a request to the agent record the time and the request requests.log .claude/settings.json "hooks": { "UserPromptSubmit": [ { "hooks": [ { "type": "command", "command": ".claude/hooks/log-prompt.sh" } ] } ] .claude/hooks/log-prompt.sh INPUT=$(cat) PROMPT=$(echo "$INPUT" | jq -r '.prompt') echo "[$(date '+%H:%M')] $PROMPT" >> requests.log catch the packet → pull out the request text → append a line You said it in words — the agent translated it into its language. All three fields are there“Why a separate script, not a line right here?”
“Because the text of your request isn’t handed to the hook in some random way, but as a bundle — in JSON format, which we worked with on the radar. The script will unpack that bundle and pull out the request itself. Take a look at what the agent put there; it’s tiny.”
Alex opens the file .claude/hooks/log-prompt.sh, which the agent just created:
#!/bin/bash
INPUT=$(cat) # bundle with data arrives here
PROMPT=$(echo "$INPUT" | jq -r '.prompt') # extract the request text from it
echo "[$(date '+%H:%M')] $PROMPT" >> requests.log # append to the log
“Three lines: catch the bundle, extract the request text from it, append it to requests.log with a timestamp. That’s the same arrow event → action, only in live code. The script needs jq — that’s the standard tool for parsing JSON, and the file itself must be executable, but the agent will do that for you.”
What happens when you send a request. Top lane — the hook: you sent the request “Fix the scoring function in Tetris” — the UserPromptSubmit event happened — the agent passes the hook a JSON packet, the prompt field holds the request text — the script catches the packet and pulls out the text with jq — appends a line with the time — a new line appears in requests.log. Bottom lane — the agent: then it takes the same request into work as usual and fixes the code; the hook fires at the moment of sending. This hook doesn’t change the agent’s work — it only leaves a trace outside What happens when you send a request You sent a request “Fix the scoring function in Tetris” pressed Enter — and that’s it, the rest happens by itself HOOK 1. Event 2. Packet to the hook 3. Script UserPromptSubmit happened by itself { "prompt": "…" } JSON — text inside cat → jq caught, pulled out text 4. Log requests.log + [time] Fix… AGENT — then as usual takes the same request into work — reads the code, fixes the scoring function Why a separate script, not a line in the config: the request comes not as plain text but as a JSON packet — the script unpacks it and takes the “prompt” field This hook doesn’t change the agent’s work — it only leaves a trace outside. You didn’t lift a finger“So those are my three lines.” Tommy peers closer. That abstract arrow from the previous lecture — event → action — now lies in front of him as two files: here is the event (UserPromptSubmit), here is the action (command → script), here is the file (requests.log). Not just a hand-wavy diagram, but a real configuration that is about to work.
“Good thing we asked the agent to create this hook. I wouldn’t want to write something like that myself.” Tommy almost shudders. “Good thing AI writes such things now. Brr.”
Alex checks that the hook is in place and suggests working as usual:
/hooks # shows configured hooks — our UserPromptSubmit should be here
Fix the scoring function in Tetris.
“/hooks is a command inside the session; it shows all enabled hooks. Ours should be in the list — if it’s not there, then the config wasn’t picked up, look for a typo. And if it is there — then you just keep working, you don’t do anything special.”
Tommy sends a request. And on its own a line appears in requests.log: the time and the text of what he just asked. He didn’t add it. He sends the next one — another line.
“I didn’t even lift a finger.” He watches the file fill up without a single movement from him. Something shifted under that: he no longer keeps notes by hand every time; he has configured the behavior once. In an hour there will be a ready log of all his requests that he didn’t keep for a second.
3. Bonus: let it say “Done” out loud
“Since we can attach actions to events,” Alex says with a smirk, “let’s attach something fun. Want the agent to speak out loud when it’s finished? That’s a hook too, just for a different event — Stop, meaning ‘the agent finished its reply.’ And you set it up the same way — with words, not hands.”
Tommy is already throwing the phrase at the agent without any help:
Add one more hook: when you finish the reply, say “Done” out loud.
The agent adds another hook to settings.json — this time for the Stop event:
{
"hooks": {
"Stop": [
{ "hooks": [ { "type": "command", "command": "say 'Done, sir'" } ] }
]
}
}
“say is a command from your operating system; it speaks text aloud,” Alex explains. “It’s built into macOS; other systems have their own equivalents. As soon as the agent finishes the task, the computer will say ‘Done.’”
“Whoa, it talked!” Tommy jumps up: the machine answered in a voice. “Butler, damn it! I have a butler-computer now: I lie down — it reports ‘everything is ready, sir.’ How did I live without this?!”
“Here, remember this, it’s important.” Alex immediately draws the line. “This is not ‘the agent started speaking.’ Nobody came to life. This is your hook triggering a system speech command — the same say, or another one for your OS. You yourself attached the hook ‘finished work → say the word.’ The magic is not in the AI, but in the fact that you bound an action to an event. Look at it that way: the same auto-action as with the log, only this one speaks aloud. But yeah — pretty cool.”
“Yeah, yeah, I get it.” Tommy nods, but can’t help grinning: the talking computer still scares him and delights him.
4. Hard boundary: a trace, not memory
And then Tommy blurts out:
“So that means I made a log, which means the agent remembers everything now! Does it have memory now or what?”
“No,” Alex cuts him off sharply, without a smile. “This is the most important warning of the day, don’t miss it. requests.log is an external trace, a log file outside. It is not the agent’s memory and not a ‘knowledge base from which it learns something.’ The log is for you — to check what was done and when. The agent didn’t get smarter because this file exists, and it didn’t learn anything new.”
“Then what’s the difference?” Tommy frowns, not seeing it right away. “The file exists; everything is written in it.”
“In who it serves.” Alex separates the two things. “Look: hook is an external log plus an auto-reaction to an event. That’s what we just did. And the agent’s memory — so that it remembers context between sessions on its own, recognizes your project tomorrow — is a completely different thing, a separate topic, and we’ll get to it later. Don’t mix them up. Today we didn’t ‘fix Claude’s memory.’ We set up an external log that writes itself. But that’s cool too, agreed.”
A trace, not memory. Left — what we did today: the hook writes the log requests.log — a file outside, it fills itself on every event; you read it to find what was done and when; the agent doesn’t read it by itself, got no smarter from it and remembered nothing. Right — the agent’s memory: for the agent to remember the context itself and know your project tomorrow, it needs something it picks up itself at the start of a new session — that is a different thing and a separate topic, we’ll get to it later. The difference is whom it serves: the log — you, memory — the agent. I set up a notebook for myself, not a brain transplant for the agent A trace, not memory Hook + log done today event in the session hook requests.log you read you • a file outside — written by itself • read by you: what was done and when • the agent doesn’t read it by itself • got no smarter, remembered nothing ≠ The agent’s memory a different topic — later sessiontoday sessiontomorrow agent picks it up itself • the agent remembers the context • tomorrow it knows your project • picks it up itself — at the start of a new session • not done today The difference is whom it serves: the log — you, memory — the agent. I set up a notebook for myself, not a brain transplant for the agent“Ah, right.” Tommy runs it through his head and gets it. In the morning he’d diagnosed it himself: the problem wasn’t the agent’s memory, but the fact that there was no log outside. He made the log. Memory has nothing to do with it.
“Got it,” he says. “The log is for me, not for it. I set up a notebook for myself, not transplanted a brain into the agent.”
“Now that’s right.” Alex nods.