Skip to content

feat(claudecode): follow the DirectoryAdded event, documented hook handler fields, and skill background - #2471

Merged
dyoshikawa merged 2 commits into
mainfrom
resolve-scrap-issue-2397-claudecode-hooks
Jul 29, 2026
Merged

feat(claudecode): follow the DirectoryAdded event, documented hook handler fields, and skill background#2471
dyoshikawa merged 2 commits into
mainfrom
resolve-scrap-issue-2397-claudecode-hooks

Conversation

@dyoshikawa

Copy link
Copy Markdown
Owner

Background

Related issue: #2397 (partial — this PR covers gaps 1, 2, 3 and 5; gaps 4 and 6 follow separately)

Claude Code added a DirectoryAdded hook event, documents a set of per-handler hook fields that rulesync silently dropped on generate, lists two more events as taking no matcher, and added a background skill frontmatter field. Each was verified against the hooks docs, the skills docs and the upstream CHANGELOG before implementing.

Changes

DirectoryAdded (gap 1). Added as canonical directoryAdded plus the Claude mapping. The event is announced in the 2.1.219 changelog ("fires after /add-dir or the SDK register_repo_root control request registers a new working directory mid-session") but has no row in the docs' event table yet, so its matcher support is unknown and it is treated as no-matcher — a matcher authored on it is dropped with the existing warning rather than written into settings.json to be ignored. Noted in a code comment.

Dropped handler fields (gap 2). args, async, asyncRewake, shell, statusMessage, once and continueOnBlock now generate and import for claudecode and claudecode-plugin (which shares the converter config). asyncRewake and continueOnBlock are new on the canonical HookDefinitionSchema; the rest already existed. The boolean and string passthrough unions widened accordingly.

applyCommandPrefix no longer rewrites command when the exec form is in use: with args present the tool spawns command directly, with no shell to expand $CLAUDE_PROJECT_DIR or strip the quotes the prefix adds, so the prefixed string would be looked up as a literal file name. The check is gated on the converter actually emitting args, so shell-form hooks and other tools are unaffected — verified both branches.

Missing no-matcher events (gap 3). beforeSubmitPrompt (→ UserPromptSubmit) and stop added to CLAUDE_NO_MATCHER_EVENTS, matching the docs' matcher table.

Skill background (gap 5). Added to the Claude Code skill frontmatter schema and the claudecode section of the rulesync skill schema, carried as a defined field rather than a truthy one — background: false is the whole point, and a truthy check would drop it. Applies to claudecode-plugin too, since ClaudecodePluginSkill extends ClaudecodeSkill.

Deferred to follow-up PRs

This PR therefore does not close #2397.

Verification

  • pnpm cicheck (full: code + content)
  • npx vitest run --config vitest.e2e.config.ts src/e2e/e2e-hooks.spec.ts src/e2e/e2e-skills.spec.ts
  • Manual generate/import round trips for hooks and skills in a scratch project.

…ndler fields, and skill background

Adds the DirectoryAdded hook event, carries the documented per-handler fields (args, async, asyncRewake, shell, statusMessage, once, continueOnBlock) through generate and import for both claudecode and claudecode-plugin, drops matchers on UserPromptSubmit and Stop as the docs' matcher table requires, and makes the skill frontmatter background field authorable.
…mand-only fields off other hook types

Review follow-ups: an empty args array selects the exec form too, which is the form the docs' own example uses. Rather than dropping the project-directory prefix there, emit the braced ${CLAUDE_PROJECT_DIR} placeholder that Claude Code substitutes itself, and strip it again on import. args/async/asyncRewake/shell are documented on command hooks only, so passthrough descriptors gained a commandOnly flag.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants