Context: Studying Claude Code source code (backup branch)
Message Ordering When Hooks Fire on SkillTool
From toolExecution.ts, the resultingMessages array builds in this order for non-MCP tools (which SkillTool is):
1. PreToolUse hook messages (line 815) hook_success attachments
2. PreToolUse additionalContext (line 846) hook_additional_context, <system-reminder> wrapped
3. [SkillTool.call() executes]
4. tool_result (line 1478) SkillTool output + contextModifier
5. PostToolUse hook results (line 1515) pushed immediately for non-MCP tools
(includes PostToolUse additionalContext from toolHooks.ts:133-142)
6. PostToolUse timing summary (line 1548) ant-only, if slow
7. newMessages from SkillTool (line 1566) skill metadata, SKILL.md content, attachments, permissions
8. hook_stopped_continuation (line 1572) if PreToolUse set preventContinuation
9. MCP hookResults (line 1585) only for MCP tools, empty here
Key insight: skill content (newMessages) always lands last for non-MCP tools. No hook event fires after it. This means skill instructions have the strongest positional influence (model weighs recency).
Options to Override Skill Content
- Edit SKILL.md directly: put instructions at the tail (strongest position within the skill block)
- CLAUDE.md: positionally first (weakest by recency) but architecturally privileged as system prompt
- Wrapper skill: nest the target skill, append instructions after. Outer skill’s post-invocation text lands in a later newMessages batch
- Hook the tools the skill calls (not Skill itself): PreToolUse on Bash/Edit/Read injects
context at action time - PostToolUse on Skill: lands before skill body (positional disadvantage), but
wrapping gives some weight for strong directives