# Zettel Memory
> **v0.0.1** - Local-first persistent memory MCP server
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org/)
[](https://www.typescriptlang.org/)
로컬 퍼시스턴트 메모리를 **MCP 서버**로 노출하여, Claude 등 MCP 호환 AI 에이전트가 당신의 지식 베이스를 활용할 수 있게 합니다.
## ✨ Features
- 📝 **Markdown + YAML Front Matter** - 표준 포맷으로 노트 저장
- 🗂️ **PARA Organization** - Projects/Areas/Resources/Archives 분류
- 🔗 **Zettelkasten Linking** - UID 기반 노트 연결 및 백링크
- 🔍 **SQLite FTS5 Search** - 빠른 전문 검색 (P95 < 1ms)
- 🤖 **AI-Powered Organization** - Ollama 통합으로 자동 노트 정리
- 🏠 **Local-first** - 모든 데이터를 로컬에 안전하게 보관
- 🔐 **Privacy** - 네트워크 송출 없음, 원자적 쓰기
## 🚀 Quick Start
### Installation
```bash
npm install -g @inchankang/zettel-memory
```
Or use with `npx`:
```bash
npx @inchankang/zettel-memory --vault ~/my-vault
```
### Claude Desktop Setup
Add to your Claude Desktop config (`~/.config/claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"memory": {
"command": "npx",
"args": [
"@inchankang/zettel-memory",
"--vault",
"/Users/yourname/Documents/memory-vault"
]
}
}
}
```
### Create a Test Note
```bash
# Create vault directory
mkdir -p ~/my-vault
# Create a sample note
cat > ~/my-vault/my-first-note-20250101T120000Z.md << 'EOF'
---
id: "20250101T120000Z"
title: "My First Note"
category: "Resources"
tags: ["getting-started"]
created: "2025-01-01T12:00:00Z"
updated: "2025-01-01T12:00:00Z"
links: []
---
# My First Note
This is my first note in Zettel Memory!
## What I can do
- Store knowledge in Markdown
- Link notes together
- Search through my notes
- Let Claude access my knowledge base
EOF
```
## 📚 Available Tools (v0.0.1)
Zettel Memory provides 14 MCP tools for complete note management:
### Core CRUD Tools
### `create_note`
Create a new Markdown note with Front Matter.
**Input**:
```json
{
"title": "My Note",
"content": "Note content...",
"category": "Resources",
"tags": ["tag1", "tag2"],
"project": "optional-project-name"
}
```
**Output**: Note ID (UID), file path, and metadata
---
### `read_note`
Read a note by its unique ID.
**Input**:
```json
{
"uid": "20250101T120000Z",
"includeMetadata": false,
"includeLinks": false
}
```
**Options**:
- `includeMetadata`: Add file size, word count, character count
- `includeLinks`: Add backlink analysis and broken link detection
**Output**: Full note content with metadata
---
### `list_notes`
List notes with filtering, sorting, and pagination.
**Input**:
```json
{
"category": "Projects",
"tags": ["important"],
"project": "my-project",
"limit": 100,
"offset": 0,
"sortBy": "updated",
"sortOrder": "desc"
}
```
**Filters** (all optional):
- `category`: Filter by PARA category (Projects/Areas/Resources/Archives)
- `tags`: Filter by tags (OR logic - matches any tag)
- `project`: Filter by project name
**Sorting**:
- `sortBy`: `created`, `updated`, or `title`
- `sortOrder`: `asc` or `desc`
**Pagination**:
- `limit`: Max results (default 100, max 1000)
- `offset`: Skip first N results
**Output**: List of notes with metadata, total count, and pagination info
---
### `search_memory`
Full-text search powered by SQLite FTS5.
**Input**:
```json
{
"query": "zettelkasten method",
"limit": 10,
"category": "Resources",
"tags": ["productivity"]
}
```
**Features**:
- FTS5 full-text search with ranking
- Category and tag filtering
- Performance metrics (search time, result count)
- Snippet generation with query highlighting
**Output**: Ranked search results with snippets, scores, and metadata
---
### `update_note`
Update an existing note's title, content, metadata, or links.
**Input**:
```json
{
"uid": "20250101T120000Z",
"title": "Updated Title",
"content": "New content...",
"category": "Projects",
"tags": ["updated", "important"],
"project": "new-project",
"links": ["other-note-uid"]
}
```
**Features**:
- Partial updates (only provide fields you want to change)
- Auto-updates `updated` timestamp
- Syncs with search index automatically
- At least one field required (besides `uid`)
**Output**: Updated note metadata and list of modified fields
---
### `delete_note`
Delete a note permanently (requires explicit confirmation).
**Input**:
```json
{
"uid": "20250101T120000Z",
"confirm": true
}
```
**Safety**:
- `confirm: true` required to prevent accidental deletion
- Returns note info before deletion
- Removes from search index automatically
- ⚠️ **Cannot be undone**
**Output**: Deleted note information with confirmation
---
### Analytics & Organization Tools
- **`get_vault_stats`** - Get statistics about your vault (note count, categories, tags)
- **`get_backlinks`** - Find all notes linking to a specific note
- **`get_metrics`** - Get performance metrics (JSON or Prometheus format)
- **`find_orphan_notes`** - Find notes without any incoming or outgoing links
- **`find_stale_notes`** - Find notes that haven't been updated recently
- **`get_organization_health`** - Get overall health score and recommendations
- **`archive_notes`** - Batch archive old or unused notes
- **`suggest_links`** - Get AI-powered link suggestions based on content similarity
---
## 🗂️ Note Structure
Each note follows this structure:
```markdown
---
id: "20250101T120000000000Z" # Auto-generated UID (timestamp-based)
title: "Note Title"
category: "Resources" # PARA: Projects|Areas|Resources|Archives
tags: ["tag1", "tag2"] # Optional tags
project: "project-name" # Optional project association
created: "2025-01-01T12:00:00Z"
updated: "2025-01-01T12:00:00Z"
links: ["other-note-uid"] # Links to other notes
---
# Note Title
Your note content in Markdown...
## You can use
- Lists
- **Bold** and *italic*
- [Links](https://example.com)
- [[other-note-uid]] (Zettelkasten-style links)
```
**File naming**: `{sanitized-title}-{uid}.md`
- Example: `my-project-notes-20250101T120000Z.md`
## 🛠️ Development
### Prerequisites
- Node.js 18+
- npm 8+
### Setup
```bash
# Clone the repository
git clone https://github.com/inchankang/zettel-memory.git
cd zettel-memory
# Install dependencies
npm install
# Build all packages
npm run build
# Run tests
npm test
# Type check
npm run typecheck
# Lint
npm run lint
```
### Project Structure
```
zettel-memory/
├── packages/
│ ├── mcp-server/ # MCP server & CLI
│ ├── storage-md/ # Markdown storage & Front Matter
│ ├── index-search/ # FTS5 search & link graph
│ ├── assoc-engine/ # Context-aware ranking (planned for v0.1.0+)
│ └── common/ # Shared utilities & types
└── docs/ # Documentation & specs
```
### Running Locally
**Direct Execution (Recommended):**
```bash
# ✅ Root-level options (Claude Desktop compatible)
node packages/mcp-server/dist/cli.js --vault /tmp/test-vault --index /tmp/test-index.db
# Or with npm
npm start -- --vault /tmp/test-vault --index /tmp/test-index.db
# Using npx (if published)
npx @inchankang/zettel-memory --vault ~/my-vault --index ~/.memory-index.db
```
**Subcommand (Backward Compatible):**
```bash
# ⚠️ Still works but not recommended
node packages/mcp-server/dist/cli.js server --vault /tmp/test-vault
```
**Healthcheck:**
```bash
node packages/mcp-server/dist/cli.js healthcheck --vault /tmp/test-vault --index /tmp/test-index.db
```
**Available Options:**
```bash
--vault <path> # Vault directory path (default: ./vault)
--index <path> # Index database path (default: ./.memory-index.db)
--mode <mode> # Mode: dev | prod (default: dev)
--timeout <ms> # Tool execution timeout (default: 5000ms)
--retries <count> # Tool execution retry count (default: 2)
--verbose # Enable verbose logging
--help # Show help
--version # Show version
```
## 📖 Documentation
- [`docs/ROADMAP.md`](docs/ROADMAP.md) - Epic/feature tree structure
- [`docs/TECHNICAL_SPEC.md`](docs/TECHNICAL_SPEC.md) - Technical stack & KPIs
- [`docs/GOALS.md`](docs/GOALS.md) - Project goals & milestones
- [`docs/DEVELOPMENT_GUIDELINES.md`](docs/DEVELOPMENT_GUIDELINES.md) - Development principles (SOLID, TDD, SDD)
- [`docs/VALIDATION_STRATEGY.md`](docs/VALIDATION_STRATEGY.md) - Validation strategy and methodology
- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) - System architecture
- [`docs/USAGE_GUIDE.md`](docs/USAGE_GUIDE.md) - Usage guide and CLI reference
## 🗺️ Roadmap
### v0.0.1 (Current) ✅
- [x] Complete CRUD operations (create/read/update/delete/list/search)
- [x] Markdown + Front Matter storage
- [x] PARA categorization
- [x] FTS5 full-text search with ranking
- [x] Link analysis & backlinks
- [x] CLI interface
- [x] MCP server integration
- [x] Test coverage: 498 tests passing
### v0.1.0 (Next)
- [ ] Comprehensive unit tests (50%+ coverage)
- [ ] Performance benchmarks & KPI validation
- [ ] Zettelkasten link auto-suggestions
- [ ] File watcher for real-time sync
- [ ] Production error handling & logging
### v1.0.0 (Future)
- [ ] Vector embedding search
- [ ] **Olima Context-Aware Ranking Engine** ⚠️ _Planned Feature_
- Semantic similarity-based note recommendations
- Session context-aware re-ranking
- Automatic link suggestions based on content analysis
- [ ] Advanced link graph queries
- [ ] Docker image
- [ ] Production-ready CI/CD
> **Note on Olima**: The "Olima" context-aware ranking engine is a planned feature for future releases. Currently, the project uses **Ollama** (local LLM platform) for AI-powered note organization via the `organize_notes` tool.
## 🤝 Contributing
Contributions are welcome! Please follow the guidelines below.
### Development Workflow
1. Follow [DEVELOPMENT_GUIDELINES.md](docs/DEVELOPMENT_GUIDELINES.md)
2. Write tests for new features
3. Ensure `npm run build` succeeds
4. Use Conventional Commits for commit messages
5. Submit a pull request
## 📄 License
MIT License - see [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
- [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) - For the standardized protocol
- [Zettelkasten](https://zettelkasten.de/) - For the note-taking methodology
- [PARA Method](https://fortelabs.com/blog/para/) - For the organizational framework
## 📞 Support
- 🐛 [Report a bug](https://github.com/inchankang/zettel-memory/issues)
- 💡 [Request a feature](https://github.com/inchankang/zettel-memory/issues)
- 💬 [Discussions](https://github.com/inchankang/zettel-memory/discussions)
---
**Status**: 🚧 Alpha - Under active development
**Note**: This is an alpha release. APIs may change. Feedback and contributions are greatly appreciated!