Skip to main content
ClaudeWave
Skill71 repo starsupdated yesterday

agent-memory

>-

Install in Claude Code
Copy
git clone --depth 1 https://github.com/TerminalSkills/skills /tmp/agent-memory && cp -r /tmp/agent-memory/skills/agent-memory ~/.claude/skills/agent-memory
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Agent Memory

## Overview

AI agents forget everything between sessions. This skill builds persistent memory systems — from simple file-based approaches to full vector-search architectures — so agents retain context, learn from past interactions, and make better decisions over time.

## When to Use

- User wants the agent to remember decisions, preferences, or project context
- Building a coding assistant that needs to recall past conversations
- Creating a knowledge base the agent can query semantically
- Agent needs to learn from mistakes and not repeat them
- Implementing memory consolidation (daily notes → long-term memory)

## Instructions

### Strategy 1: File-Based Memory (Zero Dependencies)

The simplest approach — write memories to structured markdown files. No database, no embeddings, no API keys. Works with any agent that can read/write files.

#### Architecture

```
memory/
├── MEMORY.md              # Long-term curated knowledge
├── 2026-02-24.md          # Daily session logs
├── 2026-02-23.md
├── entities/
│   ├── projects.md        # Known projects and their state
│   ├── people.md          # People, preferences, relationships
│   └── decisions.md       # Key decisions and reasoning
└── heartbeat-state.json   # Periodic check state
```

#### Memory File Format

```markdown
# MEMORY.md — Long-Term Agent Memory

## Projects
### Terminal Skills
- Repo: https://github.com/TerminalSkills/skills
- Stack: Next.js, TypeScript
- Status: Active, 295 skills published
- Key decision: Use-cases always come first, skills serve use-cases

## Preferences
- Language: TypeScript over JavaScript
- Testing: Vitest over Jest
- Deployment: Vercel for frontend, Railway for backend

## Lessons Learned
- Sub-agents limited to 5-6 tasks max (context window overflow at 10+)
- Always check for duplicates before creating new content
- Git branches from upstream/main, never local main
```

#### Implementation

```python
# agent_memory.py — File-based agent memory with search
"""
File-based memory system for AI agents.
Stores memories as structured markdown, supports fuzzy search
across all memory files without any external dependencies.
"""
import os
import re
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional

class FileMemory:
    """Persistent file-based memory for AI agents."""

    def __init__(self, memory_dir: str = "memory"):
        self.memory_dir = Path(memory_dir)
        self.memory_dir.mkdir(parents=True, exist_ok=True)
        self.long_term_file = self.memory_dir / "MEMORY.md"
        self.entities_dir = self.memory_dir / "entities"
        self.entities_dir.mkdir(exist_ok=True)

    def log_today(self, content: str, section: str = "Notes") -> str:
        """Append to today's daily log file.

        Args:
            content: The memory content to log
            section: Section header within the daily file

        Returns:
            Path to the updated file
        """
        today = datetime.now().strftime("%Y-%m-%d")
        daily_file = self.memory_dir / f"{today}.md"

        if not daily_file.exists():
            daily_file.write_text(f"# {today}\n\n")

        with open(daily_file, "a") as f:
            f.write(f"\n## {section}\n{content}\n")

        return str(daily_file)

    def remember(self, key: str, value: str, category: str = "General") -> None:
        """Store a key-value memory in long-term storage.

        Args:
            key: Short identifier for the memory
            value: The content to remember
            category: Section to file it under (Projects, Preferences, etc.)
        """
        content = self.long_term_file.read_text() if self.long_term_file.exists() else "# Long-Term Memory\n"

        # Find or create category section
        section_header = f"## {category}"
        if section_header not in content:
            content += f"\n{section_header}\n"

        # Append the memory entry
        entry = f"- **{key}**: {value}\n"
        insert_pos = content.index(section_header) + len(section_header) + 1
        content = content[:insert_pos] + entry + content[insert_pos:]

        self.long_term_file.write_text(content)

    def search(self, query: str, max_results: int = 10) -> list[dict]:
        """Search all memory files for relevant content.

        Args:
            query: Search terms (supports multiple words)
            max_results: Maximum number of matching lines to return

        Returns:
            List of dicts with 'file', 'line_number', 'content', 'score'
        """
        terms = query.lower().split()
        results = []

        for md_file in self.memory_dir.rglob("*.md"):
            lines = md_file.read_text().splitlines()
            for i, line in enumerate(lines):
                line_lower = line.lower()
                score = sum(1 for term in terms if term in line_lower)
                if score > 0:
                    results.append({
                        "file": str(md_file.relative_to(self.memory_dir)),
                        "line_number": i + 1,
                        "content": line.strip(),
                        "score": score / len(terms),  # Normalize 0-1
                    })

        results.sort(key=lambda x: x["score"], reverse=True)
        return results[:max_results]

    def get_recent_context(self, days: int = 3) -> str:
        """Load recent daily logs for context injection.

        Args:
            days: Number of recent days to include

        Returns:
            Combined content from recent daily files
        """
        context_parts = []
        for i in range(days):
            date = (datetime.now() - timedelta(days=i)).strftime("%Y-%m-%d")
            daily_file = self.memory_dir / f"{date}.md"
            if daily_file.exists():
                context_parts.append(daily_file.read_text())

        return "\n---\n".join(context_parts)

    def consolidate(self) -> str:
        """Review recent daily logs and extract key l