#!/usr/bin/env node /** * load-core-context.ts * * Automatically loads your CORE skill context at session start by reading and injecting * the CORE SKILL.md file contents directly into Claude's context as a system-reminder. * * Purpose: * - Read CORE SKILL.md file content * - Output content as system-reminder for Claude to process * - Ensure complete context (contacts, preferences, security, identity) available at session start * - Bypass skill activation logic by directly injecting context * * Setup: * 1. Customize your ${ADAPTER_DIR}/skills/CORE/SKILL.md with your personal context * 2. Add this hook to settings.json SessionStart hooks * 3. Ensure ADAPTER_DIR environment variable is set (defaults to $HOME/.claude) * * How it works: * - Runs at the start of every Claude Code session * - Skips execution for subagent sessions (they don't need CORE context) * - Reads your CORE SKILL.md file * - Injects content as which Claude processes automatically * - Gives your AI immediate access to your complete personal context */ import { isWorkerSession } from "../lib/worker-session.js"; import { readFileSync, existsSync } from 'fs'; import { join } from 'path'; import { SKILLS_DIR } from '../lib/pai-paths'; import { isProbeSession } from '../lib/project-utils'; import { stripFrontmatter } from '../lib/frontmatter.js'; async function main() { if (isWorkerSession()) return; // disposable worker: no per-session bookkeeping try { // Check if this is a subagent session - if so, exit silently const claudeProjectDir = process.env.CLAUDE_PROJECT_DIR || ''; const isSubagent = claudeProjectDir.includes('/.claude/agents/') || process.env.CLAUDE_AGENT_TYPE !== undefined; if (isSubagent) { // Subagent sessions don't need CORE context loading console.error('Subagent session - skipping CORE context loading'); process.exit(0); } // Skip probe/health-check sessions (e.g. CodexBar ClaudeProbe) if (isProbeSession()) { console.error('Probe session detected - skipping CORE context loading'); process.exit(0); } // Get CORE skill path using PAI paths library const coreSkillPath = join(SKILLS_DIR, 'CORE/SKILL.md'); // Verify CORE skill file exists if (!existsSync(coreSkillPath)) { console.error(`CORE skill not found at: ${coreSkillPath}`); console.error(`Ensure CORE/SKILL.md exists or check ADAPTER_DIR environment variable`); process.exit(1); } console.error('Reading CORE context from skill file...'); // Read the CORE SKILL.md file content let coreContent = readFileSync(coreSkillPath, 'utf-8'); // Perform Dynamic Variable Substitution // This allows SKILL.md to be generic while the session is personalized const daName = process.env.DA || 'PAI'; const daColor = process.env.DA_COLOR || 'blue'; const engineerName = process.env.ENGINEER_NAME || ''; // Replace placeholders {{DA}}, {{DA_COLOR}}, {{ENGINEER_NAME}} coreContent = coreContent .replace(/\{\{DA\}\}/g, daName) .replace(/\{\{DA_COLOR\}\}/g, daColor) .replace(/\{\{ENGINEER_NAME\}\}/g, engineerName); console.error(`Read ${coreContent.length} characters from CORE SKILL.md (Personalized for ${engineerName} & ${daName})`); // Output the CORE content as a system-reminder, minus the frontmatter // (catalogue metadata the session already has from its skill list) — // this will be injected into Claude's context at session start const message = ` PAI CORE CONTEXT ${stripFrontmatter(coreContent)} `; // Write to stdout (will be captured by Claude Code) console.log(message); console.error('CORE context injected into session'); process.exit(0); } catch (error) { console.error('Error in load-core-context hook:', error); process.exit(1); } } main();