DirectoryAdded
Runs after you add a working directory mid-session with the /add-dir command, or after an SDK client adds one with the register_repo_root control request. Use this to prepare a newly added repository, for example by installing its dependencies.
Claude Code doesn't fire this event when:
- You pass a directory with the
--add-dirstartup flag; SessionStart covers those directories - You add a directory on the
/permissionsWorkspace tab - You add a directory that is already a working directory or inside one
Claude Code fires DirectoryAdded after refreshing sandbox and permission state, so sandboxed tools already see the new directory when your hook runs. Hook commands themselves run unsandboxed.
Claude Code doesn't wait for the hook: the add completes immediately, and the hook runs in the background with the 600-second default timeout.
The matcher filters on how the directory was added:
| Matcher | When it fires |
|---|---|
slash_command | You add a directory with /add-dir |
register_repo_root | An SDK client adds a directory with the register_repo_root control request |
DirectoryAdded input
In addition to the common input fields, DirectoryAdded hooks receive directory and source.
| Field | Description |
|---|---|
directory | Absolute path of the directory that was added |
source | How the directory was added, "slash_command" for /add-dir or "register_repo_root" for the SDK control request |
{
"session_id": "abc123",
"transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
"cwd": "/Users/my-project",
"hook_event_name": "DirectoryAdded",
"directory": "/Users/my-other-repo",
"source": "slash_command"
}DirectoryAdded hooks have no decision control. They can't block the add, which has already completed when the hook runs. Claude Code discards the continue field from their JSON output and surfaces the rest differently per source:
slash_command: Claude Code delivers the hook'ssystemMessageto Claude as context on the next conversation turn, rather than showing it to you. A count of failed hooks appears in the transcript. Full failure output goes to the debug logregister_repo_root: Claude Code writessystemMessageoutput and failure output to the debug log only