@hasna/mementos 0.4.15 → 0.4.17

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
@@ -1,10 +1,10 @@
1
1
  # @hasna/mementos
2
2
 
3
- Universal memory system for AI agents. SQLite-backed with CLI, MCP server, and library API.
3
+ Universal memory system for AI agents. SQLite-backed with CLI, MCP server, REST API, and TypeScript library.
4
4
 
5
- Agents can save, recall, search, and share memories across sessions. Memories are scoped (global, shared, private), categorized, importance-ranked, and automatically injected into agent context.
5
+ Agents save, recall, search, and share memories across sessions. Memories are scoped (global/shared/private), categorized, importance-ranked, and injected into agent context on demand.
6
6
 
7
- ## Installation
7
+ ## Install
8
8
 
9
9
  ```bash
10
10
  bun add -g @hasna/mementos
@@ -14,261 +14,222 @@ bun add -g @hasna/mementos
14
14
 
15
15
  ```bash
16
16
  # Save a memory
17
- mementos save "preferred-language" "TypeScript" --scope global --importance 8
17
+ mementos save "project-stack" "Bun + TypeScript + SQLite" --scope shared --importance 8
18
18
 
19
19
  # Recall it
20
- mementos recall "preferred-language"
20
+ mementos recall "project-stack"
21
21
 
22
- # Search across all memories
23
- mementos search "typescript"
22
+ # Search
23
+ mementos search "typescript stack"
24
24
 
25
- # List memories with filters
26
- mementos list --scope global --importance-min 5
25
+ # Inject into agent context (compact = ~60% smaller)
26
+ mementos inject --format compact --project-id <id>
27
27
 
28
28
  # Get stats
29
29
  mementos stats
30
30
  ```
31
31
 
32
- ## Memory Scopes
33
-
34
- | Scope | Visibility | Use Case |
35
- |-------|-----------|----------|
36
- | `global` | All agents, all projects | Org-wide preferences, facts |
37
- | `shared` | All agents in a project | Project conventions, decisions |
38
- | `private` | Single agent only | Agent-specific context, history |
39
-
40
- ## Memory Categories
41
-
42
- | Category | Description |
43
- |----------|------------|
44
- | `preference` | Settings, choices, style preferences |
45
- | `fact` | Verified truths, known information |
46
- | `knowledge` | Learned patterns, insights, techniques |
47
- | `history` | Session context, conversation summaries |
48
-
49
- ## CLI Reference
32
+ ## MCP Server
50
33
 
51
- ### Global Options
34
+ ### Install into Claude Code (recommended)
52
35
 
53
- ```
54
- --project <path> Project context
55
- --json Output as JSON
56
- --agent <name> Agent identifier
57
- --session <id> Session context
36
+ ```bash
37
+ mementos mcp --claude
38
+ # Or manually:
39
+ claude mcp add --transport stdio --scope user mementos -- mementos-mcp
58
40
  ```
59
41
 
60
- ### Commands
42
+ ### Install into Codex / Gemini
61
43
 
62
44
  ```bash
63
- mementos save <key> <value> # Save a memory
64
- -s, --scope <scope> # global|shared|private (default: private)
65
- -c, --category <cat> # preference|fact|knowledge|history
66
- --importance <1-10> # Importance score (default: 5)
67
- --tags <t1,t2> # Comma-separated tags
68
- --summary <text> # Brief summary
69
- --ttl <ms> # Time-to-live in milliseconds
70
- --source <src> # user|agent|system|auto|imported
71
-
72
- mementos recall <key> # Get memory by key
73
- mementos list # List memories (with filters)
74
- mementos update <id> # Update memory fields
75
- mementos forget <key|id> # Delete a memory
76
- mementos search <query> # Full-text search
77
- mementos stats # Memory statistics
78
- mementos export # Export as JSON
79
- mementos import <file> # Import from JSON
80
- mementos clean # Remove expired + enforce quotas
81
- mementos inject # Output injection context
82
- mementos init <name> # Register agent
83
- mementos agents # List agents
84
- mementos projects # Manage projects
85
- mementos bulk <action> <ids> # Batch operations
45
+ mementos mcp --codex
46
+ mementos mcp --gemini
47
+ mementos mcp --all # all agents at once
86
48
  ```
87
49
 
88
- ## MCP Server
50
+ ### Available Tools (40+)
89
51
 
90
- ### Setup for Claude Code
52
+ **Memory:** `memory_save`, `memory_recall`, `memory_get`, `memory_list`, `memory_update`, `memory_pin`, `memory_archive`, `memory_forget`, `memory_search`, `memory_stats`, `memory_export`, `memory_import`, `memory_inject`, `memory_context`, `session_extract`
91
53
 
92
- Add to `~/.claude/.mcp.json`:
54
+ **Bulk:** `bulk_forget`, `bulk_update`
93
55
 
94
- ```json
95
- {
96
- "mcpServers": {
97
- "mementos": {
98
- "command": "mementos-mcp",
99
- "args": []
100
- }
101
- }
102
- }
103
- ```
56
+ **Agents:** `register_agent`, `list_agents`, `list_agents_by_project`, `get_agent`, `update_agent`
104
57
 
105
- ### Setup for Codex
58
+ **Projects:** `register_project`, `list_projects`, `get_project`
106
59
 
107
- Add to `.codex/mcp.json`:
60
+ **Knowledge Graph:** `entity_create`, `entity_get`, `entity_list`, `entity_delete`, `entity_merge`, `entity_link`, `relation_create`, `relation_delete`, `relation_list`, `graph_query`, `graph_path`, `graph_stats`
108
61
 
109
- ```json
110
- {
111
- "mcpServers": {
112
- "mementos": {
113
- "command": "mementos-mcp"
114
- }
115
- }
116
- }
62
+ **Meta:** `search_tools`, `describe_tools` (lean stubs — full docs on demand)
63
+
64
+ **Utility:** `clean_expired`
65
+
66
+ ## CLI Reference
67
+
68
+ ```bash
69
+ mementos save <key> <value> # Save/upsert a memory
70
+ mementos recall <key> # Get memory by key
71
+ mementos list # List memories (with filters)
72
+ mementos update <id> # Update memory fields
73
+ mementos pin <key|id> # Pin a memory
74
+ mementos forget <key|id> # Delete a memory
75
+ mementos search <query> # Full-text + fuzzy search
76
+ mementos stats # Memory statistics
77
+ mementos export # Export as JSON
78
+ mementos import <file> # Import from JSON
79
+ mementos clean # Remove expired + enforce quotas
80
+ mementos inject # Output injection context
81
+ mementos init <name> # Register agent
82
+ mementos agents # List agents
83
+ mementos projects # Manage projects
84
+ mementos bulk forget <ids> # Batch delete
85
+ mementos bulk update <ids> # Batch update
86
+ mementos diff <id> # Show memory version history
87
+ mementos doctor # Diagnose DB health
88
+
89
+ # Profiles — isolated DBs per context
90
+ mementos profile set work # Switch to work profile
91
+ mementos profile list # List all profiles
92
+ mementos profile get # Show active profile
93
+ mementos profile unset # Back to default
117
94
  ```
118
95
 
119
- ### Available Tools (19)
96
+ ## Profiles
120
97
 
121
- **Memory:** `memory_save`, `memory_recall`, `memory_list`, `memory_update`, `memory_forget`, `memory_search`, `memory_stats`, `memory_export`, `memory_import`, `memory_inject`
98
+ ```bash
99
+ # Each profile is an isolated DB: ~/.mementos/profiles/<name>.db
100
+ mementos profile set work
101
+ MEMENTOS_PROFILE=work mementos list # per-command
102
+ ```
122
103
 
123
- **Agents:** `register_agent`, `list_agents`, `get_agent`
104
+ ## REST API
124
105
 
125
- **Projects:** `register_project`, `list_projects`
106
+ ```bash
107
+ mementos-serve --port 19428
108
+ ```
126
109
 
127
- **Bulk:** `bulk_forget`, `bulk_update`
110
+ Default port: **19428**. Binds to `127.0.0.1` (localhost only). Override with `MEMENTOS_HOST=0.0.0.0`.
128
111
 
129
- **Utility:** `clean_expired`, `memory_context`
112
+ ### Key Endpoints
130
113
 
131
- ### Resources
114
+ | Method | Path | Description |
115
+ |--------|------|-------------|
116
+ | GET | `/api/memories?fields=key,value` | List memories (?fields, ?scope, ?session_id, ?status) |
117
+ | POST | `/api/memories` | Create/upsert memory |
118
+ | PATCH | `/api/memories/:id` | Update (version optional — auto-fetched) |
119
+ | DELETE | `/api/memories/:id` | Delete |
120
+ | POST | `/api/memories/search` | Full-text search |
121
+ | POST | `/api/memories/extract` | Auto-extract memories from session summary |
122
+ | POST | `/api/memories/bulk-forget` | Delete multiple |
123
+ | POST | `/api/memories/bulk-update` | Update multiple |
124
+ | GET | `/api/memories/stats` | Statistics |
125
+ | POST | `/api/memories/export` | Export with filters |
126
+ | GET | `/api/inject?format=compact` | Context injection (compact/markdown/json/xml) |
127
+ | GET/POST | `/api/agents` | Agent registry |
128
+ | PATCH | `/api/agents/:id` | Update agent (including active_project_id) |
129
+ | GET/POST | `/api/projects` | Project registry |
130
+ | GET | `/api/projects/:id/agents` | Agents active on a project |
131
+ | GET | `/api/profile` | Active profile info |
132
+ | GET | `/api/health` | Health check (includes profile, hostname) |
132
133
 
133
- - `mementos://memories` — All active memories
134
- - `mementos://agents` — Registered agents
135
- - `mementos://projects` — Registered projects
134
+ ## SDK
136
135
 
137
- ## Library API
136
+ ```bash
137
+ bun add @hasna/mementos-sdk
138
+ ```
138
139
 
139
140
  ```typescript
140
- import {
141
- createMemory,
142
- getMemoryByKey,
143
- listMemories,
144
- searchMemories,
145
- MemoryInjector,
146
- } from "@hasna/mementos";
141
+ import { MementosClient } from "@hasna/mementos-sdk";
147
142
 
148
- // Save a memory
149
- const memory = createMemory({
150
- key: "db-convention",
151
- value: "Always use snake_case for column names",
152
- scope: "shared",
153
- category: "preference",
154
- importance: 8,
155
- tags: ["database", "conventions"],
156
- });
143
+ const client = new MementosClient({ baseUrl: "http://localhost:19428" });
157
144
 
158
- // Recall
159
- const recalled = getMemoryByKey("db-convention", "shared");
145
+ // Save memory
146
+ await client.saveMemory({ key: "db-convention", value: "snake_case", scope: "shared" });
160
147
 
161
148
  // Search
162
- const results = searchMemories("database");
163
-
164
- // List with filters
165
- const memories = listMemories({
166
- scope: "global",
167
- category: "fact",
168
- min_importance: 5,
169
- limit: 20,
170
- });
149
+ const { results } = await client.searchMemories("database conventions");
150
+
151
+ // Context injection (compact format — 60% smaller)
152
+ const { context } = await client.getContext({ project_id: "...", format: "compact" });
171
153
 
172
- // Inject into agent context
173
- const injector = new MemoryInjector();
174
- const context = injector.getInjectionContext({
175
- agent_id: "my-agent",
176
- project_id: "my-project",
177
- max_tokens: 500,
154
+ // Sessions mementos integration
155
+ await client.extractFromSession({
156
+ session_id: "abc123",
157
+ title: "Fix auth middleware",
158
+ key_topics: ["jwt", "compliance"],
159
+ project_id: "...",
178
160
  });
179
161
  ```
180
162
 
181
- ## REST API
163
+ ## Agent-Project Binding
164
+
165
+ Track which agent is working on which project:
182
166
 
183
- Start the server:
167
+ ```typescript
168
+ // On session start
169
+ await client.updateAgent("my-agent", { active_project_id: "project-uuid" });
170
+
171
+ // Query: who's on this project?
172
+ const { agents } = await client.getProjectAgents("open-mementos");
173
+ ```
174
+
175
+ ## Context Injection
184
176
 
185
177
  ```bash
186
- mementos-serve --port 19428
178
+ # 60% smaller with compact format
179
+ mementos inject --format compact --project-id <id> --max-tokens 400
187
180
  ```
188
181
 
189
- ### Endpoints
182
+ MCP: `memory_inject(project_id="...", format="compact", max_tokens=400)`
190
183
 
191
- | Method | Path | Description |
192
- |--------|------|-------------|
193
- | GET | `/api/memories` | List memories |
194
- | POST | `/api/memories` | Create memory |
195
- | GET | `/api/memories/:id` | Get memory |
196
- | PATCH | `/api/memories/:id` | Update memory |
197
- | DELETE | `/api/memories/:id` | Delete memory |
198
- | POST | `/api/memories/search` | Search |
199
- | GET | `/api/memories/stats` | Statistics |
200
- | POST | `/api/memories/export` | Export |
201
- | POST | `/api/memories/import` | Import |
202
- | POST | `/api/memories/clean` | Cleanup |
203
- | GET/POST | `/api/agents` | Agents |
204
- | GET/POST | `/api/projects` | Projects |
205
- | GET | `/api/inject` | Injection context |
184
+ ## Sessions Integration
206
185
 
207
- ## Configuration
186
+ After ingesting a session (open-sessions):
208
187
 
209
- Config file: `~/.mementos/config.json`
188
+ ```bash
189
+ sessions remember <session-id> --mementos-url http://localhost:19428
190
+ # Creates: session-summary (history), session-topics (knowledge), session-notes (knowledge)
191
+ ```
210
192
 
193
+ REST:
211
194
  ```json
212
- {
213
- "default_scope": "private",
214
- "default_category": "knowledge",
215
- "default_importance": 5,
216
- "max_entries": 1000,
217
- "max_entries_per_scope": {
218
- "global": 500,
219
- "shared": 300,
220
- "private": 200
221
- },
222
- "injection": {
223
- "max_tokens": 500,
224
- "min_importance": 5,
225
- "categories": ["preference", "fact"],
226
- "refresh_interval": 5
227
- },
228
- "sync_agents": ["claude", "codex", "gemini"],
229
- "auto_cleanup": {
230
- "enabled": true,
231
- "expired_check_interval": 3600
232
- }
233
- }
195
+ POST /api/memories/extract
196
+ { "session_id": "abc", "title": "Fix auth", "key_topics": ["jwt"] }
234
197
  ```
235
198
 
236
- ### Environment Variables
199
+ ## Environment Variables
237
200
 
238
- | Variable | Description |
239
- |----------|------------|
240
- | `MEMENTOS_DB_PATH` | Override database path |
241
- | `MEMENTOS_DB_SCOPE` | Set to `project` for project-level DB |
242
- | `MEMENTOS_DEFAULT_SCOPE` | Default memory scope |
201
+ | Variable | Purpose | Default |
202
+ |----------|---------|---------|
203
+ | `MEMENTOS_DB_PATH` | Override DB path (bypasses profiles) | `~/.mementos/mementos.db` |
204
+ | `MEMENTOS_PROFILE` | Named profile → `~/.mementos/profiles/<name>.db` | none |
205
+ | `MEMENTOS_DB_SCOPE` | `project` = git root `.mementos/mementos.db` | global |
206
+ | `MEMENTOS_HOST` | Server bind address | `127.0.0.1` |
207
+ | `PORT` | Server port | `19428` |
243
208
 
244
- ## Database
209
+ ## Library
245
210
 
246
- SQLite with WAL mode. Path resolution:
247
-
248
- 1. `MEMENTOS_DB_PATH` environment variable
249
- 2. Nearest `.mementos/mementos.db` (walking up from cwd)
250
- 3. `~/.mementos/mementos.db` (global fallback)
211
+ ```typescript
212
+ import {
213
+ createMemory, getMemoryByKey, listMemories, searchMemories,
214
+ registerAgent, updateAgent, listAgentsByProject,
215
+ registerProject, getProject,
216
+ getActiveProfile, setActiveProfile,
217
+ MemoryInjector,
218
+ } from "@hasna/mementos";
219
+ ```
251
220
 
252
221
  ## Architecture
253
222
 
254
223
  ```
255
224
  src/
256
- ├── types/index.ts # Type definitions, enums, errors
257
- ├── db/
258
- │ ├── database.ts # SQLite setup, migrations, utilities
259
- │ ├── memories.ts # Memory CRUD with optimistic locking
260
- │ ├── agents.ts # Agent registration (8-char UUIDs)
261
- │ └── projects.ts # Project registry
262
- ├── lib/
263
- │ ├── config.ts # Configuration loading
264
- │ ├── search.ts # Full-text search engine
265
- │ ├── injector.ts # Context injection system
266
- │ ├── retention.ts # Auto-cleanup & quota enforcement
267
- │ └── sync.ts # Multi-agent memory sync
268
- ├── cli/index.tsx # CLI (Commander.js + chalk)
269
- ├── mcp/index.ts # MCP server (19 tools, 3 resources)
270
- ├── server/index.ts # REST API server
271
- └── index.ts # Library exports
225
+ cli/ Commander.js + Ink TUI — 20+ commands
226
+ mcp/ MCP server — 40+ tools (lean stubs)
227
+ server/ REST API 37+ endpoints (Bun.serve)
228
+ db/ SQLite (bun:sqlite) — memories, agents, projects, entities, relations
229
+ lib/ FTS5 search, injection, extraction, retention, config, profiles
230
+ types/ TypeScript interfaces and errors
231
+ sdk/ @hasna/mementos-sdk — zero-dep fetch client
232
+ dashboard/ React+Vite web UI
272
233
  ```
273
234
 
274
235
  ## License
package/dist/cli/index.js CHANGED
@@ -5674,21 +5674,24 @@ program2.command("mcp").description("Install mementos MCP server into Claude Cod
5674
5674
  for (const target of targets) {
5675
5675
  try {
5676
5676
  if (target === "claude") {
5677
- const configPath = pathJoin(home, ".claude", ".mcp.json");
5678
- let config = {};
5679
- if (fileExists(configPath)) {
5680
- config = JSON.parse(readFileSync3(configPath, "utf-8"));
5681
- }
5682
- const servers = config["mcpServers"] || {};
5677
+ const { execSync } = __require("child_process");
5683
5678
  if (opts.uninstall) {
5684
- delete servers["mementos"];
5679
+ try {
5680
+ execSync(`claude mcp remove mementos`, { stdio: "pipe" });
5681
+ console.log(chalk.green("Removed mementos from Claude Code MCP"));
5682
+ } catch {
5683
+ console.log(chalk.yellow("mementos was not installed in Claude Code (or claude CLI not found)"));
5684
+ }
5685
5685
  } else {
5686
- servers["mementos"] = { command: mementosCmd, args: [] };
5686
+ try {
5687
+ execSync(`claude mcp add --transport stdio --scope user mementos -- ${mementosCmd}`, { stdio: "pipe" });
5688
+ console.log(chalk.green(`Installed mementos into Claude Code (user scope)`));
5689
+ console.log(chalk.gray(" Restart Claude Code for the change to take effect."));
5690
+ } catch (e) {
5691
+ console.log(chalk.yellow("claude CLI not found. Run this manually:"));
5692
+ console.log(chalk.white(` claude mcp add --transport stdio --scope user mementos -- ${mementosCmd}`));
5693
+ }
5687
5694
  }
5688
- config["mcpServers"] = servers;
5689
- writeFileSync3(configPath, JSON.stringify(config, null, 2) + `
5690
- `, "utf-8");
5691
- console.log(chalk.green(`${opts.uninstall ? "Removed from" : "Installed into"} Claude Code: ${configPath}`));
5692
5695
  }
5693
5696
  if (target === "codex") {
5694
5697
  const configPath = pathJoin(home, ".codex", "config.toml");
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAukCH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkH9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAulCH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkH9C"}
@@ -2451,6 +2451,11 @@ addRoute("DELETE", "/api/memories/:id", (_req, _url, params) => {
2451
2451
  addRoute("GET", "/api/agents", (_req, url) => {
2452
2452
  const q = getSearchParams(url);
2453
2453
  const agents = q["project_id"] ? listAgentsByProject(q["project_id"]) : listAgents();
2454
+ if (q["fields"]) {
2455
+ const fields = q["fields"].split(",").map((f) => f.trim());
2456
+ const filtered = agents.map((a) => Object.fromEntries(fields.map((f) => [f, a[f]]).filter(([, v]) => v !== undefined)));
2457
+ return json({ agents: filtered, count: filtered.length });
2458
+ }
2454
2459
  return json({ agents, count: agents.length });
2455
2460
  });
2456
2461
  addRoute("POST", "/api/agents", async (req) => {
@@ -2493,8 +2498,14 @@ addRoute("PATCH", "/api/agents/:id", async (req, _url, params) => {
2493
2498
  return errorResponse(e instanceof Error ? e.message : "Update failed", 400);
2494
2499
  }
2495
2500
  });
2496
- addRoute("GET", "/api/projects", () => {
2501
+ addRoute("GET", "/api/projects", (_req, url) => {
2502
+ const q = getSearchParams(url);
2497
2503
  const projects = listProjects();
2504
+ if (q["fields"]) {
2505
+ const fields = q["fields"].split(",").map((f) => f.trim());
2506
+ const filtered = projects.map((p) => Object.fromEntries(fields.map((f) => [f, p[f]]).filter(([, v]) => v !== undefined)));
2507
+ return json({ projects: filtered, count: filtered.length });
2508
+ }
2498
2509
  return json({ projects, count: projects.length });
2499
2510
  });
2500
2511
  addRoute("POST", "/api/projects", async (req) => {
@@ -2626,6 +2637,11 @@ addRoute("GET", "/api/entities", (_req, url) => {
2626
2637
  if (q["offset"])
2627
2638
  filter.offset = parseInt(q["offset"], 10);
2628
2639
  const entities = listEntities(filter);
2640
+ if (q["fields"]) {
2641
+ const fields = q["fields"].split(",").map((f) => f.trim());
2642
+ const filtered = entities.map((e) => Object.fromEntries(fields.map((f) => [f, e[f]]).filter(([, v]) => v !== undefined)));
2643
+ return json({ entities: filtered, count: filtered.length });
2644
+ }
2629
2645
  return json({ entities, count: entities.length });
2630
2646
  });
2631
2647
  addRoute("POST", "/api/entities/merge", async (req) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/mementos",
3
- "version": "0.4.15",
3
+ "version": "0.4.17",
4
4
  "description": "Universal memory system for AI agents - CLI + MCP server + library API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",