A line in CLAUDE.md that says "do not write HubSpot lifecycle" is a request. A PreToolUse hook that blocks the write is enforcement. GTM operators who already run Claude Code against files, exports, and scripts should put the hard stops in hooks, not in another reminder the model can ignore.

That is the whole argument. Skills and context files still matter. They tell the agent how the work is supposed to go. Hooks are the part that runs even when the model is tired, compacted, or working in auto mode.

Anthropic's own extension docs are blunt about it. An instruction like "never edit .env" in CLAUDE.md or a skill is a request, not a guarantee. A PreToolUse hook that blocks the edit is enforcement. If a GTM rule has to hold every time, it belongs there.

What is a Claude Code hook?

A hook is a script, HTTP call, MCP tool, prompt, or subagent that Claude Code runs at a fixed point in the session. You do not ask the model to remember to run it. The product fires it.

Anthropic's hooks guide calls this deterministic control. Certain actions always happen rather than relying on the LLM to choose to run them. The common GTM events are small:

EventWhen it firesWhat a GTM team uses it for
PreToolUseBefore a tool call runsBlock HubSpot writes, .env edits, rm -rf, unscoped MCP mutations
PostToolUseAfter a tool call succeedsLog the call, format the packet, attach a receipt
UserPromptSubmitBefore Claude reads the promptReject pasted private app tokens
StopWhen Claude tries to end the turnKeep working until the evidence packet exists
SessionStartSession start, resume, or compactRe-inject write policy after context gets summarized

The matcher is a filter, not a sermon. Edit|Write only watches file edits. Bash only watches shell. An MCP write tool can be matched by name. You do not need a hook on every event in the hooks reference. You need the two or three that match the blast radius of the job.

Hooks live in settings JSON. Project hooks go in .claude/settings.json and travel with the repo. User hooks stay on one machine. If two operators need the same GTM guardrail, commit the project file. Do not leave it in ~/.claude and then wonder why a teammate's session wrote a close date.

Why don't CLAUDE.md and skills stop a bad CRM write?

Because they are instructions. Instructions compete with the rest of the context window.

That is not a dunk on skills. A skill is the right home for the procedure: which export to read, which fields count as evidence, what the markdown packet should look like. Context files are the right home for definitions. Neither one is a permission system.

I have watched this fail in the boring way. The CLAUDE.md said read-only. The skill said draft a packet, do not patch dealstage. The session was long. Compaction summarized the early rules into "be careful with HubSpot." Then auto mode approved a Bash call that hit the private app. The model was not evil. It was doing what models do when the original sentence is no longer in working memory.

Anthropic already documents this in the permission-mode docs, not as a GTM story, as a product fact. Boundaries you state in conversation are not stored as rules. The classifier re-reads them from the transcript. A boundary can be lost if context compaction removes the message that stated it. For a hard guarantee, they tell you to add a deny rule. Hooks are the same idea applied to tool calls.

This is also why Cowork vs Claude Code still matters after the chat merge. Cowork is a good surface for a finished recap. Claude Code is the surface where a GTM repo can carry hooks, skills, and git history. If the leftover has to be a team system, the guardrail has to live in the repo.

"Claude Code should always be a WIP. Optimizing your AI environment is ongoing work, not a one-time setup." Sebastian Silva, Founder, HigherOps

A hook is part of that WIP. You add it the second time the agent does the thing you already told it not to do.

Which Claude Code hooks should GTM operators write first?

Start with blocks, not notifications. A desktop ping is nice. A blocked write is the job.

Anthropic's own first serious example is a protect-files.sh script on PreToolUse for Edit|Write. It checks the path against .env, package-lock.json, and .git/, then exits 2 to block the edit and sends the reason back to Claude. GTM teams can copy that shape without becoming platform engineers.

Three first hooks are enough.

1. Protect secrets and token files. Same script, GTM paths. Block .env, HubSpot private app JSON, Salesforce connected-app secrets, and anything named credentials. If the agent needs HubSpot, it should use a scoped connection you already set up, not a file it found in Downloads.

2. Block mutating CLI and MCP calls until a human says so. Match Bash and the HubSpot or Salesforce MCP write tools. Deny hs, hubspot, curl to api.hubapi.com with PATCH or POST, sf data update, and any MCP tool whose name includes update, create, or delete on CRM objects. Let reads through. The first useful GTM agent is an evidence collector. MCP connectors still need that write policy even when the hook is the last line of defense.

3. Refuse to stop without a packet. A Stop hook can keep the turn open until a file exists: deal IDs, source quotes, proposed field changes, and a line that says "no CRM write." Anthropic's best-practices guide treats a Stop hook as a deterministic gate. The check is a script, not a vibe. For GTM, the check is "the review packet is on disk."

Do not put formatting, lint, or Slack noise on PreToolUse if it is slow. That event sits on the hot path of every matched tool call. Keep the blocker dumb and fast. Regex the path or the command. Exit 2. Write the reason to stderr. Save the cleverness for PostToolUse, which cannot undo the action because the tool already ran.

HTTP hooks are the team version of the same pattern. Instead of a local script, you POST the event to an internal audit service and return deny from there. That is how you get one policy across laptops. It is also how you start the audit trail before anyone grants more CRM access.

How do hooks work when Claude Code is in auto mode?

They matter more.

With Claude Code v2.1.283 or later, auto mode is the built-in starting permission mode for interactive terminal and VS Code sessions. A classifier reviews actions instead of you. That is fine for git status. It is a bad sole control for a HubSpot private app sitting in the same repo as a pipeline audit.

Hooks still run. A PreToolUse deny, or exit code 2, blocks the call. Returning ask forces a prompt the classifier cannot wave through. Deny rules in settings still block in every mode, including bypassPermissions.

The failure mode I care about is not a cartoon agent dropping production. It is a RevOps lead who turned on auto mode because the permission prompts were annoying, then used the same session to "clean up a few close dates." The classifier is not your operating policy. Your operating policy is the hook and the deny list.

If the work is a one-off recap from a local CSV, stay in Cowork or merged chat and do not connect write tools. If the work is a procedure the team will rerun, open Claude Code in the GTM repo and assume auto mode will try to be helpful.

What should stay in a skill instead of a hook?

Anything that needs judgment.

Hooks are bad at "is this deal stalled." They are good at "do not call the deals update endpoint." If you try to encode the whole pipeline review in a 40-line Bash matcher, you will either block nothing useful or block the session from working.

Keep this split:

GTM rulePut it hereWhy
How to build a pipeline evidence packetSkillSequence, examples, exception paths
Lifecycle and owner definitionsContext file / CLAUDE.mdAlways-on facts
Never write dealstage, lifecyclestage, hubspot_owner_id, amountPreToolUse hookMust hold even after compaction
Never edit .env or token filesPreToolUse hookOfficial protect-files pattern
Log every MCP tool callPostToolUse or HTTP hookReceipt, not prevention
Do not end until the packet has deal IDs and quotesStop hookDeterministic done test
Draft the QBR narrativeSkill or CoworkNeeds writing judgment

If you cannot name the workflow, you cannot name the hook. That is the same argument as you cannot automate an undefined RevOps workflow. A hook does not invent process. It enforces a process you already wrote down.

People are already doing the connective GTM work in agents. Anthropic sampled 1.2 million anonymized Claude Cowork sessions from May 11 to 31, 2026. Business process and operations was 33.4% of the sample. Sales and revenue operations was 4%. The point is not that Cowork is Claude Code. The point is that operator work is already landing in agent sessions at a volume where "I told it not to" is not a control.

How should a RevOps team roll out hooks without theater?

One leftover. One block. One committed file.

  1. Pick the write you are most afraid of. Lifecycle, owner, amount, close date, or a production workflow.
  2. Keep the agent on reads and a local markdown packet for a week. No hook required yet if there is no mutating tool in the session.
  3. When a mutating tool appears, add one PreToolUse hook that denies it by name or command pattern. Test it by asking Claude to do the forbidden thing on purpose.
  4. Commit .claude/settings.json and the script under .claude/hooks/. If it is not in git, it is a personal superstition.
  5. Add the Stop check only after the packet format is stable. Do not block the turn on a file layout you have not agreed on.
  6. If two people now run it, keep the hook in the project settings. Do not Slack a screenshot of settings.json.

Skip the 12-hook platform. Skip prompt-based hooks for the first guardrail. Prompt hooks ask another model to judge the call. That is useful later for fuzzy cases. The first GTM hook should be a command that does not think.

Also skip pasting a HubSpot token into the session for one run. A UserPromptSubmit hook that rejects strings that look like private app keys is a reasonable second week add. The first week is still "the write tool cannot run."

Frequently asked questions

Do GTM operators need to write production-grade shell to use hooks?

No. The official protect-files example is a short script, a matcher, and exit code 2. If you can maintain a HubSpot workflow, you can maintain that. Have Claude Code draft the script, then you read it before it is trusted.

Will a hook replace HubSpot or Salesforce permissions?

No. CRM permissions are still the source of truth for who can edit a record. The hook stops your agent from calling the tool. MCP governance still needs scoped tokens, staged writes, and a human approval step. Stack them. Do not pick one.

What if the hook is wrong and blocks real work?

Read the stderr reason, loosen the matcher, and commit the change. A noisy hook that you can edit is better than a polite skill that failed silently on Thursday. If you are blocking more than a handful of calls a day, the matcher is too broad.

Do hooks run in Cowork?

Treat Cowork as the finished-file surface. The durable hook setup described here is a Claude Code project setting. If the GTM leftover is a team procedure, run it in Claude Code so the hook file is next to the skill and the packet.

Key takeaways

  • Prompts, skills, and CLAUDE.md request GTM policy. Hooks enforce it.
  • Put "never write these CRM fields" and "never edit token files" in PreToolUse, not in a reminder.
  • Auto mode makes this more important, not less. A classifier is not your write policy.
  • First hooks should be dumb and fast. Exit 2. Leave judgment in skills.
  • Commit project hooks. A guardrail that lives on one laptop is not a team system.
  • Do not give the session a mutating CRM tool until the hook that would block it has been tested on purpose.