Hooks
A big focus for us with agentic coding is context economy.
The model only does good work if the right knowledge is in front of it at the right time. Every token of "just in case" guidance you leave permanently in context (AGENTS.md for example) is noise and tax you pay on every single turn.
So the real question is never "where do I write the convention down?" It's "how does this convention get injected at the moment it's needed, and stay out of the way the rest of the time?"
This and the fact that skill execution can be inconsistent is what made me start trailing hooks over skills.
What each one actually is
Skills are lazy and model-judged. A skill sits dormant with a one-line description and a trigger. The agent reads the full thing only when it decides the trigger matches what it's doing. It's a fantastic and valuable concept meaning zero bloat when irrelevant, full detail when relevant. The catch is the word decides! The injection depends on the model recognising the moment. When it works it's invisible and when it doesn't, it's a silent and sometimes costly miss. You don't find out until the code is wrong.
Hooks are deterministic and boundary-bound. This means a hook fires because we reached a known step in spec-driven workflows for example before build, before tasks not because the model had a hunch. You give up "fires anywhere" but you gain "fires exactly here, every time." For a convention whose entire purpose is "applies when we write or refactor UI," and where that work flows through the same workflow steps every time, the step boundary is a near-perfect trigger. No judgement call, no silent miss.
So they're not really competitors. One is a lazy net, the other is a deterministic gate.
The principle
The problem is not the size of some additional context e.g. a conventions doc. A 150-line doc loaded once when you start UI work is free. The same doc loaded on every edit, or added permanently in AGENTS/CLAUDE.md, is the waste. The problem is not size it is frequency of injection. (which is why skills exist!)
If you agree with that then the principle becomes:
Reference, don't inline. The always-present part is a one-line pointer. The heavy payload is pulled in on demand, once, at the right boundary.
Where I am (for now)
I'm still trailing this. Not "hooks instead of skills." Hooks as the primary gate, skills as the backstop.
- A hook fires
before design or tasks/before build, checks something such as "does this touch the UI layer at all?", and if so tells the agent to read frontend conventions (written for the agent, in the context registry) and self-check against them. Deterministic, scoped, silent for backend-only work. - The skill covers the case the hook can't see which is usually ad-hoc changes outside the workflow. Skills fire on the kind of work, not the step. It's the safety net for when there's no boundary to hang a hook on.
To make this work you do need a single source of truth. The moment the hook and the skill both state their own versions of the convention they start to drift, they started to drift. Pick one canonical doc. Everything else points at it. Duplication isn't just bloat it's how your guidance starts lying to you.
Hooks are newer for me, so this is a trial, not conclusive advice. Hooks have trade-offs, they only fire inside the SDD workflow.
Skill = "when you're doing this kind of thing, here's what to know."
Hook = "at this exact point, do this, every time." Put the knowledge in one place. Make everything else a pointer to it. Pay for context only when it earns its place.