@synth-coder/memhub 0.2.4 → 0.2.6
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/.github/workflows/release.yml +3 -0
- package/README.md +17 -9
- package/README.zh-CN.md +17 -9
- package/dist/src/cli/agents/claude-code.js +1 -1
- package/dist/src/cli/agents/claude-code.js.map +1 -1
- package/dist/src/cli/agents/cline.js +1 -1
- package/dist/src/cli/agents/cline.js.map +1 -1
- package/dist/src/cli/agents/codex.js +2 -2
- package/dist/src/cli/agents/codex.js.map +1 -1
- package/dist/src/cli/agents/cursor.js +1 -1
- package/dist/src/cli/agents/cursor.js.map +1 -1
- package/dist/src/cli/agents/factory-droid.js +1 -1
- package/dist/src/cli/agents/factory-droid.js.map +1 -1
- package/dist/src/cli/agents/gemini-cli.js +1 -1
- package/dist/src/cli/agents/gemini-cli.js.map +1 -1
- package/dist/src/cli/agents/windsurf.js +1 -1
- package/dist/src/cli/agents/windsurf.js.map +1 -1
- package/dist/src/cli/init.d.ts.map +1 -1
- package/dist/src/cli/init.js +12 -11
- package/dist/src/cli/init.js.map +1 -1
- package/docs/user-guide.md +8 -6
- package/package.json +1 -1
- package/src/cli/agents/claude-code.ts +1 -1
- package/src/cli/agents/cline.ts +1 -1
- package/src/cli/agents/codex.ts +2 -2
- package/src/cli/agents/cursor.ts +1 -1
- package/src/cli/agents/factory-droid.ts +1 -1
- package/src/cli/agents/gemini-cli.ts +1 -1
- package/src/cli/agents/windsurf.ts +1 -1
- package/src/cli/init.ts +14 -14
- package/test/cli/init.test.ts +23 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Git-friendly memory MCP server for coding agents.
|
|
|
11
11
|
Configure MemHub for your AI agent with a single command:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npx -y @synth-coder/memhub init
|
|
14
|
+
npx -y @synth-coder/memhub@latest init
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
This launches an interactive prompt to select your agent. MemHub will:
|
|
@@ -34,16 +34,16 @@ This launches an interactive prompt to select your agent. MemHub will:
|
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
# Interactive selection (global - default)
|
|
37
|
-
npx -y @synth-coder/memhub init
|
|
37
|
+
npx -y @synth-coder/memhub@latest init
|
|
38
38
|
|
|
39
39
|
# Skip interactive prompt
|
|
40
|
-
npx -y @synth-coder/memhub init -a claude-code
|
|
40
|
+
npx -y @synth-coder/memhub@latest init -a claude-code
|
|
41
41
|
|
|
42
42
|
# Configure for current project only (local)
|
|
43
|
-
npx -y @synth-coder/memhub init -a cursor -l
|
|
43
|
+
npx -y @synth-coder/memhub@latest init -a cursor -l
|
|
44
44
|
|
|
45
45
|
# Update existing configuration
|
|
46
|
-
npx -y @synth-coder/memhub init -a claude-code --force
|
|
46
|
+
npx -y @synth-coder/memhub@latest init -a claude-code --force
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
| Option | Description |
|
|
@@ -55,7 +55,7 @@ npx -y @synth-coder/memhub init -a claude-code --force
|
|
|
55
55
|
### Run as MCP Server
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
npx -y @synth-coder/memhub
|
|
58
|
+
npx -y @synth-coder/memhub@latest
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
> On Windows, do **not** append `memhub` after the package name.
|
|
@@ -69,7 +69,7 @@ If you prefer manual setup, add this to your MCP client config:
|
|
|
69
69
|
"mcpServers": {
|
|
70
70
|
"memhub": {
|
|
71
71
|
"command": "npx",
|
|
72
|
-
"args": ["-y", "@synth-coder/memhub"],
|
|
72
|
+
"args": ["-y", "@synth-coder/memhub@latest"],
|
|
73
73
|
"env": {
|
|
74
74
|
"MEMHUB_STORAGE_PATH": "/absolute/path/to/memories",
|
|
75
75
|
"MEMHUB_LOG_LEVEL": "info"
|
|
@@ -79,6 +79,14 @@ If you prefer manual setup, add this to your MCP client config:
|
|
|
79
79
|
}
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
+
For Codex (`~/.codex/config.toml`), use TOML key `mcp_servers`:
|
|
83
|
+
|
|
84
|
+
```toml
|
|
85
|
+
[mcp_servers.memhub]
|
|
86
|
+
command = "npx"
|
|
87
|
+
args = ["-y", "@synth-coder/memhub@latest"]
|
|
88
|
+
```
|
|
89
|
+
|
|
82
90
|
---
|
|
83
91
|
|
|
84
92
|
## Configure Your Agent
|
|
@@ -175,7 +183,7 @@ This means "testing framework preference" finds memories about "Vitest vs Jest d
|
|
|
175
183
|
- **Markdown Storage** — Human-readable `.md` files with YAML front matter
|
|
176
184
|
- **Git-Friendly** — Version control, diff, review your memories
|
|
177
185
|
- **MCP Protocol** — Works with Claude Code, Cursor, Cline, Windsurf, and more
|
|
178
|
-
- **One-Line Setup** — `npx -y @synth-coder/memhub init`
|
|
186
|
+
- **One-Line Setup** — `npx -y @synth-coder/memhub@latest init`
|
|
179
187
|
|
|
180
188
|
---
|
|
181
189
|
|
|
@@ -267,7 +275,7 @@ memhub/
|
|
|
267
275
|
- [x] CLI init command for quick setup
|
|
268
276
|
- [ ] Integration tests
|
|
269
277
|
- [ ] Performance improvements
|
|
270
|
-
- [x] npm release (`@synth-coder/memhub@0.2.
|
|
278
|
+
- [x] npm release (`@synth-coder/memhub@0.2.6`)
|
|
271
279
|
|
|
272
280
|
---
|
|
273
281
|
|
package/README.zh-CN.md
CHANGED
|
@@ -49,7 +49,7 @@ MemHub 将“用户决策、长期偏好、可复用知识”保存为 **Markdow
|
|
|
49
49
|
- **Markdown 存储** — 人类可读的 `.md` 文件,带 YAML front matter
|
|
50
50
|
- **Git 友好** — 版本控制、diff、审查你的记忆
|
|
51
51
|
- **MCP 协议** — 支持 Claude Code、Cursor、Cline、Windsurf 等
|
|
52
|
-
- **一键配置** — `npx -y @synth-coder/memhub init`
|
|
52
|
+
- **一键配置** — `npx -y @synth-coder/memhub@latest init`
|
|
53
53
|
|
|
54
54
|
---
|
|
55
55
|
|
|
@@ -60,7 +60,7 @@ MemHub 将“用户决策、长期偏好、可复用知识”保存为 **Markdow
|
|
|
60
60
|
使用一条命令为你的 AI 代理配置 MemHub:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
npx -y @synth-coder/memhub init
|
|
63
|
+
npx -y @synth-coder/memhub@latest init
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
这将启动交互式提示选择你的代理。MemHub 会:
|
|
@@ -83,16 +83,16 @@ npx -y @synth-coder/memhub init
|
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
85
|
# 交互式选择(全局 - 默认)
|
|
86
|
-
npx -y @synth-coder/memhub init
|
|
86
|
+
npx -y @synth-coder/memhub@latest init
|
|
87
87
|
|
|
88
88
|
# 跳过交互式提示
|
|
89
|
-
npx -y @synth-coder/memhub init -a claude-code
|
|
89
|
+
npx -y @synth-coder/memhub@latest init -a claude-code
|
|
90
90
|
|
|
91
91
|
# 仅配置当前项目(本地)
|
|
92
|
-
npx -y @synth-coder/memhub init -a cursor -l
|
|
92
|
+
npx -y @synth-coder/memhub@latest init -a cursor -l
|
|
93
93
|
|
|
94
94
|
# 更新现有配置
|
|
95
|
-
npx -y @synth-coder/memhub init -a claude-code --force
|
|
95
|
+
npx -y @synth-coder/memhub@latest init -a claude-code --force
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
| 选项 | 说明 |
|
|
@@ -108,7 +108,7 @@ npx -y @synth-coder/memhub init -a claude-code --force
|
|
|
108
108
|
### 方式 A:npx 直接运行(推荐)
|
|
109
109
|
|
|
110
110
|
```bash
|
|
111
|
-
npx -y @synth-coder/memhub
|
|
111
|
+
npx -y @synth-coder/memhub@latest
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
> Windows 下不要在包名后再加 `memhub` 参数。
|
|
@@ -121,7 +121,7 @@ npx -y @synth-coder/memhub
|
|
|
121
121
|
"mcpServers": {
|
|
122
122
|
"memhub": {
|
|
123
123
|
"command": "npx",
|
|
124
|
-
"args": ["-y", "@synth-coder/memhub"],
|
|
124
|
+
"args": ["-y", "@synth-coder/memhub@latest"],
|
|
125
125
|
"env": {
|
|
126
126
|
"MEMHUB_STORAGE_PATH": "/绝对路径/你的记忆目录",
|
|
127
127
|
"MEMHUB_LOG_LEVEL": "info"
|
|
@@ -131,6 +131,14 @@ npx -y @synth-coder/memhub
|
|
|
131
131
|
}
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
如果是 Codex(`~/.codex/config.toml`),请使用 TOML 键 `mcp_servers`:
|
|
135
|
+
|
|
136
|
+
```toml
|
|
137
|
+
[mcp_servers.memhub]
|
|
138
|
+
command = "npx"
|
|
139
|
+
args = ["-y", "@synth-coder/memhub@latest"]
|
|
140
|
+
```
|
|
141
|
+
|
|
134
142
|
### 方式 B:本地仓库运行
|
|
135
143
|
|
|
136
144
|
```json
|
|
@@ -236,7 +244,7 @@ memhub/
|
|
|
236
244
|
- [x] CLI init 命令快速配置
|
|
237
245
|
- [ ] 集成测试
|
|
238
246
|
- [ ] 性能优化
|
|
239
|
-
- [x] npm 发布(`@synth-coder/memhub@0.2.
|
|
247
|
+
- [x] npm 发布(`@synth-coder/memhub@0.2.6`)
|
|
240
248
|
|
|
241
249
|
---
|
|
242
250
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../../src/cli/agents/claude-code.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IAC1D,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../../src/cli/agents/claude-code.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IAC1D,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,4BAA4B,CAAC;aAC3C;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cline.js","sourceRoot":"","sources":["../../../../src/cli/agents/cline.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"cline.js","sourceRoot":"","sources":["../../../../src/cli/agents/cline.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,4BAA4B,CAAC;aAC3C;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../../src/cli/agents/codex.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO;QACL,
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../../src/cli/agents/codex.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO;QACL,WAAW,EAAE;YACX,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,4BAA4B,CAAC;aAC3C;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../../src/cli/agents/cursor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../../src/cli/agents/cursor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,4BAA4B,CAAC;aAC3C;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory-droid.js","sourceRoot":"","sources":["../../../../src/cli/agents/factory-droid.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,0BAA0B,CAAC,WAAmB;IAC5D,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"factory-droid.js","sourceRoot":"","sources":["../../../../src/cli/agents/factory-droid.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,0BAA0B,CAAC,WAAmB;IAC5D,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,4BAA4B,CAAC;aAC3C;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../../../src/cli/agents/gemini-cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,uBAAuB,CAAC,WAAmB;IACzD,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../../../src/cli/agents/gemini-cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,uBAAuB,CAAC,WAAmB;IACzD,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,4BAA4B,CAAC;aAC3C;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../../../src/cli/agents/windsurf.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../../../src/cli/agents/windsurf.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,OAAO;QACL,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,4BAA4B,CAAC;aAC3C;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAU,KAAK,SAAS,EAAE,KAAK,WAAW,EAAgB,MAAM,YAAY,CAAC;AAKpF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC7B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAU,KAAK,SAAS,EAAE,KAAK,WAAW,EAAgB,MAAM,YAAY,CAAC;AAKpF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC7B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAqDjD;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAexE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,CAyG3D"}
|
package/dist/src/cli/init.js
CHANGED
|
@@ -28,22 +28,22 @@ function stringifyConfig(config, format) {
|
|
|
28
28
|
}
|
|
29
29
|
return JSON.stringify(config, null, 2);
|
|
30
30
|
}
|
|
31
|
+
function isRecord(value) {
|
|
32
|
+
return typeof value === 'object' && value !== null;
|
|
33
|
+
}
|
|
34
|
+
function getTargetMcpKey(config) {
|
|
35
|
+
return isRecord(config.mcp_servers) ? 'mcp_servers' : 'mcpServers';
|
|
36
|
+
}
|
|
31
37
|
/**
|
|
32
38
|
* Merge memhub config into existing config
|
|
33
39
|
* Preserves all existing servers, adds/updates memhub
|
|
34
40
|
*/
|
|
35
41
|
function mergeMcpConfig(existing, newConfig) {
|
|
36
42
|
const result = { ...existing };
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
// Merge memhub server
|
|
42
|
-
const existingServers = result.mcpServers;
|
|
43
|
-
const newServers = newConfig.mcpServers;
|
|
44
|
-
for (const [serverName, serverConfig] of Object.entries(newServers)) {
|
|
45
|
-
existingServers[serverName] = serverConfig;
|
|
46
|
-
}
|
|
43
|
+
const targetKey = getTargetMcpKey(newConfig);
|
|
44
|
+
const existingServers = isRecord(result[targetKey]) ? result[targetKey] : {};
|
|
45
|
+
const newServers = newConfig[targetKey] ?? {};
|
|
46
|
+
result[targetKey] = { ...existingServers, ...newServers };
|
|
47
47
|
return result;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
@@ -109,7 +109,8 @@ export function initAgent(options) {
|
|
|
109
109
|
try {
|
|
110
110
|
const existingContent = readFileSync(configPath, 'utf-8');
|
|
111
111
|
const existingConfig = parseConfig(existingContent, configFormat);
|
|
112
|
-
const
|
|
112
|
+
const targetKey = getTargetMcpKey(newConfig);
|
|
113
|
+
const servers = existingConfig[targetKey];
|
|
113
114
|
if (servers && 'memhub' in servers) {
|
|
114
115
|
return {
|
|
115
116
|
success: false,
|
package/dist/src/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,MAAM,EAAoC,YAAY,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,WAAW,CAAC;AA0B3E;;GAEG;AACH,SAAS,WAAW,CAClB,OAAe,EACf,MAAoC;IAEpC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC,OAAO,CAA4B,CAAC;IACvD,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CACtB,MAA+B,EAC/B,MAAoC;IAEpC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,MAAM,EAAoC,YAAY,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,WAAW,CAAC;AA0B3E;;GAEG;AACH,SAAS,WAAW,CAClB,OAAe,EACf,MAAoC;IAEpC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC,OAAO,CAA4B,CAAC;IACvD,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CACtB,MAA+B,EAC/B,MAAoC;IAEpC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,eAAe,CAAC,MAA+B;IACtD,OAAO,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CACrB,QAAiC,EACjC,SAAkC;IAElC,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,MAAM,UAAU,GAAI,SAAS,CAAC,SAAS,CAA6B,IAAI,EAAE,CAAC;IAC3E,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,UAAU,EAAE,CAAC;IAE1D,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC;QAC/B,OAAO,EAAE,sBAAsB;QAC/B,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC5B,KAAK,EAAE,KAAK,CAAC,EAAE;YACf,KAAK,EAAE,KAAK,CAAC,IAAI;YACjB,IAAI,EAAE,KAAK,CAAC,WAAW;SACxB,CAAC,CAAC;KACJ,CAAC,CAAC;IAEH,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAAoB;IAC5C,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAErE,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,kBAAkB,KAAK,mBAAmB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SACpF,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,MAAM,QAAQ,GAAG,WAAW,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IACjF,MAAM,gBAAgB,GAAG,KAAK;QAC5B,CAAC,CAAC,WAAW,CAAC,gBAAgB;QAC9B,CAAC,CAAC,WAAW,CAAC,sBAAsB,CAAC;IAEvC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAElD,6BAA6B;IAC7B,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEtC,IAAI,WAAoC,CAAC;IAEzC,iCAAiC;IACjC,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;IAC9C,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,KAAK,EAAE,CAAC;YACV,oDAAoD;YACpD,IAAI,CAAC;gBACH,MAAM,eAAe,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBAC1D,MAAM,cAAc,GAAG,WAAW,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;gBAClE,WAAW,GAAG,cAAc,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YAC1D,CAAC;YAAC,MAAM,CAAC;gBACP,iCAAiC;gBACjC,WAAW,GAAG,SAAS,CAAC;YAC1B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,2CAA2C;YAC3C,IAAI,CAAC;gBACH,MAAM,eAAe,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBAC1D,MAAM,cAAc,GAAG,WAAW,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;gBAClE,MAAM,SAAS,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;gBAC7C,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,CAAwC,CAAC;gBAEjF,IAAI,OAAO,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;oBACnC,OAAO;wBACL,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,mCAAmC,UAAU,0BAA0B;qBAC/E,CAAC;gBACJ,CAAC;gBAED,6BAA6B;gBAC7B,WAAW,GAAG,cAAc,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YAC1D,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,sCAAsC,UAAU,6BAA6B;iBACrF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,SAAS,CAAC;IAC1B,CAAC;IAED,2BAA2B;IAC3B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACjC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,0BAA0B;IAC1B,aAAa,CAAC,UAAU,EAAE,eAAe,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;IAE/E,2BAA2B;IAC3B,IAAI,eAAe,GAAG,EAAE,CAAC;IACzB,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACjC,eAAe,GAAG,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,EACJ,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,kBAAkB,GAC3B,GAAG,yBAAyB,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;IAE5D,IAAI,mBAAmB,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACzD,aAAa,CAAC,gBAAgB,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,UAAU;QACtB,gBAAgB,EAAE,gBAAgB;QAClC,mBAAmB;QACnB,kBAAkB;QAClB,KAAK,EAAE,WAAW;KACnB,CAAC;AACJ,CAAC"}
|
package/docs/user-guide.md
CHANGED
|
@@ -9,7 +9,7 @@ MemHub is a Git-friendly memory system for AI coding agents. It helps your AI re
|
|
|
9
9
|
Configure MemHub for your AI agent with one command:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npx -y @synth-coder/memhub init
|
|
12
|
+
npx -y @synth-coder/memhub@latest init
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
This will:
|
|
@@ -29,20 +29,22 @@ This will:
|
|
|
29
29
|
| Gemini CLI | `~/.gemini/settings.json` | `.gemini/settings.json` |
|
|
30
30
|
| Codex | `~/.codex/config.toml` | `.codex/config.toml` |
|
|
31
31
|
|
|
32
|
+
Note: Codex config uses TOML key `mcp_servers` (not `mcpServers`).
|
|
33
|
+
|
|
32
34
|
### CLI Options
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
37
|
# Interactive selection (global - default)
|
|
36
|
-
npx -y @synth-coder/memhub init
|
|
38
|
+
npx -y @synth-coder/memhub@latest init
|
|
37
39
|
|
|
38
40
|
# Specify agent
|
|
39
|
-
npx -y @synth-coder/memhub init -a claude-code
|
|
41
|
+
npx -y @synth-coder/memhub@latest init -a claude-code
|
|
40
42
|
|
|
41
43
|
# Configure for current project only (local)
|
|
42
|
-
npx -y @synth-coder/memhub init -a cursor -l
|
|
44
|
+
npx -y @synth-coder/memhub@latest init -a cursor -l
|
|
43
45
|
|
|
44
46
|
# Update existing configuration
|
|
45
|
-
npx -y @synth-coder/memhub init -a claude-code --force
|
|
47
|
+
npx -y @synth-coder/memhub@latest init -a claude-code --force
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
| Option | Description |
|
|
@@ -95,7 +97,7 @@ By default, memories are stored in `~/.memhub/` (global) or `./memories/` (local
|
|
|
95
97
|
|
|
96
98
|
```bash
|
|
97
99
|
# Custom storage location
|
|
98
|
-
MEMHUB_STORAGE_PATH=/path/to/memories npx -y @synth-coder/memhub
|
|
100
|
+
MEMHUB_STORAGE_PATH=/path/to/memories npx -y @synth-coder/memhub@latest
|
|
99
101
|
```
|
|
100
102
|
|
|
101
103
|
### File Format
|
package/package.json
CHANGED
package/src/cli/agents/cline.ts
CHANGED
package/src/cli/agents/codex.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
export function generateCodexConfig(_memhubPath: string): Record<string, unknown> {
|
|
6
6
|
return {
|
|
7
|
-
|
|
7
|
+
mcp_servers: {
|
|
8
8
|
memhub: {
|
|
9
9
|
command: 'npx',
|
|
10
|
-
args: ['-y', '@synth-coder/memhub'],
|
|
10
|
+
args: ['-y', '@synth-coder/memhub@latest'],
|
|
11
11
|
},
|
|
12
12
|
},
|
|
13
13
|
};
|
package/src/cli/agents/cursor.ts
CHANGED
package/src/cli/init.ts
CHANGED
|
@@ -62,6 +62,14 @@ function stringifyConfig(
|
|
|
62
62
|
return JSON.stringify(config, null, 2);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
66
|
+
return typeof value === 'object' && value !== null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getTargetMcpKey(config: Record<string, unknown>): 'mcpServers' | 'mcp_servers' {
|
|
70
|
+
return isRecord(config.mcp_servers) ? 'mcp_servers' : 'mcpServers';
|
|
71
|
+
}
|
|
72
|
+
|
|
65
73
|
/**
|
|
66
74
|
* Merge memhub config into existing config
|
|
67
75
|
* Preserves all existing servers, adds/updates memhub
|
|
@@ -71,19 +79,10 @@ function mergeMcpConfig(
|
|
|
71
79
|
newConfig: Record<string, unknown>
|
|
72
80
|
): Record<string, unknown> {
|
|
73
81
|
const result = { ...existing };
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Merge memhub server
|
|
81
|
-
const existingServers = result.mcpServers as Record<string, unknown>;
|
|
82
|
-
const newServers = newConfig.mcpServers as Record<string, unknown>;
|
|
83
|
-
|
|
84
|
-
for (const [serverName, serverConfig] of Object.entries(newServers)) {
|
|
85
|
-
existingServers[serverName] = serverConfig;
|
|
86
|
-
}
|
|
82
|
+
const targetKey = getTargetMcpKey(newConfig);
|
|
83
|
+
const existingServers = isRecord(result[targetKey]) ? result[targetKey] : {};
|
|
84
|
+
const newServers = (newConfig[targetKey] as Record<string, unknown>) ?? {};
|
|
85
|
+
result[targetKey] = { ...existingServers, ...newServers };
|
|
87
86
|
|
|
88
87
|
return result;
|
|
89
88
|
}
|
|
@@ -158,7 +157,8 @@ export function initAgent(options: InitOptions): InitOutcome {
|
|
|
158
157
|
try {
|
|
159
158
|
const existingContent = readFileSync(configPath, 'utf-8');
|
|
160
159
|
const existingConfig = parseConfig(existingContent, configFormat);
|
|
161
|
-
const
|
|
160
|
+
const targetKey = getTargetMcpKey(newConfig);
|
|
161
|
+
const servers = existingConfig[targetKey] as Record<string, unknown> | undefined;
|
|
162
162
|
|
|
163
163
|
if (servers && 'memhub' in servers) {
|
|
164
164
|
return {
|
package/test/cli/init.test.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { mkdirSync, rmSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
|
|
7
7
|
import { join } from 'path';
|
|
8
8
|
import { initAgent } from '../../src/cli/init.js';
|
|
9
9
|
import { AGENTS, type AgentType } from '../../src/cli/types.js';
|
|
10
|
+
import { parse as parseToml } from 'smol-toml';
|
|
10
11
|
import {
|
|
11
12
|
extractMemHubVersion,
|
|
12
13
|
needsUpdate,
|
|
@@ -209,6 +210,26 @@ describe('CLI Init Command', () => {
|
|
|
209
210
|
expect(config.mcpServers.memhub.command).toBe('npx');
|
|
210
211
|
});
|
|
211
212
|
|
|
213
|
+
it('should generate valid TOML config for codex', () => {
|
|
214
|
+
initAgent({
|
|
215
|
+
agent: 'codex',
|
|
216
|
+
local: true,
|
|
217
|
+
projectPath: TEST_DIR,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const configPath = join(TEST_DIR, '.codex/config.toml');
|
|
221
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
222
|
+
const config = parseToml(content) as Record<string, unknown>;
|
|
223
|
+
const servers = config.mcp_servers as Record<string, unknown>;
|
|
224
|
+
const memhub = servers.memhub as Record<string, unknown>;
|
|
225
|
+
const args = memhub.args as string[];
|
|
226
|
+
|
|
227
|
+
expect(config).toHaveProperty('mcp_servers');
|
|
228
|
+
expect(servers).toHaveProperty('memhub');
|
|
229
|
+
expect(memhub.command).toBe('npx');
|
|
230
|
+
expect(args).toContain('@synth-coder/memhub@latest');
|
|
231
|
+
});
|
|
232
|
+
|
|
212
233
|
it('should generate instructions with version tag', () => {
|
|
213
234
|
initAgent({
|
|
214
235
|
agent: 'claude-code',
|
|
@@ -260,7 +281,7 @@ describe('CLI Init Command', () => {
|
|
|
260
281
|
mcpServers: {
|
|
261
282
|
memhub: {
|
|
262
283
|
command: 'npx',
|
|
263
|
-
args: ['-y', '@synth-coder/memhub'],
|
|
284
|
+
args: ['-y', '@synth-coder/memhub@latest'],
|
|
264
285
|
},
|
|
265
286
|
},
|
|
266
287
|
};
|
|
@@ -315,6 +336,7 @@ describe('CLI Init Command', () => {
|
|
|
315
336
|
expect(config.mcpServers).toHaveProperty('memhub');
|
|
316
337
|
expect(config.mcpServers.memhub.command).toBe('npx');
|
|
317
338
|
});
|
|
339
|
+
|
|
318
340
|
});
|
|
319
341
|
|
|
320
342
|
describe('Instructions Update', () => {
|