mind
AGENTS.md193 starsChanged 26 days agoMITView on GitHub
This document describes the mind project's architecture, behavior, technical choices, and usage. It is intended for AI agents and human maintainers. Read Mind's purpose and philosophy to understand the product goal and principles, and CONTRIBUTING.md for the contribution workflow. Agents should read the philosophy page before proposing or implementing product behavior. Agents that modify this codebase must keep this file updated when they change architecture, add commands, change config, or alter behavior (see Keeping this document updated). mind is a…
- Reads credentials
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository5 other files it gives its agents.
- bun-developmentSkill
- clean-architectureSkill
- clean-backend-architectureSkill
- clean-codeSkill
- frontend-designSkill
The file
We split this AGENTS.md into the rules it gives an agent
4 rules. About 0 are common, 0 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 45
Storage: All persistent data goes through the MindStore interface (defined in src/store/mind-store.ts), implemented by createSqliteStore …
- Very specific: line 47
Output: All user-facing messages go through the Logger interface (src/helpers/logger.ts), so tests can swap in a mock logger.
- Very specific: line 105
LRU eviction: when a tier is full, the least-recently-used non-pinned memory is demoted one tier down (no cascading).
- Very specific: line 161
Search reset behavior is covered by web/test/search-controller.spec.ts (clears stale results without a request) and …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AGENTS.md — Project guide for AI agents and maintainers
This document describes the mind project's architecture, behavior, technical choices, and usage. It is intended for AI agents and human maintainers. Read Mind's purpose and philosophy to understand the product goal and principles, and CONTRIBUTING.md for the contribution workflow. Agents should read the philosophy page before proposing or implementing product behavior. Agents that modify this codebase must keep this file updated when they change architecture, add commands, change config, or alter behavior (see Keeping this document updated).
1. Project overview
mind is a local, open-source persistent cognitive workspace for AI coding agents. It preserves useful project and work context—decisions, constraints, discoveries, and unfinished tasks—so agents can resume across sessions, tools, and context windows. Its purpose and guiding principles are documented in Mind's philosophy. Data is organized into named spaces containing memories, with full-text search, tags, links, checkpoints, session summaries, living references, and a 3-tier access-frequency system.
- Runtime: Bun
- Language: TypeScript (strict mode, ESNext)
- Entry point: the
mindBash script at project root; invokessrc/mind.ts. Supports subcommands:serve(HTTP server),mcp(MCP server),setup(agent configuration), andupdate(self-update from GitHub releases). Also supports--completeflag to delegate tosrc/complete.ts(not yet implemented). - Persistence: SQLite database at
data/mind.db(path configurable viaMIND_DATA_DIRenv var orMIND_DB_PATHfor full path override). The legacybrain.jsonis supported as a migration source viamind import. - RAG/Embeddings: Optional semantic search with a selectable embedding provider (
MIND_EMBEDDING_PROVIDER:openaidefault oropenrouter; invalid values disable RAG without fallback). Enable withMIND_RAG=true+OPENAI_API_KEY(OpenAI) orOPENROUTER_API_KEY(OpenRouter). The model staystext-embedding-3-small(openai/text-embedding-3-smallon OpenRouter) at 1536 dimensions, so stored vectors remain compatible without re-embedding. Embeddings are stored as BLOBs in SQLite and generated with an awaited request on add/update/move/patch (not fire-and-forget). - Search pipeline: One unified relevance pipeline backs CLI
search, MCPmemory_query(search), andGET /api/search. A parser turns input into an AST (quoted"phrases", uppercaseOR,AND,NOT, trailing*; lowercase operator words are ordinary terms; malformed input degrades to a literal AND and never makesparseQuerythrow) and logically independent channels collect candidates: lexical rungs (phrase → all → any), trigram substring, fuzzy (Damerau–Levenshtein ≤2, capped expansions), LIKE for sub-trigram terms, token-set coverage, and the optional semantic channel. The channels execute sequentially on one synchronous SQLite connection, so “fan-out” describes the candidate model, not concurrent execution. Parser syntax fallback and search-level validation are separate: a supplied search whose positive text has no informative term after common stopwords are removed throws one typed validation error before any channel or embedding call, even when the parser degraded the query; an omitted field stays a metadata listing (MCP) or an empty 200 response (API). For plain questions containing?or¿, lexical recall uses informative non-stopword terms, keeps complementary partial matches, and lets fusion rank them; unpunctuated keyword searches and explicit searches keep strict admission. A per-query weighted fusion (with an agreement bonus) ranks results deterministically and attaches a per-resultconfidencebucket (high/medium/low) plusmethodsprovenance. Semantic admission is independent of the lexical gate: natural-language queries (one group, noNOT, only plain terms, no explicit uppercaseAND) admit semantic candidates at cosine ≥0.6 even when lexical results exist, while explicit phrases, prefixes, and operators stay lexical. With RAG off the semantic channel is omitted silently; a query-time embedding failure opens a ~5-minute in-memory breaker so a failing provider cannot trigger retry storms. - Layout:
src/contains CLI, MCP, and API server code.test/contains backend/CLI tests.web/contains frontend source (web/src), styles (web/styles), static assets (web/assets), static HTML shell (web/public), and web-specific tests (web/test).scripts/contains E2E and evaluation scripts (includingscripts/search-eval.ts, the relevance-suite runner). - Cognitive lifecycle docs: The documentation index groups all living pages.
docs/cognitive-memory-lifecycle.mdexplains the memory model, tiers, lifecycle, writing, supersession, linking, living references, and tool usage;docs/skill-first-distribution.mdexplains the skill-first activation and installation model;docs/agent-integration-matrix.mdrecords per-client paths and validation status; anddocs/search-engine.mddescribes current retrieval behavior. Exceptional historical evidence lives underdocs/history/; execution, merge, and validation reports stay in.pas/, and no report is added to the docs root. The normative agent instructions remain the canonical protocol insrc/resources/protocols/mind-cognitive-protocol.md. - Neural Map MVP: web SPA includes a read-only per-space graph view using a minimal graph API payload and on-demand memory detail fetch, with adaptive multi-lane radial placement, dense-map culling (no persistent labels; one transient label on hover/focus/selection, bounded edges, in-circle degree numbers, zero overlaps), dragging that never selects graph text (the accessible table stays selectable), and higher zoom ceiling for dense maps.
- Web SPA URL routing: client-side URL contract is
/(All spaces),/spaces/{encodedSpace}?view=list|map&memory=&q=&tag=&tier=&tiers=1,3&confidence=&semantic(space detail with in-space search), and/logs, with reload restore, browser back/forward support (popstate), and safe fallback canonicalization when route params are invalid. All spaces is the first sidebar entry (a real anchor to/witharia-currentonly on home) and the topbar has no breadcrumb. All spaces has a compact, client-only search over loaded visible spaces (name, description and tags; case- and accent-insensitive AND tokens) that never changes the URL or calls the memory API and keeps its query across space navigation; it has no space/memory/embeddings summary, and the sidebar storage row always uses the global status. Search lives inside the open space via the header search input (/focuses it); there is no global search route, and/searchcanonicalizes to/(or the current space). A query orconfidencefilter opens the space-search view;tier/tiers/tagalone stay list filters. - In-space search clearing: clearing the query removes stale results and returns to the memory list. An already loaded list is reused when its filters still match.
2. Architecture
2.1 High-level flow
User → ./mind <command> [args] [--flag value]
↓
mind (Bash script at repo root)
↓
bun run src/mind.ts "$@"
↓
executeCommand(args, store, logger)
↓
CLI command registry (atomic command modules) → command-executor (dispatch)
↓
MindStore (SQLite) + Logger (stdout/stderr)- Entry:
src/mind.tscreates store/logger and delegates all command handling toexecuteCommandfromsrc/cli/command-executor.ts. - Commands: Declared as atomic modules in
src/cli/commands/*.tsand registered bysrc/cli/commands/index.ts.src/cli/command-executor.tsacts as dispatcher/registry. - Storage: All persistent data goes through the
MindStoreinterface (defined insrc/store/mind-store.ts), implemented bycreateSqliteStore(src/store/sqlite-store.ts). Uses bun's nativebun:sqlite. - FTS: Full-text search uses SQLite's FTS5 with a porter tokenizer. FTS is synced manually (bun:sqlite has a bug with content-sync triggers — see § 3).
- Output: All user-facing messages go through the
Loggerinterface (src/helpers/logger.ts), so tests can swap in a mock logger. - Web/API: The single canonical HTTP server is
src/api/server.ts(viamind serve), and it serves API routes plus static web files from theweb/tree.
2.2 Main modules and responsibilities
| Module | Path | Responsibility |
| Entry script | mind (Bash) | Resolve repo root, dispatch to src/mind.ts. |
| Entry module | src/mind.ts | Bootstrap store/logger and run CLI command executor. |
| CLI command modules | src/cli/commands/*.ts | Atomic command definitions/handlers grouped by domain (spaces, memories, tiers, links, search, status, tags, checkpoint, guide, migration, runtime). CLI search flags include --space (* = all), --tag, --tier, --detail, --limit (default 25, max 500), and --offset. |
| CLI executor | src/cli/command-executor.ts | Load command groups from src/cli/commands/index.ts, dispatch matched command, and render help sections. |
| Arg parser | src/cli/arg-parser.ts | Match CLI args to a shape (positional <param>, aliases a|b, --flag value), extract params + flags, render help. |
| Setup/runtime helpers | src/cli/setup.ts | Agent setup, detected integration refresh, and detached process management helpers for MCP/web servers. Uses a capability-driven adapter model (L1 MCP, L2 instruction injection, L3 hooks automation) plus a separate skill-installation surface, with explicit status (supported/unsupported/unverified) and visible fallback diagnostics. Skill installation follows an exact-name policy: only mind-management in a managed path is installed or updated, with or without the ownership marker (the marker is provenance, not authorization); other skills are never touched, and content-signature heuristics were removed. Updates replace SKILL.md atomically without persistent backups inside skill paths, preserve auxiliary files, use lstat/realpath, unlink foreign or broken symlinks and replace them without writing through them while the warning names the old target, and repair a non-directory managed path instead of raising ENOTDIR; ancestor-repair and agent config backups remain outside skill paths, and historical skill backups are not auto-deleted. OpenCode/Claude/Codex/Pi L2 injection renders an activation pointer from the shared activation text, while preserving idempotent/non-destructive managed-file behavior. The complete protocol lives in the installed mind-management skill; MCP initialize.instructions is the same activation pointer and system_instructions is the full fallback. Pi is wired at ~/.pi/agent/mcp.json with a managed ~/.pi/agent/AGENTS.md pointer and the shared ~/.agents skill, without a Pi plugin. Cursor setup writes the documented {version:1,hooks:{...}} envelope with sessionStart, preCompact, sessionEnd, and stop; event payloads, argv, and execution stay unverified, so Cursor L3 is not claimed functional. All reads and writes of user-owned agent config files go through the safe-config helpers in src/setup/safe-config.ts so parse failures abort the run and content changes are backed up and atomic. |
| Safe config I/O | src/setup/safe-config.ts | readJsonOrThrow / readJsoncOrThrow parse existing JSON/JSONC strictly and throw MalformedConfigError on failure (callers abort). backupIfExists produces timestamped sibling backups before content-changing writes. atomicWriteText / safeWriteJson / safeWriteJsonc stage writes in a sibling .tmp file and rename them into place. safeWriteJsonc uses jsonc-parser.modify to preserve comments and formatting when only existing top-level keys are modified. Backups are not pruned. |
| Shared helpers | src/helpers/*.ts | Shared helpers: logger, tag normalization, formatting/memory refs, markdown resource loading, RAG helpers, embedding provider registry/resolvers (src/helpers/embedding-providers.ts), shared memory-ref resolution (resolveRefWithFallback), link-building (buildLinkedMemoriesArray, mapLinkedSummariesToLinksFormat, transformLinkedSummary), and checkpoint-content (buildCheckpointContent, fetchCheckpointContent). |
| MindStore interface | src/store/mind-store.ts | Abstract interface for all data operations. |
| SQLite store | src/store/sqlite-store.ts | Full MindStore implementation using bun:sqlite. Uses repository factory pattern internally (6 repositories in src/store/repositories/). Handles tiers, LRU eviction, tags, links, FTS (standard + trigram), status, import, and search pagination (paginateSearchResults clamps limit to [1, SEARCH_MAX_LIMIT] = 500). Generates embeddings with awaited provider requests on add/update/move/patch when RAG is enabled. |
| Store repositories | src/store/repositories/*.ts | 6 focused repositories: SpaceRepository, MemoryRepository, LinkRepository, TagRepository, LogRepository, SearchRepository. SearchRepository runs the unified search pipeline: logically independent channels (phrase/all/any rungs, trigram substring, fuzzy, LIKE, token-set, semantic) executed sequentially on one synchronous SQLite connection, coverage-based admission, NOT exclusions, and fusion via search-fusion. Composed by sqlite-store.ts into the full MindStore. |
| Store search shared | src/store/shared/*.ts | Shared relevance internals: query-parser.ts (query AST + safe FTS5 MATCH builders + relaxation rungs), matching-tokenizer.ts (fold case/accents, split camelCase/acronym boundaries, plus the per-store write-generation counter that invalidates the P-A fuzzy vocabulary cache), search-fusion.ts (per-channel normalization, weights, agreement bonus, confidence buckets, compatibility search_method mapping, admission predicate), fts-helpers.ts (manual memories_fts and contentless memories_fts_trigram sync, plus the delete-all+repopulate recovery), and index.ts re-exports. |
| Migration safety | src/store/migration-safety.ts | Opens SQLite databases through the automatic migration safety wrapper. Existing outdated DBs are backed up with VACUUM INTO, migrated, validated, restored on migration/validation failure, and pruned to the latest 3 automatic backups per DB path. Fresh/current DBs don't create migration backups. |
| Schema | src/store/schema.ts | SQLite schema (tables, indexes, FTS5 tables). No triggers (see §3). initializeDatabase() function. Schema version 10 (migrates v1→v2→v3→v4→v5→v6→v7→v8→v9→v10; v9 adds memories_fts_trigram, v10 makes it contentless + remove_diacritics 1 and is the final consolidated schema — no search-term dictionary). |
| MCP server | src/mcp/server.ts | MCP stdio server using @modelcontextprotocol/sdk. Exposes tools across spaces, memories, links, checkpoints, and system categories. |
| MCP tools | src/mcp/tools/ | Tool declarations and wiring only: spaces.ts, memories.ts, links.ts, checkpoint.ts, status.ts, system.ts. Endpoint schemas live in src/mcp/schemas/<family>/<endpoint>.ts, endpoint handlers live in src/mcp/handlers/<family>/<endpoint>.ts, and MCP-only helpers (including YAML parity + JSON-schema conversion) live in src/mcp/helpers/. |
| API server | src/api/server.ts | Bun HTTP server that serves /api/* routes and static web files from web/ (SPA shell in web/public/index.html, frontend modules in web/src, styles in web/styles, assets in web/assets). |
| API router | src/api/router.ts | Route matcher/dispatcher for API endpoints. |
| API routes | src/api/routes/*.ts | Atomic REST route declarations grouped by domain (spaces, memories, search, status, logs). GET /api/spaces/:space/tags returns that space's distinct normalized memory tags, alphabetically sorted (empty for an unknown space), and feeds the shared All tags filter select. GET /api/search accepts q, space (* = all spaces), tag, tier, tiers (comma-separated, inclusive; tier stays compatible and tiers takes precedence), confidence, semantic (on/off), and limit/offset (default 25, max 500), returns additive X-Total-Count/X-Has-More headers, and result items carry additive score/confidence/methods fields. GET /api/memories/query accepts the same tier/tiers filter pair plus space, tag, from/to, and limit/offset. GET /api/spaces returns each space's additive tier_counts {t1,t2,t3} field (the three counts sum to memory_count), and MCP space_list includes the same field. Unknown /api/* routes return a JSON 404; the memory detail presenter strips embedding, fts_id, and space_id. |
| Config | src/config.ts | CONFIG.dataDir, CONFIG.dbPath, CONFIG.legacyJsonPath, CONFIG.rag. Respects MIND_DATA_DIR and MIND_DB_PATH env vars. TIER_LIMITS per-tier capacity constants. |
| Types | src/types.ts | All domain types: Space, Memory, Link, Tier, SearchResult, StatusResult, LegacyBrain, etc. |
| Helpers | src/helpers/*.ts | Shared helpers: logger, tag normalization, formatting/memory refs, markdown resource loading, and RAG helpers. |
| Protocol resources | src/resources/protocols/*.md | mind-cognitive-protocol.md is the single token-free canonical body (ORIENT, RECALL, LEARN, RELATE, MAINTAIN, HANDOFF). The installed mind-management skill is the complete artifact: frontmatter + load note + full body. L2 setup instructions and MCP initialize.instructions are activation pointers rendered from src/cli/skill-activation.ts; system_instructions is the complete fallback when the skill is not listed or cannot be loaded. |
| Sync (Autosync) | src/sync/ | Bidirectional file sync with file-based config: ConfigFileService (read/write .mind/config.yml), FileSyncService (manifest v2 DB→FS export and managed pruning), SyncCoordinator + withAutoExport (non-blocking auto-export decorator for CLI/API/MCP store mutations), AutoSyncService (file watcher/import), importer (shared file-to-DB import with metadata parity), status-diagnostics (manifest/filesystem/DB drift evaluation), ConflictResolver (db-wins/file-wins/latest-wins), FileWatcher, Frontmatter, and Normalizer. Spaces live in .mind/spaces/<hash>/ where hash = SHA256 truncated to 8 hex chars. Manifest v2 stores canonical content/metadata hashes and UTC timestamps for baseline dirty detection. Loop prevention uses per-space DB-origin locks in .mind/spaces/<hash>/.mind-sync/.syncing. MCP server auto-starts watchers for enabled spaces. |
| Web frontend | web/src/*, web/styles/*, web/assets/*, web/public/index.html | SPA for browsing, searching, and editing spaces and memories. Frontend runtime code is native ES modules in web/src/ with no build pipeline, split into api/ (fetch boundary), domain/ (pure models, presenters, sanitizer), views/ (DOM renderers), app/ (store, search controller, page composition, polling), and features/ (routing and graph math), with @ts-check + JSDoc and web/jsconfig.json type-checking. Styles use web/styles/tokens.css plus web/styles/components/ and main.css; static assets include the vendored marked renderer (web/assets/vendor/) and the self-hosted Lucide 0.547.0 icon sprite (web/assets/icons.svg, notices in web/assets/vendor/LICENSE.lucide). Command actions render that sprite through web/src/views/icon.js (no CDN or runtime icon package); visible labels stay by default, icon-only mobile controls keep accessible names, decorative icons are aria-hidden, and state/data marks stay icon-free. Routing covers home, spaces with in-space search and list/map views, and /logs, with deep-link/reload/back-forward restoration. The home view filters loaded visible spaces locally (name, description, tags) without a request and without replacing the search input. See docs/web-ui.md. |
- Search-state handling: the search controller clears stale results when filter state updates without a search request; the app reuses a matching loaded memory list after query clear.
Neural Map API/UI touchpoints:
GET /api/spaces/:space/graph?limit=<n>(implemented in memory routes)MindStore.getSpaceGraph(space, opts)backed by SQLite implementation- SPA view toggle (
List/Neural Map) with concentric tier rings (T1..T3), anchored pan/zoom, deterministic best-effort overlap mitigation, and click-to-fetch details via the existing memory detail endpoint - Node radius encodes combined in/out degree (square-root scale, 8.5–21 px, capped for dense graphs), and the link count is rendered inside the node with a fitted font (8–13 px) so it does not overflow
- Selection highlights incoming and outgoing incident edges, emphasizes neighbors, and mutes unrelated edges; dense maps always materialise every incident edge for the selected node even when the 200-edge context cap omitted it, as a transient DOM-only patch removed on deselect without a rebuild or refetch
- Graph search highlighting/dimming, "Only matches", and tier filters are applied client-side in v1; the map requests all available nodes (backend limit 1,000) and a backend-capped payload shows only a quiet truncation note, with no "Load full graph" action
- The SVG is
role="group"with roving-tabindex nodes (arrows/Home/End/Enter); an accessible table mirrors every rendered node, node aria-labels include "N links", small maps label every node (25-char truncation) and dense maps show only one transient hover/focus/selection label (24-char truncation), with the full name available to assistive technology - SPA URL contract and state sync for search/space/view/memory:
/(All spaces, first sidebar entry with no topbar breadcrumb),/spaces/{encodedSpace}?view=list|map&memory=&q=&tag=&tier=&tiers=1,3&confidence=&semantic(search is scoped to the open space), and/logs;/searchcanonicalizes to/or the current space
2.3 Data model
- Brain: A SQLite database (
mind.db) atdata/in the repo root (orMIND_DATA_DIR). - Space:
{ id: string (UUID), name: string, description: string, hidden: boolean, tags: string[], created_at, updated_at }. Identified by name (unique); UUID primary key for internal references. - Hidden spaces: Spaces can be marked hidden and are omitted from default
list; include them withlist --hidden. - Checkpoints: Session checkpoints are stored as tagged memories (
checkpointtag) in the same project space. - Memory:
{ id: string (UUID), space_name: string, name: string, content: string, tier: 1|2|3, pinned: boolean, access_count: number, last_accessed_at: string|null, tags: string[], embedding: Float32Array|null, created_at, updated_at, changed_at }. UUID primary identity;fts_id(number) is the SQLite FTS5 surrogate. Identified by(space_name, name). - Tier system:
- 🔴 T1 (hot) — frequently accessed (limit: 25/space)
- 🟡 T2 (warm) — default for new memories (limit: 50/space)
- 🔵 T3 (cold) — rarely used (unlimited capacity)
- Auto-promotion on CLI
read: each read promotes one tier up (T3→T2, T2→T1). Skipped silently if pinned or if destination is full and all are pinned. - LRU eviction: when a tier is full, the least-recently-used non-pinned memory is demoted one tier down (no cascading). T3 is unlimited, so no eviction from T3. If all memories in a tier are pinned,
addMemoryandpromotethrow an error;recordAccesspromotion silently skips. - New memories can be added to T1, T2, or T3 only.
- Pinned memories are immune to auto-promotion and LRU eviction.
- Link: Directional edge between two memories with a label (default:
"related"). Stored as(source_id TEXT, target_id TEXT, label)(UUID foreign keys). - Tags: Both spaces and memories can have multiple string tags. Tags are normalized on input: converted to lowercase, leading
#stripped, validated against allowed characters (a-z,0-9,-,_,.,:,/,=,+,@). Tags cannot be empty or contain spaces. Displayed with#prefix in CLI output. - FTS:
memories_fts(FTS5,porter unicode61) andmemories_fts_trigram(FTS5,trigram remove_diacritics 1, contentless, schema v10) are standalone virtual tables synced manually on add/update/delete.memories_ftspowers token/fuzzy matching via the porter tokenizer;memories_fts_trigrampowers substring matching for terms of 3+ characters and folds diacritics so accented and unaccented queries match both ways (R1). - Search pipeline: Search is one unified multi-channel pipeline (
SearchRepository.searchMemories) used by the CLI, MCP, and API. A parser builds a query AST ("phrases",OR,AND,NOT, trailing*); logically independent channels collect candidates (phrase/all/any rungs, trigram substring, fuzzy Damerau–Levenshtein ≤2, LIKE for sub-trigram terms, token-set coverage, and semantic when RAG is enabled) and execute sequentially on one synchronous SQLite connection; candidates pass a coverage-based admission gate; and a weighted fusion with an agreement bonus ranks them deterministically. Semantic-only candidates from natural-language queries can bypass the lexical gate at cosine ≥0.6; explicit operators remain lexical. Each result carries a normalizedscore, aconfidencebucket (high|medium|low), andmethodsprovenance. RAG-off search stays fully functional (the semantic channel is omitted); a query-time embedding failure opens a ~5-minute in-memory breaker. The embedding provider is selectable (openaidefault oropenrouter) without changing the ranking math; both providers produce 1536-dimension vectors, so stored embeddings stay compatible.
2.4 SQLite schema tables
| Table | Key columns | Notes |
meta | key, value | Tracks schema_version. |
spaces | id (TEXT PK), name (UNIQUE), description, hidden, timestamps | UUID primary identity. |
space_tags | space_name (FK), tag | Cascades on space rename/delete. |
memories | id (TEXT PK), space_id (TEXT FK → spaces.id), name, content, tier (CHECK tier BETWEEN 1 AND 3), pinned, access_count, last_accessed_at, embedding, fts_id (INTEGER UNIQUE), timestamps (created_at, updated_at, changed_at) | UUID primary identity; fts_id is SQLite FTS5 surrogate. UNIQUE on (space_id, name). Cascades on space delete/rename. |
memory_tags | memory_id (TEXT FK), tag | Cascades on memory delete. |
links | source_id (TEXT FK), target_id (TEXT FK), label | No self-links. Cascades on memory delete. |
idx_* | idx_memories_space_id, idx_memories_fts_id, idx_memories_space_id_name, idx_spaces_id | Performance indexes for lookups. |
memories_fts | FTS5 virtual table: name, content | Synced manually (no triggers). |
memories_fts_trigram | FTS5 virtual table: name, content (tokenize trigram remove_diacritics 1; content='', contentless_delete=1) | Standalone, synced manually (no triggers); schema v10. Contentless: reads return NULL, 'rebuild' is unsupported (recovery uses delete-all + repopulate). Folds diacritics (R1). Powers substring matching for terms of 3+ characters. |
fts_id_sequence | entity (TEXT PK), next_value (INTEGER) | Transactional FTS5 surrogate ID assignment. |
logs | id (PK), source, operation, level, input_data, output_data, error_message, caller_info, duration_ms, timestamp | Operation audit logging (fire-and-forget). |
3. Technical considerations
- Schema version: Current schema is version 10. Existing v1 databases (tier
CHECK (tier BETWEEN 1 AND 3)) are migrated automatically via a 12-step rename-and-recreate pattern inMIGRATE_V1_TO_V2. V2→V3 adds theembedding BLOBcolumn. V3→V4 addschanged_atand backfills it fromupdated_at. V4→V5 addsspaces.hiddenwith default0. V5→V6 adds thelogstable for operation auditing. V6→V7 removes T4 (frozen) tier; all T4 memories migrate to T3 which becomes unlimited. V7→V8 convertsspacesandmemoriesfrom INTEGER AUTOINCREMENT to UUID TEXT primary keys, addsmemories.fts_id(INTEGER) as local surrogate for SQLite FTS5 rowid, addsmemories.space_id(TEXT FK) normalizing the relationship tospaces, addsspaces.id(TEXT PK), adds thefts_id_sequencetable for transactional ID assignment. V8→V9 adds the standalonememories_fts_trigramFTS5 table (tokenizetrigram) repopulated frommemories. V9→V10 (final consolidated schema) recreatesmemories_fts_trigramin place withremove_diacritics 1+content=''+contentless_delete=1(R1 + size) and repopulates it. The intermediate schemas v10 (with a per-document search-term dictionary) and v11 (dictionary retired) were development-only and never published; the final v10 is functionally identical to that dev v11 and has no dictionary. There is no permanentv10→v11compatibility in the engine: dev databases still stamped version 11 are normalized to 10 with the opt-inscripts/normalize-dev-db.ts(copies only; refusesdata/mind.db). Every step runs under the migration-safety wrapper. - Migration safety: Store initialization detects existing DB schema version before migration. If the DB exists and is outdated, mind creates an automatic
*.migration-backup.*.dbbackup with SQLiteVACUUM INTO, runs migrations, validates the final schema version,PRAGMA quick_check, andPRAGMA foreign_key_check, and restores the backup if migration or validation fails. Fresh/current DBs skip migration backups, and automatic migration backups are pruned to the latest 3 per DB path. - Trigram index cost:
memories_fts_trigram(contentless, schema v10+) on the real corpus is about 19.9 MB after the contentless change — roughly 24 % smaller than the old non-contentless trigram (26.18 MB → ≈19.9 MB;−6.27 MB). On the synthetic scalability corpus at 50k the contentless index measures 111.70 MB vs 149.44 MB for the old engine (−25.3 %), and the compact DB drops from 268.37 MB to 230.63 MB (−14.1 %). These are host-specific measurements from the pre-optimization comparison; seedocs/search-engine.mdfor the current envelope anddocs/search-benchmarks.mdfor reproduction. - Semantic breaker: A query-time embedding failure (for example an expired key) opens an in-memory breaker with a ~5-minute TTL (
SEMANTIC_BREAKER_TTL_MSinsrc/helpers/rag.ts). While open, the semantic channel is skipped entirely so a failing provider cannot trigger a retry storm; lexical search is unaffected. - Bun and lockfile: The project runs and tests with Bun. Use
bun run,bun test, and Bun's built-in TypeScript + SQLite support. No separate compile step.bun.lockis the only root lockfile;package-lock.jsonwas removed and the release script has no npm-lock handling. The benchmark subproject ownsbenchmarks/agent-memory/bun.lock. - CI:
.github/workflows/main.ymlpins Bun 1.3.14 and, after a frozen install, runsbun audit --audit-level=high,bun run typecheck,bun run format:check,bun run lint, andbun test test/ web/test. The benchmark job runs its own frozen install plus the blocking high-severity audit, typecheck,bun test test, andbun test experiments. No paid stage runs in CI, and audit failures are never suppressed with|| trueorcontinue-on-error. On 2026-10-24 with Bun 1.3.14, the root audit (high and default levels) reports no advisories and the benchmark high-severity audit exits 0; the benchmark's default audit still reports one low@ai-sdk/provider-utilsadvisory through the pinned@opencode/sdk@2.0.28, which has no fix inside the current pin. CI triggers on every push (including branch names with/), every pull request, and manual dispatch. Hosted run evidence for a feature commit is recorded in its.pas/feature report; do not claim a green run until it is observed. - Checkpoint completion atomicity:
MindStore.completeCheckpointcreates the T3session-*summary, copies inbound and outbound links with labels and directions, and deletes the checkpoint in one synchronous SQLite transaction. A summary, link, or delete failure rolls back the entire transformation, leaving the checkpoint and original links intact, so a retry cannot duplicate the summary. Embedding generation runs after the commit and auto-export runs once.checkpoint-done.tsonly builds content and calls the store; MCP and CLI surfaces are unchanged. - bun:sqlite FTS5 bug: bun:sqlite (v1.2.10) cannot handle FTS5
content=tablesync triggers — any UPDATE or DELETE on the source table errors with "N values for M columns". Workaround:memories_ftsandmemories_fts_trigramare standalone FTS5 tables (nocontent=option, no triggers). Both are synced manually through theFtsHelperclass insrc/store/shared/fts-helpers.ts(insert/update/delete, mirrored across both indexes) fromaddMemory,updateMemory,deleteMemory,deleteMemoryByName,deleteSpace, andimportFromJson. Because the trigram index is contentless (content=''), FTS5's'rebuild'is unsupported; recovery usesdelete-all+ repopulate (recoverTrigramIndex). - Fuzzy channel (P-A, schema v10): the fuzzy recall channel generates candidates from the full folded document vocabulary, folded once and cached in memory per store and keyed by the store write generation (
storeGeneration/bumpStoreGenerationinsrc/store/shared/matching-tokenizer.ts, bumped by everyFtsHelperwrite). A steady-state search pays no SQL round-trip for candidate generation; a write can never leave a stale vocabulary behind. Expansions usebandedOsa(OSA ≤2 with a hard cap and early exit), a length band, a deterministic sorted order, and the documented prefix-3 rule (FUZZY_PREFIX_LENGTH = 3): a typo in the first three characters of a word is not recoverable. The per-documentsearch_terms/memory_termsdictionary was a development-only prototype (never published) whose storage/rebuild cost did not pay off at 50k; the final v10 does not include it. - Styling: Terminal output uses
ansi-stylesfor bold, colors, etc. Tests assert on the styled strings. - Config / storage path:
src/config.tsresolvesCONFIG.dbPathfromMIND_DB_PATHenv var (full path override) orMIND_DATA_DIRenv var +mind.db(defaults todata/at repo root). The web server usesMIND_DATA_DIR(or/datain Docker).data/is in.gitignore. HTTP idle timeouts are configurable viaMIND_MCP_IDLE_TIMEOUT(default 120s) andMIND_API_IDLE_TIMEOUT(default 30s). Log retention is configurable viaMIND_LOG_RETENTION_MINUTES(default 10080 minutes = 7 days). Web server port is controlled viaMIND_PORT(default: 30303). RAG is disabled by default; enable it withMIND_RAG=true.MIND_EMBEDDING_PROVIDERselects the embedding provider (openaidefault oropenrouter; invalid values disable RAG without fallback), and the per-provider API keys areOPENAI_API_KEY(OpenAI) andOPENROUTER_API_KEY(OpenRouter). - Setup behavior:
mind setupconfigures all supported agent integrations;mind setup <agent>targets one agent, andmind setup compatibilityprints the capability matrix. Agent setups are isolated: when one agent fails, its error is reported and the remaining agents still run, and the success summary is printed only when every agent succeeds.mind setup refreshreconfigures detected Mind-managed integrations by default without creating unrelated first-install configs. Detection includes existing Mind MCP config/stanza, managed protocol file/block, managed hook/plugin/script, or installed mind-management skill signal. Refresh also supports--dry-run,--all, and--agent <agent>. After a successful installer run,mind updatefirst runs the newly installedmind statuswhen a DB existed before the update to force automatic migration/restore, then runs detected integration refresh unless--no-refresh-integrationsis passed. Fresh installs with no DB skip the status step to avoid creating a DB. - Claude setup behavior:
mind setup claude-codedeep-merges~/.claude/settings.json, writes/refreshes~/.claude/instructions/mind-memory-protocol.md, and upserts a managed block in~/.claude/CLAUDE.mdpointing to that protocol. Managed-block/hook wiring now self-heals dirty duplicate entries on reruns, and setup removes known legacy per-agent protocol files to prevent regressions. L3 hook automation is opt-in (MIND_SETUP_CLAUDE_ENABLE_HOOKS=true) and non-blocking; failures fall back to manual workflow guidance. - Capability declarations beyond wired adapters: VS Code/Copilot, Antigravity, and Pi Agent are supported agents with L1 wiring; their L2/L3 and skill surfaces are documented honestly in
docs/agent-integration-matrix.md. - OpenCode setup behavior:
mind setup opencodedeep-merges existing JSON config (preserving unknown keys), configuresmcp.mindas local command transport (type: "local",command: ["<path-to-mind>", "mcp"]), writes/refreshes~/.config/opencode/instructions/mind-memory-protocol.md, and ensures that exact path is present exactly once as the first entry in the OpenCodeinstructionslist. Reruns sanitize dirty instruction lists (dedupe + remove known legacy protocol paths/files). L3 prudent session/compaction automation is default-on and non-blocking: setup writes a managed plugin at~/.config/opencode/plugins/mind-automation.jsthat handlessession.created,session.compacted, compaction continuity, and prudent session-end summaries with deterministic caps/idempotency. The generated plugin default-exports an OpenCode V2 definition (id+setup, usingctx.session.hook('context'|'compaction')andctx.event.subscribe) and also exposes V1server()hooks, so it loads on OpenCode V2 and on V1 builds that support object plugin entrypoints (1.18.29+); older V1 builds keep loading the plugin through the namedMindAutomationPluginexport. - OpenCode JSONC support:
mind setup opencodeprefers~/.config/opencode/opencode.jsoncoveropencode.jsonwhen both exist, never createsopencode.jsonifopencode.jsoncis already present, and creates a new file asopencode.jsonc(the JSONC superset of JSON that OpenCode accepts natively). The setup usesjsonc-parserto parse existing JSONC and to apply edits that preserve comments and formatting when only existing top-level keys are modified. Files that mix JSONC (e.g. with comments or trailing commas) and standard JSON are both supported. - Setup file safety (parse-safely / backup / atomic write): All setup flows that touch a user-owned agent config file (JSON, JSONC, and TOML) now go through
src/setup/safe-config.ts. JSON/JSONC covers opencode, claude fallback, cursor, windsurf/devin, gemini-cli, vscode/copilot, antigravity, and pi. TOML covers codex (~/.codex/config.toml), backed byBun.TOML.parsewith a feature-detect guard (no TOML npm dependency) and a newsafeWriteTomlhelper that mirrors the JSON/JSONC contract. The contract is: existing files are parsed strictly, and a parse failure never overwrites the malformed file with an empty default. A parse failure aborts that agent's setup with a clear error: a single-agentmind setup <agent>fails outright, while a baremind setupreports the failing agent and continues with the remaining agents. Content-changing writes are preceded by a timestamped sibling backup (<file>.bak.YYYYMMDDTHHMMSSmmmZ) holding the pre-write bytes, and the new content is staged in a sibling.tmpfile and renamed into place so a crash mid-write cannot leave a partial file. Backups are intentionally not pruned by setup — users can manage them by hand. The same contract applies tomind setup refreshand to the post-update integration refresh path.MalformedConfigError.parseris now'json' | 'jsonc' | 'toml'so callers can branch on the parser without losing type safety. - Cursor setup behavior:
mind setup cursordeep-merges~/.cursor/mcp.jsonfor L1 MCP and configures managed L3 hooks in~/.cursor/hooks.jsonusing the documented{ "version": 1, "hooks": { ... } }schema (events:sessionStart,preCompact,sessionEnd,stop) backed by a non-mutating shim script at~/.cursor/hooks/mind-session-continuity.sh. The shim does not create, overwrite, or complete checkpoints. Hook setup deduplicates dirty managed entries on reruns, migrates an older top-level event map, preserves unrelated keys, and remains non-blocking with explicit safe fallback messaging. L3 staysunverifiedbecause hook execution and payload shape were not live-tested. - Codex setup behavior:
mind setup codexwrites a local MCP stanza in~/.codex/config.tomlwithcommand = "<path-to-mind>"andargs = ["mcp"](stdio/local transport, no forced HTTP args), and upserts a managed Mind activation pointer block in~/.codex/AGENTS.mdnon-destructively. ProjectAGENTS.mdfiles must point to the skill and fallback instead of restating the protocol, because project files can override the global block. Reruns collapse duplicate managed blocks and remove known legacy per-agent protocol files. The Codex write path now goes through the TOML-aware safe-config pipeline (readTomlOrThrow+safeWriteTomlinsrc/setup/safe-config.ts, backed byBun.TOML.parsewith a feature-detect guard — no TOML npm dependency): existing files are parse-validated before any write, malformed TOML aborts the run without overwriting, content-changing writes are backed up, an outdated[mcp_servers.mind]stanza is replaced in place (preserving unrelated tables and comments), and a missing stanza is appended.isAgentIntegrationDetected('codex')dispatches oncfg.formatand usestomlFileHasMindMcpfor TOML agents so the detector no longer probesconfig.tomlwithJSON.parse. - Pi setup behavior:
mind setup piwrites~/.pi/agent/mcp.jsonwithmcpServers.mindover stdio, upserts a managed activation pointer block in~/.pi/agent/AGENTS.mdnon-destructively, and installs the shared~/.agents/skills/mind-managementskill while migrating only Mind-managed~/.pi/agent/skillsshadow copies. Pi documents extensions, but Mind does not install a Pi plugin and marks L3unverified. - Corrected integration paths: Windsurf/Devin writes
~/.config/devin/mcp_config.json(legacy~/.windsurf/mcp.jsonis detection-only); VS Code/Copilot writes portable~/.copilot/mcp-config.jsonwithmcpServers(VS Code-nativeserversis documented as an alternative and not written); Antigravity writes~/.gemini/config/mcp_config.jsonand uses~/.gemini/config/skills. Codex/Gemini/VS Code/Antigravity document hooks, but Mind implements no L3 automation for them. - Skill source of truth and protocol distribution: The single canonical body is
src/resources/protocols/mind-cognitive-protocol.md(token-free, six responsibilities, real tool examples). The installedmind-managementskill composes it throughskill-mind-management.mdandsrc/cli/mind-management-skill.ts; it is the single source of truth and agents load it unconditionally at session start and after compaction, before any Mind use. L2 setup payloads (mind-memory-protocol.template.md,src/cli/memory-protocol.ts) and MCPinitialize.instructions(viasrc/cli/skill-activation.tsandsrc/mcp/server.ts) are activation pointers only and do not contain the body.system_instructionscomposes the full body throughmind-system-instructions.mdandsrc/cli/system-instructions.tsand is the complete fallback at version2.3.0when the skill is not listed or cannot be loaded; the skill is the primary source of truth. ProjectAGENTS.mdfiles must point to the skill and the fallback and must not restate the protocol, because project files can override the global Codex block. The template renderer operates in strict mode: unresolved placeholders/conditionals (or leftover template tokens) throw errors for all render paths. Skill installation uses the exactmind-managementname in managed paths; the ownership marker is provenance.docs/skill-first-distribution.mdexplains the current model and installation policy, anddocs/agent-integration-matrix.mdrecords validation status (including free OpenCode discovery versus the unrun paid B11). - MCP YAML stage 1: Structured MCP tools now return one raw YAML text item serialized directly from the same payload exposed via
structuredContent. This is built throughsrc/mcp/helpers/yaml-response.ts(not hidden insrc/mcp/server.ts). Stage-1 exclusions remain text-only:system_instructions,space_delete,memory_delete,link_create, andlink_delete.checkpoint_queryincludes an expliciterrorfield (nullon success,{ code, message }on soft error), returns fullpendingtext without preview truncation, memory/checkpoint MCP payloads rely onchanged_atinstead of exposingcreated_at/updated_at, memory MCP payloads also omitaccess_count/last_accessed_at, andspace_getnow returns an orientation summary withoverview, changed-attrending_memoriesblocks per tier (bounded T3 preview plus total availability), areferencesblock of living references, and pluralactive_checkpointswhose checkpoint items reuse thecheckpoint_queryshape. - Testing: Backend/CLI tests live in
test/. Web-specific tests live inweb/test/. Both usebun:testand rely on:test-store.ts(test/mocks/test-store.ts): creates a temporary SQLite DB in/tmp/per test instance; returns{ store, cleanup }.mocked-logger.ts(test/mocks/mocked-logger.ts): captureslogInfo/logErrorfor assertions.- Backend/CLI test files include:
test/mind-store.spec.ts(store-level, including graph retrieval),test/migration-safety.spec.ts(automatic migration backup/restore/retention),test/api-routes.spec.ts(HTTP route-level behavior),test/command-executor.spec.ts(CLI-level),test/mcp-tools.spec.ts(MCP tools),test/mcp-yaml-content.spec.ts(stage-1 YAML parity + exclusions),test/setup-safe-config.spec.ts(safe config I/O: parse-failure abort, backup, atomic write, JSONC with comments/trailing commas),test/setup-opencode.spec.ts(OpenCode JSONC preference + safe writes + parse-failure abort),test/setup-capabilities.spec.ts(cross-agent safe writes + parse-failure abort),test/skill-installation.spec.ts(exact-name updates, no skill backups, symlink safety, extras, nine clients),test/checkpoint-atomicity.spec.ts(summary/link/delete rollback and retry),test/ci-workflow.spec.ts(format, audit, Bun pin, isolated installs),test/release-script.spec.ts(no npm-lock handling),test/memory-protocol-renderer.spec.ts,test/system-tools.spec.ts,test/template-renderer.spec.ts, andtest/arg-parser.spec.ts. Search-specific suites:test/query-parser.spec.ts(grammar/AST),test/search-fusion.spec.ts(fusion/confidence math),test/trigram-search.spec.ts(substring/R1 + contentless sync parity),test/fuzzy-search.spec.ts(P-A vocabulary cache + banded OSA + the documented prefix-3 limitation),test/search-consistency.spec.ts(cross-surface ranking),test/search-scenarios.spec.ts(v2 taxonomy + snapshot gate),test/search-eval.spec.ts(v1 immutable + v2 snapshot/ranking gate),test/search-diagnostics.spec.ts(diagnostics sink byte-equivalence + content-free payload), andtest/search-bench-smoke.spec.ts(structural smoke ofscripts/bench-search.ts). - Web test files use
happy-domfor DOM integration:web/test/search-view.spec.ts/search-page.spec.ts(search UI, filters, async states),web/test/memory-list-app.spec.tsandmemory-panel-app.spec.ts(list/panel wiring, focus, CRUD),web/test/modals-app.spec.ts(dialogs and validation),web/test/graph-view.spec.ts/graph-app.spec.ts(accessible graph, filtering, keyboard),web/test/logs-view.spec.ts/logs-app.spec.ts(filters, polling lifecycle, cap),web/test/responsive-navigation.spec.ts(drawer),web/test/design-system.spec.ts(tokens/contrast),web/test/neural-map-graph-math.spec.ts(zoom/layout/label math),web/test/spa-routing.spec.ts(URL contract parse/build),web/test/css-concern-separation.spec.ts,web/test/shell-markup.spec.ts, andweb/test/web-index-assets.spec.ts(deep-route-safe asset paths).bun run typecheckalso runstsc -p web/jsconfig.jsonoverweb/srcandweb/test;web/assets/vendor/marked.min.jsis vendored locally (no CDN). - Search reset behavior is covered by
web/test/search-controller.spec.ts(clears stale results without a request) andweb/test/search-app-wiring.spec.ts(restores the existing list after query clear). scripts/test-rag.sh: E2E integration test for RAG. RequiresOPENAI_API_KEY, makes real OpenAI API calls. UsesMIND_DB_PATHto create a temp DB. Run viamake test-ragor directly.
- Docker:
web/Dockerfilebuilds the web app;docker-compose.ymlruns it with volume./data(orBRAIN_DATA_DIR) mounted at/data, port 3000, andrestart: unless-stopped. - Dependencies: Production:
@modelcontextprotocol/sdk,ansi-styles,jsonc-parser,yaml,zod. Dev:@types/bunplus the lint/format toolchain. Peer:typescript ^5. The benchmark harness owns@opencode/sdk@2.0.28and its own lockfile underbenchmarks/agent-memory/; the root does not depend on it. Rootoverridespin patched transitive versions, includingbody-parser2.4.0, which clears GHSA-27r3-jxmh-p828 under Bun 1.3.14. The benchmark keeps one flat top-levelzodoverride,4.6.7, in itspackage.json(lockfileVersion 1), which clears GHSA-mrhx-c7xc-m3w5 and resolves every consumer, includinggitlab-ai-provider, to zod 4; the free benchmark suites and the no-paid smoke path passed, but no live GitLab provider call was verified. - Shell completion: The
mindbash script supports--completeflag, delegating tosrc/complete.ts. This file is not yet implemented.
4. Usage
4.1 Setup
bun install4.2 Running the CLI
From the project root:
./mind <command> [args] [--flag value]Example: ./mind help, ./mind create my-space "Description", ./mind search "auth" --tier 1.
The data/ directory and mind.db are created automatically on first run.
4.3 Running the Web Server
./mind serve start # Start HTTP server on port 3000
./mind serve start --port 8080 # Custom port
./mind serve start --detached # Run in background
./mind serve stop # Stop detached serverClearing the in-space search removes old results and returns to the memory list. If the loaded list still matches its filters, the app reuses it without another memory-list request.
4.4 Running the MCP Server
./mind mcp # Start MCP server (stdio transport)
./mind mcp start --http # Start MCP over HTTP (foreground)
./mind mcp start --http --detached # Start MCP over HTTP (background)
./mind mcp stop # Stop detached MCP serverAdd to your agent's MCP config:
OpenCode (~/.config/opencode/opencode.jsonc, or opencode.json if only the legacy file exists):
{
"mcp": {
"mind": {
"type": "local",
"command": ["/absolute/path/to/mind", "mcp"],
"enabled": true
}
},
"instructions": ["~/.config/opencode/instructions/mind-memory-protocol.md"]
}Claude Code (~/.claude/settings.json):
{
"mcpServers": {
"mind": {
"command": ["/path/to/mind", "mcp"],
"enabled": true
}
}
}4.5 Setting up agents
./mind setup # Configure all supported agents
./mind setup compatibility # Show agent integration compatibility
./mind setup claude-code # Auto-configure Claude Code
./mind setup opencode # Auto-configure OpenCode
./mind setup cursor # Auto-configure Cursor
./mind setup codex # Auto-configure Codex
./mind setup windsurf # Auto-configure Windsurf
./mind setup gemini-cli # Auto-configure Gemini CLI
./mind setup vscode # Auto-configure VS Code / GitHub Copilot
./mind setup antigravity # Auto-configure Antigravity
./mind setup pi # Auto-configure Pi Agent
./mind setup refresh # Refresh detected mind-managed integrations./mind setup compatibility prints an explicit capability matrix for all supported adapters plus non-wired declarations. It prints full per-level status/confidence/evidence/fallback diagnostics for each listed adapter, plus the separate skill path/strategy line. Cursor L3 uses the documented hooks schema but remains unverified; Codex, Gemini CLI, VS Code/Copilot, and Antigravity document hooks but Mind implements no L3 automation for them. Windsurf/Devin, VS Code/Copilot, and Antigravity use their corrected documented MCP paths, and Pi Agent is wired without a Pi plugin. ./mind setup refresh refreshes only detected Mind-managed integrations by default; use --dry-run, --all, or --agent <agent> to control the refresh.
4.6 Running tests
# Unit tests
bun test test/ web/test
# Web-only tests
bun test web/test
# RAG E2E integration test (requires OPENAI_API_KEY, makes real API calls)
make test-rag
# or directly:
OPENAI_API_KEY=sk-... ./scripts/test-rag.sh
# Search relevance evaluation suite (deterministic fixture corpus, no API key; CI-apt)
make search-eval
# Search benchmarks / differential (opt-in, NOT part of bun test)
make bench-search # fixture corpus
make bench-scalability CORPUS=1k|10k|50k|100k
make search-diff # old-vs-new per-query comparison
# Agent memory benchmark (subproject; free tests run in CI; see benchmarks/agent-memory/README.md)
cd benchmarks/agent-memory && bun install --frozen-lockfile
cd benchmarks/agent-memory && bun test test # unit + contract (integration skipped)
cd benchmarks/agent-memory && bun test experiments
# free platform/isolation probes:
make bench-agent-memory-probe
# paid stages require --budget and are not runnable until later tasks:
# make bench-agent-memory-smoke | -locomo | -scenarios | -full | -report
# make bench-agent-memory-clean [ALL=1] # remove run dirs (ALL=1 also removes worktrees)
# Maintainer release flows
make release-patch
make release-minor
make release-major
make release-simulate TYPE=patch
./scripts/release.sh minor --notes-file docs/release-notes/v1.5.0.mdSearch benchmark methodology and reproducibility: docs/search-benchmarks.md.
OmniMemEval / LongMemEval-S lives under benchmarks/omnimemeval/.
The external 500-question answer-quality benchmark uses a pinned official
harness with a thin Mind adapter and can only be started with
.github/workflows/omnimemeval-mind.yml (workflow_dispatch).
It is paid and must never run on push, pull request, or routine CI.
OmniMemEval uses GPT-6 Luna low for both answerer and judge; results are
not directly comparable to the original GPT-4o-mini-judged published results.
The independent agent-memory paid harness also pins OpenRouter GPT-6 Luna
with variant low instead of its previous DeepSeek V4.1 Flash default.
The OmniMemEval manual workflow accepts rag_mode=off|on; RAG-on must
index and query embeddings through OpenRouter, and fail rather than silently
behave as RAG-off. Runs check the available OpenRouter key budget before
installing benchmark dependencies. The README reports the completed 120-question stratified pilot separately
from competitors' 500-question published results; the 500-question Mind
attempt was incomplete because of the OpenRouter key usage limit. Do not
present this as an official rank. The separate agent-memory benchmark and
search-relevance/latency harnesses are intentionally preserved.
The agent memory benchmark (benchmarks/agent-memory/) is a separate,
opt-in harness that compares OpenCode with and without Mind over a LoCoMo subset
and agent scenarios; its README documents isolation, budget policy and how to
add another engine. It is an independent Bun subproject with its own
package.json, bun.lock, and tsconfig.json, and it declares
@opencode/sdk@2.0.28 itself; the root project is not a workspace and does not
install those dependencies. Free unit, contract, and experiment suites run in
CI; paid stages never do. Every mind-current A2 and B run applies the real
<checkout>/mind setup opencode once per isolated environment, while
mind-v9/mind-v10 and no-memory keep their original integration;
current-versus-historical comparisons therefore include skill and L2 overhead,
and paid budgets need re-approval. It has no production impact.
4.7 Migrating from legacy brain.json
./mind importReads data/brain.json (or $MIND_DATA_DIR/brain.json) and imports all spaces and memories into SQLite at tier 2.
4.8 CLI commands
| Intent | Command | Aliases | Params | Flags | Description |
| ------------------- | --------------------- | ------------------------------------------- | ------------------------------ | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | ---- | ------ | --- | --------------------- | --------- | ---------------------------------------- |
| Help | help | h | — | — | List all commands. |
| Create space | create | c | <space> <description> | --tags | Create a new space (comma-sep tags). |
| List spaces | list | ls, l | — | --tag, --hidden | List all visible spaces by default (optionally include hidden). |
| List memories | list | ls, l | <space> | --tier, --tag | List T1+T2 memories in a space (use --tier 3 for cold). |
| Delete space | delete | d | <space> | — | Delete a space and all its memories. |
| Rename space | rename | rn | <old> <new> | — | Rename a space. |
| Describe space | describe | ds | <space> <description> | — | Change a space's description. |
| Update space | update | — | <space> | --description, --hidden, --no-hidden | Update space description and/or visibility. |
| Tag space | tag | t | <space> <tag> | — | Add a tag to a space. |
| Untag space | untag | — | <space> <tag> | — | Remove a tag from a space. |
| Add memory | add | a | <space> <name> <content> | --tags, --tier | Add a memory. |
| Read memory | read | r | <space> <name> | — | Print a memory (bumps access + auto-promote). |
| Edit memory | edit | e | <space> <name> <content> | — | Update a memory's content. |
| Remove memory | remove | rm | <space> <name> | — | Remove a memory by name. |
| Tag memory | tag | t | <space> <name> <tag> | — | Add a tag to a memory. |
| Untag memory | untag | — | <space> <name> <tag> | — | Remove a tag from a memory. |
| Promote | promote | up | <space> <name> | — | Move memory one tier up (T3→T2, T2→T1). |
| Demote | demote | down | <space> <name> | — | Move memory one tier down (T1→T2, T2→T3). |
| Pin | pin | — | <space> <name> | — | Pin a memory (immune to auto-promotion). |
| Unpin | unpin | — | <space> <name> | — | Unpin a memory. | | Link | link | — | <source> <target> | --label | Link two memories (space/name format). |
| Unlink | unlink | — | <source> <target> | — | Remove a link between memories. |
| Show links | links | — | <space> <name> | — | Show all links for a memory. |
| Search | search | s | <query> | --space, --tag, --tier, --detail, --limit, --offset | Unified relevance search across memories (fused ranking with per-result confidence). Grammar: quoted phrases, uppercase AND/OR/NOT operators, and a trailing * prefix. A supplied query with no informative term returns a validation error requiring a specific term. Default output includes memory ref, tier, changed timestamp, and [high\|medium\|low]. --detail adds content preview. --limit defaults to 25 and is capped at 500; --offset is zero-based. |
| Query | query | q | — | --space, --tag, --tier, --from, --to, --limit, --offset | Query memories by metadata/date with pagination (ordered by latest semantic memory changes). |
| Status (global) | status | — | — | — | Show storage info and per-tier breakdown. |
| Status (space) | status | — | <space> | — | Show tier breakdown for a specific space. |
| List tags | tags | tgs | — | --spaces, --memories | List all tags in the system (defaults to both). |
| Checkpoint set | checkpoint set | cp set | <space> <goal> <pending> | --notes, --linked-memories | Create or update an active checkpoint in the project space. |
| Checkpoint complete | checkpoint complete | cp complete, checkpoint done, cp done | <space> <name> <what> | — | Complete a checkpoint and transform it into a same-space session-* T3 summary in projects/<repo>. The checkpoint is deleted after the summary is created. |
| Checkpoint recover | checkpoint recover | cp recover | <space> | --name | Recover checkpoint by name (use checkpoint list first to find available checkpoints; output is JSON). |
| Checkpoint list | checkpoint list | cp list | <space> | --status | List checkpoints from the project space (filtered by checkpoint tag). |
| Session migration | migrate sessions | — | <space> | --dry-run | Explicitly migrate legacy sessions/<repo> summaries into projects/<repo> with deterministic naming and preserved links. |
| Guide | guide | g | — | — | Show usage guide (human mode). |
| Guide (mode) | guide | g | <mode> | — | Show guide (agent or human). |
| Import | import | — | — | — | Import legacy brain.json into SQLite. |
| Agent setup | setup | install | [<agent>] | — | Without an agent, configure every supported integration; with an agent, configure only that agent. |
| Compatibility | setup compatibility | install compatibility | — | — | Show the supported agents and their integration capability matrix. |
| Setup refresh | setup refresh | install refresh | — | --dry-run, --all, --agent | Refresh detected Mind-managed agent integrations without bulk-creating unrelated configs. |
| Update | update | — | — | --check, --version, --repo, --no-refresh-integrations | Update mind from GitHub releases, then refresh detected integrations unless opted out. |
| Sync init | sync init | — | — | — | Initialize .mind/ directory with config.yml and .gitignore. |
| Sync status | sync status | sync ls | — | --space | Show sync status for spaces. |
| Sync enable | sync enable | — | — | --space | Enable autosync for a project space. |
| Sync disable | sync disable | — | — | --space | Disable autosync for a space. |
| Sync now | sync now | — | — | --space | Force immediate sync (export + import). |
| Sync export | sync export | — | — | --space | Export space memories to markdown files. |
| Sync import | sync import | — | — | --space | Import markdown files into a space. |
| Sync conflict | sync conflict | — | — | --space, --strategy | Configure conflict resolution strategy. |
| Sync remove | sync remove | — | — | --space | Remove space from sync config. |
| Sync config | sync config | — | — | — | Show config file contents. |
| Sync serve | sync serve | — | — | --space | Start file watcher for a space (foreground). |
Note:
taganduntagare disambiguated by argument count: 2 positional args = space tag, 3 positional args = memory tag.
4.9 MCP Tools
The MCP server exposes 18 tools for agent integration:
Spaces (5 tools)
| Tool | Description |
space_create | Create a new space (requires tags) |
space_list | List all spaces |
space_get | Get a space by name; returns an orientation summary with overview counts, T1/T2/T3 previews with T3 availability, living references, and active checkpoints |
space_update | Update a space description |
space_delete | Delete a space and all its memories |
Memories (4 tools)
| Tool | Description |
memory_add | Add a memory to a space (requires tags); links_to is best-effort and returns links_created and links_failed arrays |
memory_read | Read + record access (auto-promote); returns links_to, linked_by, tier_change. Use noPromote:true to inspect without side effects. |
memory_update | Update name/content/tags, set pinned, or move one tier with tierTransition (promote/demote); tags replaces the existing set |
memory_delete | Delete a memory by space/name |
Query (1 tool)
| Tool | Description |
memory_query | Unified memory listing (use search parameter for full-text search; tier: null means all tiers). Search results always expose confidence (high|medium|low) plus total/limit/offset. Compact by default: score, methods, and the top-level search_method compatibility mapping (fts5/like/trigram/fuzzy/embeddings/mixed) appear only when the Mind MCP process sets USE_DEBUGGING_EXPANDED_TOOLS_RESPONSE=true (exact string); search_method stays absent when a search has no hits. Store/CLI/HTTP results keep all diagnostics |
The 00004 search optimization (R1 diacritic folding, contentless trigram, P-A fuzzy) did not change the CLI/MCP/API search contract: the channels, query grammar, result fields (score/confidence/methods), pagination, and search_method mapping are unchanged. Only recall and storage changed. See docs/search-engine.md for current behavior and docs/history/00004-search-optimization/search-optimization-report.md for the frozen measurements.
Links (2 tools)
| Tool | Description |
link_create | Create a directional link (source → target) with a label; re-creating the same pair replaces the label |
link_delete | Delete a directional link; an absent link is a no-op and memories are unaffected |
Checkpoint (4 tools)
| Tool | Description |
checkpoint_save | Create or update a checkpoint (goal, pending, notes, linked_memories). |
checkpoint_load | Restore a specific checkpoint by name. Returns full checkpoint text plus all linked_memories in memory_read format. |
checkpoint_query | Query checkpoints with filters: status, date range, tag, limit/offset, plus explicit soft-error reporting. |
checkpoint_done | Transform checkpoint to a same-space session-* T3 summary memory in projects/<repo> and delete the checkpoint |
System (2 tools)
| Tool | Description |
status | Get storage status |
system_instructions | Returns the complete Mind protocol (six responsibilities and tool examples); use it when the mind-management skill is not listed or cannot be loaded |
For stage 1 MCP content rendering, all structured tools above except system_instructions emit a single raw YAML text item that is semantically identical to structuredContent. Content-only tools (space_delete, memory_delete, link_create, link_delete) remain unchanged.
Every MCP tool call writes caller_info (agent, agentSource, clientName, clientVersion, transport, mcpSession). agent comes from MIND_AGENT, which mind setup writes into each agent's mind MCP entry, with the MCP initialize clientInfo.name as fallback; the web Logs table renders it in an Agent column. Attribution is observability only and implies no authorization.
4.10 Mind source of truth and memory protocol
The mind-management skill is the single source of truth for Mind. Load it
unconditionally at session start and after compaction, before any Mind use; do
not call a Mind MCP tool until it is loaded. AGENTS.md, MCP
initialize.instructions, tool descriptions, and these docs are activation
pointers only. If the skill is not listed or cannot be loaded, call
system_instructions and follow it.
When using mind via MCP, follow these conventions:
The full cognitive model is explained in docs/cognitive-memory-lifecycle.md, and current retrieval behavior is in docs/search-engine.md. The canonical six-responsibility protocol is src/resources/protocols/mind-cognitive-protocol.md.
Tags with prefixes:
type:project— project spacetype:user— user preferencestype:config— global configurationtype:learning— learned knowledgetype:session— session summariescat:decision— architectural decisioncat:bugfix— bug fixcat:pattern— established patterncat:discovery— technical discoverycat:preference— user preferencecat:config— configurationstatus:*— convention-only lifecycle tags, such asstatus:proposed,status:validated,status:failed,status:superseded,status:obsolete,status:final, andstatus:livingtype:reference+ exactly oneref:*+status:living— living reference memory tags
Space hierarchy (use repo name):
For software projects, use the repository/directory name as the space name (e.g.,
projects/mind,projects/arcana-web). This makes memories discoverable by future agents.
projects/<name>— one space per project- same-space session summaries live inside
projects/<name>assession-*memories taggedtype:session+cat:summaryat T3 user/preferences— global user preferencesuser/patterns— user patternsglobal/config— cross-project config
Tier usage:
- T1 (hot) — critical active info
- T2 (warm) — default for new memories
- T3 (cold) — unlimited
Memory quality guidance:
- Checkpoints are live/ephemeral work state.
- Session summaries are chronological recovery logs and evidence, not canonical truth.
- Durable/canonical memories are atomic actionable knowledge for future sessions.
- Living reference memories are maintained current-truth maps for project, architecture, style, domain, or workflow context.
- Create durable memories for stable decisions, verified root causes, final fixes, reusable patterns, user preferences, and significant config/domain facts.
- Avoid durable memories for transient observations, routine progress, or routine validation results with no new findings.
Living reference convention: use T2 by default, allow natural promotion to T1, and pin only 1–3 critical references when explicitly warranted or approved. Tags are authoritative: use type:reference, exactly one ref:* category tag, and status:living. Recommended refs are ref:project-map, ref:architecture, ref:domain, ref:workflow, ref:style, ref:key-decisions, and ref:known-pitfalls; the memory name is a readable stable kebab-case identifier such as architecture-overview, project-map, style-guide, domain-model, workflow-notes, key-decisions, or known-pitfalls. Include Purpose, Current truth, Key areas/files/concepts, Active conventions, Source memories, Last reviewed, and Maintenance notes. Update living references with memory_update when current truth changes.
Deletion guidance: delete only memories that are clearly obsolete, no longer applicable, and have no historical value. Otherwise, mark status:obsolete or status:superseded and link the replacement.
Continuity rule: link directly relevant memories for recovery continuity. memory_add with links_to is best-effort — check links_failed in the response.
4.11 Autosync (Experimental)
Mind can synchronize project spaces with .md files on the filesystem. The config is stored in .mind/config.yml and is versioned with git. Enabled spaces export automatically after successful CLI, API/web, or MCP DB mutations; export failures and conflicts are logged without reverting the primary DB operation.
Initialize sync:
mind sync initEnable a space:
mind sync enable --space projects/mindDirectory structure:
.mind/
├── config.yml # spaces config (VERSIONADO)
├── .gitignore
└── spaces/
├── a1b2c3d4/ # hash of "projects/mind"
│ ├── manifest.json
│ └── memory-1.md
└── ...Commands:
| Command | Description |
mind sync init | Initialize .mind/ directory |
mind sync status | Show configured spaces and drift summary |
mind sync enable --space <name> | Enable sync for a space |
mind sync disable --space <name> | Disable sync |
mind sync now --space <name> | Immediate sync |
mind sync export --space <name> | Export to files |
mind sync import --space <name> | Import from files |
mind sync conflict --space <name> --strategy <strategy> | Set conflict strategy |
mind sync remove --space <name> | Remove from sync |
mind sync config | Show config |
mind sync serve --space <name> | Start file watcher |
Conflict resolution strategies:
db-wins— DB version wins on real conflicts; only manifest-managed stale files are pruned.file-wins— file version wins on real conflicts; automatic DB→FS export skips conflicting files and logs a warning.latest-wins— hashes detect dirty sides first, then normalized UTC timestamps choose a winner. Near-future timestamps within 5 minutes are accepted for clock skew; farther future or invalid timestamps produce conservative warnings/skips.
Manifest v2 and conflicts: manifest entries track memory name, managed path, optional DB ID, canonical content and metadata hashes, normalized UTC timestamps, last file mtime, and last sync time. Hashes decide dirty state against the common baseline; file existence alone is not a conflict. Timestamps are for audit, ordering, and latest-wins tie-breaking only. mind sync status --space <name> reports DB/file/manifest counts, dirty DB and file counts, conflicts, tombstones, missing managed files, and the latest auto-export warning or error when available.
MCP integration: When MCP server starts, it auto-starts watchers for all enabled spaces.
config.yml format:
# mind autosync config
version: 1
# Spaces to sync with this project
# To enable a new space, add it below with enabled: true
# Valid conflictResolution values: db-wins, file-wins, latest-wins
spaces:
# projects/mind:
# enabled: true
# conflictResolution: db-winsLimitations:
- File deletion does not auto-delete from DB during watcher imports; missing managed files are reported as warning/drift by
sync statuswithout modifying the DB. - Existing-memory imports update supported metadata when file-to-DB wins: content, tags, tier, pinned state, and best-effort
links_to. Frontmatter names do not rename existing memories in this phase.
5. Keeping this document updated
If you modify this repo, keep AGENTS.md in sync with the code.
Changelog policy (mandatory):
- Every non-trivial change (features, behavior changes, architecture changes, bug fixes) must be added to
CHANGELOG.mdunder## [Unreleased]. - Release commands (
make release-patch,make release-minor,make release-major) require unreleased changelog entries and promoteUnreleasedto a versioned section. - Use
./scripts/release.sh <patch|minor|major> --notes-file <path>for curated GitHub release notes; omit--notes-fileto use GitHub generated notes. make release-simulate TYPE=patch|minor|majormust show what would happen without modifying files/tags/releases.- Changes to the
mindscript or completion: Update § 1, § 2.1, § 2.2, and § 4.2. - Changes to the web app or Docker: Update § 1, § 2.2, § 3, and § 4.3.
- New or removed commands: Update § 4.6 Commands and, if the architecture changes, § 2.1 / § 2.2.
- New modules or major refactors: Update § 2.2 Main modules and § 2.1.
- Config or storage changes: Update § 2.3 Data model, § 3, and § 4.
- New dependencies or runtime requirements: Update § 1 and § 3.
- New or removed test utilities: Update § 3 (Testing).
- Schema changes: Update § 2.4 SQLite schema tables.
After editing AGENTS.md, re-read the sections you changed to ensure they stay accurate and consistent with the rest of the document.
Before marking work done, use this checklist:
- Updated
AGENTS.mdif architecture/commands/config changed - Updated
CHANGELOG.mdunder## [Unreleased]for significant changes - Updated
README.mdif user-facing behavior/install/update/release flow changed
6. Documentation philosophy and maintenance
Documentation is part of the product. Treat it as a current map of the code, not as a record of every iteration.
Source of truth and status vocabulary
The code and tests are the source of truth for behavior. Documentation explains and points to them; it never overrides them. Use this vocabulary consistently:
- Living — describes current behavior and is maintained with the code.
- Historical — frozen evidence from a past feature. It is not current truth.
- Session — work-in-progress state or a task report; it belongs in
.pas/. - Unverified — implemented or documented, but not confirmed by a live run.
- Not run — prepared but not executed, especially for paid benchmark stages.
Never present a historical report or an unrun check as current behavior. Date
external claims and validation statements so readers can judge freshness. The
canonical agent protocol is src/resources/protocols/mind-cognitive-protocol.md;
living pages explain it but do not replace it.
Living versus temporal documentation
- Living pages live in
docs/and are indexed bydocs/README.md. They are the default place to explain current behavior. - Execution, merge, validation, and test reports belong in
.pas/and are not a permanent documentation surface. No feature is required to produce a permanent report, and a completed feature does not need a page indocs/. docs/history/is not an automatic archive. Retain a historical report there only when it has durable technical value, such as measured experiments, rejected alternatives, or open research questions that a living page does not reproduce. Every retained report is listed explicitly indocs/README.mdand keeps a two-line frozen banner naming the feature, the freeze date, and the living page that supersedes it.- Release notes live in
docs/release-notes/and are immutable; never move or rewrite them.
Documentation locations
| Content | Location |
| Documentation index | docs/README.md |
| Living behavior and concepts | docs/*.md |
| Exceptional retained evidence | docs/history/<feature>/*.md |
| Release history | docs/release-notes/*.md |
| User-facing install and usage | README.md |
| Project purpose and principles | docs/mind-philosophy.md |
| Contributor workflow | CONTRIBUTING.md |
| Agent architecture and guidance | AGENTS.md |
| Change log | CHANGELOG.md |
| Benchmark methodology | benchmarks/agent-memory/README.md |
| Generated benchmark report | benchmarks/agent-memory/REPORT.md |
Update before you create
Prefer updating the living page that already owns a topic. Create a new living
page only when the topic has a distinct audience or a clearly separate job that
would overload the existing page. Do not duplicate the same behavior across a
living page, README.md, and AGENTS.md; link to the canonical page instead.
Index and link maintenance
- Every living page must be linked from
docs/README.md. - Relative links must resolve, including links into
docs/history/,src/,test/, andbenchmarks/. - When you move or rename a page, update its inbound links in the same task.
- When you change a heading that is linked elsewhere, update the anchor.
test/docs-links.spec.tsenforces the invariants rather than a fixed list: the living index, retained-evidence links, frozen banners, non-empty Markdown, relative links, release notes, and the absence of temporal reports in the docs root. Do not add a filename to the test to make a report permanent.
Documentation update matrix
| Change | Update |
| User-facing behavior or setup | README.md and the owning living page |
| Architecture, commands, schema, config | AGENTS.md |
| Search behavior, limits, or performance | docs/search-engine.md and docs/search-benchmarks.md |
| Agent setup or capability status | docs/skill-first-distribution.md and docs/agent-integration-matrix.md |
| Verification process | docs/verification-harness.md |
| Non-trivial or user-visible change | CHANGELOG.md under ## [Unreleased] |
| Benchmark report format or links | benchmarks/agent-memory/src/report.ts and REPORT.md |
Historical evidence and benchmark reproducibility
Keep reproducible scripts and fixtures in the repository. Keep raw or host-local
artifacts external or under /tmp, and record only aggregate evidence. Historical
reports keep their original claims and measurements; do not rewrite them when
behavior changes. Instead, add or update the living page and point the historical
banner at it. There is no fixed list of retained reports: the docs test discovers
what remains under docs/history/ and checks that it is indexed. Treat
host-specific benchmark numbers as context, not contracts; document the method
and ratios, and regenerate before quoting absolutes.
Review checklist
- Living behavior changed? The owning living page is updated.
- A page moved? History banner, index, and inbound links are updated.
- New page? It is linked from
docs/README.mdand has a single clear job. - A report? It is in
.pas/unless it has durable technical value. - Claims dated or qualified where the evidence is external or unverified.
- No temporal report added to the
docs/root. bun test test/docs-links.spec.tspasses.CHANGELOG.mdandREADME.mdreflect user-visible changes.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

