On this page
Wizard hook-merge helper plus a thin delegate to the unified reconcile core.
#claudewheel.patch_profiles
#claudewheel.patch_profiles
Wizard hook-merge helper plus a thin delegate to the unified reconcile core.
The old additive, user-extras-preserving profile sync (sync_profile_settings / sync_shared_settings / run_patch_profiles) has been REPLACED by the unified reconcile core in reconcile.py, which prunes each target's guardrail sections to EXACTLY canonical. run_patch_profiles here is now a thin wrapper around that core -- the claudewheel patch-profiles command and claudewheel reconcile-permissions command do the same thing.
merge_hooks (and its _script_basename helper) remain because the wizard uses them to assemble a NEW profile's hooks from a canonical base plus any clone-source hooks at creation time. That is profile construction, distinct from the reconcile core's pruning of existing profiles.
#_script_basename
def _script_basename(command: str) -> strReturn the trailing script name of a hook command path (or "").
#merge_hooks
def merge_hooks(existing: dict[str, Any], canonical: dict[str, Any]) -> list[str]Merge canonical hooks into existing (mutated in place).
Canonical entries are matched to existing ones by their "matcher" field. Individual canonical hooks are matched to existing ones by script basename:
- a canonical hook whose basename is absent is APPENDED;
- a canonical hook whose basename is present but whose command points at a
DIFFERENT (stale) absolute path is REPATHED in place to the canonical command -- this is how a workspace relocation is healed, so a profile whose hook commands reference an old scripts directory is brought to the current one without duplicating the entry.
Only claudewheel-managed wirings (those in canonical) are ever touched; user-custom, non-canonical hooks are matched by neither basename nor matcher and so are preserved exactly. Returns human-readable descriptions of every hook added or repathed.
Used by the wizard to assemble a new profile's hooks. Existing profiles are reconciled to exact canonical by the reconcile core, not by this merge.
#run_patch_profiles
def run_patch_profiles(ws: 'Workspace', dry_run: bool=False) -> intReconcile every managed profile and shared-settings.json to exact canonical.
Thin delegate to the unified reconcile core. This PRUNES each target's guardrail sections (hooks, disallowedTools, permissions deny/ask) to exactly canonical -- the old additive, user-extras-preserving behavior is gone.