Doramagic Project Pack · Human Manual
commonplace
Commonplace operates as a flat directory of Markdown files with YAML frontmatter. Each note is a plain .md file, and embeddings are stored in .embedding sidecar files generated locally usi...
Introduction to Commonplace
Related topics: Quick Start Guide, System Architecture, Memory Data Model
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Quick Start Guide, System Architecture, Memory Data Model
Introduction to Commonplace
Commonplace is a local-first personal knowledge management system that functions as an MCP (Model Context Protocol) server. It enables AI agents to persistently store, retrieve, and reason about notes using semantic search, all without requiring external API calls or cloud services. Sources: README.md
Overview
Commonplace operates as a flat directory of Markdown files with YAML frontmatter. Each note is a plain .md file, and embeddings are stored in .embedding sidecar files generated locally using transformers.js. This architecture ensures that:
- Notes are human-readable and portable — since memories are plain Markdown files, they can be edited, backed up, or version-controlled using standard tools.
- Embeddings are derived, not the source of truth —
.embeddingfiles are regenerable from.mdfiles at any time and may be deleted or rebuilt without data loss. Sources: CLAUDE.md
Architecture
graph TD
subgraph "MCP Client Layer"
A["Claude Code / AI Agent"]
end
subgraph "MCP Server Layer"
B["commonplace MCP Server<br/>stdio interface"]
end
subgraph "Store Layer"
C["MemoryStore<br/>src/store/memory-store.ts"]
D["MemoryGraph<br/>Graph relationships"]
E["Embedder<br/>transformers.js + bge-base-en-v1.5"]
end
subgraph "Filesystem Layer"
F["COMMONPLACE_USER_DIR<br/>~/.commonplace"]
G["COMMONPLACE_PROJECT_DIR<br/>.commonplace"]
end
A -->|"MCP Protocol"| B
B --> C
C --> D
C --> E
C --> F
C --> G
F -.->|"user scope"| C
G -.->|"project scope"| CKey Components
| Component | File | Responsibility |
|---|---|---|
| MCP Server | src/server/handlers.ts | Handles MCP protocol communication, registers tools |
| MemoryStore | src/store/memory-store.ts | Manages CRUD operations, scanning, searching |
| MemoryGraph | src/store/memory-store.ts | In-memory graph for relations and mentions |
| Embedder | src/store/embedder.ts | Local embedding generation via transformers.js |
| Memory I/O | src/store/memory.ts | Parses/serializes .md files with YAML frontmatter |
| Atomic Write | src/store/atomic-write.ts | Safe file writes to prevent corruption |
| Mentions | src/store/mentions.ts | Extracts [[name]] references from body content |
Memory Model
Memory Types
Memories are classified into a four-element taxonomy defined at Sources: README.md
| Type | Purpose | Example |
|---|---|---|
user | Personal rules, preferences, identity facts about the human operator | Coding style preferences, work schedule |
feedback | Corrections and lessons learned from prior agent behavior | "Don't shrink scope unilaterally" |
project | Per-project context like architecture notes, repo conventions | API conventions, decision records |
reference | Durable, neutral knowledge: API shapes, formulas, citations | Library documentation, formulas |
Memory File Format
A memory is a Markdown file with YAML frontmatter:
Source: https://github.com/rickbassham/commonplace / Human Manual
Quick Start Guide
Related topics: Introduction to Commonplace, MCP Tool Reference
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Introduction to Commonplace, MCP Tool Reference
Quick Start Guide
Welcome to Commonplace — a persistent, embeddable memory system for AI agents that operates on plain markdown files with YAML frontmatter.
Prerequisites
Before getting started, ensure your environment meets the following requirements:
| Requirement | Version | Notes |
|---|---|---|
| Node.js | 20 or 22 | CI runs on both versions |
| pnpm | latest | Package manager for this project |
| Claude Code | compatible | For MCP tool integration |
Sources: CONTRIBUTING.md:1-20
Installation
From Source
Clone the repository and install dependencies:
git clone https://github.com/rickbassham/commonplace.git
cd commonplace
pnpm install
Build the Project
make build
This compiles the TypeScript source and prepares the CLI binary.
Sources: CONTRIBUTING.md:22-30
Core Concepts
Memory Types
Every memory in Commonplace has a type field that categorizes its content:
| Type | Purpose | Example |
|---|---|---|
user | Personal rules, preferences, identity facts | preferred_code_style, keyboard_shortcuts |
feedback | Corrections and lessons learned | dont_shrink_scope_unilaterally, verify_api_response |
project | Per-project context, architecture, conventions | monorepo_structure, db_schema_notes |
reference | Durable neutral knowledge, API docs | openapi_spec_location, rate_limit_formulas |
Sources: README.md:1-20
Memory Scopes
Commonplace supports two parallel memory stores:
graph TD
A[Claude Code Session] --> B{Scope Selection}
B -->|user| C[User Store]
B -->|project| D[Project Store]
C --> E[~/.commonplace/memory]
D --> F[COMMONPLACE_PROJECT_DIR<br/>or<br/>.commonplace/memory]
style C fill:#e1f5fe
style D fill:#fff3e0| Scope | Location | Use Case |
|---|---|---|
user | ~/.commonplace/memory (default) | Cross-project memories, personal preferences |
project | Project root .commonplace/memory | Repository-specific context |
Sources: README.md:45-70
Memory File Structure
Each memory is stored as a markdown file with YAML frontmatter:
Sources: CONTRIBUTING.md:1-20
System Architecture
Related topics: Project Structure, Embedding System, Memory Store
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Project Structure, Embedding System, Memory Store
System Architecture
Overview
Commonplace is a persistent memory system for AI agents that stores contextual knowledge as markdown files with YAML frontmatter. The system provides semantic search across memories using embeddings, a graph-based relationship model for linking related memories, and a dual-store architecture supporting both user-level and project-level contexts.
The architecture is designed around the principle that markdown files are the source of truth — .embedding sidecar files are derived and regenerable at any time. Sources: CLAUDE.md
Core Components
| Component | File | Purpose |
|---|---|---|
| MemoryStore | src/store/memory-store.ts | Central store managing in-memory index, file I/O, search, and graph edges |
| Memory I/O | src/store/memory.ts | YAML frontmatter parsing, serialization, content hashing |
| Atomic Write | src/store/atomic-write.ts | Safe file writes via temp-file + rename pattern |
| Mentions Extractor | src/store/mentions.ts | Extracts [[name]] references from memory bodies |
| MCP Server | src/server/handlers.ts | Tool handlers exposing memory operations via Model Context Protocol |
| CLI Entry | src/index.ts | Command-line interface dispatcher |
Memory Model
Data Structure
Each memory is a markdown file with the following structure:
Source: https://github.com/rickbassham/commonplace / Human Manual
Project Structure
Related topics: System Architecture, Memory Store
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: System Architecture, Memory Store
Project Structure
Overview
Commonplace is a personal knowledge management system designed for AI agents operating via Claude Code. It provides persistent memory storage through markdown files with YAML frontmatter, vector embeddings for semantic search, and a graph structure for tracking relationships between memories.
The project is structured as a Node.js CLI application with an MCP (Model Context Protocol) server component. Sources: src/index.ts:1-25
Directory Layout
commonplace/
├── src/
│ ├── index.ts # CLI entry point and dispatcher
│ ├── bin/
│ │ ├── boot.ts # Boot process for MCP server
│ │ └── commonplace-mcp.ts # MCP server stdio interface
│ ├── cli/
│ │ ├── migrate.ts # Migration command implementation
│ │ └── graph.ts # Graph query command
│ ├── server/
│ │ └── server.ts # MCP protocol server
│ ├── store/
│ │ ├── memory-store.ts # Core memory management
│ │ ├── memory.ts # Memory I/O and serialization
│ │ ├── atomic-write.ts # Atomic file operations
│ │ └── mentions.ts # [[name]] mention extraction
│ └── embedder/
│ └── index.ts # Vector embedding generation
├── package.json
└── tsconfig.json
Entry Points
The project declares two bin entries in package.json:
| Bin Name | Target | Purpose |
|---|---|---|
commonplace | dist/index.js | Human-readable CLI output for migrate and graph commands |
commonplace-mcp | dist/bin/commonplace-mcp.js | Stdio MCP server for AI tool integration |
Sources: src/index.ts:25-40
The deliberate separation ensures the MCP server's JSON-RPC framing is never polluted by CLI output. Sources: src/index.ts:42-45
CLI Dispatcher
The main CLI entry point (src/index.ts) acts as a subcommand router. It supports two primary command paths:
commonplace migrate— Detect known external memory sources and import memoriescommonplace migrate <dir>— Rebuild sidecars for an existing memory directorycommonplace graph— Query memory relationship graph Sources: src/index.ts:54-77
graph TD
A[commonplace CLI] --> B{Subcommand?}
B -->|graph| C[graphMain]
B -->|migrate| D{Args?}
D -->|detect mode| E[detectImportSources]
D -->|import mode| F[runImportFromClaudeCode]
D -->|rebuild mode| G[migrateMain]The dispatcher uses lazy embedder instantiation — the Embedder (which triggers model loading) is only constructed when migrateMain decides to run after argument parsing succeeds. Sources: src/index.ts:63-69
Core Modules
MemoryStore (`src/store/memory-store.ts`)
The MemoryStore class is the central orchestration component for memory management. It maintains:
- An in-memory index of all loaded memories
- A directory watcher for detecting changes
- An optional
MemoryGraphfor relationship tracking - A lazy embedder factory for generating vector embeddings
Key responsibilities include scanning directories, managing embedding sidecars, handling atomic writes, and processing graph edges. Sources: src/store/memory-store.ts:1-50
The store implements a lazy-scanning pattern where the directory is scanned on first access, and subsequent operations use the cached in-memory index with mtime-based invalidation. Sources: src/store/memory-store.ts:150-180
Memory I/O (`src/store/memory.ts`)
The memory.ts module handles the serialization and deserialization of individual memory files. Each memory consists of:
YAML Frontmatter:
Sources: src/index.ts:25-40
Memory Data Model
Related topics: Memory Types Taxonomy, Memory Store, Embedding System
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Memory Types Taxonomy, Memory Store, Embedding System
Memory Data Model
The Memory Data Model is the core abstraction in Commonplace—a local-first knowledge management system that persists memories as plain Markdown files with typed YAML frontmatter. Each memory represents a discrete unit of knowledge, preference, or context that the agent can recall, search, and link to other memories.
Overview
Memories are the atomic units of the Commonplace system. They are stored as .md files on disk where each file contains:
- YAML frontmatter carrying typed metadata
- Markdown body containing the actual knowledge content
The design philosophy treats the markdown file as the source of truth. Derived artifacts (such as .embedding sidecars) can be regenerated from the markdown at any time. Sources: CLAUDE.md
graph LR
A[Memory Input] --> B[YAML Frontmatter]
A --> C[Markdown Body]
B --> D[.md File]
C --> D
D --> E[.embedding Sidecar]
D --> F[Search Index]
D --> G[Graph Edges]Memory Types
Commonplace defines a four-element taxonomy for categorizing memories. Every memory must declare its type in the frontmatter. Sources: README.md
| Type | Description | Use Case |
|---|---|---|
user | Personal rules, preferences, and identity facts about the human operator | Storing user preferences, communication style, work habits |
feedback | Corrections and lessons learned from prior agent behavior | Persistent course-corrections, things that didn't work |
project | Per-project context | Architecture notes, repo conventions, decisions that bind to one codebase |
reference | Durable, neutral knowledge | API shapes, formulas, citations, lookup-by-meaning content |
Type Constraints
The type field is mandatory and validated against the allowed set. Attempting to save a memory with an invalid type throws an error:
if (!isMemoryType(memory.type)) {
throw new Error(
`memory.type must be one of ${MEMORY_TYPES.join(', ')}; got ${JSON.stringify(memory.type)}`,
);
}
Sources: src/store/memory.ts:parseMemory
Memory Structure
TypeScript Interface
interface Memory {
name: string;
description: string;
type: MemoryType;
body: string;
relations: Relation[];
supersedes: string[];
}
Frontmatter Schema
Each memory file follows this YAML frontmatter structure:
Sources: src/store/memory.ts:parseMemory
Memory Types Taxonomy
Related topics: Memory Data Model, Memory Store, Semantic Search
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Memory Data Model, Memory Store, Semantic Search
Memory Types Taxonomy
Overview
The Memory Types Taxonomy is a four-element classification system that categorizes memories stored in Commonplace. Each memory carries a type field that determines its scope, purpose, and how it should be used by the AI agent. This taxonomy enables organized knowledge management across personal rules, learned corrections, project-specific context, and reference materials.
Memory types serve as the primary organizational primitive for the entire system. They appear in YAML frontmatter of markdown files, are validated at write time, and are used to filter search results and graph traversals. Source: README.md
The Four Memory Types
| Type | Purpose | Scope | Typical Content |
|---|---|---|---|
user | Personal rules, preferences, and identity facts about the human operator | Cross-project | Operating preferences, name, role, interaction style |
feedback | Corrections and lessons learned from prior agent behavior | Cross-project | Persistent course-corrections, mistake patterns |
project | Per-project context specific to one codebase | Single project | Architecture notes, repo conventions, decisions |
reference | Durable, neutral knowledge | Cross-project | API shapes, formulas, citations, lookup knowledge |
Source: README.md
User Type
The user type captures information about the human operating the AI agent. This includes personal rules, preferences, identity facts, and operational context that should persist across all projects. Memories of this type represent the agent's understanding of who it is working with and how that person prefers to be addressed or assisted.
Example frontmatter:
Source: https://github.com/rickbassham/commonplace / Human Manual
Memory Store
Related topics: Memory Data Model, Embedding System, Semantic Search
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Memory Data Model, Embedding System, Semantic Search
Memory Store
The Memory Store is the core persistence layer of the Commonplace system. It manages the lifecycle of memory entries—markdown files with YAML frontmatter and binary embedding sidecars—providing atomic writes, concurrent access control, semantic search, and graph-based relationship tracking.
Overview
The Memory Store implements a local-first, file-based storage system where each memory is persisted as a .md file alongside a derived .embedding sidecar. It supports two independent stores (user and project) and exposes both low-level filesystem operations and high-level search/list functionality through an internal API consumed by the MCP server layer.
Key characteristics:
| Characteristic | Description |
|---|---|
| Storage model | Local filesystem with markdown + sidecar files |
| Concurrency | Per-memory advisory locking via proper-lockfile |
| Atomicity | Write-through-temp-and-rename pattern |
| Search | Offline semantic search using transformers.js + bge-base-en-v1.5 |
| Graph | In-memory adjacency list for typed relationships |
| Mentions | [[name]] extraction from body content |
Sources: memory-store.ts:1-50
Architecture
graph TD
subgraph "Memory Store Layer"
MS[MemoryStore]
G[MemoryGraph]
ATOMIC[atomicWrite]
LOCK[acquireNameLock]
end
subgraph "Persistence Layer"
FS[FileSystem]
MD[*.md Files]
EMB[*.embedding Sidecars]
end
subgraph "Integration"
HANDLERS[MCP Handlers]
SEARCH[Search Handler]
end
MS --> G
MS --> ATOMIC
MS --> LOCK
ATOMIC --> FS
LOCK --> FS
MS --> MD
MS --> EMB
HANDLER_FACTORIES[Handler Factories] --> MS
SEARCH --> MSThe MemoryStore class owns the directory-scanning, file I/O, embedding caching, and mtime-based invalidation logic. It delegates locking to acquireNameLock, writes to atomicWrite, and maintains an optional MemoryGraph instance for relationship tracking.
Sources: memory-store.ts:50-120
Memory Data Model
Memory Structure
A memory consists of:
- YAML Frontmatter: Structured metadata
- Markdown Body: Arbitrary content containing
[[name]]mention syntax
interface Memory {
name: string; // Filename stem, matches ^[a-z0-9_]+$
description: string; // Short human description
type: MemoryType; // 'user' | 'feedback' | 'project' | 'reference'
body: string; // Markdown content
relations: Relation[]; // Typed graph edges (DAR-925)
supersedes: string[]; // Names of superseded memories
}
interface Relation {
to: string; // Target memory name
type: RelationType; // 'builds-on' | 'related-to' | 'contradicts' | 'child-of'
}
Sources: memory.ts:1-80
File Format
Memory files use canonical markdown with YAML frontmatter:
Sources: memory-store.ts:1-50
Embedding System
Related topics: Memory Store, Semantic Search
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Memory Store, Semantic Search
Embedding System
The embedding system in Commonplace transforms markdown memory content into vector representations stored as sidecar files, enabling semantic search across the memory store. It is designed to treat the .md source as the single source of truth, with embeddings as derived, regenerable artifacts.
Architecture Overview
The embedding pipeline consists of three primary layers:
- Memory Layer (
src/store/memory.ts) — parses and serializes markdown with YAML frontmatter, computes canonical content hashes - Store Layer (
src/store/memory-store.ts) — orchestrates the scan/embed lifecycle, validates sidecar freshness, manages orphan cleanup - Embedder Layer (
src/embedder/index.ts) — generates vector embeddings via transformers.js
graph TD
A[Markdown File] --> B[readMemory]
B --> C[contentSha Computation]
C --> D[Load Sidecar]
D --> E{Sidecar Fresh?}
E -->|Yes| F[Skip Embedding]
E -->|No| G[Embedder.embed]
G --> H[Serialize Sidecar]
H --> I[atomicWrite]
I --> J[.embedding Sidecar]
C -.-> K[body text + frontmatter]
F --> L[Use Existing Sidecar]Content Hash (contentSha)
The canonical content hash is computed over a specific slice of the memory's data structure, deliberately excluding graph-related fields to prevent embedding invalidation when relationships change.
Canonical Hash Inputs
| Field | Included | Rationale |
|---|---|---|
type | ✅ Yes | Memory type affects semantic context |
name | ✅ Yes | Name is part of semantic identity |
description | ✅ Yes | Description is semantically meaningful |
body | ✅ Yes | Full body content |
relations | ❌ No | Graph edges are derived, not source |
supersedes | ❌ No | Graph edges are derived, not source |
Sources: src/store/memory.ts:contentSha function
The hash formula is:
sha256("${type}\n${name}\n${description}\n${body}")
This produces a 64-character lowercase hex string that uniquely identifies the semantic content of a memory.
SHA Scope Justification
The graph fields (relations, supersedes) are intentionally excluded per DAR-925 design decisions. Adding or removing graph edges must not invalidate existing embeddings because:
- Embeddings are derived from semantic content, not graph topology
- Forcing re-embedding on graph edits would create unnecessary API calls
- The sidecar is explicitly marked as derived, not authoritative
Sidecar Format
Embeddings are stored in .embedding sidecar files alongside their corresponding .md files. The sidecar encodes sufficient metadata to validate freshness without re-reading the markdown.
Sidecar Schema
| Field | Type | Purpose |
|---|---|---|
modelId | string | Identifies the embedding model used |
dim | number | Embedding vector dimensionality |
contentSha | string | Hash of canonical content |
embedding | number[] | The vector data |
Sources: src/store/sidecar.ts
Sidecar File Naming
Sidecar files follow the naming convention <name>.embedding where <name> matches the corresponding memory file <name>.md. This 1:1 correspondence enables orphan detection.
Scan Lifecycle
The MemoryStore.scan() method implements the complete embed lifecycle, checking each memory's sidecar for freshness and triggering regeneration when needed.
Freshness Criteria
A sidecar is considered fresh (reusable) when ALL of the following hold:
- The
.embeddingfile exists - It decodes successfully (magic + version + length checks pass)
decoded.modelId === embedder.modelIddecoded.dim === embedder.dimdecoded.contentSha === contentSha(memoryAsRead)
Sources: src/store/memory-store.ts:scan method
If ANY criterion fails, the memory is re-embedded and the sidecar rewritten.
Scan Process
graph TD
A[Start Scan] --> B[Read all .md files]
B --> C{For each memory}
C --> D{No sidecar?}
D -->|Yes| E[Trigger embed]
D -->|No| F{Decode passes?}
F -->|No| E
F -->|Yes| G{modelId match?}
G -->|No| E
G -->|Yes| H{dim match?}
H -->|No| E
H -->|Yes| I{contentSha match?}
I -->|Yes| J[Skip - use existing]
I -->|No| E
C --> K[Orphan Cleanup]
K --> L[Remove orphaned .embedding files]
E --> M[Write new sidecar]
J --> C
M --> COrphan Cleanup
After processing all memories, scan performs a second directory walk to detect and remove orphan sidecars — .embedding files whose matching .md no longer exists. Orphans are reported via the ScanResult.orphaned field.
Sources: src/store/memory-store.ts:orphan cleanup
Atomic Write Strategy
Sidecar writes use an atomic write-temp-rename pattern to prevent corruption from partial writes.
Write Sequence
- Generate random tmp filename:
<basename>.<8-hex-chars>.tmp - Write data to tmp file
- Verify source and target are on same filesystem (
devmatch) - Rename tmp file to target (atomic on same filesystem)
Sources: src/store/atomic-write.ts
Cross-Filesystem Guard
if (targetDirStat.dev !== tmpDirStat.dev) {
throw new Error("refusing to rename across filesystems");
}
This guard ensures rename operations remain atomic, as rename(2) is not atomic across filesystem boundaries.
Integration Points
CLI Entry Point
The main CLI (src/index.ts) wires the embedder factory into the migrate command:
embedderFactory: () => new Embedder(resolveModelId(process.env)),
The lazy factory ensures the transformers.js model is only loaded when an actual embed call occurs, not during argument parsing.
Migrate Command
The commonplace migrate <dir> command exposes scan functionality as a standalone tool:
- Re-embeds any
.mdwhose sidecar is missing or stale - Cleans up orphaned sidecars
- Optionally prunes dangling graph edges (--prune-dangling flag)
Sources: src/cli/migrate.ts:migrateScan
Configuration
Environment Variables
| Variable | Default | Purpose |
|---|---|---|
COMMONPLACE_EMBEDDING_MODEL | model-specific | Embedding model identifier |
The resolveModelId() function reads the environment to determine which embedding model to instantiate.
Embedder Initialization
The Embedder class is instantiated with the resolved model ID. Model loading (transformers.js) occurs on first embed() call, not on construction, enabling lazy initialization.
Memory Types and Embedding
All four memory types are embeddable with identical treatment:
| Type | Description | Embedding Behavior |
|---|---|---|
user | Personal rules and preferences | Standard |
feedback | Lessons from prior behavior | Standard |
project | Per-project context | Standard |
reference | Durable knowledge | Standard |
Memory type is included in the content hash, so type changes trigger re-embedding.
Summary
The embedding system provides:
- Semantic search via vector embeddings
- Source-of-truth isolation with SHA-scoped content hashes
- Automatic regeneration when content changes
- Orphan cleanup for stale sidecars
- Atomic writes for corruption prevention
- Model portability validation through metadata checks
All embedding behavior is derived from markdown content; the .embedding files are regenerable artifacts that can be deleted and rebuilt via the migrate command at any time.
Sources: src/store/memory.ts:contentSha function
Semantic Search
Related topics: Embedding System, Graph Features, MCP Tool Reference
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Embedding System, Graph Features, MCP Tool Reference
Semantic Search
Semantic search enables finding memories by meaning rather than exact keyword matching. The system embeds memory content into high-dimensional vectors and uses cosine similarity to rank results against a query.
Overview
The semantic search system consists of three main layers:
- Embedding Pipeline — Converts text into dense vectors using a local transformer model
- Vector Storage — Binary
.embeddingsidecar files generated from markdown content - Search Engine — Cosine similarity ranking across one or both memory stores
Memories are stored as markdown files with YAML frontmatter. Each memory has a corresponding .embedding sidecar containing its pre-computed vector representation. The embedding is derived from the canonical memory content and cached until the content changes (detected via SHA-256 hash).
Sources: src/store/memory.ts:1-50
Architecture
graph TD
subgraph "CLI / MCP Layer"
H[handlers.ts]
end
subgraph "Store Layer"
MS[MemoryStore]
G[MemoryGraph]
end
subgraph "I/O Layer"
FS[File System]
end
subgraph "Embedding Layer"
E[Embedder]
TFM[transformers.js]
BGE[bge-base-en-v1.5]
end
H --> MS
MS --> E
E --> TFM
TFM --> BGE
MS <--> G
MS <--> FS
G -.-> MS
style E fill:#e1f5fe
style BGE fill:#fff3e0Component Responsibilities
| Component | File | Role |
|---|---|---|
MemoryStore | memory-store.ts | Manages scanning, embedding, and search operations |
Embedder | embedder.ts | Wraps transformers.js for local inference |
MemoryGraph | graph.ts | Tracks relations and enriches search results |
handlers.ts | handlers.ts | MCP tool handler for memory_search |
Sources: src/store/memory-store.ts:1-100
Embedding Pipeline
Model Configuration
The system uses bge-base-en-v1.5 from the BGE (BAAI General Embedding) family. This model produces 768-dimensional dense vectors optimized for semantic similarity tasks.
// Resolved from environment: EMBEDDING_MODEL_ID
const DEFAULT_MODEL_ID = 'Xenova/bge-base-en-v1.5';
The embedder runs entirely offline via @huggingface/transformers (transformers.js), requiring no external API calls or internet connectivity after the initial model load.
Sources: src/store/memory-store.ts:100-150
Embedding Derivation
Embeddings are derived from the canonical memory content, defined as:
${type}\n${name}\n${description}\n${body}
The SHA-256 hash of this canonical string is computed and compared against stored hashes to detect content changes. This ensures embeddings are regenerated only when necessary.
export const contentSha = (memory: Memory): string =>
createHash('sha256')
.update(`${memory.type}\n${memory.name}\n${description}\n${body}`, 'utf8')
.digest('hex');
Important: Graph fields (relations, supersedes) do NOT affect the canonical content or embedding. Adding or removing graph edges does not invalidate the embedding sidecar.
Sources: src/store/memory.ts:80-100
Sidecar Format
Each memory generates a binary .embedding sidecar file in the same directory as the .md file:
~/.commonplace/memory/
├── feedback_scope.md
├── feedback_scope.embedding ← binary float32 vectors
└── architecture.md
└── architecture.embedding
The sidecar is derived data — it can be deleted and regenerated at any time from the markdown source.
Sources: CLAUDE.md:1-30
Search Workflow
sequenceDiagram
participant C as MCP Client
participant H as memory_search Handler
participant MS as MemoryStore
participant E as Embedder
participant FS as File System
C->>H: memory_search({ query, k?, scope? })
H->>MS: search(query, k, opts)
Note over MS: Load user store<br/>+ project store if present
MS->>E: embed(query)
E->>E: Load model (lazy)
E-->>MS: queryVector[768]
MS->>FS: Load all .embedding sidecars
FS-->>MS: Float32Array vectors
loop Per-memory
MS->>MS: cosineSimilarity(queryVector, memoryVector)
end
MS->>G: Filter supersedes, enrich relations
G-->>MS: Augmented matches
MS-->>H: MemorySearchResult[]
H-->>C: JSON responseSearch Flow Details
- Query embedding — The search query is embedded using the same model as memory content
- Vector loading — All
.embeddingsidecars are loaded into memory (lazy, cached) - Similarity computation — Brute-force cosine similarity between query vector and all memory vectors
- Result filtering — Superseded memories are excluded by default
- Graph enrichment — Results include outgoing relations from the frontmatter
Sources: src/store/memory-store.ts:200-300
Memory Search API
MCP Tool: `memory_search`
Input schema:
| Argument | Type | Required | Default | Description | |
|---|---|---|---|---|---|
query | string | Yes | — | Natural language search query | |
k | integer | No | 5 | Maximum number of results to return | |
type | MemoryType | No | — | Filter by memory type (user/feedback/project/reference) | |
includeSuperseded | boolean | No | false | Include memories superseded by others | |
expandTypes | string[] | No | ['builds-on', 'related-to'] | Edge types to include in results | |
scope | 'user' \ | 'project' | No | merged | Which store to search |
Response Schema
interface MemorySearchResult {
query: string;
matches: MemorySearchMatch[];
scope: 'user' | 'project' | 'merged';
}
interface MemorySearchMatch {
name: string;
type: MemoryType;
description: string;
body: string; // Full body verbatim (never truncated)
score: number; // Cosine similarity, 3 decimals
relations: Relation[]; // Outgoing edges from frontmatter
scope: 'user' | 'project';
}
Note: The body is never truncated, summarized, or transformed. The caller receives exactly what was persisted.
Sources: src/server/handlers.ts:50-120
Default Expand Types
Only builds-on and related-to are included by default. Other edge types require explicit opt-in:
export const DEFAULT_EXPAND_TYPES: readonly EdgeType[] =
['builds-on', 'related-to'] as const;
This prevents surprising the agent with mentions, supersedes, contradicts, or child-of edges unless requested.
Sources: src/server/handlers.ts:15-25
Memory Stores and Scoping
Dual-Store Architecture
The system supports two independent memory stores:
| Store | Location | Purpose |
|---|---|---|
| User Store | ~/.commonplace/memory (default) | Personal rules, preferences, feedback |
| Project Store | <project-root>/.commonplace/memory | Per-project context |
Detection Priority
Project store selection follows this priority:
COMMONPLACE_PROJECT_DIRenv var (explicit override)- MCP
roots/listresponse - Current working directory
If none apply, only the user store is loaded.
Merged Search
When scope is omitted, search merges results from both stores by descending score. Each match carries a scope tag identifying its source.
Sources: src/server/handlers.ts:150-200
Scan and Re-embedding
Trigger Conditions
The store performs a lazy rescan when:
- Directory mtime advances past the baseline (new files detected)
- Memory is saved (triggers immediate re-embedding)
// MemoryStore.scan() behavior:
// - Skips if dir mtime hasn't changed (lastScanMtimeMs baseline)
// - Regenerates embedding for any memory with changed sha
// - Stores new dir mtime as baseline after scan
Lazy Re-embedding
On save, the system:
- Computes
contentShafor the new content - Compares against stored hash
- Regenerates embedding only if hash differs
This avoids redundant model inference for graph-only changes (relation additions/removals).
Sources: src/store/memory-store.ts:250-280
Content-Based Mention Extraction
While not part of the vector search pipeline, [[name]] mentions in body text create graph edges that enrich search results:
// Mention extraction (DAR-927)
// Scanned during save/scan, not during search
// Creates 'mentions' edges in MemoryGraph
Mention extraction is controlled by COMMONPLACE_EXTRACT_MENTIONS env var (default: enabled). Regex pattern matches <name> tokens against ^[a-z0-9_]+$.
Sources: src/store/mentions.ts:1-50
Related Features
| Feature | Description |
|---|---|
| Memory List | List memories without semantic scoring |
| Memory Graph | Graph traversal and path finding |
| Memory Link/Unlink | Manual edge creation |
| Migrate | Import from Claude Code auto-memory |
Configuration Reference
| Variable | Default | Description |
|---|---|---|
EMBEDDING_MODEL_ID | Xenova/bge-base-en-v1.5 | HuggingFace model identifier |
COMMONPLACE_USER_DIR | ~/.commonplace/memory | User store root |
COMMONPLACE_PROJECT_DIR | — | Project store override |
COMMONPLACE_EXTRACT_MENTIONS | true | Enable [[name]] extraction |
COMMONPLACE_EMBED_BATCH_SIZE | — | Batch size for embedding |
Sources: src/store/memory.ts:1-50
Graph Features
Related topics: Semantic Search, MCP Tool Reference
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Semantic Search, MCP Tool Reference
Graph Features
Overview
The Graph Features system provides a network-based view of memories, enabling relationships between notes to be tracked, queried, and visualized. Rather than treating each memory as an isolated entity, the graph layer exposes connections through authored relations in frontmatter, supersedes declarations, and automatic [[name]] mention extraction from body content.
The graph is not a separate data store—it derives from the same markdown files that form the memory corpus. Each .md file in a memory store may declare outgoing edges via its YAML frontmatter, and the in-memory MemoryGraph maintains an adjacency list for efficient traversal.
Sources: src/store/graph.ts:1-30
Architecture
graph TD
subgraph "Memory Sources"
UserStore["User Memory Store<br/>(~/.commonplace)"]
ProjectStore["Project Memory Store<br/>(./.commonplace)"]
end
subgraph "Graph Layer"
MemoryGraph["MemoryGraph"]
AdjacencyList["Adjacency List<br/>(Map<name, Edge[]>)"]
end
subgraph "Edge Sources"
Relations["relations[]<br/>frontmatter field"]
Supersedes["supersedes[]<br/>frontmatter field"]
Mentions["[[name]] mentions<br/>body extraction"]
end
UserStore --> MemoryGraph
ProjectStore --> MemoryGraph
MemoryGraph --> AdjacencyList
Relations --> MemoryGraph
Supersedes --> MemoryGraph
Mentions --> MemoryGraphCore Components
| Component | File | Purpose |
|---|---|---|
MemoryGraph | src/store/graph.ts | In-memory graph with adjacency list, edge management, and traversal |
Edge / DanglingEdge | src/store/graph.ts | Data models for directed edges |
MemoryStore | src/store/memory-store.ts | Persists graph edges via frontmatter, maintains in-memory sync |
mentions.ts | src/store/mentions.ts | Extracts [[name]] tokens from body content |
handlers.ts | src/server/handlers.ts | MCP tool handlers for graph operations |
graph.ts CLI | src/cli/graph.ts | Command-line graph visualization |
Sources: src/store/graph.ts:25-45
Edge Types
The graph supports a union of edge types drawn from three sources:
| Edge Type | Source | Description |
|---|---|---|
related-to | relations[] frontmatter | General-purpose association between memories |
builds-on | relations[] frontmatter | Memory that extends or depends on another |
contradicts | relations[] frontmatter | Memory that opposes or negates another |
child-of | relations[] frontmatter | Hierarchical parent-child relationship |
supersedes | supersedes[] frontmatter | Memory that replaces or renders another obsolete |
mentions | Body [[name]] extraction | Memory references another by name in its body |
Sources: src/store/graph.ts:15-25
Frontmatter Declaration
Memories declare outgoing edges in YAML frontmatter:
Sources: src/store/graph.ts:1-30
MCP Tool Reference
Related topics: Server Handlers, Semantic Search, Graph Features
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Server Handlers, Semantic Search, Graph Features
MCP Tool Reference
The Model Context Protocol (MCP) server exposes a set of tools that enable external clients—primarily Claude Code—to interact with the commonplace book. These tools provide CRUD operations for memories, semantic search, and graph management. The MCP stdio server acts as the bridge between the local embedding pipeline and any MCP-compatible client.
Sources: src/server/handlers.ts:1-25
Architecture Overview
The MCP server is implemented in src/server/ and wired to the memory store layer. Tool requests arrive via stdio JSON-RPC, are validated in handler functions, dispatched to the MemoryStore, and returned as JSON-serializable responses wrapped in MCP content blocks.
graph TD
A[MCP Client<br/>Claude Code] --> B[stdio JSON-RPC]
B --> C[server.ts<br/>CallToolRequest Dispatcher]
C --> D[handlers.ts<br/>Tool Handlers]
D --> E[MemoryStore]
E --> F[memory.ts<br/>YAML + Embedding I/O]
E --> G[graph.ts<br/>In-memory Graph]
F --> H[.md Files<br/>+ .embedding Sidecars]Sources: src/server/handlers.ts:17-23
Tool Categories
The MCP server exposes two categories of tools:
| Category | Purpose | Tools |
|---|---|---|
| Memory CRUD | Create, read, delete, and search memories | memory_save, memory_list, memory_delete, memory_search |
| Graph Management | Manage relationships between memories | memory_link, memory_unlink |
Sources: README.md:1-50
Scope Model
Every tool accepts an optional scope argument that selects which memory store to address:
| Scope | Description |
|---|---|
user | Cross-project memories stored in COMMONPLACE_USER_DIR |
project | Project-specific memories stored in COMMONPLACE_PROJECT_DIR |
When scope is omitted, reads merge across both stores and writes default to user.
Sources: src/server/handlers.ts:30-35
Memory Types
All memory tools operate on a four-element taxonomy defined in the store layer:
| Type | Purpose |
|---|---|
user | Personal rules, preferences, and identity facts about the human operator |
feedback | Corrections and lessons learned from prior agent behaviour; persistent course-corrections |
project | Per-project context like architecture notes, repo conventions, and decisions |
reference | Durable, neutral knowledge: API shapes, formulas, citations |
Sources: src/store/memory.ts:1-30
Memory CRUD Tools
memory_save
Save a memory as a markdown file with YAML frontmatter and a derived embedding sidecar. Refuses to overwrite an existing entry; the contract is delete + save.
Input Schema:
| Argument | Type | Required | Description | |||
|---|---|---|---|---|---|---|
name | string | Yes | Memory name. Must match ^[a-z0-9_]+$. Becomes the filename stem. | |||
type | `user \ | feedback \ | project \ | reference` | Yes | One of the four memory types. |
description | string | Yes | Short description used in search result summaries. | |||
body | string | Yes | Markdown content of the memory. | |||
scope | `'user' \ | 'project'` | No | Which store to write to. Defaults to 'user'. |
Sources: README.md:50-80
Validation: Arguments are validated manually at handler entry. The handler checks name against validateName, type against MEMORY_TYPES, and passes store errors through unchanged.
Sources: src/server/handlers.ts:40-55
memory_list
List all memories, optionally filtered by type.
Input Schema:
| Argument | Type | Required | Description | |||
|---|---|---|---|---|---|---|
type | `user \ | feedback \ | project \ | reference` | No | Filter to memories of this type only. |
scope | `'user' \ | 'project'` | No | Which store to query. Defaults to merging both stores. |
Response: Returns an array of memory entries with name, type, description, and body fields.
Sources: src/server/handlers.ts:60-75
memory_delete
Delete a memory by name from the specified store.
Input Schema:
| Argument | Type | Required | Description | |
|---|---|---|---|---|
name | string | Yes | Name of the memory to delete. | |
scope | `'user' \ | 'project'` | No | Which store to delete from. Defaults to 'user'. |
Sources: src/server/handlers.ts:80-95
memory_search
Semantic search across all memories using local embeddings.
Input Schema:
| Argument | Type | Required | Description | |||
|---|---|---|---|---|---|---|
query | string | Yes | Natural language search query. | |||
type | `user \ | feedback \ | project \ | reference` | No | Filter to memories of this type only. |
limit | number | No | Maximum results to return. Defaults to DEFAULT_SEARCH_LIMIT. | |||
scope | `'user' \ | 'project'` | No | Which store to search. Defaults to merging both stores. |
Sources: src/server/handlers.ts:100-130
Response Enrichment: Search results include relations from connected memories and exclude notes marked as superseded. This is handled by MemoryGraph integration.
Sources: src/store/memory-store.ts:1-50
Graph Management Tools
memory_link
Create a directed edge between two memories, establishing a typed relationship.
Input Schema:
| Argument | Type | Required | Description | |
|---|---|---|---|---|
from | string | Yes | Source memory name. | |
to | string | Yes | Target memory name. | |
type | `RelationType \ | 'supersedes'` | Yes | Relationship type. |
scope | `'user' \ | 'project'` | No | Which store contains both memories. |
Relation Types:
| Type | Description |
|---|---|
builds-on | The source memory builds upon the target |
implements | The source memory implements the target |
relates-to | General relationship between memories |
supersedes | The source memory supersedes the target |
Behavior:
- Throws if the edge already exists (no duplicate edges).
- Updates the
relationsarray in the source memory's YAML frontmatter. - Mutates the in-memory entry in place for consistency.
- Refreshes the directory mtime baseline to avoid wasteful rescans.
Sources: src/store/memory-store.ts:200-280
graph LR
A[memory: feedback_scope] -->|builds-on| B[memory: scope_management]
A -->|supersedes| C[memory: old_feedback_v1]memory_unlink
Remove a directed edge between two memories.
Input Schema:
| Argument | Type | Required | Description | |
|---|---|---|---|---|
from | string | Yes | Source memory name. | |
to | string | Yes | Target memory name. | |
type | `RelationType \ | 'supersedes'` | No | Specific edge type to remove. If omitted, removes ALL edges from from to to. |
Behavior:
- No-op when the requested edge does not exist (no atomic write, no graph mutation).
- Returns
{ ..., note: '<reason>' }for friendly messaging when edges don't exist. - When edges are removed, writes the source
.mdthroughatomicWrite, updates the in-memory entry in place, and callsMemoryGraph.removeEdge.
Sources: src/store/memory-store.ts:300-400
Validation Strategy
Tool argument validation is deliberately manual rather than schema-library-based:
- Zero new dependencies for validation logic.
- Rejection messages are tailored to name the offending field.
- Store layer errors are passed through unchanged to preserve context.
Sources: src/server/handlers.ts:15-20
Response Format
All tool responses are JSON-serializable shapes wrapped in a single text content block by the MCP server's CallToolRequest dispatcher in server.ts. The dispatcher handles both the CRUD tools and graph tools uniformly.
Sources: src/server/handlers.ts:20-23
Environment Variables
The MCP server respects the following environment variables:
| Variable | Default | Description |
|---|---|---|
COMMONPLACE_USER_DIR | ~/.commonplace | Directory for user-scoped memories |
COMMONPLACE_PROJECT_DIR | <cwd>/.commonplace | Directory for project-scoped memories |
COMMONPLACE_EXTRACT_MENTIONS | 'true' | Enable [[name]] mention extraction from body content |
Sources: src/store/mentions.ts:1-30
MCP Server Binary
The MCP server is exposed as the commonplace-mcp binary, separate from the CLI's commonplace command. This separation ensures the MCP stdio framing channel is never polluted by CLI output.
Sources: src/index.ts:1-30
See Also
- Memory Store Architecture — In-depth details on embedding, sidecars, and graph integration
- CLI Reference — The
commonplaceCLI for migration and graph commands - Memory File Format — YAML frontmatter schema and content hashing
Sources: src/server/handlers.ts:1-25
Server Handlers
Related topics: MCP Tool Reference, System Architecture
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: MCP Tool Reference, System Architecture
Server Handlers
Overview
Server Handlers are the core request-processing layer in the Commonplace MCP server. They implement the MCP (Model Context Protocol) tool handlers that bridge the MCP client interface to the underlying MemoryStore persistence layer. Each handler is a factory function that produces an MCP-compatible request handler with consistent validation, error handling, and response shaping.
The handler system is designed around:
- Factory pattern: Each handler is created via a factory function (e.g.,
createMemorySaveHandler,createMemoryListHandler) that encapsulates store access and validation logic. - Typed interfaces: All inputs and outputs use TypeScript interfaces exported from
handlers.tsfor compile-time safety. - Scope awareness: Handlers support both
userandprojectscopes, allowing memories to be stored in different directories. - Graph integration: Handlers can optionally work with the
MemoryGraphto enrich responses with relation data.
Architecture
Request Flow
graph TD
A[MCP Request] --> B[Server dispatch]
B --> C{Handler Factory}
C --> D[createMemorySaveHandler]
C --> E[createMemoryListHandler]
C --> F[createMemorySearchHandler]
C --> G[createMemoryDeleteHandler]
C --> H[createMemoryLinkHandler]
C --> I[createMemoryUnlinkHandler]
D --> J[MemoryStore]
E --> J
F --> J
G --> J
H --> J
I --> J
J --> K[MemoryGraph]
J --> L[File System]
K --> M[Relation Enrichment]
L --> N[.md + .embedding files]
M --> O[MCP Response]
N --> OHandler Factory Pattern
Each handler follows the factory pattern documented in handlers.ts:
export const createMemorySaveHandler = (opts: CreateHandlerOptions) => {
const { userStore, projectStore } = resolveStores(opts);
return async (request: MemorySaveRequest): Promise<MemorySaveResult> => {
// Validation and processing
};
};
Sources: src/server/handlers.ts:1-50
Handler Types
MemorySaveHandler
Purpose: Creates or updates a memory note with YAML frontmatter and markdown body.
Factory: createMemorySaveHandler(options: CreateHandlerOptions)
Request Interface:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Memory identifier matching ^[a-z0-9_]+$ |
type | MemoryType | Yes | One of: user, feedback, project, reference |
description | string | Yes | Brief description for search relevance |
body | string | Yes | Markdown content |
scope | Scope | No | user (default) or project |
Response Interface:
export interface MemorySaveResult {
saved: {
name: string;
type: MemoryType;
description: string;
};
path: string;
/** Which store the memory was written to (DAR-924) */
scope: Scope;
}
Sources: src/server/handlers.ts:80-95
Validation:
- Name must match
NAME_PATTERN(^[a-z0-9_]+$) - Type must be one of
MEMORY_TYPES - Scope is validated via
validateScope()helper - Duplicate relations are deduplicated on write
Sources: src/store/memory.ts:1-50
MemoryListHandler
Purpose: Returns all memories from a store, optionally filtered by type and scope.
Factory: createMemoryListHandler(options: CreateHandlerOptions)
Request Interface:
| Field | Type | Required | Description |
|---|---|---|---|
type | MemoryType | No | Filter by memory type |
scope | Scope | No | Filter by scope (user/project) |
Response Interface:
export interface MemoryListResult {
memories: Array<{
name: string;
type: MemoryType;
description: string;
/** Which store this entry came from */
scope: Scope;
}>;
}
Sources: src/server/handlers.ts:97-108
MemorySearchHandler
Purpose: Performs semantic search across memory embeddings using cosine similarity.
Factory: createMemorySearchHandler(options: CreateHandlerOptions)
Request Interface:
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Natural language search query |
limit | number | No | Max results (default: 10) |
type | MemoryType | No | Filter by type |
scope | Scope | No | Filter by scope |
expand | boolean | No | Include related memories (default: true) |
expandTypes | EdgeType[] | No | Which relation types to expand |
Response Interface:
export interface MemorySearchMatch {
name: string;
type: MemoryType;
description: string;
body: string; // Full body, never truncated
score: number; // Cosine similarity, 3 decimals
relations: Relation[]; // Outgoing graph edges
}
Sources: src/server/handlers.ts:35-60
Expand Types Configuration:
| Type | Default | Description |
|---|---|---|
builds-on | Yes | Included by default |
related-to | Yes | Included by default |
mentions | No | Requires opt-in |
supersedes | No | Requires opt-in |
contradicts | No | Requires opt-in |
child-of | No | Requires opt-in |
export const DEFAULT_EXPAND_TYPES: readonly EdgeType[] = ['builds-on', 'related-to'] as const;
Sources: src/server/handlers.ts:20-30
Response Enrichment:
When expand is enabled, the handler enriches results by:
- Fetching direct matches from
MemoryStore.search() - For each match, query
MemoryGraphfor outgoing edges matchingexpandTypes - Add expanded memories to response (marked with
expanded: true) - Exclude superseded memories unless explicitly requested
MemoryDeleteHandler
Purpose: Removes a memory from the store by name.
Factory: createMemoryDeleteHandler(options: CreateHandlerOptions)
Request Interface:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Memory name to delete |
scope | Scope | No | Scope hint for store resolution |
Response Interface:
export interface MemoryDeleteResult {
deleted: string;
scope: Scope;
}
MemoryLinkHandler
Purpose: Creates a directed edge between two memories in the graph.
Factory: createMemoryLinkHandler(options: CreateHandlerOptions)
Request Interface:
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Source memory name |
to | string | Yes | Target memory name |
type | RelationType | Yes | Edge type |
scope | Scope | No | Scope for operation |
Relation Types:
| Type | Description |
|---|---|
builds-on | Memory extends or depends on another |
related-to | Memory has loose association |
contradicts | Memory refutes another |
child-of | Memory is subordinate to another |
Internal Behavior: The handler delegates to MemoryStore.linkEdge() which:
- Validates both memory names exist
- Adds the relation to the source memory's frontmatter
- If type is
supersedes, also adds tosupersedeslist - Writes updated markdown via atomic write
- Updates the in-memory
MemoryGraph
Sources: src/store/memory-store.ts:1-50
MemoryUnlinkHandler
Purpose: Removes a directed edge between two memories.
Factory: createMemoryUnlinkHandler(options: CreateHandlerOptions)
Request Interface:
| Field | Type | Required | Description | |
|---|---|---|---|---|
from | string | Yes | Source memory name | |
to | string | Yes | Target memory name | |
type | `RelationType \ | 'supersedes'` | No | Specific edge type to remove. Omit to remove all edges to target |
Behavior:
- No-op when the requested edge does not exist
- When
typeis omitted, removes ALL edges fromfrom->to - Returns
{ relations, supersedes, note }describing the new state
Sources: src/store/memory-store.ts:100-150
Store Resolution
Handlers use the resolveStores helper to map request scopes to actual store instances:
const resolveStores = (opts: { store?: MemoryStore; userStore?: MemoryStore; projectStore?: MemoryStore }) => {
const userStore = opts.userStore ?? opts.store;
if (userStore === undefined) {
throw new Error(`${toolName}: handler factory requires a userStore`);
}
return { userStore, projectStore: opts.projectStore };
};
Sources: src/server/handlers.ts:65-75
Scope System
The scope system allows memories to be stored in different locations:
| Scope | Directory | Use Case |
|---|---|---|
user | COMMONPLACE_USER_DIR | Cross-project knowledge |
project | COMMONPLACE_PROJECT_DIR | Project-specific facts |
Validation:
const SCOPES = ['user', 'project'] as const;
type Scope = typeof SCOPES[number];
const isScope = (v: unknown): v is Scope =>
typeof v === 'string' && (SCOPES as readonly string[]).includes(v);
Sources: src/server/handlers.ts:55-70
Server Initialization
The handlers are wired into the MCP server in server.ts:
graph LR
A[MCP Server] --> B[registerTools]
B --> C[MemorySaveHandler]
B --> D[MemoryListHandler]
B --> E[MemorySearchHandler]
B --> F[MemoryDeleteHandler]
B --> G[MemoryLinkHandler]
B --> H[MemoryUnlinkHandler]The main entry point (src/index.ts) dispatches to the server module:
if (argv[0] === 'graph') {
const result = await graphMain({ argv, ... });
return result.exitCode;
}
Sources: src/index.ts:1-30
Error Handling
All handlers follow consistent error handling patterns:
| Error Type | Cause | Response |
|---|---|---|
| Validation error | Invalid input format | Throws with descriptive message |
| Not found | Memory doesn't exist | Handled by store methods |
| Duplicate edge | Edge already exists | Handled by linkEdge |
| Store unavailable | Store not initialized | Factory throws on construction |
Integration with MemoryStore
Handlers delegate to MemoryStore methods for all persistence operations:
| Handler | Store Method |
|---|---|
| MemorySaveHandler | MemoryStore.save() |
| MemoryListHandler | MemoryStore.all() |
| MemorySearchHandler | MemoryStore.search() |
| MemoryDeleteHandler | MemoryStore.delete() |
| MemoryLinkHandler | MemoryStore.linkEdge() |
| MemoryUnlinkHandler | MemoryStore.unlinkEdge() |
Sources: src/store/memory-store.ts:1-200
Mention Extraction
When a memory is saved, the body is scanned for [[name]] wiki-link syntax:
graph TD
A[Memory Save] --> B[Extract mentions]
B --> C{NAME_PATTERN test}
C -->|pass| D[Add to MemoryGraph]
C -->|fail| E[Skip]
D --> F[edgesPruned count]This extraction is controlled by the COMMONPLACE_EXTRACT_MENTIONS environment variable (default: enabled).
Sources: src/store/mentions.ts:1-60
Configuration
Handlers are configured via environment variables managed in DAR-913:
| Variable | Default | Effect |
|---|---|---|
COMMONPLACE_USER_DIR | ~/.commonplace | User memory directory |
COMMONPLACE_PROJECT_DIR | ./.commonplace | Project memory directory |
COMMONPLACE_MODEL_ID | Xenova/bge-base-en-v1.5 | Embedding model |
COMMONPLACE_EXTRACT_MENTIONS | true | Enable [[name]] extraction |
Related Documentation
- Memory Store:
src/store/memory-store.ts- Persistence layer - Memory Types:
src/store/memory.ts- Type definitions - Atomic Write:
src/store/atomic-write.ts- Safe file operations - Mention Extraction:
src/store/mentions.ts-[[name]]parsing - CLI Entry:
src/index.ts- Command dispatch
Sources: src/server/handlers.ts:1-50
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
The project should not be treated as fully validated until this signal is reviewed.
The project should not be treated as fully validated until this signal is reviewed.
Users cannot judge support quality until recent activity, releases, and issue response are checked.
The project may affect permissions, credentials, data exposure, or host boundaries.
Doramagic Pitfall Log
Doramagic extracted 8 source-linked risk signals. Review them before installing or handing real data to the project.
1. Capability assumption: README/documentation is current enough for a first validation pass.
- Severity: medium
- Finding: README/documentation is current enough for a first validation pass.
- User impact: The project should not be treated as fully validated until this signal is reviewed.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: capability.assumptions | github_repo:1232879661 | https://github.com/rickbassham/commonplace | README/documentation is current enough for a first validation pass.
2. Project risk: Project risk needs validation
- Severity: medium
- Finding: Project risk is backed by a source signal: Project risk needs validation. Treat it as a review item until the current version is checked.
- User impact: The project should not be treated as fully validated until this signal is reviewed.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: packet_text.keyword_scan | github_repo:1232879661 | https://github.com/rickbassham/commonplace | matched external service / cloud / webhook / database keyword
3. Maintenance risk: Maintainer activity is unknown
- Severity: medium
- Finding: Maintenance risk is backed by a source signal: Maintainer activity is unknown. Treat it as a review item until the current version is checked.
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1232879661 | https://github.com/rickbassham/commonplace | last_activity_observed missing
4. Security or permission risk: no_demo
- Severity: medium
- Finding: no_demo
- User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: downstream_validation.risk_items | github_repo:1232879661 | https://github.com/rickbassham/commonplace | no_demo; severity=medium
5. Security or permission risk: No sandbox install has been executed yet; downstream must verify before user use.
- Severity: medium
- Finding: No sandbox install has been executed yet; downstream must verify before user use.
- User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: risks.safety_notes | github_repo:1232879661 | https://github.com/rickbassham/commonplace | No sandbox install has been executed yet; downstream must verify before user use.
6. Security or permission risk: no_demo
- Severity: medium
- Finding: no_demo
- User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: risks.scoring_risks | github_repo:1232879661 | https://github.com/rickbassham/commonplace | no_demo; severity=medium
7. Maintenance risk: issue_or_pr_quality=unknown
- Severity: low
- Finding: issue_or_pr_quality=unknown。
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1232879661 | https://github.com/rickbassham/commonplace | issue_or_pr_quality=unknown
8. Maintenance risk: release_recency=unknown
- Severity: low
- Finding: release_recency=unknown。
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1232879661 | https://github.com/rickbassham/commonplace | release_recency=unknown
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using commonplace with real data or production workflows.
- v0.2.1 - github / github_release
- v0.1.0 - github / github_release
- v0.0.1-canary.2 - github / github_release
- README/documentation is current enough for a first validation pass. - GitHub / issue
Source: Project Pack community evidence and pitfall evidence