gnosys-mcp 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -245,18 +245,29 @@ ANTHROPIC_API_KEY = "your-key-here"
245
245
  | `gnosys_ask` | Ask a question, get a synthesized answer with citations |
246
246
  | `gnosys_reindex` | Rebuild semantic embeddings from all memories |
247
247
  | `gnosys_list` | List memories with optional filters |
248
+ | `gnosys_lens` | Filtered views — combine category, tag, status, confidence, date filters |
248
249
  | `gnosys_add` | Add a memory (LLM-structured) |
249
250
  | `gnosys_add_structured` | Add with explicit fields (no LLM) |
250
251
  | `gnosys_update` | Update frontmatter or content |
251
252
  | `gnosys_reinforce` | Signal usefulness of a memory |
252
253
  | `gnosys_commit_context` | Extract memories from conversation context |
254
+ | `gnosys_bootstrap` | Batch-import existing markdown documents |
253
255
  | `gnosys_import` | Bulk import from CSV, JSON, or JSONL |
254
256
  | `gnosys_init` | Initialize a new store |
255
- | `gnosys_maintain` | Run vault maintenance (decay, dedup, consolidation) |
256
- | `gnosys_dashboard` | System dashboard (memory count, health, graph, LLM status) |
257
+ | `gnosys_stale` | Find memories not modified within N days |
258
+ | `gnosys_history` | Git-backed version history for a memory |
259
+ | `gnosys_rollback` | Rollback a memory to a previous commit |
260
+ | `gnosys_timeline` | Show when memories were created/modified over time |
261
+ | `gnosys_stats` | Summary statistics for the memory store |
262
+ | `gnosys_links` | Show wikilinks and backlinks for a memory |
263
+ | `gnosys_graph` | Full cross-reference graph across all memories |
264
+ | `gnosys_maintain` | Run vault maintenance (decay, dedup, consolidation, archiving) |
265
+ | `gnosys_dearchive` | Force-dearchive memories from archive back to active |
266
+ | `gnosys_dashboard` | System dashboard (memory count, health, archive, graph, LLM status) |
257
267
  | `gnosys_reindex_graph` | Build/rebuild the wikilink graph |
258
268
  | `gnosys_stores` | Show active stores |
259
269
  | `gnosys_tags` | List tag registry |
270
+ | `gnosys_tags_add` | Add a new tag to the registry |
260
271
 
261
272
  ---
262
273
 
@@ -276,6 +287,7 @@ your-project/
276
287
  nvd-cves/
277
288
  cve-2024-1234.md
278
289
  gnosys.json # configuration
290
+ archive.db # two-tier memory archive (SQLite)
279
291
  .config/tags.json # tag registry
280
292
  CHANGELOG.md
281
293
  .git/ # auto-versioned
@@ -528,26 +540,70 @@ The `gnosys_maintain` MCP tool lets agents trigger maintenance programmatically
528
540
 
529
541
  ## Comparison
530
542
 
531
- | Feature | **Gnosys** | NotebookLM | Official MCP Memory |
532
- |---------|-----------|------------|-------------------|
533
- | Storage | Markdown files + Git | Google proprietary | JSON file |
534
- | Transparent/editable | ✅ Plain `.md` files | ❌ Opaque | ✅ But flat JSON |
535
- | Version history | Full Git history | | |
536
- | Obsidian vault | Native | | |
537
- | Bulk import | CSV/JSON/JSONL | Manual | |
538
- | MCP server | Native | | |
539
- | CLI | Full-featured | | |
540
- | Layered stores | 4 layers | | |
541
- | Wikilinks | Auto-generated | | |
542
- | Search | Hybrid: FTS5 + semantic + RRF | Proprietary | None |
543
- | Freeform Q&A | gnosys_ask with citations | Built-in | |
544
- | Self-hosted | | | |
545
- | LLM providers | 5 (Anthropic, Ollama, Groq, OpenAI, LM Studio) | Proprietary | No LLM |
546
- | Wikilink graph | Persistent JSON graph | | |
547
- | System dashboard | Pretty CLI + MCP tool | | |
548
- | Auto maintenance | Decay, dedup, consolidation | | |
549
- | Docker support | | | |
550
- | Price | Free / MIT | Free tier, then paid | Free |
543
+ Agent memory is a spectrum from a single markdown file to full knowledge graphs. Here's an honest look at the trade-offs.
544
+
545
+ | Aspect | Plain Markdown | RAG (Vector DB) | Knowledge Graph | **Gnosys** |
546
+ |--------|---------------|-----------------|-----------------|-----------|
547
+ | **Examples** | CLAUDE.md, .cursorrules | Mem0, LangChain Memory | Graphiti/Zep, Mem0 Graph | |
548
+ | **Storage** | `.md` files | Embeddings in vector DB | Nodes/edges in graph DB | `.md` files + SQLite index + SQLite archive |
549
+ | **Transparency** | Perfect | Lossy (embeddings) | High (query nodes) | High (readable markdown) |
550
+ | **Version history** | Git native | None built-in | None built-in | Git native |
551
+ | **Keyword search** | Manual / grep | BM25 layer (some) | BM25 layer (some) | FTS5 (built-in) |
552
+ | **Semantic search** | None | Vector similarity | Graph + vectors | Vector + FTS5 hybrid (RRF) |
553
+ | **Relationship traversal** | None | None | Multi-hop graph queries | Wikilinks (manual encoding) |
554
+ | **Automatic extraction** | No | Yes (embeddings) | Yes (entities + edges) | No (explicit structuring) |
555
+ | **Conflict detection** | No | No | Yes (graph rules) | No |
556
+ | **Scale comfort zone** | ~5K memories | 100K+ | 100K+ | 100K+ (two-tier: active `.md` + SQLite archive) |
557
+ | **Setup time** | < 5 min | 30 min 2 hours | 4 – 8 hours | 15 30 min |
558
+ | **Infrastructure** | None | Vector DB + embeddings API | Graph DB + LLM | SQLite (embedded) |
559
+ | **Human editability** | Excellent | Poor (re-embed) | Moderate | Excellent |
560
+ | **MCP integration** | Via skill files | Custom server | Mem0 ships MCP | MCP server (included) |
561
+ | **Obsidian compatible** | Partially | No | No | Yes (full vault) |
562
+ | **Cost** | Free | $0–500+/mo (cloud DB + embeddings) | $250+/mo (Mem0 Pro) or self-host | Free (MIT) |
563
+ | **Memory lifecycle** | Manual cleanup | Manual / TTL | Manual / TTL | Auto-archive + auto-dearchive on cite |
564
+ | **Offline capable** | Yes | Self-hosted only | Self-hosted only | Yes (Ollama/LM Studio) |
565
+
566
+ ### Where others genuinely win
567
+
568
+ - **Knowledge graphs** (Graphiti, Mem0 Graph) excel at multi-hop reasoning ("Who does Alice report to?") and automatic conflict detection. If your domain has clear entities and relationships — org charts, dependency trees, CRM data — a graph DB is the right tool.
569
+ - **RAG/vector search** handles fuzzy semantic matching without requiring explicit keyword clouds. You don't need to think about relevance fields — the embeddings handle conceptual similarity automatically.
570
+ - **Automatic extraction** in both RAG and graph approaches means the system learns from conversations without you explicitly structuring each fact.
571
+
572
+ ### Where Gnosys wins
573
+
574
+ - **Zero infrastructure**: No vector DB to deploy, no graph DB to manage. SQLite is embedded.
575
+ - **Full transparency**: Every memory is a readable, editable `.md` file. No opaque embeddings.
576
+ - **Git versioning**: Complete history, rollback, diff, blame. No other memory system versions every write.
577
+ - **Obsidian native**: Browse, edit, graph view, wikilinks — all with your existing Obsidian setup.
578
+ - **Hybrid search without a vector DB**: FTS5 keyword search is built-in. Semantic search is optional (local embeddings via Ollama, no API costs).
579
+ - **Bulk import**: CSV, JSON, JSONL. Turn a dataset into a searchable knowledge base in seconds.
580
+ - **Cost**: Genuinely free. No cloud service, no API costs if using local LLM providers.
581
+ - **Two-tier memory**: Active memories stay lightning-fast as markdown files. Old/low-confidence memories automatically archive to SQLite — and auto-dearchive when needed by search or ask.
582
+
583
+ ### Two-Tier Memory (Active + Archive)
584
+
585
+ Gnosys uses a two-tier architecture so your current work stays fast while safely growing to 100k+ memories:
586
+
587
+ **Active layer** — `.gnosys/<category>/*.md` — fast markdown files for day-to-day work.
588
+
589
+ **Archive layer** — `.gnosys/archive.db` — SQLite database for old or low-confidence memories.
590
+
591
+ The flow is fully automatic and bidirectional:
592
+ 1. `gnosys maintain --auto-apply` moves stale memories (>90 days unreinforced + confidence below 0.3) from active → archive
593
+ 2. Every search and ask query checks the archive if active results are insufficient
594
+ 3. Archived memories that get cited in an answer are automatically restored to active and reinforced
595
+
596
+ You can also force-dearchive with `gnosys dearchive "query"` or the `gnosys_dearchive` MCP tool.
597
+
598
+ Configure thresholds in `gnosys.json`:
599
+ ```json
600
+ {
601
+ "archive": {
602
+ "maxActiveDays": 90,
603
+ "minConfidence": 0.3
604
+ }
605
+ }
606
+ ```
551
607
 
552
608
  ---
553
609
 
@@ -558,30 +614,39 @@ gnosys --help # List all commands
558
614
  gnosys init # Initialize a new store
559
615
  gnosys add "raw input" # Add memory via LLM
560
616
  gnosys add-structured ... # Add memory with explicit fields
617
+ gnosys commit-context "..." # Extract memories from conversation
618
+ gnosys bootstrap <dir> # Batch-import existing markdown files
619
+ gnosys import <file> ... # Bulk import CSV/JSON/JSONL data
561
620
  gnosys discover "keywords" # Find relevant memories (metadata only)
562
621
  gnosys search "query" # Full-text search with snippets
563
622
  gnosys hybrid-search "q" # Hybrid keyword + semantic search
564
623
  gnosys semantic-search "q" # Semantic similarity search
565
624
  gnosys ask "question" # Ask a question, get cited answer
566
- gnosys reindex # Build/rebuild semantic embeddings
567
625
  gnosys read <path> # Read a specific memory
568
626
  gnosys list # List all memories
627
+ gnosys lens # Filtered views (category, tag, status, date...)
569
628
  gnosys update <path> ... # Update a memory
570
629
  gnosys reinforce <id> ... # Signal memory usefulness
571
630
  gnosys stale # Find stale memories
572
- gnosys commit-context "..." # Extract memories from conversation
573
- gnosys import <file> ... # Bulk import data
631
+ gnosys history <path> # Git-backed version history
632
+ gnosys rollback <path> <hash> # Rollback to a previous commit
633
+ gnosys timeline # Knowledge evolution over time
634
+ gnosys stats # Summary statistics
635
+ gnosys links <path> # Wikilinks and backlinks for a memory
636
+ gnosys graph # Full cross-reference graph
637
+ gnosys tags # List tag registry
638
+ gnosys tags-add # Add a new tag
639
+ gnosys reindex # Build/rebuild semantic embeddings
640
+ gnosys reindex-graph # Build/rebuild wikilink graph
574
641
  gnosys maintain # Run vault maintenance (dry run by default)
575
- gnosys maintain --dry-run # Preview changes without modifying
576
- gnosys maintain --auto-apply # Apply all maintenance automatically
642
+ gnosys maintain --auto-apply # Apply all maintenance + archiving automatically
643
+ gnosys dearchive "query" # Force-dearchive memories from archive to active
577
644
  gnosys dashboard # Pretty system dashboard
578
645
  gnosys dashboard --json # Dashboard as JSON
579
- gnosys reindex-graph # Build/rebuild wikilink graph
580
646
  gnosys config show # Show SOC configuration
581
647
  gnosys config set provider <name> # Set default provider
582
648
  gnosys config set task <task> <provider> <model> # Route task
583
649
  gnosys doctor # Full system health check (all providers)
584
- gnosys tags # List tag registry
585
650
  gnosys stores # Show active stores
586
651
  gnosys serve # Start MCP server (stdio)
587
652
  gnosys serve --with-maintenance # MCP server + maintenance every 6h
@@ -612,7 +677,8 @@ src/
612
677
  hybridSearch.ts # Hybrid search with RRF fusion
613
678
  ask.ts # Freeform Q&A with LLM synthesis + citations
614
679
  llm.ts # LLM abstraction — System of Cognition (5 providers)
615
- maintenance.ts # Auto-maintenance: decay, dedup, consolidation, reinforcement
680
+ maintenance.ts # Auto-maintenance: decay, dedup, consolidation, archiving
681
+ archive.ts # Two-tier memory: active ↔ archive (SQLite)
616
682
  dashboard.ts # Aggregated system dashboard
617
683
  graph.ts # Persistent wikilink graph (graph.json)
618
684
  tags.ts # Tag registry management
@@ -636,22 +702,20 @@ src/
636
702
 
637
703
  Real numbers from our demo vault (120 memories — 100 USDA foods + 20 NVD CVEs):
638
704
 
639
- | Metric | Gnosys | NotebookLM |
640
- |--------|--------|------------|
641
- | Import 100 records | 0.6s (structured) | Manual upload |
642
- | Cold start (first load) | 0.3s | ~5s (cloud) |
643
- | Keyword search | <10ms (FTS5) | Cloud-dependent |
644
- | Hybrid search (keyword + semantic) | ~50ms | N/A |
645
- | Reindex 120 embeddings | ~8s (first run: model download ~80 MB) | N/A |
646
- | Maintenance dry-run (120 memories) | ~2s | N/A |
647
- | Graph reindex (120 memories) | <1s | N/A |
648
- | Storage per memory | ~1 KB `.md` file | Opaque |
649
- | Embedding storage | ~0.3 MB for 120 memories | Cloud |
650
- | LLM providers | 5 (Anthropic, Ollama, Groq, OpenAI, LM Studio) | 1 (Google) |
651
- | Offline capable | ✅ (Ollama / LM Studio) | ❌ |
652
- | Test suite | 143 tests, 0 errors | N/A |
653
-
654
- All benchmarks on Apple M-series hardware, Node.js 20+. Import speed depends on mode — `structured` bypasses LLM entirely. LLM-enriched imports depend on provider latency.
705
+ | Metric | Result |
706
+ |--------|--------|
707
+ | Import 100 records (structured) | 0.6s |
708
+ | Cold start (first load) | 0.3s |
709
+ | Keyword search (FTS5) | <10ms |
710
+ | Hybrid search (keyword + semantic) | ~50ms |
711
+ | Reindex 120 embeddings | ~8s (first run downloads ~80 MB model) |
712
+ | Maintenance dry-run (120 memories) | ~2s |
713
+ | Graph reindex (120 memories) | <1s |
714
+ | Storage per memory | ~1 KB `.md` file |
715
+ | Embedding storage (120 memories) | ~0.3 MB |
716
+ | Test suite | 143 tests, 0 errors |
717
+
718
+ All benchmarks on Apple M-series hardware, Node.js 20+. Structured imports bypass LLM entirely. LLM-enriched imports depend on provider latency.
655
719
 
656
720
  ---
657
721
 
@@ -678,14 +742,6 @@ Gnosys is open source (MIT) and actively developed. Here's how to get involved:
678
742
 
679
743
  ---
680
744
 
681
- ## Roadmap
682
-
683
- See the [6-phase roadmap](https://gnosys.ai/roadmap) for what's next.
684
-
685
- **Have ideas?** [Join the discussion →](https://github.com/proticom/gnosys-mcp/discussions)
686
-
687
- ---
688
-
689
745
  ## License
690
746
 
691
747
  MIT — [LICENSE](LICENSE)
package/dist/cli.js CHANGED
@@ -1163,7 +1163,7 @@ program
1163
1163
  }
1164
1164
  const embeddings = new GnosysEmbeddings(storePath);
1165
1165
  const hybridSearch = new GnosysHybridSearch(search, embeddings, resolver, storePath);
1166
- const ask = new GnosysAsk(hybridSearch, cliConfig);
1166
+ const ask = new GnosysAsk(hybridSearch, cliConfig, resolver, storePath);
1167
1167
  if (!ask.isLLMAvailable) {
1168
1168
  console.error("No LLM provider available. Set ANTHROPIC_API_KEY or switch to Ollama: gnosys config set provider ollama");
1169
1169
  process.exit(1);
@@ -1453,10 +1453,53 @@ program
1453
1453
  console.log("");
1454
1454
  console.log(formatMaintenanceReport(report));
1455
1455
  });
1456
+ // ─── gnosys dearchive ───────────────────────────────────────────────────
1457
+ program
1458
+ .command("dearchive <query>")
1459
+ .description("Force-dearchive memories matching a query from archive.db back to active")
1460
+ .option("--limit <n>", "Max memories to dearchive", "5")
1461
+ .action(async (query, opts) => {
1462
+ const { GnosysArchive } = await import("./lib/archive.js");
1463
+ const resolver = await getResolver();
1464
+ const stores = resolver.getStores();
1465
+ if (stores.length === 0) {
1466
+ console.error("No Gnosys stores found. Run gnosys init first.");
1467
+ process.exit(1);
1468
+ }
1469
+ const writeTarget = resolver.getWriteTarget();
1470
+ if (!writeTarget) {
1471
+ console.error("No writable store found.");
1472
+ process.exit(1);
1473
+ }
1474
+ const archive = new GnosysArchive(writeTarget.path);
1475
+ if (!archive.isAvailable()) {
1476
+ console.error("Archive not available. Is better-sqlite3 installed?");
1477
+ process.exit(1);
1478
+ }
1479
+ const results = archive.searchArchive(query, parseInt(opts.limit));
1480
+ if (results.length === 0) {
1481
+ console.log(`No archived memories found matching "${query}".`);
1482
+ archive.close();
1483
+ return;
1484
+ }
1485
+ console.log(`Found ${results.length} archived memories matching "${query}":\n`);
1486
+ for (const r of results) {
1487
+ console.log(` • ${r.title} (${r.id})`);
1488
+ }
1489
+ console.log("");
1490
+ // Dearchive all found
1491
+ const ids = results.map((r) => r.id);
1492
+ const restored = await archive.dearchiveBatch(ids, writeTarget.store);
1493
+ archive.close();
1494
+ console.log(`Dearchived ${restored.length} memories back to active:`);
1495
+ for (const rp of restored) {
1496
+ console.log(` → ${rp}`);
1497
+ }
1498
+ });
1456
1499
  // ─── gnosys doctor ──────────────────────────────────────────────────────
1457
1500
  program
1458
1501
  .command("doctor")
1459
- .description("Check system health: stores, LLM connectivity, embeddings")
1502
+ .description("Check system health: stores, LLM connectivity, embeddings, archive")
1460
1503
  .action(async () => {
1461
1504
  const resolver = await getResolver();
1462
1505
  const stores = resolver.getStores();
@@ -1474,6 +1517,31 @@ program
1474
1517
  }
1475
1518
  }
1476
1519
  console.log("");
1520
+ // Check archive
1521
+ if (stores.length > 0) {
1522
+ console.log("Archive (Two-Tier Memory):");
1523
+ try {
1524
+ const { GnosysArchive } = await import("./lib/archive.js");
1525
+ const archive = new GnosysArchive(stores[0].path);
1526
+ if (archive.isAvailable()) {
1527
+ const stats = archive.getStats();
1528
+ console.log(` Archived memories: ${stats.totalArchived}`);
1529
+ if (stats.totalArchived > 0) {
1530
+ console.log(` Archive DB size: ${stats.dbSizeMB.toFixed(2)} MB`);
1531
+ console.log(` Oldest archived: ${stats.oldestArchived}`);
1532
+ console.log(` Newest archived: ${stats.newestArchived}`);
1533
+ }
1534
+ archive.close();
1535
+ }
1536
+ else {
1537
+ console.log(" Not available (better-sqlite3 not installed)");
1538
+ }
1539
+ }
1540
+ catch {
1541
+ console.log(" Not initialized");
1542
+ }
1543
+ console.log("");
1544
+ }
1477
1545
  // Check config — SOC routing
1478
1546
  const cfg = stores.length > 0 ? await loadConfig(stores[0].path) : DEFAULT_CONFIG;
1479
1547
  console.log("System of Cognition (SOC):");