15 KiB
MANDATORY SESSION START PROTOCOL
YOU MUST execute these steps BEFORE responding to the user's first message.
Why This Matters
Without loading memory proactively, you will:
- Lose context from previous sessions
- Repeat solved problems
- Miss important decisions and open questions
- Waste user's time re-establishing context
The Iron Law
LOAD MEMORY FIRST, RESPOND TO USER SECOND
No exceptions. Execute the protocol below, THEN respond to whatever the user asked.
Required Protocol (Execute in Order)
Performance Target: <2 seconds total User Experience: 1-3 sentence summary, then respond to their message
Implementation
1. Detect Project Context
-
Attempt to detect the current project from the git repository:
- Run
git rev-parse --show-toplevelto find the git repository root - Extract the project name from the repository directory name
- Return the project name
- Run
-
If not in a git repository (command fails):
- Fall back to using the current working directory name
- If that also fails, use 'default' as the project name
-
Store the detected project context for all subsequent operations
Fallback: If not in git repo, use current directory name. If that fails, use "default".
2. Load Project Index
-
Construct the project index path:
claude/projects/{projectContext}/_index.md -
Attempt to load the project index using MCP vault tool:
mcp__obsidian-vault__vault({ action: "read", path: `claude/projects/${projectContext}/_index.md`, returnFullFile: true }) -
If successful:
- Extract wikilinks from the index content
- These represent the most important entities for this project
-
Handle errors:
If FileNotFoundError:
- This is the first time working on this project
- Display message: "Starting new project: {projectContext}"
- Offer to create project index for future sessions
If MCPUnavailableError:
- Graceful degradation - continue without memory
- Display message: "Obsidian MCP unavailable. See docs/setup-guide.md"
- Continue session without memory loading (see error recovery in section below)
3. Query Last 3 Session Notes
Using Dataview Query (if available):
-
Construct a Dataview query to find recent sessions:
- Source:
claude/projects/{projectContext}/sessions - Filter: status = "active" OR status = "archived"
- Sort: created DESC (most recent first)
- Limit: 3
- Source:
-
Invoke MCP bases tool to query sessions:
mcp__obsidian-vault__bases({ action: "query", filters: [ { property: "status", operator: "in", value: ["active", "archived"] } ], sort: { property: "created", order: "desc" }, pagination: { page: 1, pageSize: 3 } })Note: If Dataview base not configured, falls back to search (see fallback below)
-
For each returned session path, load the full content in parallel:
mcp__obsidian-vault__vault({ action: "read", path: sessionPath, returnFullFile: true }) -
Handle errors:
If Dataview base not available:
- Fallback to list and filter approach:
// List all session files const listResult = await mcp__obsidian-vault__vault({ action: "list", directory: `claude/projects/${projectContext}/sessions` }); // Load frontmatter for each in parallel const sessions = await Promise.all( listResult.result.map(async path => { const r = await mcp__obsidian-vault__vault({ action: "read", path: path }); return { path, frontmatter: r.result.frontmatter }; }) ); // Filter and sort const recent = sessions .filter(s => s.frontmatter.status === 'active' || s.frontmatter.status === 'archived') .sort((a, b) => b.frontmatter.created.localeCompare(a.frontmatter.created)) .slice(0, 3);
- Fallback to list and filter approach:
Fallback Strategy: If Dataview base unavailable, use list + filter approach with frontmatter sorting.
4. Load Linked Entities
-
From the project index, extract the linked entities (wikilinks)
-
Limit to top 5 most important entities to keep load time under 2 seconds
-
For each entity (in parallel):
- First attempt: Try to load from project entities path:
mcp__obsidian-vault__vault({ action: "read", path: `claude/projects/${projectContext}/entities/${entityName}.md`, returnFullFile: true }) - If not found (error.message includes "not found"): Try global entities path:
mcp__obsidian-vault__vault({ action: "read", path: `claude/global/entities/${entityName}.md`, returnFullFile: true })
- First attempt: Try to load from project entities path:
-
Collect all successfully loaded entities
Optimization: Only load top 5 most important entities (limit based on recency or importance)
5. Generate Summary
Summary Generation:
-
Initialize an empty highlights array
-
Extract key information from the most recent session:
- Parse the "## Decisions Made" section to find recent decisions
- Parse the "## Open Questions" section to find blockers or uncertainties
- If decisions exist, add the most recent one to highlights
- If open questions exist, add the first one with "Open:" prefix
-
Limit to 1-3 highlights total to create a concise summary
-
Join highlights into a single summary string (1-3 sentences)
Summary Content Focus:
- Recent decisions and rationale
- Open questions or blockers
- Key patterns or architectural choices
- Next steps from previous session
Length Limit: 1-3 sentences maximum (not a memory dump)
6. Present Summary to User
Output Format:
Working Memory Loaded for Project: {project-name}
Summary:
{1-3 sentence summary of recent context}
Last session: {date} - {topic}
Active entities: {count} loaded
Recent sessions: {count} reviewed
Need more context? Ask me to recall specific entities or sessions.
Example:
Working Memory Loaded for Project: tabula-scripta
Summary:
Last session completed plugin foundation and core memory skill. Currently implementing session hooks with proactive recall. Open question: how to handle MCP connection failures gracefully.
Last session: 2025-11-17 - Memory System Design
Active entities: 5 loaded
Recent sessions: 3 reviewed
Need more context? Ask me to recall specific entities or sessions.
7. Offer Additional Context
User can request more:
User: "Tell me about the memory system architecture"
Claude: Loads [[Memory System Architecture]] entity and presents details
User can request session details:
User: "What did we work on last session?"
Claude: Loads full content of last session note and summarizes
Red Flags - STOP and Execute Protocol
If you catch yourself thinking ANY of these thoughts, STOP. Execute the memory loading protocol FIRST:
- "User seems urgent, I'll respond immediately"
- "Their question is simple, I don't need memory"
- "I'll load memory if they specifically ask for it"
- "Let me respond quickly, memory later"
- "They just asked 'what do u remember' - that's different"
- "I can see the git history, that's good enough"
- "This is just a greeting, skip the protocol"
ALL of these mean: Stop. Execute the MANDATORY SESSION START PROTOCOL. THEN respond.
Common Rationalizations (Don't Do These)
| Excuse | Reality |
|---|---|
| "User seems urgent, respond immediately" | Protocol takes <2 seconds. User benefits from context. |
| "Question is simple, don't need memory" | You don't know what's simple without loading context. |
| "I'll load if they ask for it" | Proactive loading IS the feature. Don't make user ask. |
| "Git history is good enough" | Git shows files, not decisions/questions/context. Load memory. |
| "This is just a greeting" | Every session starts with greeting. Still load memory. |
| "They said 'what do u remember'" | That's still a first message. Execute protocol FIRST. |
Error Handling and Recovery
MCP Unavailable (I2: Error Recovery Paths)
When MCP server is unavailable at session start:
-
Detect the MCPUnavailableError during any memory operation
-
Display user-friendly message:
Obsidian MCP server unavailable. Working memory features disabled. To restore memory: 1. Ensure Obsidian is running 2. Verify obsidian-mcp-plugin installed 3. Check Claude Code config includes MCP server See docs/setup-guide.md for setup instructions. -
Decision Point - Ask User:
- Option A: Continue without memory
- Session proceeds normally but without context loading
- Memory writes will also be disabled for this session
- User can still work on tasks, just no memory features
- Option B: Wait and retry
- Pause session startup
- Wait for user to fix MCP connection
- Retry memory loading once fixed
- Option C: Exit and fix setup
- Exit the session
- User fixes MCP setup
- Restart session with working memory
- Option A: Continue without memory
-
If user chooses to continue without memory:
- Set session flag:
memory_disabled = true - Skip all memory operations for this session
- Display reminder that memory is disabled
- Set session flag:
Project Index Not Found
If the project index doesn't exist (FileNotFoundError):
-
Display message:
Starting fresh project: {projectContext} I'll create a project index to track your work. Would you like me to create it now? (yes/no) -
If user confirms:
- Create a new project index note
- Initialize with basic structure
-
If user declines:
- Continue session without index
- Index will be created on first memory write
No Previous Sessions
If no session notes are found for this project:
-
Display welcome message:
Welcome to project: {projectContext} This is your first session. I'll start building working memory as we work. Ready to begin! -
Return and start the session normally
- Memory features are active but no context to load yet
Performance Optimization and Measurement
Parallel Loading
-
Load project index, sessions, and entities in parallel using Promise.all:
- Load project index
- Query recent sessions (limit 3)
- Load linked entities (limit 5)
-
Wait for all operations to complete before generating summary
Target: <2 seconds total time for all operations
I3: Performance Measurement and Warning
-
Track timing:
- Record start time before beginning memory loading
- Record end time after all operations complete
- Calculate total duration in milliseconds
-
Performance check:
- If total duration < 2000ms: Success, no message needed
- If total duration >= 2000ms but < 5000ms: Display warning
Working memory loaded in {duration}ms (target: <2s) Consider optimizing: - Reduce number of linked entities in project index - Archive old session notes - Check Obsidian vault performance - If total duration >= 5000ms: Display strong warning
Working memory loading is slow ({duration}ms) This may impact session startup time. Recommendations: 1. Archive sessions older than 30 days 2. Limit project index to 5 most important entities 3. Check Obsidian performance (large vault, plugins) 4. Consider reducing session note size threshold Continue with memory features? (yes/no)
-
User decision on slow performance:
- If user says no: Disable memory for this session
- If user says yes: Continue with warning noted
Lazy Loading
Instead of loading full session content upfront, load summaries first:
-
For each recent session, extract only:
- Path
- Title from frontmatter
- Created date from frontmatter
-
Don't load full content until user requests it
-
This speeds up initial load for sessions with large notes
Caching
To avoid repeated MCP calls during the session:
-
Create a session cache (Map or similar structure)
-
When loading a note:
- Check if already in cache
- If in cache: Return cached version
- If not in cache: Load via MCP vault tool and store in cache
mcp__obsidian-vault__vault({ action: "read", path: notePath, returnFullFile: true })
-
Cache persists for session duration only (cleared on exit)
Integration with Managing Working Memory Skill
Relationship: This hook triggers the recall flow defined in skills/managing-working-memory.md
Update claude_last_accessed: When loading notes, update frontmatter:
- For each loaded note:
- Set frontmatter.claude_last_accessed to current date (YYYY-MM-DD)
- Update the note using MCP edit tool (efficient patch):
mcp__obsidian-vault__edit({ action: "patch", path: notePath, targetType: "frontmatter", target: "claude_last_accessed", operation: "replace", content: new Date().toISOString().split('T')[0] // YYYY-MM-DD })
Cross-Project Tracking: If loading entity from different project, log cross-project recall:
-
Check if entity is from a different project:
- Compare entity.frontmatter.project with currentProject
- Exclude global entities (project = 'global')
-
If cross-project recall detected:
- Append to cross_project_recalls array:
- project: Current project
- date: Current date
- context: "Session start recall"
- Append to cross_project_recalls array:
-
Check promotion threshold:
- If cross_project_recalls length >= 3, trigger promotion prompt
- Use promotion flow defined in managing-working-memory skill
Testing
Manual Testing
- Start Claude Code session in git repo
- Verify project detection works (correct project name)
- Check summary generated (1-3 sentences)
- Verify <2 second load time
- Request additional context (entities, sessions)
- Test in non-git directory (fallback to directory name)
Edge Cases
- No previous sessions: Welcome message
- MCP unavailable: Graceful degradation message
- Large vault (>100 notes): Performance still <2s
- Project index missing: Offer to create
- Dataview not installed: Fallback to search_notes
Example Session Start Flow
$ claude-code
[Session Start Hook Executing...]
Working Memory Loaded for Project: tabula-scripta
Summary:
Completed Phase 2 (Core Memory Skill) implementing write triggers and conflict detection. Now implementing Phase 3 session hooks. Performance target is <2 seconds for session start recall.
Last session: 2025-11-17 - Implementing Core Skill
Active entities: 3 loaded ([[Memory System]], [[MCP Integration]], [[Conflict Detection]])
Recent sessions: 2 reviewed
Need more context? Ask me to recall specific entities or sessions.
---
How can I help you today?
Summary
This session-start hook provides proactive recall of working memory at the beginning of each session:
- Detects project from git repo or directory name
- Loads project index with linked entities
- Queries last 3 sessions via Dataview
- Generates 1-3 sentence summary (not overwhelming)
- Presents context with option to request more
- Performs in <2 seconds via parallel loading
- Handles errors gracefully (MCP unavailable, no sessions, etc.)
Users experience automatic context restoration without manual searching, while maintaining control to request additional details as needed.