Hook event 29 of 33

DirectoryAdded

Runs in the background after a working directory is added to an active session through /add-dir or an SDK control request.

Exit code veto
Exit code cannot block
Matchers
slash_command, register_repo_root
if filter
Does not apply
Docs checked
2026-08-29

Two ways in, and three that do not count

You add a directory and want setup to run. Only two paths trigger this event. DirectoryAdded fires after /add-dir, with source: "slash_command", and after an SDK control request named register_repo_root, with source: "register_repo_root". The matcher filters on those two values, and the payload carries directory, the absolute path added, and source.

The hooks reference names three ways a directory can be added that do not fire it: the --add-dir startup flag, the Workspace tab under /permissions, and a failed attempt to add a directory the session already has.

It runs in the background, after the fact

The directory is already live when your hook starts. Sandbox and permission state for the new directory are refreshed and active before the hook runs. Claude Code does not wait for it, and it runs under the 600-second default timeout. Exit 0 can do background work and cannot change the add. Exit 1 cannot undo it. Exit 2 cannot block it, and its stderr goes to the debug log.

Where a message lands depends on source

For slash_command, systemMessage becomes context Claude sees on the next turn, and a failing hook contributes a failure count to the transcript with the full output in debug. For register_repo_root, systemMessage goes to the debug log, and so does failure output. continue is discarded on both, and there is no decision field.

The mistake most people make first

You expect the hook to fire for the directories you pass with --add-dir at startup. It never does.

Start with claude --add-dir ../shared and no hook runs. Type /add-dir ../shared inside the session and it does. The startup flag is one of the three paths that do not fire, and there is no error, because nothing was configured wrong.

For a directory present from startup, the event does not exist. SessionStart is the startup moment.