diff --git a/LifeOS/install/hooks/hooks.json b/LifeOS/install/hooks/hooks.json index e9fc09f189..c751ca0566 100644 --- a/LifeOS/install/hooks/hooks.json +++ b/LifeOS/install/hooks/hooks.json @@ -6,7 +6,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/ContextReduction.hook.sh" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ContextReduction.hook.sh" } ] }, @@ -28,7 +28,7 @@ }, { "type": "command", - "command": "$HOME/.claude/hooks/AgentInvocation.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/AgentInvocation.hook.ts" } ] }, @@ -37,7 +37,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/TabState.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/TabState.hook.ts" } ] }, @@ -46,7 +46,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/PreToolGuard.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/PreToolGuard.hook.ts" } ] } @@ -57,7 +57,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/AgentInvocation.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/AgentInvocation.hook.ts" } ] }, @@ -66,7 +66,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/Safety.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/Safety.hook.ts", "timeout": 5 } ] @@ -76,7 +76,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/Safety.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/Safety.hook.ts", "timeout": 5 } ] @@ -86,7 +86,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/Safety.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/Safety.hook.ts", "timeout": 5 } ] @@ -96,7 +96,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/Safety.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/Safety.hook.ts", "timeout": 5 } ] @@ -106,7 +106,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/TabState.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/TabState.hook.ts" } ] }, @@ -115,7 +115,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/ISAStaleWriteGuard.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ISAStaleWriteGuard.hook.ts" } ] }, @@ -124,34 +124,34 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/ISASync.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ISASync.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/ISAStaleWriteGuard.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ISAStaleWriteGuard.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/CheckpointPerISC.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/CheckpointPerISC.hook.ts", "timeout": 30 }, { "type": "command", - "command": "$HOME/.claude/hooks/ConfigEvalFire.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ConfigEvalFire.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/AtlasEventCapture.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/AtlasEventCapture.hook.ts", "timeout": 5 }, { "type": "command", - "command": "$HOME/.claude/hooks/KnowledgeWriteGuard.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/KnowledgeWriteGuard.hook.ts", "timeout": 5 }, { "type": "command", - "command": "$HOME/.claude/hooks/ComplexityRatchet.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ComplexityRatchet.hook.ts" } ] }, @@ -160,34 +160,34 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/ISASync.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ISASync.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/ISAStaleWriteGuard.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ISAStaleWriteGuard.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/CheckpointPerISC.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/CheckpointPerISC.hook.ts", "timeout": 30 }, { "type": "command", - "command": "$HOME/.claude/hooks/ConfigEvalFire.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ConfigEvalFire.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/AtlasEventCapture.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/AtlasEventCapture.hook.ts", "timeout": 5 }, { "type": "command", - "command": "$HOME/.claude/hooks/KnowledgeWriteGuard.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/KnowledgeWriteGuard.hook.ts", "timeout": 5 }, { "type": "command", - "command": "$HOME/.claude/hooks/ComplexityRatchet.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ComplexityRatchet.hook.ts" } ] }, @@ -196,34 +196,34 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/ISASync.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ISASync.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/ISAStaleWriteGuard.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ISAStaleWriteGuard.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/CheckpointPerISC.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/CheckpointPerISC.hook.ts", "timeout": 30 }, { "type": "command", - "command": "$HOME/.claude/hooks/ConfigEvalFire.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ConfigEvalFire.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/AtlasEventCapture.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/AtlasEventCapture.hook.ts", "timeout": 5 }, { "type": "command", - "command": "$HOME/.claude/hooks/KnowledgeWriteGuard.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/KnowledgeWriteGuard.hook.ts", "timeout": 5 }, { "type": "command", - "command": "$HOME/.claude/hooks/ComplexityRatchet.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ComplexityRatchet.hook.ts" } ] }, @@ -231,7 +231,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/EventLogger.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/EventLogger.hook.ts", "timeout": 5, "async": true } @@ -242,11 +242,11 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/PostToolObserver.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/PostToolObserver.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/LoopDetector.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/LoopDetector.hook.ts", "timeout": 5 } ] @@ -256,7 +256,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/AtlasEventCapture.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/AtlasEventCapture.hook.ts", "timeout": 5 } ] @@ -267,27 +267,27 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/WorkCompletionLearning.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/WorkCompletionLearning.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/SessionCleanup.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/SessionCleanup.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/UpdateCounts.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/UpdateCounts.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/MemoryHealthGate.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/MemoryHealthGate.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/DocIntegrity.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/DocIntegrity.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/IntegrityCheck.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/IntegrityCheck.hook.ts" } ] } @@ -297,7 +297,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/PromptProcessing.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/PromptProcessing.hook.ts", "timeout": 30, "async": true } @@ -307,7 +307,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/SatisfactionCapture.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/SatisfactionCapture.hook.ts", "timeout": 20, "async": true } @@ -317,7 +317,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/ReminderRouter.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ReminderRouter.hook.ts", "timeout": 5, "async": true } @@ -327,7 +327,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/VersionDrift.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/VersionDrift.hook.ts", "timeout": 10, "async": true } @@ -337,7 +337,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/MemoryTurnStart.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/MemoryTurnStart.hook.ts", "timeout": 8 } ] @@ -347,7 +347,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/DriftReminder.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/DriftReminder.hook.ts" } ] }, @@ -356,7 +356,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/AlgorithmNudge.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/AlgorithmNudge.hook.ts" } ] }, @@ -364,7 +364,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/TimeContext.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/TimeContext.hook.ts", "timeout": 5, "async": true } @@ -374,7 +374,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/ModelRungGuard.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ModelRungGuard.hook.ts", "timeout": 5, "async": true } @@ -386,7 +386,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/EventLogger.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/EventLogger.hook.ts" } ] }, @@ -394,7 +394,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/AlgorithmNudge.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/AlgorithmNudge.hook.ts", "timeout": 5 } ] @@ -403,7 +403,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/LoopDetector.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/LoopDetector.hook.ts", "timeout": 5 } ] @@ -414,7 +414,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/TaskGovernance.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/TaskGovernance.hook.ts" } ] } @@ -424,7 +424,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/EventLogger.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/EventLogger.hook.ts" } ] } @@ -434,26 +434,26 @@ "hooks": [ { "type": "command", - "command": "bun $HOME/.claude/hooks/HookHealer.hook.ts", + "command": "bun ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/HookHealer.hook.ts", "timeout": 10 }, { "type": "command", - "command": "$HOME/.claude/hooks/KittyEnvPersist.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/KittyEnvPersist.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/LoadContext.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/LoadContext.hook.ts" }, { "type": "command", - "command": "bun $HOME/.claude/LIFEOS/TOOLS/FreshnessCache.ts --quiet", + "command": "bun ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/LIFEOS/TOOLS/FreshnessCache.ts --quiet", "timeout": 5, "async": true }, { "type": "command", - "command": "bun $HOME/.claude/LIFEOS/TOOLS/SettingsBackport.ts; bun $HOME/.claude/LIFEOS/TOOLS/MergeSettings.ts --system $HOME/.claude/settings.system.json --user $HOME/.claude/LIFEOS/USER/CONFIG/settings.user.json --output $HOME/.claude/settings.json", + "command": "bun ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/LIFEOS/TOOLS/SettingsBackport.ts; bun ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/LIFEOS/TOOLS/MergeSettings.ts --system ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.system.json --user ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/LIFEOS/USER/CONFIG/settings.user.json --output ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json", "timeout": 15, "async": true } @@ -465,31 +465,31 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/LastResponseCache.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/LastResponseCache.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/TabState.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/TabState.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/VoiceCompletion.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/VoiceCompletion.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/ISARenderOnStop.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/ISARenderOnStop.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/SpendAuditor.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/SpendAuditor.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/StopGates.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/StopGates.hook.ts" }, { "type": "command", - "command": "$HOME/.claude/hooks/MemoryReviewFire.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/MemoryReviewFire.hook.ts" } ] }, @@ -497,7 +497,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/MemoryHealthGate.hook.ts", + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/MemoryHealthGate.hook.ts", "timeout": 15, "async": true } @@ -509,7 +509,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/EventLogger.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/EventLogger.hook.ts" } ] } @@ -520,7 +520,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/Safety.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/Safety.hook.ts" } ] }, @@ -529,7 +529,7 @@ "hooks": [ { "type": "command", - "command": "$HOME/.claude/hooks/Safety.hook.ts" + "command": "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hooks/Safety.hook.ts" } ] } diff --git a/LifeOS/install/hooks/lib/paths.ts b/LifeOS/install/hooks/lib/paths.ts index 205c4ef7fd..6873c0b06c 100755 --- a/LifeOS/install/hooks/lib/paths.ts +++ b/LifeOS/install/hooks/lib/paths.ts @@ -31,7 +31,8 @@ export function expandPath(path: string): string { * Priority: * 1. CLAUDE_PLUGIN_ROOT (plugin install) → /PAI * 2. LIFEOS_DIR env var (expanded) - * 3. ~/.claude/LIFEOS (live default — byte-identical to pre-plugin behavior) + * 3. /LIFEOS — honors CLAUDE_CONFIG_DIR, else ~/.claude/LIFEOS + * (live default — byte-identical to pre-plugin behavior) * * The CLAUDE_PLUGIN_ROOT guard MUST precede the LIFEOS_DIR check: in a packed * plugin, bin/pai exports LIFEOS_DIR equal to CLAUDE_PLUGIN_ROOT (the flattened @@ -51,16 +52,23 @@ export function getLifeosDir(): string { return expandPath(envLifeosDir); } - return join(homedir(), '.claude', 'LIFEOS'); + return join(getClaudeDir(), 'LIFEOS'); } /** * Get the Claude Code home directory. * - * Plugin install: CLAUDE_PLUGIN_ROOT is the flattened plugin root that plays the - * live ~/.claude role (skills/ and hooks/ sit directly under it, matching live - * .claude/skills and .claude/hooks). Live default: ~/.claude — byte-identical to - * pre-plugin behavior, since CLAUDE_PLUGIN_ROOT is unset on a normal install. + * Priority: + * 1. CLAUDE_PLUGIN_ROOT (plugin install) — the flattened plugin root that + * plays the live ~/.claude role (skills/ and hooks/ sit directly under it, + * matching live .claude/skills and .claude/hooks). + * 2. CLAUDE_CONFIG_DIR (relocated config root) — the same relocation the + * install tools and every other runtime module already honor (Doctor.ts, + * PULSE Conduit/paths.ts). Without it the hooks pin to ~/.claude even under + * a relocated install, so their commands resolve to the global dir (none of + * the copied scripts) and MergeSettings rewrites the global settings.json. + * 3. ~/.claude — live default, byte-identical to pre-plugin behavior since + * neither env var is set on a normal install. */ export function getClaudeDir(): string { const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT; @@ -69,6 +77,12 @@ export function getClaudeDir(): string { return expandPath(pluginRoot); } + const configDir = process.env.CLAUDE_CONFIG_DIR; + + if (configDir) { + return expandPath(configDir); + } + return join(homedir(), '.claude'); }