A memory management system for GitHub Copilot CLI using Obsidian-compatible Markdown. Enables persistent context across work sessions through handoffs, phases, and structured note-taking.
- 📝 Handoff Management: Create handoff notes to capture work state and transition smoothly between sessions
- 🔄 Continuous Resume: Automatically resume from the latest handoff
- 📊 Phase Organization: Structure work into phases with research, execution, and handoff tracking
- 🔍 Content Search: Full-text search across all vault notes
- 🏥 Health Checks: Validate vault structure and note integrity
- 🧹 Pruning: Clean up old notes to keep the vault manageable
- 🎯 Deterministic Tracker: Store active phase/session/handoff state in
indexes/tracker-state.json - 🔗 Obsidian Compatible: Use Obsidian or any Markdown editor alongside the CLI
- 📦 Minimal Dependencies: Zero runtime dependencies, built on Node.js stdlib
# Clone the repository
git clone https://github.com/yourusername/copilot-memory.git
cd copilot-memory
# Install globally
npm install -g .
# Or use locally without installation
npm link# Install from local path
copilot plugin install ./plugin
# Install from GitHub repository
copilot plugin install OWNER/copilot-memory
# Verify installation
copilot plugin listThe plugin provides:
- Agent (
memory.agent.md): A context management agent that knows how to use all copilot-memory commands - Skills (11 skills): Each command is a skill that Copilot loads when relevant to your task
- Hooks:
sessionStartauto-resumes from the latest handoff;sessionEndauto-creates a handoff
# Initialize vault
copilot-memory init
# Create a handoff note
copilot-memory handoff --title "Feature Complete" --content "## Progress
- Implemented authentication
- Added tests
## Next Steps
- Deploy to staging"
# Resume from latest handoff
copilot-memory resume
# Create a phase
copilot-memory phase create --title "Authentication" --goal "Implement OAuth2 with JWT"
# Add research to phase
copilot-memory phase research --phase <phase-id> --title "OAuth2 Best Practices" --stdin < research.md
# Complete a phase
copilot-memory phase handoff --phase <phase-id> --title "Auth Complete"
# Search vault
copilot-memory vault search "authentication"
# Check vault health
copilot-memory vault doctor
copilot-memory vault tracker
# Regenerate indexes
copilot-memory vault index
# Clean up old notes
copilot-memory vault prune --days 90 --dry-runCommands use a simple, flat structure:
Core Commands:
copilot-memory init- Initialize vaultcopilot-memory handoff- Create handoff notecopilot-memory resume- Resume from latest handoffcopilot-memory help- Show command help
Phase Commands:
copilot-memory phase create- Create new phasecopilot-memory phase research- Add research to phasecopilot-memory phase handoff- Complete phase
Vault Commands:
copilot-memory vault index- Regenerate indexescopilot-memory vault search- Search contentcopilot-memory vault doctor- Run health checkscopilot-memory vault prune- Prune old notescopilot-memory vault tracker- Deterministic project state (active phase/session/handoff)
The vault follows a standardized directory structure:
.copilot-memory-vault/
├── handoffs/
│ └── YYYY/
│ └── MM/
│ └── YYYYMMDD-HHmmssZ--handoff--session--slug.md
├── sessions/
│ └── YYYY/
│ └── MM/
│ └── YYYYMMDD-HHmmssZ--session--session--slug.md
├── phases/
│ └── <phase-id>/
│ ├── phase.md
│ ├── research/
│ │ └── YYYYMMDD-HHmmssZ--research--phase--slug.md
│ ├── execution/
│ └── handoffs/
│ └── YYYYMMDD-HHmmssZ--handoff--phase--slug.md
├── indexes/
│ ├── latest-handoff.md # Wikilink pointer to newest handoff
│ ├── catalog.md
│ └── phase-summary.md
└── templates/
All notes follow the exact format: YYYYMMDD-HHmmssZ--<type>--<scope>--<slug>.md
Examples:
20240115-143000Z--handoff--session--sprint-complete.md20240115-150000Z--research--phase--oauth2-investigation.md20240116-091500Z--handoff--phase--feature-complete.md
Each handoff automatically:
- Links to the previous handoff in frontmatter (
previous_handofffield) - Includes a wikilink to the previous handoff in content
- Updates
indexes/latest-handoff.mdwith a wikilink pointer to itself
Every note includes YAML frontmatter with required fields:
---
id: uuid-here
type: handoff
created_at: 2024-01-15T14:30:00.000Z
updated_at: 2024-01-15T14:30:00.000Z
session_id: session-uuid
phase_id: null
status: active
tags:
- handoff
- sprint
links: []
title: Sprint Complete
---Initialize a new vault.
copilot-memory init
copilot-memory init ~/my-vaultCreate a handoff note.
copilot-memory handoff --title "Work Complete" --content "Summary"
echo "Content" | copilot-memory handoff --stdin --title "From stdin"Options:
--title <title>: Handoff title--content <text>: Handoff content--stdin: Read content from stdin--session <id>: Session ID--phase <id>: Phase ID--tags <tag1,tag2>: Tags
Resume from the latest handoff.
copilot-memory resumeCreate a new phase.
copilot-memory phase create \
--title "Authentication" \
--goal "Implement OAuth2 authentication with JWT tokens"Options:
--title <title>: Phase title--goal <goal>: Phase goal--id <id>: Custom phase ID (optional)--tags <tags>: Tags
Create a research note for a phase.
copilot-memory phase research \
--phase <phase-id> \
--title "OAuth2 Investigation" \
--content "Research findings..."Options:
--phase <id>: Phase ID (optional if active phase is set viavault tracker --phase)--title <title>: Research title--content <text>: Content--stdin: Read from stdin--tags <tags>: Tags
Create a handoff note for a phase.
copilot-memory phase handoff \
--phase <phase-id> \
--title "Phase Complete" \
--content "Summary of completed work"Options:
--phase <id>: Phase ID (optional if active phase is set viavault tracker --phase)--title <title>: Handoff title--session <id>: Session ID--content <text>: Content--stdin: Read from stdin--tags <tags>: Tags
Regenerate vault indexes.
copilot-memory vault indexRegenerates:
indexes/catalog.md: Complete note inventoryindexes/phase-summary.md: Phase overviewindexes/latest-handoff.md: Latest handoff wikilink pointer
Search vault content.
copilot-memory vault search "authentication"
copilot-memory vault search "TODO" --case
copilot-memory vault search "bug" --dir .copilot-memory-vault/phasesOptions:
--case: Case-sensitive search--dir <path>: Search specific directory
Run vault health checks.
copilot-memory vault doctor
copilot-memory vault doctor --fixChecks:
- Required folders exist
- Index files are valid
- Frontmatter is complete
Options:
--fix: Attempt auto-fix (creates missing folders)
Prune old notes.
# Preview (dry run)
copilot-memory vault prune --days 60 --dry-run
# Actually delete
copilot-memory vault prune --days 90
# Prune research notes
copilot-memory vault prune --research --days 120
# Prune specific phase research
copilot-memory vault prune --research --phase <phase-id> --days 90Options:
--days <n>: Age threshold (default: 30)--dry-run: Preview without deleting--research: Prune research notes--phase <id>: Target specific phase
Read/update deterministic project state used by phase commands and hooks.
copilot-memory vault tracker
copilot-memory vault tracker --phase auth-phase
copilot-memory vault tracker --session session-123
copilot-memory vault tracker --clear-phaseShorthand aliases are supported:
copilot-memory h→copilot-memory handoffcopilot-memory r→copilot-memory resumecopilot-memory p→copilot-memory phasecopilot-memory v→copilot-memory vault
Show help for commands.
copilot-memory help
copilot-memory help handoff
copilot-memory help phaseThe vault path is resolved in the following priority order:
- Command line option:
--vault /path/to/vault - Environment variable:
COPILOT_MEMORY_VAULT - Config file:
.copilot-memory/config.jsonin current directory - Default:
.copilot-memory-vaultin current directory
Create .copilot-memory/config.json in your project root:
{
"vaultPath": "/custom/vault/path",
"notesmdPath": "notesmd-cli",
"useNotesmd": true
}# Set vault path
export COPILOT_MEMORY_VAULT=/path/to/vault
# Set notesmd path (if not in PATH)
export COPILOT_MEMORY_NOTESMD_PATH=/path/to/notesmd
# Use commands
copilot-memory handoff --title "Test"The system uses notesmd-cli as the primary adapter with automatic filesystem fallback:
- Create/Read operations: Attempts notesmd-cli first (using
createandprintcommands), falls back to filesystem with warning - Update operations: Always uses filesystem (notesmd-cli does not support reliable update)
- List operations: Attempts notesmd-cli for basic listing, falls back to filesystem for recursive/pattern filtering
- Search operations: Attempts notesmd-cli
search-contentcommand, falls back to filesystem with warning - Automatic detection: Checks for notesmd-cli availability on first use
- Explicit warnings: Clear messages when falling back to filesystem
- Zero-dependency fallback: Always works even without notesmd-cli installed
To disable notesmd integration, set in config.json:
{
"useNotesmd": false
}The vault is fully compatible with Obsidian:
- Open Obsidian
- "Open folder as vault"
- Select
.copilot-memory-vault
Features that work in Obsidian:
- Wikilinks (
[[note-name]]) - YAML frontmatter
- Tags
- Graph view
- Search
- Daily notes
npm testTests cover:
- Handoff → resume flow
- Phase create → research → handoff
- Index generation
- Doctor diagnostics
- Prune dry-run and execution
copilot-memory/
├── bin/
│ └── copilot-memory.js # CLI entry point
├── src/
│ ├── config.js # Configuration management
│ ├── adapters/
│ │ ├── filesystem.js # Direct filesystem operations
│ │ └── notesmd.js # NotesMD CLI wrapper
│ ├── services/
│ │ ├── vault.js # Vault operations
│ │ ├── index.js # Index generation
│ │ ├── doctor.js # Health checks
│ │ └── prune.js # Note pruning
│ ├── commands/
│ │ ├── handoff.js # Handoff commands
│ │ ├── phase.js # Phase commands
│ │ ├── memory.js # Memory commands
│ │ └── registry.js # Command registry
│ └── utils/
│ └── frontmatter.js # Frontmatter utilities
├── plugin/ # Copilot CLI plugin
│ ├── plugin.json # Plugin manifest
│ ├── agents/
│ │ └── memory.agent.md # Memory management agent
│ ├── skills/ # 11 skill definitions
│ │ ├── init/SKILL.md
│ │ ├── handoff/SKILL.md
│ │ ├── resume/SKILL.md
│ │ └── ...
│ └── hooks.json # Lifecycle hooks (sessionStart, sessionEnd)
├── .github/plugin/
│ ├── plugin.json # Root plugin metadata
│ └── marketplace.json # Marketplace metadata
├── test/
│ └── integration.test.js # Integration tests
└── package.json
# Start of day: resume from yesterday
copilot-memory resume
# During work: capture progress
copilot-memory handoff --title "Auth module complete" --stdin < notes.txt
# End of day: final handoff
copilot-memory handoff --title "EOD - Auth testing" --content "..."# Start new phase
PHASE_ID=$(copilot-memory phase create --title "User Management" --goal "CRUD for users" | grep ID | awk '{print $2}')
# Research
copilot-memory phase research --phase $PHASE_ID --title "User schema design" --stdin < design.md
# More research
copilot-memory phase research --phase $PHASE_ID --title "Security considerations" --stdin < security.md
# Complete phase
copilot-memory phase handoff --phase $PHASE_ID --title "User Management Complete" --stdin < summary.md# Search for past decisions
copilot-memory vault search "architecture decision"
# Review phase history
cat .copilot-memory-vault/indexes/phase-summary.md
# Check vault health monthly
copilot-memory vault doctor
# Clean up quarterly
copilot-memory vault prune --days 90 --dry-run
copilot-memory vault prune --days 90- Regular Handoffs: Create handoffs at natural breakpoints (end of task, day, sprint)
- Descriptive Titles: Use clear titles for easy searching later
- Tag Consistently: Use consistent tags for better organization
- Phase Discipline: Keep phase scope focused and manageable
- Search Often: Your past notes are valuable - search them!
- Prune Periodically: Keep vault size manageable with regular pruning
- Obsidian Sync: Use Obsidian alongside CLI for rich viewing/editing
- Backup: Vault is just markdown - version control it!
# Check current vault path
copilot-memory status
# Set explicit vault path
export COPILOT_MEMORY_VAULT=/path/to/vault# Regenerate all indexes
copilot-memory vault indexThis project integrates with GitHub Copilot CLI using the modern plugin architecture:
- Plugin: Install via
copilot plugin install ./plugin— provides an agent, 11 skills, and lifecycle hooks - Agent:
memory.agent.mdteaches Copilot how to use copilot-memory for persistent context - Skills: Each command (init, handoff, resume, phase-, vault-) is a skill Copilot loads when relevant
- Hooks:
sessionStartauto-resumes context;sessionEndauto-creates handoffs - Deterministic state:
vault trackerstores active phase/session in JSON for scripting and hooks - Agent instructions:
AGENTS.mdis included for Copilot coding agent behavior
If using copilot-memory without the plugin, add hooks manually:
copilot-memory vault tracker --phase "$COPILOT_PHASE_ID"
copilot-memory vault tracker --session "$COPILOT_SESSION_ID"# Run doctor with auto-fix
copilot-memory vault doctor --fixThe system automatically falls back to filesystem operations. To explicitly disable notesmd:
# Set in config or it will auto-detectContributions welcome! The codebase is intentionally minimal with zero runtime dependencies.
MIT
- Inspired by Obsidian's markdown-based knowledge management
- Built for seamless integration with GitHub Copilot CLI
- Designed for developer workflows and context persistence