Publishing hooks
Best practices for publishing artifacts that include hooks.
How hooks are installed
When a user runs grekt add, hooks go through this process:
- Script files (non-JSON) in the artifact's
hooks/directory are copied flat to.claude/hooks/ - Hook definitions from JSON files are merged into
.claude/settings.json - On
grekt remove, definitions are removed from settings and script files are deleted
No path rewriting happens. Commands are inserted into settings exactly as you define them.
File naming
Script files are copied flat to .claude/hooks/ — there are no subdirectories per artifact. If two artifacts ship a file with the same name, the second one will be skipped with a collision warning.
Prefix your scripts with the artifact name to avoid collisions:
hooks/
├── hooks.json
├── my-artifact-format.sh # Good
├── my-artifact-lint.sh # Good
├── format.sh # Bad — too generic, will collide
└── lint.sh # BadCommand paths
Since scripts end up in .claude/hooks/, commands should use paths relative to that directory:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/my-artifact-format.sh"
}
]
}
]
}
}If your hook scripts reference other scripts, use relative paths between them since they all end up in the same directory.
Hook types
Hooks follow the Claude Code hooks specification. Three handler types are supported:
Command
Runs a shell command:
{
"type": "command",
"command": ".claude/hooks/my-script.sh",
"timeout": 30
}Prompt
Processed by a model:
{
"type": "prompt",
"prompt": "Check if this change follows our coding standards",
"model": "haiku"
}Agent
Can use tools for up to 50 turns:
{
"type": "agent",
"prompt": "Review and fix any linting issues",
"model": "haiku"
}Supported events
All 14 Claude Code hook events are supported:
| Event | When it fires |
|---|---|
SessionStart | Session begins |
SessionEnd | Session ends |
UserPromptSubmit | User sends a prompt |
PreToolUse | Before a tool is called |
PostToolUse | After a tool is called |
PostToolUseFailure | After a tool call fails |
PermissionRequest | When a permission is needed |
Notification | When a notification is sent |
SubagentStart | Subagent starts |
SubagentStop | Subagent stops |
Stop | Agent stops |
TeammateIdle | Teammate becomes idle |
TaskCompleted | Task finishes |
PreCompact | Before context compaction |
Complete example
my-artifact/
├── grekt.yaml
└── hooks/
├── hooks.json
└── my-artifact-format.shhooks/hooks.json:
{
"grk-type": "hooks",
"grk-name": "auto-format",
"grk-description": "Format files after edit",
"target": "claude",
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/my-artifact-format.sh"
}
]
}
]
}
}hooks/my-artifact-format.sh:
#!/bin/bash
npx prettier --write "$CLAUDE_FILE_PATHS"Related
- Artifacts - Hook component overview
- grekt add - Installing artifacts with hooks
- grekt remove - Removing artifacts and their hooks