Skip to content

How to Build Claude Code Session Persistence Across Sessions

Problem

Every Claude Code session starts fresh. When I close a session and return the next day, Claude has no memory of yesterday’s work. I have to re-explain project goals, constraints, and decisions.

The session reset problem
Day 1: Explain project → Claude understands → Work done
Day 2: Claude forgets everything → Re-explain → More work
Day 3: Same cycle repeats...

This wastes 15-30 minutes per session on context-setting.

What happened?

I realized I needed persistent memory that survives session resets. The solution is “campaign files”—structured documents that capture what was built, decisions made, and remaining work.

How to solve it?

The Campaign File Structure

I created a campaign file with these sections:

.claude/campaign.yaml
# Campaign: [Project Name]
## Identity
- Purpose: [One-line project description]
- Tech Stack: [Core technologies]
- Constraints: [Key limitations to respect]
## Active Session
- Started: [Date]
- Focus: [Current session goal]
- Blockers: [If any]
## Build Log
### 2026-03-21: Authentication System
- Implemented JWT-based auth
- Added refresh token rotation
- Decision: Chose short-lived access tokens (15min)
### 2026-03-20: Database Schema
- Created user and session tables
- Added indexes for common queries
- Decision: PostgreSQL over MongoDB for relational data
## Remaining Work
1. [HIGH] Implement password reset flow
2. [MEDIUM] Add rate limiting to auth endpoints
3. [LOW] Write API documentation
## Decisions Log
| Date | Decision | Rationale |
|------|----------|-----------|
| 2026-03-21 | JWT tokens | Stateless auth, scalable |
| 2026-03-20 | PostgreSQL | ACID compliance needed |
## Constraints
- No external auth providers (self-hosted requirement)
- Must support offline-first mobile clients
## Handoff Notes
- Next session: Start with password reset
- Check /auth/reset branch for partial implementation

Session Handoff Pattern

Here’s how I use campaign files in practice:

session_manager.py
from datetime import datetime
from pathlib import Path
import yaml
class CampaignManager:
def __init__(self, campaign_path: str):
self.campaign_path = Path(campaign_path)
self.campaign = self._load_campaign()
def start_session(self, focus: str) -> dict:
"""Initialize new session with context from campaign."""
session_context = {
"started": datetime.now().isoformat(),
"focus": focus,
"project_identity": self.campaign.get("identity", {}),
"remaining_work": self.campaign.get("remaining_work", []),
"constraints": self.campaign.get("constraints", []),
"recent_decisions": self.campaign.get("decisions_log", [])[-5:],
}
# Update active session
self.campaign["active_session"] = session_context
self._save_campaign()
return session_context
def end_session(self, accomplishments: list, next_steps: list):
"""Record session outcomes and update campaign."""
today = datetime.now().strftime("%Y-%m-%d")
# Add to build log
self.campaign["build_log"].append({
"date": today,
"accomplishments": accomplishments,
})
# Update remaining work
self.campaign["remaining_work"] = next_steps
# Clear active session
self.campaign["active_session"] = None
self._save_campaign()
def _save_campaign(self):
"""Persist campaign state."""
self.campaign_path.write_text(yaml.dump(self.campaign))
# Usage
if __name__ == "__main__":
manager = CampaignManager(".claude/campaign.yaml")
# Start session - gets context from previous work
context = manager.start_session("Implement password reset")
print(f"Continuing project: {context['project_identity']}")
print(f"Remaining work: {context['remaining_work']}")
# End session - persists progress
manager.end_session(
accomplishments=["Password reset flow complete", "Added email templates"],
next_steps=["Add rate limiting", "Write tests for reset flow"]
)

Governance File Integration

I also updated my CLAUDE.md to reference the campaign file:

CLAUDE.md with campaign integration
# Project Governance
## Session Protocol
1. **Always read** `.claude/campaign.yaml` at session start
2. **Update campaign** after completing each major task
3. **Record decisions** with rationale, not just outcomes
4. **Sync CLAUDE.md** if patterns change
## Active Patterns
- Authentication: JWT with refresh tokens
- Database: PostgreSQL with SQLAlchemy
- API: REST with OpenAPI documentation
## Recent Decisions
See `.claude/campaign.yaml` -> decisions_log for full history.

The reason

I think the key reason this works is:

  1. Structure matters: A structured document is easier for Claude to parse and use
  2. Identity persistence: The campaign file becomes the “load-bearing identity layer” for each session
  3. Decision continuity: Architectural choices persist rather than being forgotten or contradicted

As one Reddit user said: “The governance file isn’t just orientation. It’s the load-bearing identity layer. When you point a new model at the same home directory, that file is what makes the agent wake up as the same entity.”

Summary

In this post, I showed how to build session persistence for Claude Code using campaign files. The key point is: capture what matters—identity, build log, decisions, remaining work, and constraints—in a structured form that the next session can immediately use.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments