claudewheel v0.20.1 /claudewheel.patch_profiles
Edit
On this page

Sync existing profiles and shared-settings.json toward canonical defaults.

#claudewheel.patch_profiles

#claudewheel.patch_profiles

Sync existing profiles and shared-settings.json toward canonical defaults.

Canonical defaults advance in defaults.py (new disallowedTools entries, new hook scripts), but per-profile settings.json files are only written at creation and shared-settings.json only when it is first created. This module backs the claudewheel patch-profiles command, which additively brings every discovered profile and shared-settings.json up to the current canonical hook wiring and disallowedTools list without disturbing anything else.

The sync is purely additive and idempotent: - Canonical hook entries (matched by their "matcher" field) are merged in, de-duplicated by script basename, preserving any user-added hooks. - claudewheel.disallowedTools (top-level for shared-settings) is made a superset of defaults.DISALLOWED_TOOLS; user-added extras are kept. - The inert top-level disallowedTools key that Claude Code ignores is folded into the claudewheel namespace and removed. - Missing built-in hook scripts referenced by the canonical hooks are deployed via the shared deploy-hooks code path.

Permissions, credentials, tokens, and all unrelated keys are never touched.

#_script_basename

python
def _script_basename(command: str) -> str

Return the trailing script name of a hook command path (or "").

#merge_hooks

python
def merge_hooks(existing: dict, canonical: dict) -> list[str]

Additively merge canonical hooks into existing (mutated in place).

Canonical entries are matched to existing ones by their "matcher" field. Individual hooks are de-duplicated by script basename, so a profile that already wires a script under a different absolute path is left untouched. Returns a list of human-readable descriptions of every hook added.

#_append_missing

python
def _append_missing(current: list, wanted: list) -> list[str]

Append entries of wanted absent from current (mutated). Returns them.

#sync_profile_settings

python
def sync_profile_settings(settings: dict, canonical: dict) -> list[str]

Additively sync one profile's settings dict toward canonical (mutated).

Returns descriptions of every change. Empty list means already in sync.

#sync_shared_settings

python
def sync_shared_settings(shared: dict, canonical: dict) -> list[str]

Additively sync shared-settings.json dict toward canonical (mutated).

Returns descriptions of every change. Empty list means already in sync. In shared-settings.json, disallowedTools canonically lives at the top level (unlike profiles, where it is under the claudewheel namespace).

#_referenced_scripts

python
def _referenced_scripts(hooks: dict) -> list[str]

Collect the ordered, unique script basenames referenced by hooks.

#run_patch_profiles

python
def run_patch_profiles(dry_run: bool=False) -> int

Sync every discovered profile and shared-settings.json toward canonical.

Deploys any missing built-in hook scripts, then additively patches shared-settings.json and each profile's settings.json. With dry_run, reports what would change and writes nothing.