Setup Hook — runtime test
Hands-on runtime battle-test of Setup Hook. Result: PASS.
Setup Hook is a runtime hook event that runs initialization or maintenance commands at session start, triggered via --init, --init-only, or --maintenance CLI flags.
How It Works
Setup is registered in ~/.claude/settings.json under hooks.Setup, like any other hook event. The runtime fires it with trigger information specifying which flag invoked it. Input includes session_id, transcript_path, cwd, hook_event_name ("Setup"), and trigger ("init" or "maintenance"). The hook script receives this as JSON and can log, configure, or validate before the session begins. Hooks support command execution via type: "command" in the hook definition.
The Test Runtime
Setup hooks were tested against all three CLI patterns on January 16, 2026. For --init (normal session start) and --maintenance (maintenance-mode session), a Setup hook script was registered and invoked via bash. Both fired correctly and passed context including working directory and session ID. The hook ran before the session accepted input, allowing pre-session setup. For --init-only, the Setup hook fired and the CLI exited immediately without starting a session or waiting for a prompt. No user input required. All three triggers correctly received the hook input payload.
What This Enables
--init-only is the significant discovery: a no-session setup mode suitable for CI/CD pipelines, cron jobs, and repository bootstrapping. Standard --init and --maintenance let hooks run initialization logic before accepting interactive prompts. The trigger field in hook input allows a single Setup handler to distinguish init from maintenance without inspecting CLI environment. Combined, these unlock pre-flight validation, environment checks, and cache warming in unattended contexts.
Known Gaps
The --init, --init-only, and --maintenance flags do not appear in claude --help output, creating discoverability friction. Both --init-only and --init use trigger: "init" rather than trigger: "init-only", requiring hook logic to check for session presence if intent differentiation is critical. No documented guarantee on hook execution order when multiple Setup handlers are registered.
Setup Hook Test Results
Feature: Setup hook event Version: 2.1.10 Status: PASS ✅ Tested: 2026-01-16
What Was Tested
The new Setup hook event that can be triggered via --init, --init-only, or --maintenance CLI flags.
Test Setup
Created hook in ~/.claude/settings.json:
"hooks": {
"Setup": [
{
"hooks": [
{
"type": "command",
"command": "bash /Users/ryanhunter/.claude/hooks/setup-test.sh"
}
]
}
]
}
Hook script logs to /tmp/setup-hook-test.log.
Test Results
--init flag
echo "hello" | claude --init -p
Result: ✅ Setup hook fires Hook input:
{
"session_id": "...",
"transcript_path": "...",
"cwd": "/Users/ryanhunter/projects/claude/claude-feature-demos",
"hook_event_name": "Setup",
"trigger": "init"
}
--init-only flag
claude --init-only
Result: ✅ Setup hook fires, then CLI exits immediately (no session)
Hook input: Same as --init with "trigger": "init"
Key insight: --init-only runs Setup hooks then exits. No prompt required, no session started. Perfect for CI/automation.
--maintenance flag
echo "test" | claude --maintenance -p
Result: ✅ Setup hook fires Hook input:
{
"session_id": "...",
"hook_event_name": "Setup",
"trigger": "maintenance"
}
Hook Input Schema
| Field | Type | Description |
|---|---|---|
session_id |
string | UUID for the session |
transcript_path |
string | Path to session transcript |
cwd |
string | Current working directory |
hook_event_name |
string | Always "Setup" |
trigger |
string | "init" or "maintenance" |
Key Findings
Three triggers, two behaviors:
--initand--maintenancestart a session after Setup hook--init-onlyexits immediately after Setup hook (no session)
Trigger field distinguishes intent:
trigger: "init"for--initand--init-onlytrigger: "maintenance"for--maintenance
No prompt required for
--init-only:- Perfect for CI/CD pipelines, cron jobs, repo bootstrapping
Flags not in
--help:- These flags work but aren't documented in
claude --helpoutput
- These flags work but aren't documented in
Surprises
--init-onlyusestrigger: "init"nottrigger: "init-only"- makes sense semantically but could trip up hook logic trying to distinguish
test_6805ffcdac86fbb737aef913ed255199b87705613b1e2fd064d57fa75a6b679d2856ceafad6b1daa8f982493871b6dd1bc6aa69f9d04ee4f37e993437e30bcc2c55b2a80880a837d8e2e5c30d8f1ec1f7bc0d88baf1280ea4d3bfaf780060248b50c964b7664b82e110a88315ba4601Signed with an ed25519 key held off the repo. Anyone can verify against the published public key; nobody without the secret key can forge it. Click verify: it recomputes the signature in your browser. The signature proves integrity and authorship of this exact content — not a third-party timestamp or that the underlying claim is objectively true. signedAt is when the @f3/attest pipeline ran, not when the work happened; the evidence refs carry the source dates.
- verifies Setup Hook Primitive