Context
Claude Code's /add-dir command does not send notifications/roots/list_changed to MCP servers. This means Catenary never learns about directories added mid-session, and path-validated tools like list_directory reject paths in the new directory.
Upstream issue: anthropics/claude-code#26663
Current Workaround
A PreToolUse hook runs catenary sync-roots on every tool call. It:
- Parses the Claude Code transcript JSONL for
/add-dir confirmation messages
- Sends discovered roots to the running session's notify socket
- Uses a byte-offset cache to avoid re-scanning the full transcript
Files involved:
src/main.rs — SyncRoots subcommand and run_sync_roots()
src/notify.rs — AddRoots variant in NotifyRequest, process_add_roots()
src/bridge/path_security.rs — roots() getter on PathValidator
plugins/catenary/hooks/hooks.json — PreToolUse hook entry
When to close
When Claude Code sends notifications/roots/list_changed after /add-dir, the sync-roots hook becomes unnecessary. At that point:
- Remove the
SyncRoots subcommand from src/main.rs
- Remove the
AddRoots variant from NotifyRequest in src/notify.rs (keep process_add_roots on the server side — it's useful for any root addition path)
- Remove the
PreToolUse hook from plugins/catenary/hooks/hooks.json
- The
roots() getter on PathValidator can stay — it's generally useful
Context
Claude Code's
/add-dircommand does not sendnotifications/roots/list_changedto MCP servers. This means Catenary never learns about directories added mid-session, and path-validated tools likelist_directoryreject paths in the new directory.Upstream issue: anthropics/claude-code#26663
Current Workaround
A
PreToolUsehook runscatenary sync-rootson every tool call. It:/add-dirconfirmation messagesFiles involved:
src/main.rs—SyncRootssubcommand andrun_sync_roots()src/notify.rs—AddRootsvariant inNotifyRequest,process_add_roots()src/bridge/path_security.rs—roots()getter onPathValidatorplugins/catenary/hooks/hooks.json—PreToolUsehook entryWhen to close
When Claude Code sends
notifications/roots/list_changedafter/add-dir, thesync-rootshook becomes unnecessary. At that point:SyncRootssubcommand fromsrc/main.rsAddRootsvariant fromNotifyRequestinsrc/notify.rs(keepprocess_add_rootson the server side — it's useful for any root addition path)PreToolUsehook fromplugins/catenary/hooks/hooks.jsonroots()getter onPathValidatorcan stay — it's generally useful