@vuau/agent-memory 0.5.4 → 0.6.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 +12 -7
- package/README.vi.md +12 -7
- package/dist/bin/cli.js +103 -29
- package/dist/index.js +98 -23
- package/package.json +2 -2
- package/templates/AGENTS.md +4 -1
- package/templates/CLAUDE.md +14 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @vuau/agent-memory
|
|
2
2
|
|
|
3
|
-
Structured AI memory for codebases. Works with GitHub Copilot, Cursor, Windsurf, and any AI coding assistant that reads markdown files.
|
|
3
|
+
Structured AI memory for codebases. Works with GitHub Copilot, Cursor, Windsurf, Claude Code, OpenCode, and any AI coding assistant that reads markdown files.
|
|
4
4
|
|
|
5
5
|
**[Tiếng Việt →](./README.vi.md)**
|
|
6
6
|
|
|
@@ -18,7 +18,8 @@ npx @vuau/agent-memory init
|
|
|
18
18
|
|
|
19
19
|
```
|
|
20
20
|
/ (Project Root)
|
|
21
|
-
├── AGENTS.md #
|
|
21
|
+
├── AGENTS.md # Copilot, Cursor, Windsurf, OpenCode …
|
|
22
|
+
├── CLAUDE.md # Claude Code (symlink → AGENTS.md on macOS/Linux)
|
|
22
23
|
└── .agents/
|
|
23
24
|
├── CUSTOM.md # Project-specific rules & spec mapping
|
|
24
25
|
├── MEMORY.md # Long-term memory (decisions, patterns)
|
|
@@ -29,15 +30,15 @@ npx @vuau/agent-memory init
|
|
|
29
30
|
## How It Works
|
|
30
31
|
|
|
31
32
|
1. **You run `init`** → Creates the structure. `AGENTS.md` points to `.agents/CUSTOM.md`.
|
|
32
|
-
2. **Agent reads rules** → Follows the priority: CUSTOM.md > AGENTS.md > spec files.
|
|
33
|
+
2. **Agent reads rules** → Follows the priority: CUSTOM.md > AGENTS/CLAUDE.md > spec files.
|
|
33
34
|
3. **Agent works** → Updates MEMORY.md for decisions and TASKS.md for progress.
|
|
34
|
-
4. **Update package** → Run `agent-memory update` to get the latest
|
|
35
|
+
4. **Update package** → Run `agent-memory update` to get the latest router files without losing your custom rules.
|
|
35
36
|
|
|
36
37
|
## CLI Commands
|
|
37
38
|
|
|
38
39
|
```bash
|
|
39
40
|
npx @vuau/agent-memory init # Scaffold .agents/ structure
|
|
40
|
-
npx @vuau/agent-memory update # Update AGENTS.md
|
|
41
|
+
npx @vuau/agent-memory update # Update router files (AGENTS.md, CLAUDE.md) to latest version
|
|
41
42
|
npx @vuau/agent-memory doctor # Validate structure integrity
|
|
42
43
|
npx @vuau/agent-memory help # Show help
|
|
43
44
|
```
|
|
@@ -46,8 +47,12 @@ npx @vuau/agent-memory help # Show help
|
|
|
46
47
|
|
|
47
48
|
### The Router Split
|
|
48
49
|
|
|
49
|
-
-
|
|
50
|
-
|
|
50
|
+
- **`AGENTS.md`** — For GitHub Copilot, Cursor, Windsurf, OpenCode, and general AI coding assistants.
|
|
51
|
+
Read by: Copilot (`.github/copilot-instructions.md` instructions point here), Cursor (`@AGENTS.md`), Windsurf (`.windsurfrules` references).
|
|
52
|
+
- **`CLAUDE.md`** — For Claude Code exclusively.
|
|
53
|
+
On macOS/Linux it's a **symlink to `AGENTS.md`** so content is always in sync.
|
|
54
|
+
On Windows it's a **hook file** that tells Claude Code to read `AGENTS.md`.
|
|
55
|
+
- **`.agents/CUSTOM.md`** — Your project's home for custom rules, architectural decisions, and documentation mapping.
|
|
51
56
|
|
|
52
57
|
### Memory Files
|
|
53
58
|
|
package/README.vi.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @vuau/agent-memory
|
|
2
2
|
|
|
3
|
-
Bộ nhớ AI có cấu trúc cho các codebase. Hoạt động với GitHub Copilot, Cursor, Windsurf, và bất kỳ AI coding assistant nào đọc markdown files.
|
|
3
|
+
Bộ nhớ AI có cấu trúc cho các codebase. Hoạt động với GitHub Copilot, Cursor, Windsurf, Claude Code, OpenCode, và bất kỳ AI coding assistant nào đọc markdown files.
|
|
4
4
|
|
|
5
5
|
**[English →](./README.md)**
|
|
6
6
|
|
|
@@ -18,7 +18,8 @@ npx @vuau/agent-memory init
|
|
|
18
18
|
|
|
19
19
|
```
|
|
20
20
|
/ (Project Root)
|
|
21
|
-
├── AGENTS.md #
|
|
21
|
+
├── AGENTS.md # Copilot, Cursor, Windsurf, OpenCode …
|
|
22
|
+
├── CLAUDE.md # Claude Code (symlink → AGENTS.md trên macOS/Linux)
|
|
22
23
|
└── .agents/
|
|
23
24
|
├── CUSTOM.md # Rules riêng của project & mapping tài liệu
|
|
24
25
|
├── MEMORY.md # Bộ nhớ dài hạn (quyết định, patterns)
|
|
@@ -29,15 +30,15 @@ npx @vuau/agent-memory init
|
|
|
29
30
|
## Cách hoạt động
|
|
30
31
|
|
|
31
32
|
1. **Bạn chạy `init`** → Tạo cấu trúc thư mục. `AGENTS.md` sẽ trỏ đến `.agents/CUSTOM.md`.
|
|
32
|
-
2. **Agent đọc rules** → Tuân theo ưu tiên: CUSTOM.md > AGENTS.md > spec files.
|
|
33
|
+
2. **Agent đọc rules** → Tuân theo ưu tiên: CUSTOM.md > AGENTS/CLAUDE.md > spec files.
|
|
33
34
|
3. **Agent làm việc** → Cập nhật MEMORY.md cho các quyết định và TASKS.md cho tiến độ công việc.
|
|
34
|
-
4. **Cập nhật package** → Chạy `agent-memory update` để nhận router
|
|
35
|
+
4. **Cập nhật package** → Chạy `agent-memory update` để nhận các router files mới nhất mà không mất rules tùy chỉnh của bạn.
|
|
35
36
|
|
|
36
37
|
## Các lệnh CLI
|
|
37
38
|
|
|
38
39
|
```bash
|
|
39
40
|
npx @vuau/agent-memory init # Khởi tạo cấu trúc .agents/
|
|
40
|
-
npx @vuau/agent-memory update # Cập nhật router AGENTS.md lên bản mới nhất
|
|
41
|
+
npx @vuau/agent-memory update # Cập nhật router files (AGENTS.md, CLAUDE.md) lên bản mới nhất
|
|
41
42
|
npx @vuau/agent-memory doctor # Kiểm tra tính toàn vẹn của cấu trúc
|
|
42
43
|
npx @vuau/agent-memory help # Hiện trợ giúp
|
|
43
44
|
```
|
|
@@ -46,8 +47,12 @@ npx @vuau/agent-memory help # Hiện trợ giúp
|
|
|
46
47
|
|
|
47
48
|
### Phân tách Router
|
|
48
49
|
|
|
49
|
-
-
|
|
50
|
-
|
|
50
|
+
- **`AGENTS.md`** — Dành cho GitHub Copilot, Cursor, Windsurf, OpenCode, và các AI coding assistants thông thường.
|
|
51
|
+
Cách đọc: Copilot (chỉ định trong `.github/copilot-instructions.md`), Cursor (`@AGENTS.md`), Windsurf (tham chiếu trong `.windsurfrules`).
|
|
52
|
+
- **`CLAUDE.md`** — Riêng cho Claude Code.
|
|
53
|
+
Trên macOS/Linux: **symlink đến `AGENTS.md`** để luôn đồng bộ.
|
|
54
|
+
Trên Windows: **hook file** yêu cầu Claude Code đọc `AGENTS.md`.
|
|
55
|
+
- **`.agents/CUSTOM.md`** — Nơi dành riêng cho dự án của bạn để viết custom rules, quyết định kiến trúc và mapping tài liệu.
|
|
51
56
|
|
|
52
57
|
### Các file bộ nhớ
|
|
53
58
|
|
package/dist/bin/cli.js
CHANGED
|
@@ -5,9 +5,10 @@ import { existsSync as existsSync3 } from "fs";
|
|
|
5
5
|
import { join as join3 } from "path";
|
|
6
6
|
|
|
7
7
|
// src/scaffold.ts
|
|
8
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
8
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, symlinkSync, lstatSync, unlinkSync } from "fs";
|
|
9
9
|
import { join, resolve, dirname } from "path";
|
|
10
10
|
import { fileURLToPath } from "url";
|
|
11
|
+
import { platform } from "os";
|
|
11
12
|
|
|
12
13
|
// src/types.ts
|
|
13
14
|
var AGENTS_DIR = ".agents";
|
|
@@ -17,6 +18,7 @@ var MEMORY_DETAIL_FILE = ".agents/MEMORY-DETAIL.md";
|
|
|
17
18
|
var TASKS_FILE = ".agents/TASKS.md";
|
|
18
19
|
var CUSTOM_FILE = ".agents/CUSTOM.md";
|
|
19
20
|
var AGENTS_MD = "AGENTS.md";
|
|
21
|
+
var CLAUDE_MD = "CLAUDE.md";
|
|
20
22
|
|
|
21
23
|
// src/scaffold.ts
|
|
22
24
|
function getTemplatesDir() {
|
|
@@ -93,6 +95,7 @@ function scaffold(projectDir, options = {}) {
|
|
|
93
95
|
result,
|
|
94
96
|
force
|
|
95
97
|
);
|
|
98
|
+
writeClaudeMd(projectDir, vars, result, force);
|
|
96
99
|
return result;
|
|
97
100
|
}
|
|
98
101
|
function writeFileIfNeeded(targetPath, content, displayName, result, force) {
|
|
@@ -114,13 +117,67 @@ function guessProjectName(dir) {
|
|
|
114
117
|
}
|
|
115
118
|
return dir.split("/").pop() || "Project";
|
|
116
119
|
}
|
|
120
|
+
var IS_WIN = platform() === "win32";
|
|
121
|
+
function writeClaudeMd(projectDir, vars, result, force) {
|
|
122
|
+
const targetPath = join(projectDir, CLAUDE_MD);
|
|
123
|
+
if (IS_WIN) {
|
|
124
|
+
writeFileIfNeeded(
|
|
125
|
+
targetPath,
|
|
126
|
+
applyVars(readTemplate("CLAUDE.md"), vars),
|
|
127
|
+
CLAUDE_MD,
|
|
128
|
+
result,
|
|
129
|
+
force
|
|
130
|
+
);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const linkTarget = AGENTS_MD;
|
|
134
|
+
if (existsSync(targetPath)) {
|
|
135
|
+
if (!force) {
|
|
136
|
+
result.skipped.push(CLAUDE_MD);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
unlinkSync(targetPath);
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
symlinkSync(linkTarget, targetPath);
|
|
143
|
+
result.created.push(`${CLAUDE_MD} \u2192 ${AGENTS_MD}`);
|
|
144
|
+
} catch (err) {
|
|
145
|
+
writeFileSync(targetPath, applyVars(readTemplate("CLAUDE.md"), vars));
|
|
146
|
+
result.created.push(`${CLAUDE_MD} (symlink failed, wrote file)`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
117
149
|
function updateRouter(projectDir) {
|
|
118
|
-
const targetPath = join(projectDir, AGENTS_MD);
|
|
119
|
-
if (!existsSync(targetPath)) return false;
|
|
120
150
|
const projectName = guessProjectName(projectDir);
|
|
121
151
|
const vars = { PROJECT_NAME: projectName };
|
|
122
|
-
const
|
|
123
|
-
|
|
152
|
+
const agentsPath = join(projectDir, AGENTS_MD);
|
|
153
|
+
if (!existsSync(agentsPath)) return false;
|
|
154
|
+
writeFileSync(agentsPath, applyVars(readTemplate("AGENTS.md"), vars));
|
|
155
|
+
const claudePath = join(projectDir, CLAUDE_MD);
|
|
156
|
+
if (IS_WIN) {
|
|
157
|
+
writeFileSync(claudePath, applyVars(readTemplate("CLAUDE.md"), vars));
|
|
158
|
+
} else {
|
|
159
|
+
let needsRecreate = false;
|
|
160
|
+
if (!existsSync(claudePath)) {
|
|
161
|
+
needsRecreate = true;
|
|
162
|
+
} else {
|
|
163
|
+
try {
|
|
164
|
+
const stat = lstatSync(claudePath);
|
|
165
|
+
if (!stat.isSymbolicLink()) {
|
|
166
|
+
needsRecreate = true;
|
|
167
|
+
}
|
|
168
|
+
} catch {
|
|
169
|
+
needsRecreate = true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (needsRecreate) {
|
|
173
|
+
try {
|
|
174
|
+
if (existsSync(claudePath)) unlinkSync(claudePath);
|
|
175
|
+
symlinkSync(AGENTS_MD, claudePath);
|
|
176
|
+
} catch {
|
|
177
|
+
writeFileSync(claudePath, applyVars(readTemplate("CLAUDE.md"), vars));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
124
181
|
const managedSpecs = [
|
|
125
182
|
{ target: `${SPEC_DIR}/coding-principles.md`, template: "spec/coding-principles.md" }
|
|
126
183
|
];
|
|
@@ -134,12 +191,14 @@ function updateRouter(projectDir) {
|
|
|
134
191
|
}
|
|
135
192
|
|
|
136
193
|
// src/doctor.ts
|
|
137
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
194
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, lstatSync as lstatSync2 } from "fs";
|
|
138
195
|
import { join as join2 } from "path";
|
|
196
|
+
import { platform as platform2 } from "os";
|
|
139
197
|
function doctor(projectDir) {
|
|
140
198
|
const issues = [];
|
|
141
199
|
const required = [
|
|
142
|
-
{ file: AGENTS_MD, desc: "Root router file" },
|
|
200
|
+
{ file: AGENTS_MD, desc: "Root router file (OpenCode)" },
|
|
201
|
+
{ file: CLAUDE_MD, desc: "Root router file (Claude Code)" },
|
|
143
202
|
{ file: CUSTOM_FILE, desc: "Project specific rules" },
|
|
144
203
|
{ file: MEMORY_FILE, desc: "Long-term memory" },
|
|
145
204
|
{ file: TASKS_FILE, desc: "Working memory" },
|
|
@@ -156,22 +215,37 @@ function doctor(projectDir) {
|
|
|
156
215
|
issues.push({ level: "error", file: dir, message: "Directory missing" });
|
|
157
216
|
}
|
|
158
217
|
}
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
218
|
+
const routerFiles = [AGENTS_MD, CLAUDE_MD];
|
|
219
|
+
for (const rf of routerFiles) {
|
|
220
|
+
const rfPath = join2(projectDir, rf);
|
|
221
|
+
if (existsSync2(rfPath)) {
|
|
222
|
+
if (rf === CLAUDE_MD && platform2() !== "win32") {
|
|
223
|
+
try {
|
|
224
|
+
if (!lstatSync2(rfPath).isSymbolicLink()) {
|
|
225
|
+
issues.push({
|
|
226
|
+
level: "warning",
|
|
227
|
+
file: CLAUDE_MD,
|
|
228
|
+
message: "Plain file \u2014 should be a symlink to AGENTS.md. Run 'agent-memory update' to fix"
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
} catch {
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const content = readFileSync2(rfPath, "utf-8");
|
|
235
|
+
if (!content.includes(".agents/")) {
|
|
236
|
+
issues.push({
|
|
237
|
+
level: "warning",
|
|
238
|
+
file: rf,
|
|
239
|
+
message: "No references to .agents/ \u2014 agents may not find memory files"
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (content.split("\n").length > 150) {
|
|
243
|
+
issues.push({
|
|
244
|
+
level: "warning",
|
|
245
|
+
file: rf,
|
|
246
|
+
message: "Over 150 lines \u2014 consider keeping it concise as a router"
|
|
247
|
+
});
|
|
248
|
+
}
|
|
175
249
|
}
|
|
176
250
|
}
|
|
177
251
|
const memoryPath = join2(projectDir, MEMORY_FILE);
|
|
@@ -196,8 +270,8 @@ function printUsage() {
|
|
|
196
270
|
@vuau/agent-memory \u2014 Structured AI memory for codebases
|
|
197
271
|
|
|
198
272
|
Usage:
|
|
199
|
-
agent-memory init [options] Scaffold .agents/ structure and
|
|
200
|
-
agent-memory update Update
|
|
273
|
+
agent-memory init [options] Scaffold .agents/ structure, AGENTS.md and CLAUDE.md
|
|
274
|
+
agent-memory update Update router files to latest version
|
|
201
275
|
agent-memory doctor Validate .agents/ structure
|
|
202
276
|
agent-memory help Show this help
|
|
203
277
|
|
|
@@ -239,7 +313,7 @@ Initializing agent memory in ${cwd}...
|
|
|
239
313
|
}
|
|
240
314
|
}
|
|
241
315
|
console.log("\nNext steps:");
|
|
242
|
-
console.log(" 1. Edit AGENTS.md
|
|
316
|
+
console.log(" 1. Edit AGENTS.md (OpenCode) / CLAUDE.md (Claude Code) with project-specific rules");
|
|
243
317
|
console.log(" 2. Add spec files to .agents/spec/ for detailed documentation");
|
|
244
318
|
console.log(" 3. Agent will read rules and write to .agents/MEMORY.md automatically");
|
|
245
319
|
console.log("");
|
|
@@ -252,14 +326,14 @@ async function runUpdate() {
|
|
|
252
326
|
process.exit(1);
|
|
253
327
|
}
|
|
254
328
|
console.log(`
|
|
255
|
-
Updating ${AGENTS_MD} in ${cwd}...
|
|
329
|
+
Updating ${AGENTS_MD} / ${CLAUDE_MD} in ${cwd}...
|
|
256
330
|
`);
|
|
257
331
|
const updated = updateRouter(cwd);
|
|
258
332
|
if (updated) {
|
|
259
|
-
console.log(` \u2713 ${AGENTS_MD} updated to the latest template.`);
|
|
333
|
+
console.log(` \u2713 ${AGENTS_MD} and ${CLAUDE_MD} updated to the latest template.`);
|
|
260
334
|
console.log(` (Note: Your custom rules in .agents/CUSTOM.md were not affected)`);
|
|
261
335
|
} else {
|
|
262
|
-
console.error("\u2717 Failed to update
|
|
336
|
+
console.error("\u2717 Failed to update router files");
|
|
263
337
|
process.exit(1);
|
|
264
338
|
}
|
|
265
339
|
console.log("");
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/scaffold.ts
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, symlinkSync, lstatSync, unlinkSync } from "fs";
|
|
3
3
|
import { join, resolve, dirname } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
+
import { platform } from "os";
|
|
5
6
|
|
|
6
7
|
// src/types.ts
|
|
7
8
|
var AGENTS_DIR = ".agents";
|
|
@@ -11,6 +12,7 @@ var MEMORY_DETAIL_FILE = ".agents/MEMORY-DETAIL.md";
|
|
|
11
12
|
var TASKS_FILE = ".agents/TASKS.md";
|
|
12
13
|
var CUSTOM_FILE = ".agents/CUSTOM.md";
|
|
13
14
|
var AGENTS_MD = "AGENTS.md";
|
|
15
|
+
var CLAUDE_MD = "CLAUDE.md";
|
|
14
16
|
|
|
15
17
|
// src/scaffold.ts
|
|
16
18
|
function getTemplatesDir() {
|
|
@@ -87,6 +89,7 @@ function scaffold(projectDir, options = {}) {
|
|
|
87
89
|
result,
|
|
88
90
|
force
|
|
89
91
|
);
|
|
92
|
+
writeClaudeMd(projectDir, vars, result, force);
|
|
90
93
|
return result;
|
|
91
94
|
}
|
|
92
95
|
function writeFileIfNeeded(targetPath, content, displayName, result, force) {
|
|
@@ -108,13 +111,67 @@ function guessProjectName(dir) {
|
|
|
108
111
|
}
|
|
109
112
|
return dir.split("/").pop() || "Project";
|
|
110
113
|
}
|
|
114
|
+
var IS_WIN = platform() === "win32";
|
|
115
|
+
function writeClaudeMd(projectDir, vars, result, force) {
|
|
116
|
+
const targetPath = join(projectDir, CLAUDE_MD);
|
|
117
|
+
if (IS_WIN) {
|
|
118
|
+
writeFileIfNeeded(
|
|
119
|
+
targetPath,
|
|
120
|
+
applyVars(readTemplate("CLAUDE.md"), vars),
|
|
121
|
+
CLAUDE_MD,
|
|
122
|
+
result,
|
|
123
|
+
force
|
|
124
|
+
);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const linkTarget = AGENTS_MD;
|
|
128
|
+
if (existsSync(targetPath)) {
|
|
129
|
+
if (!force) {
|
|
130
|
+
result.skipped.push(CLAUDE_MD);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
unlinkSync(targetPath);
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
symlinkSync(linkTarget, targetPath);
|
|
137
|
+
result.created.push(`${CLAUDE_MD} \u2192 ${AGENTS_MD}`);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
writeFileSync(targetPath, applyVars(readTemplate("CLAUDE.md"), vars));
|
|
140
|
+
result.created.push(`${CLAUDE_MD} (symlink failed, wrote file)`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
111
143
|
function updateRouter(projectDir) {
|
|
112
|
-
const targetPath = join(projectDir, AGENTS_MD);
|
|
113
|
-
if (!existsSync(targetPath)) return false;
|
|
114
144
|
const projectName = guessProjectName(projectDir);
|
|
115
145
|
const vars = { PROJECT_NAME: projectName };
|
|
116
|
-
const
|
|
117
|
-
|
|
146
|
+
const agentsPath = join(projectDir, AGENTS_MD);
|
|
147
|
+
if (!existsSync(agentsPath)) return false;
|
|
148
|
+
writeFileSync(agentsPath, applyVars(readTemplate("AGENTS.md"), vars));
|
|
149
|
+
const claudePath = join(projectDir, CLAUDE_MD);
|
|
150
|
+
if (IS_WIN) {
|
|
151
|
+
writeFileSync(claudePath, applyVars(readTemplate("CLAUDE.md"), vars));
|
|
152
|
+
} else {
|
|
153
|
+
let needsRecreate = false;
|
|
154
|
+
if (!existsSync(claudePath)) {
|
|
155
|
+
needsRecreate = true;
|
|
156
|
+
} else {
|
|
157
|
+
try {
|
|
158
|
+
const stat = lstatSync(claudePath);
|
|
159
|
+
if (!stat.isSymbolicLink()) {
|
|
160
|
+
needsRecreate = true;
|
|
161
|
+
}
|
|
162
|
+
} catch {
|
|
163
|
+
needsRecreate = true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (needsRecreate) {
|
|
167
|
+
try {
|
|
168
|
+
if (existsSync(claudePath)) unlinkSync(claudePath);
|
|
169
|
+
symlinkSync(AGENTS_MD, claudePath);
|
|
170
|
+
} catch {
|
|
171
|
+
writeFileSync(claudePath, applyVars(readTemplate("CLAUDE.md"), vars));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
118
175
|
const managedSpecs = [
|
|
119
176
|
{ target: `${SPEC_DIR}/coding-principles.md`, template: "spec/coding-principles.md" }
|
|
120
177
|
];
|
|
@@ -128,12 +185,14 @@ function updateRouter(projectDir) {
|
|
|
128
185
|
}
|
|
129
186
|
|
|
130
187
|
// src/doctor.ts
|
|
131
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
188
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, lstatSync as lstatSync2 } from "fs";
|
|
132
189
|
import { join as join2 } from "path";
|
|
190
|
+
import { platform as platform2 } from "os";
|
|
133
191
|
function doctor(projectDir) {
|
|
134
192
|
const issues = [];
|
|
135
193
|
const required = [
|
|
136
|
-
{ file: AGENTS_MD, desc: "Root router file" },
|
|
194
|
+
{ file: AGENTS_MD, desc: "Root router file (OpenCode)" },
|
|
195
|
+
{ file: CLAUDE_MD, desc: "Root router file (Claude Code)" },
|
|
137
196
|
{ file: CUSTOM_FILE, desc: "Project specific rules" },
|
|
138
197
|
{ file: MEMORY_FILE, desc: "Long-term memory" },
|
|
139
198
|
{ file: TASKS_FILE, desc: "Working memory" },
|
|
@@ -150,22 +209,37 @@ function doctor(projectDir) {
|
|
|
150
209
|
issues.push({ level: "error", file: dir, message: "Directory missing" });
|
|
151
210
|
}
|
|
152
211
|
}
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
212
|
+
const routerFiles = [AGENTS_MD, CLAUDE_MD];
|
|
213
|
+
for (const rf of routerFiles) {
|
|
214
|
+
const rfPath = join2(projectDir, rf);
|
|
215
|
+
if (existsSync2(rfPath)) {
|
|
216
|
+
if (rf === CLAUDE_MD && platform2() !== "win32") {
|
|
217
|
+
try {
|
|
218
|
+
if (!lstatSync2(rfPath).isSymbolicLink()) {
|
|
219
|
+
issues.push({
|
|
220
|
+
level: "warning",
|
|
221
|
+
file: CLAUDE_MD,
|
|
222
|
+
message: "Plain file \u2014 should be a symlink to AGENTS.md. Run 'agent-memory update' to fix"
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
} catch {
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const content = readFileSync2(rfPath, "utf-8");
|
|
229
|
+
if (!content.includes(".agents/")) {
|
|
230
|
+
issues.push({
|
|
231
|
+
level: "warning",
|
|
232
|
+
file: rf,
|
|
233
|
+
message: "No references to .agents/ \u2014 agents may not find memory files"
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
if (content.split("\n").length > 150) {
|
|
237
|
+
issues.push({
|
|
238
|
+
level: "warning",
|
|
239
|
+
file: rf,
|
|
240
|
+
message: "Over 150 lines \u2014 consider keeping it concise as a router"
|
|
241
|
+
});
|
|
242
|
+
}
|
|
169
243
|
}
|
|
170
244
|
}
|
|
171
245
|
const memoryPath = join2(projectDir, MEMORY_FILE);
|
|
@@ -184,6 +258,7 @@ function doctor(projectDir) {
|
|
|
184
258
|
export {
|
|
185
259
|
AGENTS_DIR,
|
|
186
260
|
AGENTS_MD,
|
|
261
|
+
CLAUDE_MD,
|
|
187
262
|
CUSTOM_FILE,
|
|
188
263
|
MEMORY_DETAIL_FILE,
|
|
189
264
|
MEMORY_FILE,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vuau/agent-memory",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Structured AI memory for codebases — scaffolding CLI for OpenCode, Copilot, Cursor, Windsurf",
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Structured AI memory for codebases — scaffolding CLI for OpenCode, Copilot, Cursor, Windsurf, Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"exports": {
|
package/templates/AGENTS.md
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
# {{PROJECT_NAME}} - AGENTS
|
|
2
2
|
|
|
3
|
-
Router file for AI
|
|
3
|
+
Router file for AI coding assistants: OpenCode, GitHub Copilot, Cursor, Windsurf, and others.
|
|
4
4
|
|
|
5
5
|
> **Note**: This file is automatically managed by `@vuau/agent-memory`.
|
|
6
6
|
> Do not add project-specific rules here, as they may be overwritten by `agent-memory update`.
|
|
7
7
|
>
|
|
8
8
|
> 👉 **For project-specific rules, context, and document mapping, see `.agents/CUSTOM.md`**
|
|
9
|
+
>
|
|
10
|
+
> 💡 **Claude Code users**: Install `@vuau/agent-memory` and run `init` to auto-generate `CLAUDE.md` —
|
|
11
|
+
> a companion file that references this `AGENTS.md` so you get the same rules.
|
|
9
12
|
|
|
10
13
|
## Priority
|
|
11
14
|
1. User request first.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# {{PROJECT_NAME}} - CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Router file for Claude Code.
|
|
4
|
+
|
|
5
|
+
> **Note**: This file is auto-generated by `@vuau/agent-memory`.
|
|
6
|
+
> Do not edit directly.
|
|
7
|
+
>
|
|
8
|
+
> 👉 **All project rules live in `AGENTS.md`** — you MUST read that file for context and instructions.
|
|
9
|
+
|
|
10
|
+
## Rules
|
|
11
|
+
|
|
12
|
+
All project rules, memory protocol, and response style are defined in **[AGENTS.md](./AGENTS.md)**.
|
|
13
|
+
|
|
14
|
+
Read `AGENTS.md` before making any changes.
|