memoryrail 0.1.0 → 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.
- package/README.md +14 -7
- package/dist/cli.js +6 -3
- package/dist/doctor.js +10 -1
- package/dist/sync.d.ts +2 -0
- package/dist/sync.js +6 -1
- package/docs/CLIENTS.md +163 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# MemoryRail
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/memoryrail)
|
|
4
|
+
[](https://github.com/OutVersus/memoryrail/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
**Git-native project memory for coding agents.** Website: [memoryrail.si](https://memoryrail.si)
|
|
4
8
|
|
|
5
9
|
Decisions, constraints, gotchas and failed attempts live in your repo as plain Markdown. People can read and review them in a PR. Any agent that speaks MCP (Claude Code, Cursor, Codex, Copilot, Aider, ...) can read and write them, and gets warned before it repeats a mistake.
|
|
6
10
|
|
|
@@ -45,14 +49,13 @@ Six types: `decision`, `constraint`, `gotcha`, `attempt` (tried and failed, with
|
|
|
45
49
|
|
|
46
50
|
## Install
|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
Needs Node 20 or newer.
|
|
49
53
|
|
|
50
54
|
```sh
|
|
51
|
-
|
|
52
|
-
npm install && npm run build && npm link # puts `memoryrail` on your PATH
|
|
55
|
+
npm install -g memoryrail # puts `memoryrail` on your PATH
|
|
53
56
|
```
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
Or run any command without installing, as `npx memoryrail <command>`. Note that `memoryrail install` registers the server as the command `memoryrail`, so that needs the global install; use `memoryrail install claude --npx` to register `npx -y memoryrail serve` instead.
|
|
56
59
|
|
|
57
60
|
## Quick start
|
|
58
61
|
|
|
@@ -69,6 +72,8 @@ git add .memoryrail AGENTS.md CLAUDE.md .mcp.json && git commit -m "Add project
|
|
|
69
72
|
|
|
70
73
|
## Connect an agent (MCP)
|
|
71
74
|
|
|
75
|
+
Setup for **Claude Code, Cursor, OpenAI Codex and GitHub Copilot** (VS Code, CLI and the cloud agent) is in [docs/CLIENTS.md](docs/CLIENTS.md). The short version for Claude Code and Cursor:
|
|
76
|
+
|
|
72
77
|
```sh
|
|
73
78
|
# Claude Code or Cursor, written into the repo's own config (keeps other servers)
|
|
74
79
|
memoryrail install claude # .mcp.json
|
|
@@ -116,7 +121,7 @@ memoryrail review | approve <id>... [--all] | reject <id>...
|
|
|
116
121
|
memoryrail config review [off|agents]
|
|
117
122
|
memoryrail handoff --summary <text> [--next <step>]... [--title ..] [--link ..]
|
|
118
123
|
memoryrail resume
|
|
119
|
-
memoryrail sync [--check]
|
|
124
|
+
memoryrail sync [--check] [--also <path>]...
|
|
120
125
|
memoryrail lint [--strict] [--no-git] [--json]
|
|
121
126
|
memoryrail doctor
|
|
122
127
|
memoryrail install <claude|cursor|all> [--npx]
|
|
@@ -156,7 +161,9 @@ memoryrail precheck --staged --fail || echo "Review the memories above before co
|
|
|
156
161
|
- **Search is lexical** (BM25 over title, tags, links and body, with a mild recency boost). It has no synonym or semantic matching, so `recall "database"` will not find a memory that only says "Postgres". Write titles that state the conclusion in the words you would search for, and use tags. Optional embeddings are planned.
|
|
157
162
|
- `maybe-stale` relies on git history; it is skipped outside a git repository.
|
|
158
163
|
- **The secret scanner is a pattern check, not a guarantee.** It catches common key formats and `password = ...` assignments, and it will miss secrets in unusual shapes. Treat it as a safety net, and don't paste credentials into memory.
|
|
159
|
-
- `install` configures Claude Code and Cursor only.
|
|
164
|
+
- `install` configures Claude Code and Cursor only. For Codex and Copilot, follow [docs/CLIENTS.md](docs/CLIENTS.md); those snippets come from the vendors' documentation and haven't been run against MemoryRail by us.
|
|
165
|
+
- Codex stops reading `AGENTS.md` after 32 KiB by default. `memoryrail doctor` warns when yours gets that large.
|
|
166
|
+
- This is an early release (0.x). The format and commands may change before 1.0, and it has had little use on real projects so far. Please open issues.
|
|
160
167
|
- The memory is only as good as what agents and people record. MemoryRail makes recording cheap and reviewable; it does not do it for you.
|
|
161
168
|
|
|
162
169
|
## Library
|
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { precheck } from "./precheck.js";
|
|
|
11
11
|
import { refOf } from "./refs.js";
|
|
12
12
|
import { recall, renderMemory } from "./search.js";
|
|
13
13
|
import { Store, DIR_NAME, initRoot, openStore, writeConfig } from "./store.js";
|
|
14
|
-
import { sync } from "./sync.js";
|
|
14
|
+
import { DEFAULT_TARGETS, sync } from "./sync.js";
|
|
15
15
|
import { VERSION } from "./version.js";
|
|
16
16
|
import { isMemoryType, MEMORY_TYPES } from "./types.js";
|
|
17
17
|
const HELP = `memoryrail ${VERSION} — git-native project memory for coding agents
|
|
@@ -48,6 +48,8 @@ Commands:
|
|
|
48
48
|
resume Print a prompt that brings a fresh agent up to speed
|
|
49
49
|
sync Write AGENTS.md, CLAUDE.md and .cursor/rules from memory
|
|
50
50
|
--check Exit 1 if generated files are out of date (for CI)
|
|
51
|
+
--also <path> Also write the block into this file (repeatable), e.g.
|
|
52
|
+
.github/copilot-instructions.md
|
|
51
53
|
lint Find stale links, duplicates, and broken files
|
|
52
54
|
--strict Treat warnings as errors --no-git --json
|
|
53
55
|
doctor Health check: valid, safe, synced, and reachable by agents
|
|
@@ -319,8 +321,9 @@ async function run(argv) {
|
|
|
319
321
|
return 0;
|
|
320
322
|
}
|
|
321
323
|
case "sync": {
|
|
322
|
-
const { values } = parse({ check: { type: "boolean" } });
|
|
323
|
-
const
|
|
324
|
+
const { values } = parse({ check: { type: "boolean" }, also: { type: "string", multiple: true } });
|
|
325
|
+
const targets = [...DEFAULT_TARGETS, ...(values.also ?? []).map((p) => ({ path: p }))];
|
|
326
|
+
const changes = sync(openStore(), { check: values.check, targets });
|
|
324
327
|
const pending = changes.filter((c) => c.action !== "unchanged");
|
|
325
328
|
for (const c of changes)
|
|
326
329
|
out(`${values.check && c.action !== "unchanged" ? "out of date" : c.action}: ${c.path}`);
|
package/dist/doctor.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { CLIENT_FILES, isInstalled } from "./install.js";
|
|
4
4
|
import { lint } from "./lint.js";
|
|
5
|
-
import { sync } from "./sync.js";
|
|
5
|
+
import { CODEX_DOC_LIMIT_BYTES, sync } from "./sync.js";
|
|
6
6
|
import { DIR_NAME, FORMAT_VERSION } from "./store.js";
|
|
7
7
|
/** One-shot health report: is memory present, valid, safe, synced and reachable by agents? */
|
|
8
8
|
export function doctor(store) {
|
|
@@ -42,6 +42,15 @@ export function doctor(store) {
|
|
|
42
42
|
add("warn", "sync", `${drift.map((d) => d.path).join(", ")} out of date; run \`memoryrail sync\``);
|
|
43
43
|
else
|
|
44
44
|
add("ok", "sync", "AGENTS.md, CLAUDE.md and Cursor rules are up to date");
|
|
45
|
+
try {
|
|
46
|
+
const bytes = fs.statSync(path.join(store.root, "AGENTS.md")).size;
|
|
47
|
+
if (bytes > CODEX_DOC_LIMIT_BYTES) {
|
|
48
|
+
add("warn", "size", `AGENTS.md is ${Math.round(bytes / 1024)} KiB; Codex stops reading it after 32 KiB by default. Archive stale memories or raise project_doc_max_bytes`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
/* no AGENTS.md yet; the sync check above already says so */
|
|
53
|
+
}
|
|
45
54
|
const wired = Object.keys(CLIENT_FILES).filter((c) => isInstalled(store.root, c));
|
|
46
55
|
if (wired.length)
|
|
47
56
|
add("ok", "agents", `MCP server registered for: ${wired.join(", ")}`);
|
package/dist/sync.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export interface SyncChange {
|
|
|
14
14
|
path: string;
|
|
15
15
|
action: "created" | "updated" | "unchanged";
|
|
16
16
|
}
|
|
17
|
+
/** Codex stops reading AGENTS.md after this many bytes by default (project_doc_max_bytes). */
|
|
18
|
+
export declare const CODEX_DOC_LIMIT_BYTES: number;
|
|
17
19
|
export declare function sync(store: Store, opts?: {
|
|
18
20
|
check?: boolean;
|
|
19
21
|
targets?: Target[];
|
package/dist/sync.js
CHANGED
|
@@ -60,11 +60,16 @@ function applyBlock(existing, block, preamble = "") {
|
|
|
60
60
|
return existing.slice(0, s) + block + existing.slice(e + END.length);
|
|
61
61
|
return existing.replace(/\s+$/, "") + `\n\n${block}\n`;
|
|
62
62
|
}
|
|
63
|
+
/** Codex stops reading AGENTS.md after this many bytes by default (project_doc_max_bytes). */
|
|
64
|
+
export const CODEX_DOC_LIMIT_BYTES = 32 * 1024;
|
|
63
65
|
export function sync(store, opts = {}) {
|
|
64
66
|
const block = renderBlock(store.list());
|
|
65
67
|
const changes = [];
|
|
66
68
|
for (const t of opts.targets ?? DEFAULT_TARGETS) {
|
|
67
|
-
const abs = path.
|
|
69
|
+
const abs = path.resolve(store.root, t.path);
|
|
70
|
+
if (!abs.startsWith(store.root + path.sep)) {
|
|
71
|
+
throw new Error(`refusing to write outside the repository: ${t.path}`);
|
|
72
|
+
}
|
|
68
73
|
const existing = fs.existsSync(abs) ? fs.readFileSync(abs, "utf8").replace(/\r\n/g, "\n") : null;
|
|
69
74
|
const next = applyBlock(existing, block, t.preamble);
|
|
70
75
|
if (existing === next) {
|
package/docs/CLIENTS.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Connect your agent
|
|
2
|
+
|
|
3
|
+
MemoryRail reaches an agent in two ways:
|
|
4
|
+
|
|
5
|
+
1. **The MCP server** (`memoryrail serve`): the agent calls tools like `precheck`, `recall` and `remember`. This is the full experience.
|
|
6
|
+
2. **Generated instruction files** (`memoryrail sync`): your rules, decisions and failed attempts are written into `AGENTS.md`, `CLAUDE.md` and `.cursor/rules/memoryrail.mdc`. Agents that read those files see the memory even without MCP, but can't write to it.
|
|
7
|
+
|
|
8
|
+
Install the CLI first: `npm install -g memoryrail` (Node 20 or newer). Then pick your client below.
|
|
9
|
+
|
|
10
|
+
> **How much of this is tested.** The server is tested with the official MCP SDK client over stdio, and the config shapes below were checked against each vendor's documentation (linked in each section, checked 2026-10-10). We have **not** run Codex or any Copilot surface against MemoryRail ourselves. If a snippet doesn't work, please open an issue with the client version and the error.
|
|
11
|
+
|
|
12
|
+
## How the server finds your memory
|
|
13
|
+
|
|
14
|
+
The server looks for `.memoryrail/` starting in the directory the client launches it in, then walks up. If your client launches servers somewhere else (a user-level config shared by many projects, or a cloud runner), point it at the repo:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
memoryrail serve --root /path/to/repo
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
or set `MEMORYRAIL_ROOT=/path/to/repo` in the server's environment.
|
|
21
|
+
|
|
22
|
+
## Claude Code
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
memoryrail install claude
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This adds a `memoryrail` server to the project's `.mcp.json`, keeping any other servers. Restart Claude Code. `CLAUDE.md` is updated by `memoryrail sync`.
|
|
29
|
+
|
|
30
|
+
## Cursor
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
memoryrail install cursor
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This adds the server to `.cursor/mcp.json`. `memoryrail sync` also writes `.cursor/rules/memoryrail.mdc` (always applied).
|
|
37
|
+
|
|
38
|
+
## OpenAI Codex
|
|
39
|
+
|
|
40
|
+
Codex reads MCP servers from `~/.codex/config.toml`, or from `.codex/config.toml` in a project (trusted projects only). Add one with the CLI:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
codex mcp add memoryrail -- memoryrail serve
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
or edit the TOML:
|
|
47
|
+
|
|
48
|
+
```toml
|
|
49
|
+
[mcp_servers.memoryrail]
|
|
50
|
+
command = "memoryrail"
|
|
51
|
+
args = ["serve"]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If you haven't installed MemoryRail globally, use `command = "npx"` and `args = ["-y", "memoryrail", "serve"]`. The server looks for `.memoryrail/` from the directory Codex launches it in (we haven't confirmed which directory that is for a user-level config), so for a single project you can pin it with `args = ["serve", "--root", "/path/to/repo"]`.
|
|
55
|
+
|
|
56
|
+
**Instructions:** Codex reads `AGENTS.md` from the project root down to your working directory, which `memoryrail sync` writes. By default Codex **stops reading after 32 KiB** of combined instructions (`project_doc_max_bytes`), so a large memory can be silently cut off. `memoryrail doctor` warns when `AGENTS.md` passes 32 KiB; archive stale memories (`memoryrail forget <ref>`) or raise the limit in your Codex config.
|
|
57
|
+
|
|
58
|
+
Sources: [Codex MCP](https://developers.openai.com/codex/mcp), [Codex AGENTS.md](https://developers.openai.com/codex/guides/agents-md).
|
|
59
|
+
|
|
60
|
+
## GitHub Copilot
|
|
61
|
+
|
|
62
|
+
Copilot has several surfaces, and they are configured differently.
|
|
63
|
+
|
|
64
|
+
### Copilot in VS Code
|
|
65
|
+
|
|
66
|
+
Create `.vscode/mcp.json` in the workspace. The top-level key is `servers` (not `mcpServers`):
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"servers": {
|
|
71
|
+
"memoryrail": {
|
|
72
|
+
"type": "stdio",
|
|
73
|
+
"command": "memoryrail",
|
|
74
|
+
"args": ["serve"]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
MCP tools are available in Copilot's agent mode. VS Code starts the server with the workspace folder as its working directory by default, so no `--root` is needed.
|
|
81
|
+
|
|
82
|
+
Source: [VS Code MCP configuration reference](https://code.visualstudio.com/docs/agents/reference/mcp-configuration).
|
|
83
|
+
|
|
84
|
+
### Copilot CLI
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
copilot mcp add memoryrail -- memoryrail serve
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This writes to `~/.copilot/mcp-config.json`. To configure it by hand, or per project in `.github/mcp.json`, the top-level key is `mcpServers` and each server has a `type`:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"mcpServers": {
|
|
95
|
+
"memoryrail": {
|
|
96
|
+
"type": "local",
|
|
97
|
+
"command": "memoryrail",
|
|
98
|
+
"args": ["serve"],
|
|
99
|
+
"tools": ["*"]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Copilot CLI can also read a project-level `.mcp.json`, but expects its own format. The entry that `memoryrail install claude` writes has no `type` field, which the Copilot CLI docs show, so use `copilot mcp add` or the JSON above for Copilot CLI instead of relying on that file.
|
|
106
|
+
|
|
107
|
+
Source: [Adding MCP servers for GitHub Copilot CLI](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-mcp-servers).
|
|
108
|
+
|
|
109
|
+
### Copilot cloud agent (assigned issues and pull requests)
|
|
110
|
+
|
|
111
|
+
The cloud agent doesn't read a file from your repo for MCP. A repository administrator pastes JSON into the repository's settings on GitHub.com (under Copilot, in the cloud/coding agent section; the exact menu name has changed between releases). `tools` is required:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"mcpServers": {
|
|
116
|
+
"memoryrail": {
|
|
117
|
+
"type": "local",
|
|
118
|
+
"command": "npx",
|
|
119
|
+
"args": ["-y", "memoryrail", "serve"],
|
|
120
|
+
"tools": ["resume", "precheck", "recall", "list_memories"]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Notes:
|
|
127
|
+
|
|
128
|
+
- The cloud agent runs on GitHub's side, not on your machine, so MemoryRail isn't installed there. Use `npx`.
|
|
129
|
+
- The example allows **read-only** tools. Add `"remember"` and `"handoff"` to let the agent write memory; its changes then appear in the pull request for you to review. Turning on `memoryrail config review agents` makes those writes wait for your approval.
|
|
130
|
+
- The cloud agent supports MCP **tools** only, not resources or prompts. MemoryRail exposes tools only, so nothing is lost.
|
|
131
|
+
- **Not verified:** which directory the cloud agent starts MCP servers in. If the server reports that it can't find `.memoryrail/`, add `"--root", "."` or the checkout path to `args`.
|
|
132
|
+
|
|
133
|
+
Source: [Configure MCP servers for the Copilot cloud agent](https://docs.github.com/en/copilot/how-tos/agents/copilot-coding-agent/extending-copilot-coding-agent-with-mcp).
|
|
134
|
+
|
|
135
|
+
### Copilot instructions
|
|
136
|
+
|
|
137
|
+
- The Copilot cloud agent and Copilot CLI read `AGENTS.md` from the repository root, which `memoryrail sync` writes. ([Changelog](https://github.blog/changelog/2025-08-28-copilot-coding-agent-now-supports-agents-md-custom-instructions/))
|
|
138
|
+
- Copilot also reads **`.github/copilot-instructions.md`**. `sync` doesn't write that file by default. To have it written there too, add `--also`:
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
memoryrail sync --also .github/copilot-instructions.md
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Pass the same flag to `sync --check` in CI. Existing content in that file is kept; MemoryRail only manages the block between its markers. ([Copilot custom instructions](https://docs.github.com/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot))
|
|
145
|
+
|
|
146
|
+
## Any other MCP client
|
|
147
|
+
|
|
148
|
+
Register this as a stdio server in the client's MCP config:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
command: memoryrail
|
|
152
|
+
args: serve
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Clients differ in file name and top-level key (`mcpServers` or `servers`) and some require a `type`; check the client's docs. If the client can't use MCP, the same commands work in a terminal (`memoryrail precheck "..." --file path`), and any tool that reads `AGENTS.md` still gets the summary from `memoryrail sync`.
|
|
156
|
+
|
|
157
|
+
## Check it worked
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
memoryrail doctor
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
reports whether memory is valid, synced, and registered for Claude Code or Cursor (it doesn't detect Codex or Copilot config). To test the server itself, ask your agent to call `list_memories`; it should return the memories in the repo.
|
package/package.json
CHANGED