Skip to content

Honor PAI_DIR consistently in three lingering hardcodes#1138

Closed
MarvinDontPanic wants to merge 1 commit into
danielmiessler:mainfrom
MarvinDontPanic:fix/honor-pai-dir-in-paths
Closed

Honor PAI_DIR consistently in three lingering hardcodes#1138
MarvinDontPanic wants to merge 1 commit into
danielmiessler:mainfrom
MarvinDontPanic:fix/honor-pai-dir-in-paths

Conversation

@MarvinDontPanic

Copy link
Copy Markdown

Problem

PAI_DIR is honored inconsistently in v5.0.0. PAI/TOOLS/paths.ts (paiPath()) reads it at runtime as designed, and PAI/statusline-command.sh (line 14) does PAI_DIR="${PAI_DIR:-$HOME/.claude/PAI}" and uses the variable in the rest of the script. Three other files hardcode $HOME/.claude/PAI/... directly, breaking the contract for any caller that sets PAI_DIR to a non-default location.

For default upstream installs (where PAI_DIR=$HOME/.claude/PAI per settings.json:4) the behavior is identical, so this is invisible. The bug only surfaces if a downstream installer or user overrides PAI_DIR.

Fix

Three small changes (~3 lines total) — same fallback pattern that statusline-command.sh:14 already uses:

  1. PAI/PULSE/manage.sh:5PULSE_DIR="$HOME/.claude/PAI/PULSE"PULSE_DIR="${PAI_DIR:-$HOME/.claude/PAI}/PULSE". Otherwise manage.sh start/stop/restart points at the wrong directory under non-default PAI_DIR.

  2. PAI/PULSE/modules/hooks.ts:118 — Watchdog Monitor command string interpolated bun $HOME/.claude/PAI/TOOLS/AgentWatchdog.ts. Switched to runtime process.env.PAI_DIR with $HOME/.claude/PAI fallback. Otherwise the watchdog launches the wrong path under non-default PAI_DIR.

  3. skills/Agents/Tools/ComposeAgent.ts:38USER_TRAITS_PATH was ${HOME}/.claude/PAI/USER/SKILLCUSTOMIZATIONS/Agents/Traits.yaml. Now reads PAI_DIR from env. The other paths in the same block (BASE_TRAITS_PATH, TEMPLATE_PATH, CUSTOM_AGENTS_DIR) target ~/.claude/skills/ and ~/.claude/custom-agents/ which are install-root paths, NOT inside PAI_DIR — those correctly stay as-is.

What I deliberately did NOT change

  • PAI/statusline-command.sh:63,77 — these look like hardcodes but are actually intentional defensive fallbacks. Lines 61-65 try $PAI_DIR/ALGORITHM/LATEST first, then literal paths. Comments on lines 57-59 explicitly explain: "Hardened against Claude Code's hook-spawn context where $HOME or $PAI_DIR may not resolve as expected." Not a bug.

  • settings.json:9 (GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE) and settings.json:381 (statusline command path). I couldn't verify whether Claude Code's settings parser resolves ${PAI_DIR} from the env block at parse time. Without that verification, refusing to file as a bug.

  • PAI/TOOLS/gmail.ts:17 — comment only, not code.

Scope

3 files, 4 insertions, 3 deletions. No new dependencies. No API changes. Behavior unchanged for default upstream installs (where PAI_DIR=$HOME/.claude/PAI).

Verified

  • rg -n 'HOME/\.claude/PAI' Releases/v5.0.0/.claude/ returns these 3 plus the intentional fallbacks and the gmail.ts comment, no other production code.
  • All 3 changes use the same fallback pattern (${PAI_DIR:-$HOME/.claude/PAI} for shell, process.env.PAI_DIR ?? \${process.env.HOME}/.claude/PAI`` for TS) that's already established in the codebase.

paths.ts and statusline-command.sh both honor PAI_DIR (via paiPath() and
${PAI_DIR:-...} fallbacks respectively), but three other files hardcode
$HOME/.claude/PAI directly. The hardcodes work fine for default upstream
installs (where PAI_DIR=$HOME/.claude/PAI) but break the contract for any
caller that sets PAI_DIR to a non-default location.

Fixes (~3 line changes total):

* PAI/PULSE/manage.sh: PULSE_DIR derived from PAI_DIR with same fallback
  pattern statusline-command.sh uses on line 14.

* PAI/PULSE/modules/hooks.ts: Watchdog Monitor command string now reads
  PAI_DIR at runtime instead of hardcoding the path interpolation. Falls
  back to $HOME/.claude/PAI if PAI_DIR isn't set.

* skills/Agents/Tools/ComposeAgent.ts: USER_TRAITS_PATH now uses PAI_DIR.
  The other paths in this block (BASE_TRAITS_PATH, TEMPLATE_PATH,
  CUSTOM_AGENTS_DIR) target ~/.claude/skills/ and ~/.claude/custom-agents/
  which are install-root paths, NOT inside PAI_DIR — those stay as-is.

Verified: `rg -n 'HOME/\.claude/PAI'` across the v5.0.0 release tree
returns these three plus statusline-command.sh's defensive fallbacks
(intentional, not a bug) and a single comment in TOOLS/gmail.ts (also
not code). Settings.json values are not changed because Claude Code's
JSON parser may or may not resolve ${PAI_DIR} from the env block at
parse time — that's a separate verification I haven't done yet.
@danielmiessler

Copy link
Copy Markdown
Owner

Hey @MarvinDontPanic, thanks for raising this, and sorry it sat for a while.

We're changing how LifeOS ships. Instead of cloning a full ~/.claude directory and running it as a complete system, LifeOS is becoming a skill you install through an agentic installer. The installer hands integration to your own AI, which reads your actual machine (your OS, your paths, your harness) and wires the hooks and system prompt in where they belong.

That's aimed right at what you hit here. The old "one directory, one layout, hope it matches your setup" approach is exactly what broke for so many people, and the new model should handle it far better because your AI does the integration per machine instead of us guessing.

So we're closing this in prep for that release. If it still bites you once the skill-based version is out, reopen or file a fresh one and we'll jump on it. Appreciate you taking the time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants