fix: port getPaiDir() CLAUDE_CONFIG_DIR portability to v4.0.3#873
Open
raychaser wants to merge 14 commits intodanielmiessler:mainfrom
Open
fix: port getPaiDir() CLAUDE_CONFIG_DIR portability to v4.0.3#873raychaser wants to merge 14 commits intodanielmiessler:mainfrom
raychaser wants to merge 14 commits intodanielmiessler:mainfrom
Conversation
* fix: make PAI v4.0.1 portable for non-default CLAUDE_CONFIG_DIR installs
Replace hardcoded ~/.claude paths with process.env.PAI_DIR fallback pattern
across 31 TypeScript files. Add .claude/settings.json traversal blocker to
prevent Claude Code from loading ancestor ~/.claude/settings.json as project
settings when PAI is installed at a custom CLAUDE_CONFIG_DIR location.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address PR review findings — missed hardcoded paths, PROJECTS_DIR slug, mkdir safety
- chat/route.ts: PAI_DIR fallback for Inference.ts spawn path
- AlgorithmBridge.ts: PAI_DIR fallback for ISCManager.ts shell command
- BugBountyTool/config.ts: replaced 4 hardcoded ~/.claude paths with join(paiDir, ...)
- ActivityParser.ts: dynamic CWD_SLUG (was hardcoded -Users-${USERNAME}--claude), replaced
5 hardcoded /.claude/ string matches with CLAUDE_DIR_MARKER for non-default installs
- LastResponseCache.hook.ts: mkdirSync before writeFileSync to prevent ENOENT on fresh installs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: harden error handling and centralize PAI_DIR resolution
- ActivityParser.ts & SessionHarvester.ts: use getPaiDir() from hooks/lib/paths
instead of inline process.env.PAI_DIR || process.env.HOME! pattern (throws
explicitly when HOME is undefined instead of producing "undefined/.claude")
- ActivityParser.ts: add PROJECTS_DIR diagnostic (lists available slugs when
computed slug doesn't match), JSONL parse counter (warns when all lines fail),
CLAUDE_DIR_MARKER miss counter (warns when no file paths match marker)
- SessionHarvester.ts: same PROJECTS_DIR diagnostic and JSONL parse counter
- AlgorithmBridge.ts: use homedir() instead of process.env.HOME, add existsSync
check before shell exec, wrap in try-catch (was silently swallowed by .quiet())
- chat/route.ts: use homedir()/join() instead of template literal with HOME,
surface actual error message in 500 response instead of generic text
- LastResponseCache.hook.ts: separate mkdir and write error paths for clearer
diagnostics
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: eliminate silent failures and complete getPaiDir() migration
- AlgorithmBridge: migrate to getPaiDir() for $HOME expansion
- chat/route.ts: fix variable shadowing, prevent info disclosure in 500 response
- file/save/route.ts, upload/route.ts: log actual error messages server-side
- AlgorithmPhaseReport: add console.error to 3 empty catch blocks
- LoadContext.hook.ts: add error logging to 7 empty catch blocks
- notifications.ts: add error logging to 3 empty catch blocks
- ActivityParser, SessionHarvester: guard diagnostic readdirSync with try-catch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: complete getPaiDir() migration and restore stack trace logging
- AlgorithmPhaseReport: migrate to getPaiDir() (was missed in prior commit)
- notifications.ts: log sendPush() failures instead of silent catch
- Telos routes: restore full error object in console.error (stack traces)
- chat/route.ts: remove unused errorMessage variable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: AlgorithmPhaseReport exits non-zero on error, preserve stack traces in notifications
- AlgorithmPhaseReport: writeState() re-throws on failure, top-level catch exits with code 1
- notifications.ts: pass full error objects to console.error instead of string interpolation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: migrate remaining 35 files from inline PAI_DIR to getPaiDir()
Replace all remaining `process.env.PAI_DIR || join(homedir(), '.claude')`
inline patterns with the centralized `getPaiDir()` helper from
hooks/lib/paths.ts, which provides $HOME/~/~ expansion, safe homedir()
fallback, and a single source of truth for PAI directory resolution.
Files intentionally kept as-is: VoiceServer/server.ts and 4 Telos
DashboardTemplate routes (standalone deployable contexts).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: migrate VoiceServer to getPaiDir() for expandPath() support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: preserve stack traces in LoadContext, suppress ENOENT noise, guard NaN
- LoadContext.hook.ts: Change 12 catch blocks from `${err}` template
interpolation to `, err` argument passing to preserve stack traces.
Replace emoji prefixes with consistent [LoadContext] tag.
- AlgorithmPhaseReport.ts: Suppress expected ENOENT errors on first run
(state file doesn't exist yet) alongside the existing 'empty' sentinel.
- notifications.ts: Guard against NaN propagation when session start file
contains corrupted/non-numeric data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* revert: restore AlgorithmPhaseReport silent error handling
Revert writeState re-throw and top-level process.exit(1) back to
original non-blocking catch blocks. A reporting tool should not be
capable of killing the process on transient filesystem errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* cleanup: remove unused getHooksDir, getSkillsDir, getMemoryDir exports
These three functions have zero consumers. paiPath and getSettingsPath
are kept — they have active consumers across the codebase.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* add non-default CLAUDE_CONFIG_DIR test script and README note
Temporary manual deployment script for testing PAI at paths other than
~/.claude. Copies release files, patches settings.json paths, manages
shell aliases, and cleans up stale caches. Will be superseded once the
installer handles non-default config directories natively.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…em state 21 stale tips fixed (wrong counts, removed effort tiers, non-existent agents, outdated ISC scales). 14 new tips added for v4.0 features (Components, LoadContext, hierarchical skills, PRD format, voice announcements, context compaction). Algorithm version bumped to v3.6.0. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added section 4 documenting spinner tips audit (21 fixed, 14 added) - Updated badges (workflows 180→338, added Tips badge) - Created RELEASE.json with version metadata and change highlights - Updated files-changed table to reflect settings.json scope Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes applied to Releases/v4.0.1/.claude/ (matching live ~/.claude/): - danielmiessler#825: Fix wrong pai alias path (skills/PAI → PAI) - danielmiessler#757: Detect user shell for alias (.zshrc/.bashrc/.config/fish) - danielmiessler#819: Write algorithmVersion to settings.json from CLAUDE.md - danielmiessler#772: Add 'explicit' to rating source union type - danielmiessler#768: LoadContext exits 0 on error (non-fatal) - danielmiessler#766: DocCrossRefIntegrity uses configured voice, not hardcoded ID - danielmiessler#747: Persistent terminal width cache prevents mini mode on re-render - danielmiessler#755: Auto-detect headless/SSH, fall back to CLI installer - danielmiessler#832: Skip inference when 0 drift detected (saves ~15s/response) - danielmiessler#767: Track lineageSubKey instead of fragile .pop() in YAML parser - danielmiessler#769: Remove dead TrendingAnalysis.ts code and all call sites Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: make PAI v4.0.1 portable for non-default CLAUDE_CONFIG_DIR installs
Replace hardcoded ~/.claude paths with process.env.PAI_DIR fallback pattern
across 31 TypeScript files. Add .claude/settings.json traversal blocker to
prevent Claude Code from loading ancestor ~/.claude/settings.json as project
settings when PAI is installed at a custom CLAUDE_CONFIG_DIR location.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address PR review findings — missed hardcoded paths, PROJECTS_DIR slug, mkdir safety
- chat/route.ts: PAI_DIR fallback for Inference.ts spawn path
- AlgorithmBridge.ts: PAI_DIR fallback for ISCManager.ts shell command
- BugBountyTool/config.ts: replaced 4 hardcoded ~/.claude paths with join(paiDir, ...)
- ActivityParser.ts: dynamic CWD_SLUG (was hardcoded -Users-${USERNAME}--claude), replaced
5 hardcoded /.claude/ string matches with CLAUDE_DIR_MARKER for non-default installs
- LastResponseCache.hook.ts: mkdirSync before writeFileSync to prevent ENOENT on fresh installs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: harden error handling and centralize PAI_DIR resolution
- ActivityParser.ts & SessionHarvester.ts: use getPaiDir() from hooks/lib/paths
instead of inline process.env.PAI_DIR || process.env.HOME! pattern (throws
explicitly when HOME is undefined instead of producing "undefined/.claude")
- ActivityParser.ts: add PROJECTS_DIR diagnostic (lists available slugs when
computed slug doesn't match), JSONL parse counter (warns when all lines fail),
CLAUDE_DIR_MARKER miss counter (warns when no file paths match marker)
- SessionHarvester.ts: same PROJECTS_DIR diagnostic and JSONL parse counter
- AlgorithmBridge.ts: use homedir() instead of process.env.HOME, add existsSync
check before shell exec, wrap in try-catch (was silently swallowed by .quiet())
- chat/route.ts: use homedir()/join() instead of template literal with HOME,
surface actual error message in 500 response instead of generic text
- LastResponseCache.hook.ts: separate mkdir and write error paths for clearer
diagnostics
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: eliminate silent failures and complete getPaiDir() migration
- AlgorithmBridge: migrate to getPaiDir() for $HOME expansion
- chat/route.ts: fix variable shadowing, prevent info disclosure in 500 response
- file/save/route.ts, upload/route.ts: log actual error messages server-side
- AlgorithmPhaseReport: add console.error to 3 empty catch blocks
- LoadContext.hook.ts: add error logging to 7 empty catch blocks
- notifications.ts: add error logging to 3 empty catch blocks
- ActivityParser, SessionHarvester: guard diagnostic readdirSync with try-catch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: complete getPaiDir() migration and restore stack trace logging
- AlgorithmPhaseReport: migrate to getPaiDir() (was missed in prior commit)
- notifications.ts: log sendPush() failures instead of silent catch
- Telos routes: restore full error object in console.error (stack traces)
- chat/route.ts: remove unused errorMessage variable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: AlgorithmPhaseReport exits non-zero on error, preserve stack traces in notifications
- AlgorithmPhaseReport: writeState() re-throws on failure, top-level catch exits with code 1
- notifications.ts: pass full error objects to console.error instead of string interpolation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: migrate remaining 35 files from inline PAI_DIR to getPaiDir()
Replace all remaining `process.env.PAI_DIR || join(homedir(), '.claude')`
inline patterns with the centralized `getPaiDir()` helper from
hooks/lib/paths.ts, which provides $HOME/~/~ expansion, safe homedir()
fallback, and a single source of truth for PAI directory resolution.
Files intentionally kept as-is: VoiceServer/server.ts and 4 Telos
DashboardTemplate routes (standalone deployable contexts).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: migrate VoiceServer to getPaiDir() for expandPath() support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: preserve stack traces in LoadContext, suppress ENOENT noise, guard NaN
- LoadContext.hook.ts: Change 12 catch blocks from `${err}` template
interpolation to `, err` argument passing to preserve stack traces.
Replace emoji prefixes with consistent [LoadContext] tag.
- AlgorithmPhaseReport.ts: Suppress expected ENOENT errors on first run
(state file doesn't exist yet) alongside the existing 'empty' sentinel.
- notifications.ts: Guard against NaN propagation when session start file
contains corrupted/non-numeric data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* revert: restore AlgorithmPhaseReport silent error handling
Revert writeState re-throw and top-level process.exit(1) back to
original non-blocking catch blocks. A reporting tool should not be
capable of killing the process on transient filesystem errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* cleanup: remove unused getHooksDir, getSkillsDir, getMemoryDir exports
These three functions have zero consumers. paiPath and getSettingsPath
are kept — they have active consumers across the codebase.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* add non-default CLAUDE_CONFIG_DIR test script and README note
Temporary manual deployment script for testing PAI at paths other than
~/.claude. Copies release files, patches settings.json paths, manages
shell aliases, and cleans up stale caches. Will be superseded once the
installer handles non-default config directories natively.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* sync: port upstream v4.0.2 bugfixes onto getPaiDir() branch
Merges upstream's 5 hook bugfixes while preserving our getPaiDir() portability
migration. Changes: remove dead triggerTrending code, add explicit rating source
field, fix YAML lineage parsing, non-fatal LoadContext exit, dynamic voice ID
via getIdentity(), algorithm version extraction in UpdateCounts, and conditional
inference skip in DocCrossRefIntegrity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Same migration as v4.0.1 (danielmiessler#838): centralizes all PAI directory resolution into getPaiDir() in hooks/lib/paths.ts, replacing ~15 different inline patterns across 49 files. Handles $HOME, ${HOME}, and ~ expansion. Byte-identical behavior when PAI_DIR is unset. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced Mar 2, 2026
Verifies that BuildCLAUDE.ts can find CLAUDE.md.template via getPaiDir() when running from a non-default CLAUDE_CONFIG_DIR. Without PAI_DIR set, getPaiDir() falls back to ~/.claude where the template doesn't exist — this test catches that. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Follows the upstream upgrade flow (backup → copy → rebuild) but adapted for non-default target directories. Does not use the installer. Preserves user data (MEMORY, .env, agents), removes stale files, updates settings.json paths, and rebuilds CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add file-history, shell-snapshots, commands, and .DS_Store to skip list. Add skills to preserve list. These are Claude Code internals or user-generated content that don't come from the release and should never be deleted during upgrades. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The upstream upgrade flow (cp -r .claude ~/) overlays new files without deleting anything. The stale file cleanup step had no upstream precedent and was deleting Claude Code runtime data (file-history, commands, skills). Removed entirely — upgrades should only add/overwrite, never delete. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DevenDucommun
added a commit
to DevenDucommun/Personal_AI_Infrastructure
that referenced
this pull request
Mar 6, 2026
Algorithm v3.8.0: merge v3.6.0 cognitive scaffolding (self-interrogation, constraint extraction, confidence tags, priority classification, coverage map, QG2-QG7 gates) into v3.7.0. Split ISC methodology, capability selection, and examples into dedicated files. Standard PRD skip. Session- safe context recovery. Voice curls fire-and-forget. Hooks: consolidate 4 terminal hooks → TerminalState.hook.ts. Add ModeClassifier (deterministic mode pre-classification, PR danielmiessler#840) and PostCompactRecovery (context re-injection after compaction, PR danielmiessler#799). Portability: replace hardcoded join(homedir(),'.claude') with paiPath() across 22 TS files (PR danielmiessler#873). Docs: slim SKILLSYSTEM.md and THEHOOKSYSTEM.md to ~80 lines each; move full content to PAI/dev/. Move MEMORYSYSTEM migration history to MEMORY-CHANGELOG.md. Add TELOS/DIGEST.md template to loadAtStartup. Clean CLAUDE.md MINIMAL format. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
getPaiDir()centralized path resolution from v4.0.1 (fix: make PAI v4.0.1 portable for non-default CLAUDE_CONFIG_DIR installs #838) to the v4.0.3 releasegetPaiDir()fromhooks/lib/paths.ts$HOME,${HOME}, and~expansion (Claude Code doesn't expand shell variables insettings.jsonenv values)PAI_DIRis unset, behavior is byte-identical to before this PRThis is the v4.0.3 counterpart to #838 (v4.0.1). See #838 for the full design rationale, or issue #830 for the original problem description.
What changed (51 files, +546 −135)
Identical migration pattern as #838, applied to
Releases/v4.0.3/:getPaiDir()import replacing inlineprocess.env.HOME! + '/.claude',join(homedir(), '.claude'), etc.hooks/lib/paths.ts— removed 3 unused convenience wrappers.claude/.claude/settings.json— ancestor traversal blockertest-nondefault-install.sh— validation scriptIntentionally NOT migrated:
skills/Telos/DashboardTemplate/(4 Next.js route handlers) andPAI-Install/(3 installer files) — both run in separate bundling contexts.Test plan
CLAUDE_CONFIG_DIR=~/raychaser/claude~/.claudebehavior unchanged whenPAI_DIRis unset🤖 Generated with Claude Code