LifeOS Context Injection and Per-Turn Context Loading: How It Works
LifeOS context injection is a dynamic system that assembles a situational-awareness block from identity files, hot-layer memory, and optional query-relevant snippets, then streams it to Claude on every turn via the LoadContext hook.
LifeOS is an open-source framework by Daniel Miessler for managing AI-augmented personal and professional workflows. Its context injection system ensures Claude-Code sessions maintain continuous awareness of your identity, goals, projects, and recent notes without reloading the entire knowledge base each time.
What Is LifeOS Context Injection?
Context injection is the automated insertion of a dynamic context block into Claude's system prompt at the start of every turn. This block contains structured personal data that primes the model with relevant background before processing your request.
The block comprises six core components:
- DA identity β The Digital Assistant's defined role and capabilities
- Principal identity β Your personal identity, preferences, and working style
- Principal TELOS β Your overarching life goals and values framework
- Projects β Active project definitions and current session states
- Principal MEMORY β Recent notes, learnings, and signals about you
- DA MEMORY β Recent interactions and learned patterns about the assistant's performance
These files live in your LifeOS directory as markdown documents, with the two *_MEMORY.md files forming a memory hot-layer that updates continuously through the system's feedback loops.
How Per-Turn Context Is Loaded
The loading mechanism centers on the LoadContext hook (LifeOS/install/hooks/LoadContext.hook.ts). This hook triggers automatically on Claude-Code's SessionStart event, orchestrating the entire per-turn flow.
Step 1: Hook Activation
The hook system must first be installed and activated:
bun Tools/InstallHooks.ts --apply
bun Tools/ActivateImports.ts --apply
The first command merges LoadContext.hook.ts into your Claude-Code settings.json. The second enables @imports for static files. Once applied, the hook fires automatically on every new turn.
Step 2: Context Block Assembly
The hook delegates to buildLifeosContextBlock() in LifeOS/install/LIFEOS/PULSE/lib/lifeos-context.ts. This function executes a five-phase pipeline:
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Static Sources β ββββ Hot Memory β ββββ Cache Check β
β (4 files) β β (2 files) β β (60s + mtime) β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β
βββββββββββββββββββ β
β Query Handling β ββββ (if fresh)
β (BM25 search) β
βββββββββββββββββββ
β
βββββββββββββββββββ
β Format Block β
β (markdown) β
βββββββββββββββββββ
Phase Details
- Static collection β Reads the four identity/TELOS/Projects markdown files from disk
- Hot-layer read β Calls
MemoryWriter.read()to fetch and sanitizePrincipal_MEMORY.mdandDA_MEMORY.md - Cache validation β Stores assembled markdown with file modification times (mtimes). Returns cached block if within 60 seconds and no files changed
- Query enrichment β Bypasses cache if a query is present, running
MemoryRetriever.getRelevantContext()for BM25-based retrieval from the knowledge corpus and memory files - Markdown formatting β Produces final block with header, "Today" timestamp, DA section, Principal section, memory blocks, query-specific snippets (if any), and active project sessions
Step 3: Streaming to Claude
The assembled block wraps in XML tags and streams via --append-system-prompt-file:
// Conceptual flow from LoadContext.hook.ts
const ctxBlock = await buildLifeosContextBlock(userQuery)
console.log('<system-reminder>' + ctxBlock + '</system-reminder>')
This appears in Claude's context window before your actual message, giving the model immediate access to your situational data.
The 60-Second Cache: Performance and Freshness Balance
The caching strategy optimizes for both speed and recency:
| Aspect | Implementation |
|---|---|
| Cache duration | 60 seconds |
| Invalidation trigger | File mtime change on any source |
| Scope | In-process only (no persistence) |
| Query impact | Cache bypassed entirely |
This design means:
- Rapid back-and-forth turns reuse the same context block without filesystem hits
- Any Reviewer-generated memory entry becomes visible within 60 seconds or immediately on the next mtime-detecting check
- Explicit questions always retrieve the most relevant information via BM25, regardless of cache state
Query-Driven Dynamic Relevance
When you ask a concrete question, the system shifts from static context to targeted retrieval:
import { buildLifeosContextBlock } from '../../PULSE/lib/lifeos-context'
// Static path - uses cache, no search overhead
const staticBlock = await buildLifeosContextBlock()
// Dynamic path - BM25 search, cache bypassed
const dynamicBlock = await buildLifeosContextBlock(
'What were my key insights from the Q4 review?'
)
The getRelevantContext() call indexes your knowledge corpus plus both memory files, scoring passages by BM25 relevance and inserting the top snippet into the context block. This keeps prompts concise while surfacing pertinent historical information.
Memory Hot-Layer Architecture
The two *_MEMORY.md files function as a working memory buffer distinct from long-term storage:
- Principal MEMORY β Your notes, observations, preferences learned by the system
- DA MEMORY β Assistant reflections on effective patterns and interaction history
These files receive continuous updates from LifeOS's Reviewer loop, which analyzes turns for notable information. Because the per-turn loader checks mtimes, new entries propagate to Claude's context automaticallyβno manual refresh required.
Hook System Integration
Context injection is one component of LifeOS's broader Hooks architecture (LifeOS/install/LIFEOS/DOCUMENTATION/Hooks/HookSystem.md). The unified system enables:
- Always-on behaviors without manual invocation
- Composable triggers tied to Claude-Code lifecycle events
- Modular activation via the
InstallHooks.tsandActivateImports.tstooling
The LoadContext hook specifically binds to SessionStart, ensuring consistent initialization state across all interactions.
Key Implementation Files
| File Path | Purpose |
|---|---|
LifeOS/install/hooks/LoadContext.hook.ts |
Entry point hook triggering on session start |
LifeOS/install/LIFEOS/PULSE/lib/lifeos-context.ts |
Core buildLifeosContextBlock() implementation |
LifeOS/install/INSTALL.md |
Feature documentation and enablement instructions |
LifeOS/install/LIFEOS/DOCUMENTATION/Hooks/HookSystem.md |
Hooks architecture overview |
LifeOS/install/LIFEOS/DOCUMENTATION/Memory/MemorySystem.md |
Memory hot-layer and caching specification |
Summary
- LifeOS context injection streams a dynamic situational-awareness block to Claude on every turn
- Per-turn loading runs through the
LoadContext.hook.tsβbuildLifeosContextBlock()pipeline - Six source files populate the block: four static identities/goals/projects plus two hot-layer memory files
- 60-second mtime cache eliminates redundant filesystem reads while preserving freshness
- Query-triggered BM25 retrieval adds targeted memory snippets when you ask specific questions
- Hook-based activation via
bun Tools/InstallHooks.ts --applyenables the entire system
Frequently Asked Questions
How do I enable per-turn context injection in LifeOS?
Run bun Tools/InstallHooks.ts --apply from your LifeOS directory. This merges the LoadContext hook into your Claude-Code settings.json. Then run bun Tools/ActivateImports.ts --apply to enable static file importing. The hook activates automatically on your next Claude-Code session.
What happens if I modify a memory file during an active session?
The 60-second cache checks file modification times (mtimes). If Principal_MEMORY.md or DA_MEMORY.md changes, the next context load detects the new mtime and rebuilds the block. In practice, updates from the Reviewer loop appear within one turn or at most 60 seconds.
Does context injection slow down Claude-Code responses?
No. The filesystem-caching layer ensures static blocks reuse assembled context for rapid back-and-forth exchanges. Only explicit queries trigger BM25 search overhead, and this targeted retrieval typically adds minimal latency compared to loading full knowledge bases.
What's the difference between hot-layer memory and the knowledge corpus?
Hot-layer memory (Principal_MEMORY.md and DA_MEMORY.md) loads automatically into every context block. The knowledge corpus remains disk-resident until a query triggers getRelevantContext() to extract specific passages via BM25 scoring.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too β