You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Claude Code shipped several config-surface changes between 2.1.113 (2026-04-17) and 2.1.219 (2026-07-24) that rulesync has not followed: a new DirectoryAdded hook event, a set of documented hook handler fields that rulesync silently drops on generate, a permission-rule form that Claude Code now warns about at startup, a new skill frontmatter field, and the still-unauthorable sandbox.* settings subtree.
Upstream: DirectoryAdded fires after /add-dir or the SDK register_repo_root control request registers a new working directory mid-session. CHANGELOG 2.1.219 (2026-07-24). Not yet in the hooks docs event table.
rulesync: unsupported. CLAUDE_HOOK_EVENTS (src/types/hooks.ts) lists 30 events with no directoryAdded, and CANONICAL_TO_CLAUDE_EVENT_NAMES has no mapping. buildEffectiveHooks filters to supportedEvents, so the event is silently dropped.
2. hooks — documented handler fields are dropped on generate
Upstream (hooks docs): common statusMessage, once; command hooks args: string[] (exec form — no shell, so path placeholders never need quoting), async, asyncRewake, shell (bash | powershell); prompt hooks continueOnBlock. args and continueOnBlock landed in 2.1.139 (2026-05-11); 2.1.207 (2026-07-10) rejects ${user_config.*} in shell-form plugin hook commands and directs users to the exec form.
rulesync: unsupported for claudecode and claudecode-plugin. buildToolHooks (src/features/hooks/tool-hooks-converter.ts) emits only type, command, timeout, prompt, type-specific payload fields, plus declared passthrough. CLAUDE_CONVERTER_CONFIG (src/features/hooks/claudecode-hooks.ts) declares only stringPassthroughFields: [{ canonical: "if", tool: "if" }]. args, asyncRewake and continueOnBlock are not in the canonical HookDefinitionSchema (src/types/hooks.ts) at all. Verified: a hook authored with args, shell, async, asyncRewake, statusMessage, once and continueOnBlock generated {"type":"command","command":"node"} and {"type":"prompt","prompt":"check"} only. ClaudecodePluginHooks inherits the same converter config, so plugin hooks/hooks.json is equally lossy — and that is exactly the surface upstream now steers to exec form.
3. hooks — UserPromptSubmit and Stop missing from the no-matcher set
Upstream: the hooks docs matcher table lists UserPromptSubmit, PostToolBatch, Stop, TeammateIdle, TaskCreated, TaskCompleted, WorktreeCreate, WorktreeRemove, MessageDisplay and CwdChanged as having no matcher support.
rulesync: CLAUDE_NO_MATCHER_EVENTS (src/features/hooks/claudecode-hooks.ts) lists 8 of those 10 — beforeSubmitPrompt (→ UserPromptSubmit) and stop are missing, so a matcher authored on them is written into .claude/settings.json and silently ignored upstream instead of being dropped with the existing warning.
4. permissions — rulesync emits the now-warned Write(path) / NotebookEdit(path) / Glob(path) forms
Upstream: "File permission checks match only Edit(path) and Read(path) rules. A Write(path), NotebookEdit(path), or Glob(path) rule is accepted but never matched by those checks, so Claude Code warns at startup for each allow, deny, or ask rule in one of these unmatched forms." — permissions docs, CHANGELOG 2.1.210 (2026-07-14). A tool-name-only rule (no path) is unaffected.
rulesync: project, and it generates exactly the warned forms. CANONICAL_TO_CLAUDE_TOOL_NAMES (src/features/permissions/claudecode-permissions.ts) maps write → Write, notebookedit → NotebookEdit, glob → Glob, and buildClaudePermissionEntry keeps the pattern, so {"permission":{"write":{"docs/**":"deny"}}} produces "deny": ["Write(docs/**)"].
5. skills — background frontmatter not authorable, dropped on import
Upstream: background — "Only applies with context: fork. Set to false to wait for the forked subagent's result in the turn that invoked the skill, instead of running it in the background. Default: true." — skills docs, requires 2.1.218 (2026-07-22).
rulesync: unsupported. ClaudecodeSkillFrontmatterSchema (src/features/skills/claudecode-skill.ts) has context and agent but no background, and the claudecode section of RulesyncSkillFrontmatter (src/features/skills/rulesync-skill.ts) has none either. buildClaudecodeSkillFrontmatter copies a fixed truthyFields/definedFields list rather than spreading, so an authored background never reaches SKILL.md, and toRulesyncSkill drops it on import. (Contrast: ClaudecodeCommand spreads the whole claudecode section and is lossless.)
6. permissions — the sandbox.* settings subtree is still not authorable
Upstream: sandbox.* sits next to permissions in .claude/settings.json and keeps growing — sandbox.network.strictAllowlist (2.1.219), sandbox.filesystem.disabled (2.1.216), sandbox.credentials (2.1.187), sandbox.allowAppleEvents (2.1.181), sandbox.network.deniedDomains (2.1.113). See sandboxing docs.
rulesync: unsupported. ClaudecodePermissionsOverrideSchema (src/types/permissions.ts) exposes only permission and permissions, and ClaudecodePermissions.fromRulesyncPermissions merges the override strictly into settings.permissions. There is no path from .rulesync/permissions.json to a top-level sandbox key. Claude Code permissions: support permissions.defaultMode and permissions.additionalDirectories (and note sandbox.*) #2129 explicitly deferred sandbox.* as out of scope for its first iteration and no follow-up was filed.
Proposed Follow-up
Add canonical directoryAdded to HOOK_EVENTS + CLAUDE_HOOK_EVENTS and the DirectoryAdded mapping. Matcher support is undocumented — treat as no-matcher for now and note that in a code comment.
Add args (string array), asyncRewake and continueOnBlock to the canonical HookDefinitionSchema, and extend CLAUDE_CONVERTER_CONFIG so args, shell, statusMessage, once, async, asyncRewake and continueOnBlock are emitted and imported for claudecode and claudecode-plugin. applyCommandPrefix / prefixDotRelativeCommandsOnly must not rewrite command when args is present — the exec form resolves command as an executable, not a shell string.
Add beforeSubmitPrompt and stop to CLAUDE_NO_MATCHER_EVENTS.
On generate, when the pattern is not *, map write/notebookedit → Edit(...) and glob → Read(...) (merging with any existing edit/read entries), keeping the bare tool name for the * pattern. Import should stay tolerant of the legacy forms so existing .claude/settings.json files still round-trip.
Add background: z.optional(z.boolean()) to both the Claude Code skill frontmatter schema and the claudecode section of the rulesync skill schema, and carry it in buildClaudecodeSkillFrontmatter (as a definedFields entry, since false is the meaningful value) and toRulesyncSkill. Applies to claudecode-plugin too, since ClaudecodePluginSkill extends ClaudecodeSkill.
Add a sandbox key to ClaudecodePermissionsOverrideSchema (loose passthrough, mirroring permissions) and merge it into the top level of .claude/settings.json, with reverse routing in toRulesyncPermissions. Existing sandbox content in a user's settings must be preserved on merge.
Open questions / unconfirmed
DirectoryAdded matcher support is unconfirmed — the CHANGELOG announces the event but the hooks docs have no row for it yet.
Skill frontmatter display-name, default-enabled, fallback, metadata.* (CHANGELOG 2.1.186, 2026-06-22, "now accept kebab-case, snake_case, and camelCase") do not appear in the Claude Code skill frontmatter table; they are most likely Agent Skills open-standard / plugin-manifest keys, so whether rulesync should carry them for claudecode is unconfirmed.
shell, async, asyncRewake and statusMessage are documented today but no introduction version could be pinned in the CHANGELOG; only args and continueOnBlock have explicit 2.1.139 entries. The gap itself (dropped on generate) is confirmed either way.
.ignore / .rgignore / .worktreeinclude appear in CHANGELOG bug-fix lines but are not documented as a Claude Code ignore-configuration surface, so they are treated as not a gap.
Summary
Claude Code shipped several config-surface changes between 2.1.113 (2026-04-17) and 2.1.219 (2026-07-24) that rulesync has not followed: a new
DirectoryAddedhook event, a set of documented hook handler fields that rulesync silently drops on generate, a permission-rule form that Claude Code now warns about at startup, a new skill frontmatter field, and the still-unauthorablesandbox.*settings subtree.Recent Releases
Source:
anthropics/claude-codeCHANGELOG.md (dates fromnpm view @anthropic-ai/claude-code time).DirectoryAddedhook event;sandbox.network.strictAllowlistsetting.background(only meaningful withcontext: fork).sandbox.filesystem.disabledsetting.Write(path)/NotebookEdit(path)/Glob(path)permission rules;continueOnBlocksemantics change forPreToolUseprompt hooks.${user_config.*}; docs steer users to the exec form (args).sandbox.credentialssetting.sandbox.allowAppleEventssetting.args: string[]exec form; hookcontinueOnBlockforPostToolUse.sandbox.network.deniedDomains.Gaps
1. hooks —
DirectoryAddedevent unsupportedDirectoryAddedfires after/add-diror the SDKregister_repo_rootcontrol request registers a new working directory mid-session. CHANGELOG 2.1.219 (2026-07-24). Not yet in the hooks docs event table.unsupported.CLAUDE_HOOK_EVENTS(src/types/hooks.ts) lists 30 events with nodirectoryAdded, andCANONICAL_TO_CLAUDE_EVENT_NAMEShas no mapping.buildEffectiveHooksfilters tosupportedEvents, so the event is silently dropped.2. hooks — documented handler fields are dropped on generate
statusMessage,once; command hooksargs: string[](exec form — no shell, so path placeholders never need quoting),async,asyncRewake,shell(bash|powershell); prompt hookscontinueOnBlock.argsandcontinueOnBlocklanded in 2.1.139 (2026-05-11); 2.1.207 (2026-07-10) rejects${user_config.*}in shell-form plugin hook commands and directs users to the exec form.unsupportedforclaudecodeandclaudecode-plugin.buildToolHooks(src/features/hooks/tool-hooks-converter.ts) emits onlytype,command,timeout,prompt, type-specific payload fields, plus declared passthrough.CLAUDE_CONVERTER_CONFIG(src/features/hooks/claudecode-hooks.ts) declares onlystringPassthroughFields: [{ canonical: "if", tool: "if" }].args,asyncRewakeandcontinueOnBlockare not in the canonicalHookDefinitionSchema(src/types/hooks.ts) at all. Verified: a hook authored withargs,shell,async,asyncRewake,statusMessage,onceandcontinueOnBlockgenerated{"type":"command","command":"node"}and{"type":"prompt","prompt":"check"}only.ClaudecodePluginHooksinherits the same converter config, so pluginhooks/hooks.jsonis equally lossy — and that is exactly the surface upstream now steers to exec form.3. hooks —
UserPromptSubmitandStopmissing from the no-matcher setUserPromptSubmit,PostToolBatch,Stop,TeammateIdle,TaskCreated,TaskCompleted,WorktreeCreate,WorktreeRemove,MessageDisplayandCwdChangedas having no matcher support.CLAUDE_NO_MATCHER_EVENTS(src/features/hooks/claudecode-hooks.ts) lists 8 of those 10 —beforeSubmitPrompt(→UserPromptSubmit) andstopare missing, so a matcher authored on them is written into.claude/settings.jsonand silently ignored upstream instead of being dropped with the existing warning.4. permissions — rulesync emits the now-warned
Write(path)/NotebookEdit(path)/Glob(path)formsEdit(path)andRead(path)rules. AWrite(path),NotebookEdit(path), orGlob(path)rule is accepted but never matched by those checks, so Claude Code warns at startup for each allow, deny, or ask rule in one of these unmatched forms." — permissions docs, CHANGELOG 2.1.210 (2026-07-14). A tool-name-only rule (no path) is unaffected.project, and it generates exactly the warned forms.CANONICAL_TO_CLAUDE_TOOL_NAMES(src/features/permissions/claudecode-permissions.ts) mapswrite→Write,notebookedit→NotebookEdit,glob→Glob, andbuildClaudePermissionEntrykeeps the pattern, so{"permission":{"write":{"docs/**":"deny"}}}produces"deny": ["Write(docs/**)"].5. skills —
backgroundfrontmatter not authorable, dropped on importbackground— "Only applies withcontext: fork. Set tofalseto wait for the forked subagent's result in the turn that invoked the skill, instead of running it in the background. Default:true." — skills docs, requires 2.1.218 (2026-07-22).unsupported.ClaudecodeSkillFrontmatterSchema(src/features/skills/claudecode-skill.ts) hascontextandagentbut nobackground, and theclaudecodesection ofRulesyncSkillFrontmatter(src/features/skills/rulesync-skill.ts) has none either.buildClaudecodeSkillFrontmattercopies a fixedtruthyFields/definedFieldslist rather than spreading, so an authoredbackgroundnever reachesSKILL.md, andtoRulesyncSkilldrops it on import. (Contrast:ClaudecodeCommandspreads the wholeclaudecodesection and is lossless.)6. permissions — the
sandbox.*settings subtree is still not authorablesandbox.*sits next topermissionsin.claude/settings.jsonand keeps growing —sandbox.network.strictAllowlist(2.1.219),sandbox.filesystem.disabled(2.1.216),sandbox.credentials(2.1.187),sandbox.allowAppleEvents(2.1.181),sandbox.network.deniedDomains(2.1.113). See sandboxing docs.unsupported.ClaudecodePermissionsOverrideSchema(src/types/permissions.ts) exposes onlypermissionandpermissions, andClaudecodePermissions.fromRulesyncPermissionsmerges the override strictly intosettings.permissions. There is no path from.rulesync/permissions.jsonto a top-levelsandboxkey. Claude Code permissions: supportpermissions.defaultModeandpermissions.additionalDirectories(and notesandbox.*) #2129 explicitly deferredsandbox.*as out of scope for its first iteration and no follow-up was filed.Proposed Follow-up
directoryAddedtoHOOK_EVENTS+CLAUDE_HOOK_EVENTSand theDirectoryAddedmapping. Matcher support is undocumented — treat as no-matcher for now and note that in a code comment.args(string array),asyncRewakeandcontinueOnBlockto the canonicalHookDefinitionSchema, and extendCLAUDE_CONVERTER_CONFIGsoargs,shell,statusMessage,once,async,asyncRewakeandcontinueOnBlockare emitted and imported forclaudecodeandclaudecode-plugin.applyCommandPrefix/prefixDotRelativeCommandsOnlymust not rewritecommandwhenargsis present — the exec form resolvescommandas an executable, not a shell string.beforeSubmitPromptandstoptoCLAUDE_NO_MATCHER_EVENTS.*, mapwrite/notebookedit→Edit(...)andglob→Read(...)(merging with any existingedit/readentries), keeping the bare tool name for the*pattern. Import should stay tolerant of the legacy forms so existing.claude/settings.jsonfiles still round-trip.background: z.optional(z.boolean())to both the Claude Code skill frontmatter schema and theclaudecodesection of the rulesync skill schema, and carry it inbuildClaudecodeSkillFrontmatter(as adefinedFieldsentry, sincefalseis the meaningful value) andtoRulesyncSkill. Applies toclaudecode-plugintoo, sinceClaudecodePluginSkillextendsClaudecodeSkill.sandboxkey toClaudecodePermissionsOverrideSchema(loose passthrough, mirroringpermissions) and merge it into the top level of.claude/settings.json, with reverse routing intoRulesyncPermissions. Existing sandbox content in a user's settings must be preserved on merge.Open questions / unconfirmed
DirectoryAddedmatcher support is unconfirmed — the CHANGELOG announces the event but the hooks docs have no row for it yet.display-name,default-enabled,fallback,metadata.*(CHANGELOG 2.1.186, 2026-06-22, "now accept kebab-case, snake_case, and camelCase") do not appear in the Claude Code skill frontmatter table; they are most likely Agent Skills open-standard / plugin-manifest keys, so whether rulesync should carry them forclaudecodeis unconfirmed.shell,async,asyncRewakeandstatusMessageare documented today but no introduction version could be pinned in the CHANGELOG; onlyargsandcontinueOnBlockhave explicit 2.1.139 entries. The gap itself (dropped on generate) is confirmed either way..ignore/.rgignore/.worktreeincludeappear in CHANGELOG bug-fix lines but are not documented as a Claude Code ignore-configuration surface, so they are treated as not a gap.References
Write()/NotebookEdit()/Glob()warning text (gap 4).background(gap 5).sandbox.*settings subtree (gap 6).hooks/hooks.jsonshape, confirmingclaudecode-pluginshares the lossy hook path.