Build a hierarchical context management system with CLAUDE.md global instructions, MEMORY.md session persistence, and enforced rules that survive conversation boundaries.
Claude Code conversations are stateless by default. Each new conversation starts with zero context about your preferences, workflows, project history, or learned patterns. This creates three critical problems:
The Context Guard system solves this by establishing a three-tier instruction hierarchy:
This is NOT a vector database. This is NOT about semantic search. This is about explicit, enforced, persistent instructions that load into every conversation and override default behavior.
The ~/.claude/CLAUDE.md file contains user-level preferences and enforced rules. This file is loaded into every conversation regardless of project or directory.
What belongs here:
Enforced rules pattern:
Use ENFORCED or CRITICAL tags to override default behavior:
## Code Standards (ENFORCED)
- No placeholder code or stubs. Full production code only.
- No hardcoded secrets. Use environment variables.
- No arbitrary code execution with user input.
- No `git add .` without review. Stage specific files.
## Privacy (CRITICAL)
NEVER include: employer name, job title, certifications, or identifying info.
Reference frameworks (NIST, ISO 27001) not credentials.
Why this works: The ENFORCED tag signals high priority. Claude Code's instruction parser treats these as hard constraints, not suggestions.
Each project gets a hashed directory under ~/.claude/projects/. The hash is computed from the project's absolute path to ensure uniqueness.
Path structure:
~/.claude/projects/-Users-user-Documents-Code-myapp/
├── memory/
│ ├── MEMORY.md # Main index (always loaded)
│ ├── debugging.md # Topic: debugging patterns
│ ├── patterns.md # Topic: reusable patterns
│ └── audit-history.md # Session-by-session notes
What belongs in MEMORY.md:
users.firstName not displayName)Example MEMORY.md excerpt:
## Schema Facts (error-prone)
- `users.firstName` (NOT `displayName`)
- `agents` table: `createdBy`/`ownedBy` (NOT `ownerId`)
- `testRunStatusEnum`: `pending | running | completed | failed | cancelled` (NO `passed`)
## API Patterns
- `authenticateRequest(request)` → `AuthenticatedRequest | NextResponse`
- `requirePermission(authResult, 'resource.action')` → `null | NextResponse`
- `paginatedResponse(data, total, params)` — 3 args
- ILIKE escape: `search.replace(/[%_\\]/g, '\\$&')`
## Gotchas (error-prone patterns)
- Drizzle `gt(column, value)` NOT `gt(value, column)` — column always first
- Every PATCH handler needs Zod validation — never destructure raw body
- ALL UPDATE/DELETE WHERE clauses include `organizationId` (TOCTOU prevention)
Why this works: The next time you ask Claude to "add a new API route," it will automatically apply your auth pattern, pagination logic, and error handling conventions without being told.
As projects grow, MEMORY.md becomes unwieldy. Break specialized knowledge into topic files:
debugging.md — stack trace patterns, error resolutions, flaky test fixespatterns.md — authentication flows, rate limiting, SSRF preventiondeployment.md — Docker compose configs, healthcheck patterns, secret managementtesting.md — mock patterns, snapshot strategies, integration test setupReference pattern in MEMORY.md:
## Extended Documentation
See topic-specific memory files:
- `debugging.md` — error resolution history
- `patterns.md` — reusable authentication/security patterns
- `deployment.md` — Docker stack configuration
Claude Code will auto-load referenced files when they're mentioned in MEMORY.md or when you explicitly ask about a topic.
Long conversations hit Claude's context window limit. The PreCompact hook runs before compression and saves ephemeral context to MEMORY.md.
What gets saved:
What does NOT get saved:
This is a manual process. At the end of a productive session, you run /memory-save to append new learnings to MEMORY.md.
The system MUST load ~/.claude/CLAUDE.md into every conversation at session start, regardless of project or working directory.
The system MUST compute a deterministic hash from the project's absolute path using base64url(sha256(path)) to create a unique project identifier.
The system MUST load ~/.claude/projects/<hash>/memory/MEMORY.md (if it exists) after loading CLAUDE.md.
When conflicting instructions exist, the system MUST prioritize: (1) CLAUDE.md ENFORCED rules, (2) project MEMORY.md, (3) session-level context, (4) Claude defaults.
The system MUST treat sections tagged with ENFORCED or CRITICAL as hard constraints that override default behavior.
If MEMORY.md references topic files (e.g., "See debugging.md"), the system SHOULD load those files when the topic becomes relevant in conversation.
The system MUST provide a /memory-save command that appends new learnings from the current session to MEMORY.md with a timestamp.
The system MUST provide a /memory-resume command that re-loads CLAUDE.md and MEMORY.md mid-conversation to pick up external edits.
The system MUST trigger a PreCompact hook before compressing conversation history, allowing plugins to save ephemeral context to persistent storage.
The system MUST NOT auto-create MEMORY.md files. Users explicitly create them when a project warrants persistent context.
If CLAUDE.md contains privacy rules (e.g., "NEVER include employer name"), the system MUST enforce these rules when generating MEMORY.md updates.
MEMORY.md SHOULD be organized by topic (schema, API patterns, gotchas) NOT chronologically. Session-by-session notes belong in a separate audit-history.md file.
I need to build a Context Guard system for Claude Code that provides hierarchical, persistent instructions across conversations. Here's what I need:
## Core Functionality
1. **Global instructions (CLAUDE.md)**:
- Create ~/.claude/CLAUDE.md that loads into EVERY conversation
- Support ENFORCED/CRITICAL tags for hard constraints
- Sections: Core Behavior, Code Standards, Privacy Rules, Git Workflow, Testing Requirements
2. **Project-level memory (MEMORY.md)**:
- Compute project hash: base64url(sha256(absolute_path))
- Auto-create directory: ~/.claude/projects//memory/
- Load MEMORY.md at session start (if exists)
- Sections: Schema Facts, API Patterns, Gotchas, Build Notes, Stats
3. **Topic files**:
- Support references like "See debugging.md" in MEMORY.md
- Auto-load topic files when mentioned or when topic becomes relevant
- Suggested topics: debugging.md, patterns.md, deployment.md, testing.md
4. **Session commands**:
- /memory-save — append new learnings to MEMORY.md with timestamp
- /memory-resume — reload CLAUDE.md + MEMORY.md mid-conversation
- /memory-stats — show loaded files and instruction count
5. **PreCompact hook**:
- Trigger before conversation compression
- Extract: schema facts, error resolutions, performance optimizations, security fixes
- Skip: exploratory commands, rejected drafts, temporary workarounds
## Instruction Priority
(1) CLAUDE.md ENFORCED rules
(2) MEMORY.md project facts
(3) Session context
(4) Claude defaults
## Privacy Enforcement
If CLAUDE.md has privacy rules (e.g., "NEVER include employer name"), enforce them when generating MEMORY.md updates.
## Semantic Organization
MEMORY.md organized by topic, NOT chronologically. Session notes go in audit-history.md.
Build this system with:
- Bash script for hash computation and directory setup
- Hook implementation for PreCompact and SessionStart
- Commands for /memory-save, /memory-resume, /memory-stats
- Markdown template for CLAUDE.md and MEMORY.md
Start with the project hash computation script and SessionStart hook.
Decision: Use global (CLAUDE.md), project (MEMORY.md), and session context instead of a flat single-file approach.
Rationale:
Trade-off: More complexity in the load sequence, but dramatically better context relevance and maintainability.
Decision: Use base64url(sha256(path)) instead of human-readable project names.
Rationale:
Trade-off: Directories are not human-readable. Solution: MEMORY.md includes a header with the original path for reference.
Decision: Require users to explicitly create MEMORY.md files. No auto-generation.
Rationale:
Trade-off: Users must remember to create MEMORY.md for new projects. Mitigated with a /memory-init command.
Decision: Organize MEMORY.md by topic (schema, API patterns, gotchas) instead of chronologically (session 1, session 2, session 3).
Rationale:
Trade-off: Harder to audit "what changed when." Solution: Maintain a separate audit-history.md for session-by-session notes.
Decision: Require users to run /memory-save instead of auto-saving after every conversation.
Rationale:
Trade-off: Users might forget to save. Mitigated with an end-of-session reminder if new learnings were detected.
Context Guard (CLAUDE.md + MEMORY.md) provides explicit, structured instructions. The Vector Memory System provides semantic search across unstructured learnings.
How they work together:
Example: "Never use gt(value, column) in Drizzle" goes in MEMORY.md. "Optimized query performance by adding index on user_id" goes in vector memory.
The Conductor plugin orchestrates multi-agent workflows. It reads CLAUDE.md to understand user preferences for agent selection.
Integration:
The Governance plugin enforces approval gates and data classification rules. It reads CLAUDE.md for privacy policies.
Integration:
Skills can reference CLAUDE.md for user-specific overrides (e.g., "Use user's preferred cloud provider for deployment").
Integration:
The Context Guard system relies on two hooks:
Other plugins can also register PreCompact hooks to save domain-specific context (e.g., test results, deployment logs).