@repomem/memory 0.0.0-stage → 0.1.1

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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +208 -2
  3. package/assets/kiro/hooks/repomem-validate.sh +10 -0
  4. package/assets/kiro/skills/repomem-distill/SKILL.md +56 -0
  5. package/assets/kiro/skills/repomem-memory/SKILL.md +41 -0
  6. package/dist/cli.d.ts +13 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +194 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/index.d.ts +7 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +43 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/schema.d.ts +97 -0
  15. package/dist/schema.d.ts.map +1 -0
  16. package/dist/schema.js +86 -0
  17. package/dist/schema.js.map +1 -0
  18. package/dist/search.d.ts +55 -0
  19. package/dist/search.d.ts.map +1 -0
  20. package/dist/search.js +160 -0
  21. package/dist/search.js.map +1 -0
  22. package/dist/server.d.ts +26 -0
  23. package/dist/server.d.ts.map +1 -0
  24. package/dist/server.js +176 -0
  25. package/dist/server.js.map +1 -0
  26. package/dist/setup/spec.d.ts +11 -0
  27. package/dist/setup/spec.d.ts.map +1 -0
  28. package/dist/setup/spec.js +44 -0
  29. package/dist/setup/spec.js.map +1 -0
  30. package/dist/store.d.ts +119 -0
  31. package/dist/store.d.ts.map +1 -0
  32. package/dist/store.js +350 -0
  33. package/dist/store.js.map +1 -0
  34. package/dist/validate.d.ts +42 -0
  35. package/dist/validate.d.ts.map +1 -0
  36. package/dist/validate.js +164 -0
  37. package/dist/validate.js.map +1 -0
  38. package/package.json +67 -4
  39. package/templates/context.md +25 -0
  40. package/templates/convention.md +16 -0
  41. package/templates/decision.md +20 -0
  42. package/templates/learning.md +16 -0
  43. package/templates/limitation.md +16 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nicolás Rickert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,209 @@
1
- # Temporary Holding Version
1
+ # @repomem/memory
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Your repo's memory, available to every AI tool your team uses.**
4
+
5
+ > npm package: [`@repomem/memory`](https://www.npmjs.com/package/@repomem/memory) ·
6
+ > CLI command: `repomem-memory`.
7
+
8
+ `@repomem/memory` is a local [Model Context Protocol](https://modelcontextprotocol.io)
9
+ (MCP) server that turns a `memory/` folder in your repository into searchable,
10
+ shared context for AI assistants. Decisions, conventions, limitations,
11
+ learnings and project context live as reviewable markdown files with structured
12
+ frontmatter, versioned with git and shared through normal pull requests. AI
13
+ tools can search and read them, and propose new entries as drafts that a human
14
+ approves in the same PR as the code change.
15
+
16
+ ## Why it exists
17
+
18
+ Teams accumulate hard-won context — why a library was chosen, which approach
19
+ failed, what a module is allowed to touch. That knowledge usually lives in
20
+ people's heads, scattered chat logs, or stale wiki pages that no AI tool can
21
+ see. `repomem` keeps it next to the code, in git, where both humans and AI
22
+ assistants can find it.
23
+
24
+ Design principles:
25
+
26
+ - **Markdown is the source of truth.** No external database, no derived index
27
+ committed to git.
28
+ - **The AI proposes, the human accepts.** AI-written entries are always created
29
+ as `draft` and reviewed in a pull request.
30
+ - **Zero native dependencies**, so `npx` works everywhere.
31
+ - **Tool-agnostic.** Works with Kiro, Claude Code, and any MCP client.
32
+
33
+ ## Quick start
34
+
35
+ Scaffold a `memory/` folder in your repo (no install needed, `npx` fetches it):
36
+
37
+ ```bash
38
+ npx --package @repomem/memory repomem-memory init
39
+ ```
40
+
41
+ Prefer a pinned local install? Add the package (the CLI bin is `repomem-memory`):
42
+
43
+ ```bash
44
+ npm install -D @repomem/memory
45
+ ```
46
+
47
+ Register the server with your AI tool (see [MCP client config](#mcp-client-config)),
48
+ then ask it to search or propose memory. Before committing, validate:
49
+
50
+ ```bash
51
+ npx --package @repomem/memory repomem-memory validate
52
+ ```
53
+
54
+ `validate` exits non-zero on any problem, so it fits in a pre-commit hook or CI.
55
+
56
+ ## Entry format
57
+
58
+ Entries live at `memory/<type>s/<slug>.md`. The `id` of an entry is its file
59
+ slug. Each file starts with YAML frontmatter:
60
+
61
+ ```markdown
62
+ ---
63
+ type: decision # decision | convention | limitation | learning | context
64
+ title: Use PostgreSQL as the primary data store
65
+ status: accepted # draft | accepted | deprecated (default: draft)
66
+ date: 2026-01-15 # ISO date
67
+ scope: project # project (default, repo-wide) or a module name (db, auth…)
68
+ author: platform-team # optional
69
+ tags: [database, architecture]
70
+ related_paths: # globs this entry relates to
71
+ - "src/db/**"
72
+ - "migrations/**"
73
+ # supersedes: old-entry-id # optional
74
+ # last_verified: 2026-02-01 # optional
75
+ ---
76
+
77
+ We chose PostgreSQL because the domain is relational and we rely on
78
+ transactional guarantees across several tables.
79
+ ```
80
+
81
+ | Field | Required | Notes |
82
+ |-----------------|----------|---------------------------------------------------|
83
+ | `type` | yes | One of decision, convention, limitation, learning, context |
84
+ | `title` | yes | Human-readable title; the slug is derived from it |
85
+ | `status` | no | Defaults to `draft` |
86
+ | `date` | yes | ISO date (`YYYY-MM-DD`) |
87
+ | `scope` | no | Free text; defaults to `project`. Use a module name (`db`, `auth`…) for module-specific entries. Complements `related_paths`. |
88
+ | `author` | no | Freeform |
89
+ | `tags` | no | Defaults to `[]` |
90
+ | `related_paths` | no | Globs; power `memory_for_path`. Defaults to `[]` |
91
+ | `supersedes` | no | Id of an entry this one replaces |
92
+ | `last_verified` | no | ISO date |
93
+
94
+ ## Tools
95
+
96
+ | Tool | What it does |
97
+ |---------------------|------------------------------------------------------------------------------|
98
+ | `search_memory` | Full-text search returning compact summaries (id, type, title, status, snippet). Excludes deprecated by default. Optional `type` and `tags` (OR) filters. |
99
+ | `get_memory` | Returns the full content of one entry by `id`. |
100
+ | `memory_for_path` | Returns entries whose `related_paths` globs match a file path. Prioritizes accepted over draft; excludes deprecated. |
101
+ | `propose_memory` | Creates a new entry, **always as `draft`**. Rejects duplicates, never overwrites. |
102
+ | `deprecate_memory` | Marks an entry `deprecated`, recording a reason and optional `superseded_by`. |
103
+
104
+ ## The propose-then-review workflow
105
+
106
+ 1. While working, an AI assistant proposes an entry with `propose_memory`. It
107
+ lands on disk as `status: draft`.
108
+ 2. The draft shows up in your working tree as a normal file change.
109
+ 3. You review it in the **same pull request** as the related code, edit if
110
+ needed, and flip `status` to `accepted`.
111
+ 4. `npx --package @repomem/memory repomem-memory validate` runs in CI to catch
112
+ malformed entries, dangling `supersedes` references, and accidentally
113
+ committed secrets.
114
+
115
+ Nothing becomes "accepted" memory without a human in the loop.
116
+
117
+ ## Root discovery
118
+
119
+ The memory root is resolved in this order:
120
+
121
+ 1. `--root <dir>` flag
122
+ 2. `MEMORY_ROOT` environment variable
123
+ 3. `<git root>/.repomem/memory`
124
+
125
+ The server re-checks file modification times before each search, so a
126
+ `git pull` is picked up without a restart.
127
+
128
+ ## MCP client config
129
+
130
+ ### Kiro — `.kiro/settings/mcp.json`
131
+
132
+ ```json
133
+ {
134
+ "mcpServers": {
135
+ "repomem": {
136
+ "command": "npx",
137
+ "args": ["-y", "--package", "@repomem/memory", "repomem-memory", "serve"],
138
+ "env": {},
139
+ "disabled": false,
140
+ "autoApprove": ["search_memory", "get_memory", "memory_for_path"]
141
+ }
142
+ }
143
+ }
144
+ ```
145
+
146
+ Instead of writing this by hand, run the one-step setup:
147
+
148
+ ```bash
149
+ npx --package @repomem/memory repomem-memory setup --agent kiro # from your repository root
150
+ ```
151
+
152
+ Or configure both repomem servers at once with the installer: `npx @repomem/cli setup`.
153
+
154
+ It installs a `repomem-memory` skill (how to record and recall memory), a
155
+ `repomem-distill` skill (how to distill a finished plan into durable entries as
156
+ its final step), an `agentSpawn` validate hook, a shared
157
+ `.kiro/agents/repomem.json` agent config, and merges the server into
158
+ `.kiro/settings/mcp.json`. The command is idempotent and never overwrites your
159
+ existing entries (pass `--force` to replace repomem's own entry). Only `kiro` is
160
+ supported today.
161
+
162
+ ### Claude Code — `.mcp.json`
163
+
164
+ ```json
165
+ {
166
+ "mcpServers": {
167
+ "repomem": {
168
+ "command": "npx",
169
+ "args": ["-y", "--package", "@repomem/memory", "repomem-memory", "serve"]
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ In both cases the server resolves its memory root from the git repository it
176
+ runs in. To point at a specific folder, add `"--root", "/path/to/memory"` to
177
+ `args` or set `MEMORY_ROOT` in `env`.
178
+
179
+ ## CLI
180
+
181
+ ```bash
182
+ repomem-memory serve [--root <dir>] # start the MCP server over stdio (what agents invoke)
183
+ repomem-memory init [--root <dir>] # scaffold memory/ with templates and a README
184
+ repomem-memory validate [--root <dir>] # validate frontmatter, supersedes refs, and scan for secrets
185
+ repomem-memory setup --agent kiro # install skills, hooks and MCP config for an agent
186
+ ```
187
+
188
+ `validate` returns a non-zero exit code on any error, for use in pre-commit and CI.
189
+
190
+ `setup` resolves the repository root via `--root` > `REPOMEM_REPO_ROOT` > the
191
+ enclosing git root, and writes under `.kiro/`.
192
+
193
+ ## Development
194
+
195
+ Requires **Node.js 22+**.
196
+
197
+ ```bash
198
+ npm install
199
+ npm run build # tsc -> dist/
200
+ npm test # vitest
201
+ npm run typecheck
202
+ ```
203
+
204
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the branching model, commit
205
+ conventions, and the test-driven workflow.
206
+
207
+ ## License
208
+
209
+ [MIT](./LICENSE)
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+ # repomem-validate.sh — validate the repository's memory folder.
3
+ #
4
+ # Wired as a Kiro `agentSpawn` hook by `repomem setup --agent kiro`. It runs on
5
+ # agent start to surface any invalid memory entries early. The exit code is not
6
+ # used to block (agentSpawn hooks only add stdout to context), so a failure here
7
+ # is informational.
8
+ set -euo pipefail
9
+
10
+ npx -y repomem validate
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: repomem-distill
3
+ description: How to distill a finished piece of work into durable repomem entries. Use as the FINAL STEP after executing a plan or completing a substantial task — review what the session produced and propose the decisions, learnings, limitations, and context worth keeping for next time.
4
+ ---
5
+
6
+ # repomem — distilling a session into memory
7
+
8
+ When you finish executing a plan or a substantial task, the valuable knowledge
9
+ lives only in this session: why you chose an approach, what surprised you, what
10
+ constraints you hit. Once the session ends, it is gone unless you write it down.
11
+ This skill is the final step of a plan: turn that knowledge into a small number
12
+ of durable `repomem` entries.
13
+
14
+ This is NOT about saving the plan. Do not persist the step-by-step plan, task
15
+ lists, progress logs, or any other ephemeral session state — that noise does not
16
+ belong in memory and the agent's own session already holds it. Distill only
17
+ knowledge that will still matter weeks from now.
18
+
19
+ ## When to run it
20
+
21
+ - As the explicit final step after completing a plan or a non-trivial task.
22
+ - When the user asks you to "record" or "distill" what was done.
23
+
24
+ ## What to distill
25
+
26
+ Review the session and identify, if any:
27
+
28
+ - **decisions** — non-obvious choices and the reasoning behind them.
29
+ - **learnings** — things that surprised you or cost time, worth remembering.
30
+ - **limitations** — new constraints or gotchas you discovered.
31
+ - **context** — project or module-level understanding that changed or is newly
32
+ worth writing down (what a thing is, why it exists, how it fits together).
33
+
34
+ If nothing durable came out of the work, propose nothing. A clean "no entries
35
+ needed" is a valid outcome — do not invent memory.
36
+
37
+ ## How to do it
38
+
39
+ 1. Reflect on what the session actually accomplished and changed.
40
+ 2. For each durable item, call `propose_memory` once, with:
41
+ - a clear, specific `title`,
42
+ - the right `type` (decision / convention / limitation / learning / context),
43
+ - meaningful `related_paths` so `memory_for_path` can surface it later,
44
+ - a `scope`: `project` for repo-wide knowledge, or a module name
45
+ (e.g. `db`, `auth`, `frontend`) for module-specific knowledge.
46
+ 3. Keep each entry focused: one decision/learning/limitation/context per file.
47
+ 4. **Never** mark an entry `accepted` yourself. Every entry is a `draft` for a
48
+ human to review and accept in the same pull request as the code.
49
+ 5. Remind the user to run `repomem validate` before committing.
50
+
51
+ ## Guidelines
52
+
53
+ - Prefer a few high-signal entries over many shallow ones.
54
+ - Write for a teammate (human or AI) who was not in this session.
55
+ - Reuse existing entries by proposing a `supersedes` reference when a decision
56
+ replaces an earlier one, rather than silently contradicting it.
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: repomem-memory
3
+ description: How to use the repomem MCP server to record and recall a repository's shared memory — decisions, conventions, limitations, and learnings. Use when you make a non-obvious choice worth remembering, when you need prior context before changing code, or when the user asks what the team already decided.
4
+ ---
5
+
6
+ # repomem — the repository's shared memory
7
+
8
+ repomem turns a `memory/` folder into searchable, git-versioned context served
9
+ over MCP. Entries are markdown files with structured frontmatter, grouped by
10
+ type: `decisions/`, `conventions/`, `limitations/`, `learnings/`.
11
+
12
+ ## When to use it
13
+
14
+ - **Before changing unfamiliar code**: search memory for related decisions and
15
+ limitations so you don't contradict an earlier choice.
16
+ - **After making a non-obvious decision**: propose a new entry so the rationale
17
+ survives beyond the current conversation.
18
+ - **When the user asks "why is it this way?"**: look it up instead of guessing.
19
+
20
+ ## The propose-then-review workflow
21
+
22
+ AI tools **propose** entries as drafts (`status: draft`). A human reviews and
23
+ **accepts** them in the same pull request as the related change. Never mark an
24
+ entry `accepted` yourself — leave it as a draft for review.
25
+
26
+ ## Tools
27
+
28
+ - `search_memory` — full-text search across all entries. Start here.
29
+ - `get_memory` — fetch a specific entry by slug.
30
+ - `memory_for_path` — find entries whose `related_paths` match a file you are
31
+ about to touch.
32
+ - Write tools propose new draft entries; prefer small, specific entries with a
33
+ clear title and `related_paths`.
34
+
35
+ ## Guidelines
36
+
37
+ - Keep entries focused: one decision/convention/limitation/learning per file.
38
+ - Always set meaningful `related_paths` so `memory_for_path` can surface the
39
+ entry later.
40
+ - Run `repomem validate` before committing — it checks frontmatter, supersedes
41
+ references, and scans for secrets.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cli.ts — `repomem-memory` command line.
4
+ *
5
+ * repomem-memory serve [--root <dir>] start the MCP server over stdio
6
+ * repomem-memory init [--root <dir>] scaffold the memory/ folder + templates
7
+ * repomem-memory validate [--root <dir>] check frontmatter, supersedes refs, secrets
8
+ * repomem-memory setup --agent <name> install skills, hooks and MCP config
9
+ *
10
+ * `validate` exits non-zero on any error so it can gate pre-commit and CI.
11
+ */
12
+ export declare function run(argv?: string[]): Promise<number>;
13
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AA8IH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDjF"}
package/dist/cli.js ADDED
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cli.ts — `repomem-memory` command line.
4
+ *
5
+ * repomem-memory serve [--root <dir>] start the MCP server over stdio
6
+ * repomem-memory init [--root <dir>] scaffold the memory/ folder + templates
7
+ * repomem-memory validate [--root <dir>] check frontmatter, supersedes refs, secrets
8
+ * repomem-memory setup --agent <name> install skills, hooks and MCP config
9
+ *
10
+ * `validate` exits non-zero on any error so it can gate pre-commit and CI.
11
+ */
12
+ import { promises as fs } from "node:fs";
13
+ import { existsSync } from "node:fs";
14
+ import path from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+ import { ENTRY_TYPES, TYPE_DIRS } from "./schema.js";
17
+ import { resolveMemoryRoot } from "./store.js";
18
+ import { validateRoot, formatReport } from "./validate.js";
19
+ import { main as startServer } from "./index.js";
20
+ import { runSetup } from "@repomem/core";
21
+ import { repomemSpec } from "./setup/spec.js";
22
+ const here = path.dirname(fileURLToPath(import.meta.url));
23
+ // Templates ship alongside dist/ at the package root: dist/cli.js -> ../templates
24
+ const TEMPLATES_DIR = path.resolve(here, "..", "templates");
25
+ function out(message) {
26
+ process.stdout.write(message + "\n");
27
+ }
28
+ function err(message) {
29
+ process.stderr.write(message + "\n");
30
+ }
31
+ function parseFlag(argv, name) {
32
+ const i = argv.indexOf(name);
33
+ if (i !== -1 && i + 1 < argv.length)
34
+ return argv[i + 1];
35
+ return undefined;
36
+ }
37
+ function hasFlag(argv, name) {
38
+ return argv.includes(name);
39
+ }
40
+ const MEMORY_README = `# Memory
41
+
42
+ This folder is your repository's shared memory, read and extended by AI tools
43
+ through the \`repomem\` MCP server.
44
+
45
+ Each entry is a markdown file with structured frontmatter, organized by type:
46
+
47
+ - \`decisions/\` — choices made and why
48
+ - \`conventions/\` — rules the team follows
49
+ - \`limitations/\` — known constraints and gotchas
50
+ - \`learnings/\` — lessons worth remembering
51
+ - \`contexts/\` — project and module-level context (what things are and why)
52
+
53
+ ## How it works
54
+
55
+ AI tools **propose** new entries as drafts (\`status: draft\`). A human reviews
56
+ and **accepts** them in the same pull request as the related change. Entries are
57
+ versioned with git — no external database.
58
+
59
+ Run \`npx --package @repomem/memory repomem-memory validate\` to check entries before committing.
60
+
61
+ See \`templates/\` for a starting point for each entry type.
62
+ `;
63
+ async function cmdInit(root) {
64
+ const created = [];
65
+ const skipped = [];
66
+ async function ensureDir(dir) {
67
+ if (existsSync(dir)) {
68
+ skipped.push(dir);
69
+ }
70
+ else {
71
+ await fs.mkdir(dir, { recursive: true });
72
+ created.push(dir);
73
+ }
74
+ }
75
+ await ensureDir(root);
76
+ for (const type of ENTRY_TYPES) {
77
+ await ensureDir(path.join(root, TYPE_DIRS[type]));
78
+ }
79
+ // README (never overwrite).
80
+ const readme = path.join(root, "README.md");
81
+ if (existsSync(readme)) {
82
+ skipped.push(readme);
83
+ }
84
+ else {
85
+ await fs.writeFile(readme, MEMORY_README, "utf8");
86
+ created.push(readme);
87
+ }
88
+ // Templates (never overwrite individual files).
89
+ const destTemplates = path.join(root, "templates");
90
+ await ensureDir(destTemplates);
91
+ for (const type of ENTRY_TYPES) {
92
+ const src = path.join(TEMPLATES_DIR, `${type}.md`);
93
+ const dest = path.join(destTemplates, `${type}.md`);
94
+ if (existsSync(dest)) {
95
+ skipped.push(dest);
96
+ continue;
97
+ }
98
+ try {
99
+ const content = await fs.readFile(src, "utf8");
100
+ await fs.writeFile(dest, content, "utf8");
101
+ created.push(dest);
102
+ }
103
+ catch {
104
+ err(`warning: template not found: ${src}`);
105
+ }
106
+ }
107
+ out(`Initialized memory at ${root}`);
108
+ if (created.length)
109
+ out(` created:\n${created.map((c) => ` + ${c}`).join("\n")}`);
110
+ if (skipped.length)
111
+ out(` already present (left untouched):\n${skipped.map((c) => ` = ${c}`).join("\n")}`);
112
+ return 0;
113
+ }
114
+ async function cmdValidate(root) {
115
+ if (!existsSync(root)) {
116
+ err(`No memory folder at ${root}. Run \`repomem-memory init\` first.`);
117
+ return 1;
118
+ }
119
+ const report = await validateRoot(root);
120
+ const text = formatReport(report, root);
121
+ if (report.ok) {
122
+ out(text);
123
+ return 0;
124
+ }
125
+ err(text);
126
+ return 1;
127
+ }
128
+ function usage() {
129
+ out([
130
+ "repomem-memory — your repo's memory for AI tools",
131
+ "",
132
+ "Usage:",
133
+ " repomem-memory serve [--root <dir>] Start the MCP server over stdio (default for agents)",
134
+ " repomem-memory init [--root <dir>] Scaffold the memory/ folder and templates",
135
+ " repomem-memory validate [--root <dir>] Validate entries (frontmatter, refs, secrets)",
136
+ " repomem-memory setup --agent <name> Install skills, hooks and MCP config for an agent",
137
+ "",
138
+ "Root resolution: --root > MEMORY_ROOT env > <git root>/.repomem/memory",
139
+ "setup root resolution: --root > REPOMEM_REPO_ROOT env > <git root>",
140
+ ].join("\n"));
141
+ }
142
+ export async function run(argv = process.argv.slice(2)) {
143
+ const command = argv[0];
144
+ if (!command || command === "--help" || command === "-h" || command === "help") {
145
+ usage();
146
+ return command ? 0 : 1;
147
+ }
148
+ // `setup` resolves the repository root (not the memory root), so handle it
149
+ // before the memory-root resolution below.
150
+ if (command === "setup") {
151
+ return runSetup(repomemSpec, {
152
+ agent: parseFlag(argv, "--agent"),
153
+ rootFlag: parseFlag(argv, "--root"),
154
+ force: hasFlag(argv, "--force"),
155
+ }, { out, err });
156
+ }
157
+ // `serve` starts the MCP server over stdio. This is what agents invoke
158
+ // through the generated mcp.json. It resolves its own memory root and runs
159
+ // until the transport closes, so it never returns a non-zero code here.
160
+ if (command === "serve") {
161
+ await startServer(argv.slice(1));
162
+ return 0;
163
+ }
164
+ let root;
165
+ try {
166
+ root = resolveMemoryRoot({ rootFlag: parseFlag(argv, "--root") });
167
+ }
168
+ catch (e) {
169
+ err(e.message);
170
+ return 1;
171
+ }
172
+ switch (command) {
173
+ case "init":
174
+ return cmdInit(root);
175
+ case "validate":
176
+ return cmdValidate(root);
177
+ default:
178
+ err(`Unknown command: ${command}`);
179
+ usage();
180
+ return 1;
181
+ }
182
+ }
183
+ // Only auto-run when invoked directly (not when imported by tests).
184
+ const invokedDirectly = process.argv[1] !== undefined &&
185
+ path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
186
+ if (invokedDirectly) {
187
+ run()
188
+ .then((code) => process.exit(code))
189
+ .catch((e) => {
190
+ err(`fatal: ${e.message}`);
191
+ process.exit(1);
192
+ });
193
+ }
194
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * index.ts — bootstrap. Wires the McpServer to a StdioServerTransport.
3
+ *
4
+ * All logging goes to stderr; stdout is reserved for the MCP protocol.
5
+ */
6
+ export declare function main(argv?: string[]): Promise<void>;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAqBH,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhF"}
package/dist/index.js ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * index.ts — bootstrap. Wires the McpServer to a StdioServerTransport.
3
+ *
4
+ * All logging goes to stderr; stdout is reserved for the MCP protocol.
5
+ */
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+ import path from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { resolveMemoryRoot } from "./store.js";
11
+ import { MemoryIndex } from "./search.js";
12
+ import { registerAllTools, SERVER_INFO } from "./server.js";
13
+ function log(message) {
14
+ process.stderr.write(`[repomem] ${message}\n`);
15
+ }
16
+ /** Read an optional `--root <path>` from argv. */
17
+ function parseRootFlag(argv) {
18
+ const i = argv.indexOf("--root");
19
+ if (i !== -1 && i + 1 < argv.length)
20
+ return argv[i + 1];
21
+ return undefined;
22
+ }
23
+ export async function main(argv = process.argv.slice(2)) {
24
+ const root = resolveMemoryRoot({ rootFlag: parseRootFlag(argv) });
25
+ log(`memory root: ${root}`);
26
+ const index = new MemoryIndex(root);
27
+ const server = new McpServer(SERVER_INFO);
28
+ registerAllTools(server, root, index);
29
+ const transport = new StdioServerTransport();
30
+ await server.connect(transport);
31
+ log("server ready on stdio");
32
+ }
33
+ // Only auto-run when invoked directly (e.g. `node dist/index.js`), not when
34
+ // imported (the CLI imports `main` to implement the `serve` subcommand).
35
+ const invokedDirectly = process.argv[1] !== undefined &&
36
+ path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
37
+ if (invokedDirectly) {
38
+ main().catch((err) => {
39
+ log(`fatal: ${err.message}`);
40
+ process.exit(1);
41
+ });
42
+ }
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE5D,SAAS,GAAG,CAAC,OAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,OAAO,IAAI,CAAC,CAAC;AACjD,CAAC;AAED,kDAAkD;AAClD,SAAS,aAAa,CAAC,IAAc;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClE,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IAE5B,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC;IAC1C,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAEtC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAC/B,CAAC;AAED,4EAA4E;AAC5E,yEAAyE;AACzE,MAAM,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS;IAC7B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEnE,IAAI,eAAe,EAAE,CAAC;IACpB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QAC5B,GAAG,CAAC,UAAW,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}