memorix 0.3.8 → 0.4.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 +48 -21
- package/dist/cli/index.js +193 -28
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +172 -23
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -2,21 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
> Universal memory layer for AI coding agents via MCP
|
|
4
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/memorix)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
5
8
|
## What is Memorix?
|
|
6
9
|
|
|
7
|
-
Memorix is a lightweight local MCP server that acts as a **universal memory layer** across AI coding agents. Your knowledge from Cursor, Claude Code, Codex, and
|
|
10
|
+
Memorix is a lightweight local MCP server that acts as a **universal memory layer** across AI coding agents. Your knowledge from **Windsurf, Cursor, Claude Code, Codex, and VS Code Copilot** is stored once and shared everywhere.
|
|
8
11
|
|
|
9
12
|
### The Problem
|
|
10
13
|
|
|
11
14
|
- claude-mem only serves Claude Code
|
|
12
|
-
-
|
|
15
|
+
- mcp-memory-service has no cross-agent workspace sync
|
|
13
16
|
- Your architecture decisions in Cursor are invisible to Claude Code
|
|
14
17
|
- Bug fix knowledge in Windsurf doesn't transfer to Codex
|
|
15
|
-
- **No one
|
|
18
|
+
- **No one bridges memory AND workspace configs across agents**
|
|
16
19
|
|
|
17
20
|
### The Solution
|
|
18
21
|
|
|
19
|
-
Memorix stores and indexes project knowledge (architecture decisions, bug fixes, code style preferences) and exposes it via MCP — so **any MCP-supporting agent** can access it.
|
|
22
|
+
Memorix stores and indexes project knowledge (architecture decisions, bug fixes, code style preferences) and exposes it via MCP — so **any MCP-supporting agent** can access it. It also **syncs MCP configs, rules, skills, and workflows** across all your agents automatically.
|
|
20
23
|
|
|
21
24
|
## Features
|
|
22
25
|
|
|
@@ -39,18 +42,21 @@ Memorix stores and indexes project knowledge (architecture decisions, bug fixes,
|
|
|
39
42
|
- **Graceful Degradation**: No fastembed? Falls back to BM25 fulltext automatically
|
|
40
43
|
- **Token Budget**: `maxTokens` parameter trims results to fit context windows
|
|
41
44
|
|
|
42
|
-
### P2 — Cross-Agent Sync
|
|
45
|
+
### P2 — Cross-Agent Workspace Sync
|
|
43
46
|
|
|
47
|
+
- **5 Agent Adapters**: Windsurf, Cursor, Claude Code, Codex, VS Code Copilot
|
|
48
|
+
- **MCP Config Sync**: Detect and migrate MCP server configs across agents (merges into existing files — never overwrites)
|
|
44
49
|
- **Rules Parser**: 4 format adapters (Cursor `.mdc`, Claude Code `CLAUDE.md`, Codex `SKILL.md`, Windsurf `.windsurfrules`)
|
|
45
50
|
- **Rules Syncer**: Scan → Deduplicate → Conflict detection → Cross-format generation
|
|
46
|
-
- **
|
|
47
|
-
- **
|
|
51
|
+
- **Skills Sync**: Scan `.codex/skills/`, `.cursor/skills/`, `.windsurf/skills/`, `.claude/skills/` → copy entire skill folders across agents
|
|
52
|
+
- **Sync Advisory**: On first `memorix_search`, auto-detects available configs/skills from other agents and prompts the user
|
|
53
|
+
- **Selective Sync**: Sync specific items by name (e.g. `items=["figma-remote-mcp-server", "create-subagent"]`)
|
|
48
54
|
- **Apply with Safety**: Backup → Atomic write → Auto-rollback on failure
|
|
49
55
|
|
|
50
56
|
### P3 — Auto-Memory Hooks
|
|
51
57
|
|
|
52
58
|
- **Hook Events**: `user_prompt`, `post_response`, `post_edit`, `post_command`, `post_tool`, `session_end`
|
|
53
|
-
- **Agent Normalizer**: Maps Windsurf/Cursor/Claude/Codex native events to unified hook events
|
|
59
|
+
- **Agent Normalizer**: Maps Windsurf/Cursor/Claude Code/Codex native events to unified hook events
|
|
54
60
|
- **Pattern Detection**: Auto-detects decisions, errors, gotchas, configurations, learnings, implementations
|
|
55
61
|
- **Cooldown Filtering**: Prevents duplicate storage within configurable time windows
|
|
56
62
|
- **Noise Filtering**: Skips trivial commands (`ls`, `cat`, `pwd`, etc.)
|
|
@@ -80,42 +86,63 @@ Memorix stores and indexes project knowledge (architecture decisions, bug fixes,
|
|
|
80
86
|
### Install
|
|
81
87
|
|
|
82
88
|
```bash
|
|
83
|
-
npm install memorix
|
|
89
|
+
npm install -g memorix
|
|
84
90
|
```
|
|
85
91
|
|
|
86
92
|
### Configure in your agent
|
|
87
93
|
|
|
88
|
-
**
|
|
94
|
+
**Windsurf** (`~/.codeium/windsurf/mcp_config.json`):
|
|
89
95
|
```json
|
|
90
96
|
{
|
|
91
97
|
"mcpServers": {
|
|
92
98
|
"memorix": {
|
|
93
|
-
"command": "
|
|
94
|
-
"args": ["
|
|
99
|
+
"command": "memorix",
|
|
100
|
+
"args": ["serve"]
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
103
|
}
|
|
98
104
|
```
|
|
99
105
|
|
|
100
|
-
**
|
|
106
|
+
**Cursor** (`.cursor/mcp.json`):
|
|
101
107
|
```json
|
|
102
108
|
{
|
|
103
109
|
"mcpServers": {
|
|
104
110
|
"memorix": {
|
|
105
|
-
"command": "
|
|
106
|
-
"args": ["
|
|
111
|
+
"command": "memorix",
|
|
112
|
+
"args": ["serve"]
|
|
107
113
|
}
|
|
108
114
|
}
|
|
109
115
|
}
|
|
110
116
|
```
|
|
111
117
|
|
|
112
|
-
**
|
|
118
|
+
**Claude Code** (`~/.claude.json`):
|
|
113
119
|
```json
|
|
114
120
|
{
|
|
115
121
|
"mcpServers": {
|
|
116
122
|
"memorix": {
|
|
117
|
-
"command": "
|
|
118
|
-
"args": ["
|
|
123
|
+
"command": "memorix",
|
|
124
|
+
"args": ["serve"]
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Codex** (`~/.codex/config.toml`):
|
|
131
|
+
```toml
|
|
132
|
+
[mcp_servers.memorix]
|
|
133
|
+
command = "memorix"
|
|
134
|
+
args = ["serve"]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**VS Code Copilot** (VS Code `settings.json` or `.vscode/mcp.json`):
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"mcp": {
|
|
141
|
+
"servers": {
|
|
142
|
+
"memorix": {
|
|
143
|
+
"command": "memorix",
|
|
144
|
+
"args": ["serve"]
|
|
145
|
+
}
|
|
119
146
|
}
|
|
120
147
|
}
|
|
121
148
|
}
|
|
@@ -154,7 +181,7 @@ npm install memorix
|
|
|
154
181
|
```
|
|
155
182
|
┌─────────────────────────────────────────────┐
|
|
156
183
|
│ MCP Clients │
|
|
157
|
-
│
|
|
184
|
+
│ Windsurf│Cursor│Claude Code│Codex│Copilot │
|
|
158
185
|
└──────────────────┬──────────────────────────┘
|
|
159
186
|
│ stdio
|
|
160
187
|
┌──────────────────▼──────────────────────────┐
|
|
@@ -177,7 +204,7 @@ npm install memorix
|
|
|
177
204
|
│ │
|
|
178
205
|
│ ┌────────────────────────────────────┐ │
|
|
179
206
|
│ │ Rules & Skills Syncer │ │
|
|
180
|
-
│ │ Cursor│Claude│Codex│Windsurf
|
|
207
|
+
│ │ Cursor│Claude Code│Codex│Windsurf│Copilot│ │
|
|
181
208
|
│ │ rules: scan→dedup→conflict→gen │ │
|
|
182
209
|
│ │ skills: scan→copy (no convert) │ │
|
|
183
210
|
│ └────────────────────────────────────┘ │
|
|
@@ -246,4 +273,4 @@ Memorix stands on the shoulders of these excellent projects:
|
|
|
246
273
|
|
|
247
274
|
## License
|
|
248
275
|
|
|
249
|
-
|
|
276
|
+
Apache 2.0 — see [LICENSE](LICENSE)
|
package/dist/cli/index.js
CHANGED
|
@@ -1520,6 +1520,93 @@ var init_windsurf = __esm({
|
|
|
1520
1520
|
}
|
|
1521
1521
|
});
|
|
1522
1522
|
|
|
1523
|
+
// src/rules/adapters/antigravity.ts
|
|
1524
|
+
import matter5 from "gray-matter";
|
|
1525
|
+
var AntigravityAdapter;
|
|
1526
|
+
var init_antigravity = __esm({
|
|
1527
|
+
"src/rules/adapters/antigravity.ts"() {
|
|
1528
|
+
"use strict";
|
|
1529
|
+
init_esm_shims();
|
|
1530
|
+
init_utils();
|
|
1531
|
+
AntigravityAdapter = class {
|
|
1532
|
+
source = "antigravity";
|
|
1533
|
+
filePatterns = [
|
|
1534
|
+
"GEMINI.md",
|
|
1535
|
+
".agent/rules/*.md",
|
|
1536
|
+
".agent/skills/*/SKILL.md"
|
|
1537
|
+
];
|
|
1538
|
+
parse(filePath, content) {
|
|
1539
|
+
if (filePath.includes("SKILL.md")) {
|
|
1540
|
+
return this.parseSkillMd(filePath, content);
|
|
1541
|
+
}
|
|
1542
|
+
if (filePath.includes(".agent/rules/")) {
|
|
1543
|
+
return this.parseAgentRule(filePath, content);
|
|
1544
|
+
}
|
|
1545
|
+
if (filePath === "GEMINI.md" || filePath.endsWith("/GEMINI.md")) {
|
|
1546
|
+
return this.parseGeminiMd(filePath, content);
|
|
1547
|
+
}
|
|
1548
|
+
return [];
|
|
1549
|
+
}
|
|
1550
|
+
generate(rules) {
|
|
1551
|
+
const projectRules = rules.filter((r) => r.scope !== "path-specific");
|
|
1552
|
+
const pathRules = rules.filter((r) => r.scope === "path-specific");
|
|
1553
|
+
const files = [];
|
|
1554
|
+
for (const rule of [...projectRules, ...pathRules]) {
|
|
1555
|
+
const fm = {};
|
|
1556
|
+
if (rule.description) fm.description = rule.description;
|
|
1557
|
+
const fileName = rule.id.replace(/^antigravity:/, "").replace(/[^a-zA-Z0-9-_]/g, "-") || "rule";
|
|
1558
|
+
const body = Object.keys(fm).length > 0 ? matter5.stringify(rule.content, fm) : rule.content;
|
|
1559
|
+
files.push({
|
|
1560
|
+
filePath: `.agent/rules/${fileName}.md`,
|
|
1561
|
+
content: body
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
return files;
|
|
1565
|
+
}
|
|
1566
|
+
parseGeminiMd(filePath, content) {
|
|
1567
|
+
const trimmed = content.trim();
|
|
1568
|
+
if (!trimmed) return [];
|
|
1569
|
+
return [{
|
|
1570
|
+
id: generateRuleId("antigravity", filePath),
|
|
1571
|
+
content: trimmed,
|
|
1572
|
+
source: "antigravity",
|
|
1573
|
+
scope: "global",
|
|
1574
|
+
priority: 10,
|
|
1575
|
+
hash: hashContent(trimmed)
|
|
1576
|
+
}];
|
|
1577
|
+
}
|
|
1578
|
+
parseAgentRule(filePath, content) {
|
|
1579
|
+
const { data, content: body } = matter5(content);
|
|
1580
|
+
const trimmed = body.trim();
|
|
1581
|
+
if (!trimmed) return [];
|
|
1582
|
+
return [{
|
|
1583
|
+
id: generateRuleId("antigravity", filePath),
|
|
1584
|
+
content: trimmed,
|
|
1585
|
+
description: data.description,
|
|
1586
|
+
source: "antigravity",
|
|
1587
|
+
scope: "project",
|
|
1588
|
+
priority: 5,
|
|
1589
|
+
hash: hashContent(trimmed)
|
|
1590
|
+
}];
|
|
1591
|
+
}
|
|
1592
|
+
parseSkillMd(filePath, content) {
|
|
1593
|
+
const { data, content: body } = matter5(content);
|
|
1594
|
+
const trimmed = body.trim();
|
|
1595
|
+
if (!trimmed) return [];
|
|
1596
|
+
return [{
|
|
1597
|
+
id: generateRuleId("antigravity", filePath),
|
|
1598
|
+
content: trimmed,
|
|
1599
|
+
description: data.description || void 0,
|
|
1600
|
+
source: "antigravity",
|
|
1601
|
+
scope: "project",
|
|
1602
|
+
priority: 5,
|
|
1603
|
+
hash: hashContent(trimmed)
|
|
1604
|
+
}];
|
|
1605
|
+
}
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
});
|
|
1609
|
+
|
|
1523
1610
|
// src/rules/syncer.ts
|
|
1524
1611
|
var syncer_exports = {};
|
|
1525
1612
|
__export(syncer_exports, {
|
|
@@ -1536,6 +1623,7 @@ var init_syncer = __esm({
|
|
|
1536
1623
|
init_claude_code();
|
|
1537
1624
|
init_codex();
|
|
1538
1625
|
init_windsurf();
|
|
1626
|
+
init_antigravity();
|
|
1539
1627
|
RulesSyncer = class {
|
|
1540
1628
|
projectRoot;
|
|
1541
1629
|
adapters;
|
|
@@ -1546,7 +1634,8 @@ var init_syncer = __esm({
|
|
|
1546
1634
|
new CursorAdapter(),
|
|
1547
1635
|
new ClaudeCodeAdapter(),
|
|
1548
1636
|
new CodexAdapter(),
|
|
1549
|
-
new WindsurfAdapter()
|
|
1637
|
+
new WindsurfAdapter(),
|
|
1638
|
+
new AntigravityAdapter()
|
|
1550
1639
|
];
|
|
1551
1640
|
for (const a of all) {
|
|
1552
1641
|
this.adapters.set(a.source, a);
|
|
@@ -2085,8 +2174,78 @@ var init_copilot = __esm({
|
|
|
2085
2174
|
}
|
|
2086
2175
|
});
|
|
2087
2176
|
|
|
2177
|
+
// src/workspace/mcp-adapters/antigravity.ts
|
|
2178
|
+
import { homedir as homedir6 } from "os";
|
|
2179
|
+
import { join as join6 } from "path";
|
|
2180
|
+
var AntigravityMCPAdapter;
|
|
2181
|
+
var init_antigravity2 = __esm({
|
|
2182
|
+
"src/workspace/mcp-adapters/antigravity.ts"() {
|
|
2183
|
+
"use strict";
|
|
2184
|
+
init_esm_shims();
|
|
2185
|
+
AntigravityMCPAdapter = class {
|
|
2186
|
+
source = "antigravity";
|
|
2187
|
+
parse(content) {
|
|
2188
|
+
try {
|
|
2189
|
+
const config = JSON.parse(content);
|
|
2190
|
+
const servers = config.mcpServers ?? config.mcp_servers ?? {};
|
|
2191
|
+
return Object.entries(servers).map(([name, entry]) => {
|
|
2192
|
+
const result = {
|
|
2193
|
+
name,
|
|
2194
|
+
command: entry.command ?? "",
|
|
2195
|
+
args: entry.args ?? []
|
|
2196
|
+
};
|
|
2197
|
+
if (entry.serverUrl) {
|
|
2198
|
+
result.url = entry.serverUrl;
|
|
2199
|
+
} else if (entry.url) {
|
|
2200
|
+
result.url = entry.url;
|
|
2201
|
+
}
|
|
2202
|
+
if (entry.headers && typeof entry.headers === "object" && Object.keys(entry.headers).length > 0) {
|
|
2203
|
+
result.headers = entry.headers;
|
|
2204
|
+
}
|
|
2205
|
+
if (entry.env && typeof entry.env === "object" && Object.keys(entry.env).length > 0) {
|
|
2206
|
+
result.env = entry.env;
|
|
2207
|
+
}
|
|
2208
|
+
if (entry.disabled === true) {
|
|
2209
|
+
result.disabled = true;
|
|
2210
|
+
}
|
|
2211
|
+
return result;
|
|
2212
|
+
});
|
|
2213
|
+
} catch {
|
|
2214
|
+
return [];
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
generate(servers) {
|
|
2218
|
+
const mcpServers = {};
|
|
2219
|
+
for (const s of servers) {
|
|
2220
|
+
const entry = {};
|
|
2221
|
+
if (s.url) {
|
|
2222
|
+
entry.url = s.url;
|
|
2223
|
+
if (s.headers && Object.keys(s.headers).length > 0) {
|
|
2224
|
+
entry.headers = s.headers;
|
|
2225
|
+
}
|
|
2226
|
+
} else {
|
|
2227
|
+
entry.command = s.command;
|
|
2228
|
+
entry.args = s.args;
|
|
2229
|
+
}
|
|
2230
|
+
if (s.env && Object.keys(s.env).length > 0) {
|
|
2231
|
+
entry.env = s.env;
|
|
2232
|
+
}
|
|
2233
|
+
if (s.disabled === true) {
|
|
2234
|
+
entry.disabled = true;
|
|
2235
|
+
}
|
|
2236
|
+
mcpServers[s.name] = entry;
|
|
2237
|
+
}
|
|
2238
|
+
return JSON.stringify({ mcpServers }, null, 2);
|
|
2239
|
+
}
|
|
2240
|
+
getConfigPath(_projectRoot) {
|
|
2241
|
+
return join6(homedir6(), ".gemini", "antigravity", "mcp_config.json");
|
|
2242
|
+
}
|
|
2243
|
+
};
|
|
2244
|
+
}
|
|
2245
|
+
});
|
|
2246
|
+
|
|
2088
2247
|
// src/workspace/workflow-sync.ts
|
|
2089
|
-
import
|
|
2248
|
+
import matter6 from "gray-matter";
|
|
2090
2249
|
var WorkflowSyncer;
|
|
2091
2250
|
var init_workflow_sync = __esm({
|
|
2092
2251
|
"src/workspace/workflow-sync.ts"() {
|
|
@@ -2101,7 +2260,7 @@ var init_workflow_sync = __esm({
|
|
|
2101
2260
|
let description = "";
|
|
2102
2261
|
let content = raw;
|
|
2103
2262
|
try {
|
|
2104
|
-
const parsed =
|
|
2263
|
+
const parsed = matter6(raw);
|
|
2105
2264
|
description = parsed.data?.description ?? "";
|
|
2106
2265
|
content = parsed.content.trim();
|
|
2107
2266
|
} catch {
|
|
@@ -2123,7 +2282,7 @@ var init_workflow_sync = __esm({
|
|
|
2123
2282
|
if (wf.description) {
|
|
2124
2283
|
fm.description = wf.description;
|
|
2125
2284
|
}
|
|
2126
|
-
const content =
|
|
2285
|
+
const content = matter6.stringify(wf.content, fm);
|
|
2127
2286
|
return {
|
|
2128
2287
|
filePath: `.agents/skills/${safeName}/SKILL.md`,
|
|
2129
2288
|
content
|
|
@@ -2140,7 +2299,7 @@ var init_workflow_sync = __esm({
|
|
|
2140
2299
|
}
|
|
2141
2300
|
fm.globs = "";
|
|
2142
2301
|
fm.alwaysApply = "false";
|
|
2143
|
-
const content =
|
|
2302
|
+
const content = matter6.stringify(wf.content, fm);
|
|
2144
2303
|
return {
|
|
2145
2304
|
filePath: `.cursor/rules/${safeName}.mdc`,
|
|
2146
2305
|
content
|
|
@@ -2328,8 +2487,8 @@ var init_applier = __esm({
|
|
|
2328
2487
|
|
|
2329
2488
|
// src/workspace/engine.ts
|
|
2330
2489
|
import { readFileSync as readFileSync2, readdirSync, existsSync as existsSync4, cpSync, mkdirSync as mkdirSync2 } from "fs";
|
|
2331
|
-
import { join as
|
|
2332
|
-
import { homedir as
|
|
2490
|
+
import { join as join8 } from "path";
|
|
2491
|
+
import { homedir as homedir7 } from "os";
|
|
2333
2492
|
var WorkspaceSyncEngine;
|
|
2334
2493
|
var init_engine2 = __esm({
|
|
2335
2494
|
"src/workspace/engine.ts"() {
|
|
@@ -2340,6 +2499,7 @@ var init_engine2 = __esm({
|
|
|
2340
2499
|
init_codex2();
|
|
2341
2500
|
init_claude_code2();
|
|
2342
2501
|
init_copilot();
|
|
2502
|
+
init_antigravity2();
|
|
2343
2503
|
init_workflow_sync();
|
|
2344
2504
|
init_syncer();
|
|
2345
2505
|
init_sanitizer();
|
|
@@ -2352,7 +2512,8 @@ var init_engine2 = __esm({
|
|
|
2352
2512
|
["cursor", new CursorMCPAdapter()],
|
|
2353
2513
|
["codex", new CodexMCPAdapter()],
|
|
2354
2514
|
["claude-code", new ClaudeCodeMCPAdapter()],
|
|
2355
|
-
["copilot", new CopilotMCPAdapter()]
|
|
2515
|
+
["copilot", new CopilotMCPAdapter()],
|
|
2516
|
+
["antigravity", new AntigravityMCPAdapter()]
|
|
2356
2517
|
]);
|
|
2357
2518
|
this.workflowSyncer = new WorkflowSyncer();
|
|
2358
2519
|
this.rulesSyncer = new RulesSyncer(projectRoot);
|
|
@@ -2369,7 +2530,8 @@ var init_engine2 = __esm({
|
|
|
2369
2530
|
cursor: [],
|
|
2370
2531
|
codex: [],
|
|
2371
2532
|
"claude-code": [],
|
|
2372
|
-
copilot: []
|
|
2533
|
+
copilot: [],
|
|
2534
|
+
antigravity: []
|
|
2373
2535
|
};
|
|
2374
2536
|
for (const [target, adapter] of this.adapters) {
|
|
2375
2537
|
const configPath = adapter.getConfigPath(this.projectRoot);
|
|
@@ -2460,13 +2622,14 @@ var init_engine2 = __esm({
|
|
|
2460
2622
|
cursor: [".cursor/skills", ".cursor/skills-cursor"],
|
|
2461
2623
|
windsurf: [".windsurf/skills"],
|
|
2462
2624
|
"claude-code": [".claude/skills"],
|
|
2463
|
-
copilot: []
|
|
2625
|
+
copilot: [],
|
|
2626
|
+
antigravity: [".agent/skills", ".gemini/skills", ".gemini/antigravity/skills"]
|
|
2464
2627
|
};
|
|
2465
2628
|
/** Get the target skills directory for an agent (null if agent has no skills support) */
|
|
2466
2629
|
getTargetSkillsDir(target) {
|
|
2467
2630
|
const dirs = _WorkspaceSyncEngine.SKILLS_DIRS[target];
|
|
2468
2631
|
if (!dirs || dirs.length === 0) return null;
|
|
2469
|
-
return
|
|
2632
|
+
return join8(this.projectRoot, dirs[0]);
|
|
2470
2633
|
}
|
|
2471
2634
|
/**
|
|
2472
2635
|
* Scan all agent skills directories and collect unique skills.
|
|
@@ -2475,12 +2638,12 @@ var init_engine2 = __esm({
|
|
|
2475
2638
|
const skills = [];
|
|
2476
2639
|
const conflicts = [];
|
|
2477
2640
|
const seen = /* @__PURE__ */ new Map();
|
|
2478
|
-
const home =
|
|
2641
|
+
const home = homedir7();
|
|
2479
2642
|
for (const [agent, dirs] of Object.entries(_WorkspaceSyncEngine.SKILLS_DIRS)) {
|
|
2480
2643
|
for (const dir of dirs) {
|
|
2481
2644
|
const paths = [
|
|
2482
|
-
|
|
2483
|
-
|
|
2645
|
+
join8(this.projectRoot, dir),
|
|
2646
|
+
join8(home, dir)
|
|
2484
2647
|
];
|
|
2485
2648
|
for (const skillsRoot of paths) {
|
|
2486
2649
|
if (!existsSync4(skillsRoot)) continue;
|
|
@@ -2488,7 +2651,7 @@ var init_engine2 = __esm({
|
|
|
2488
2651
|
const entries = readdirSync(skillsRoot, { withFileTypes: true });
|
|
2489
2652
|
for (const entry of entries) {
|
|
2490
2653
|
if (!entry.isDirectory()) continue;
|
|
2491
|
-
const skillMd =
|
|
2654
|
+
const skillMd = join8(skillsRoot, entry.name, "SKILL.md");
|
|
2492
2655
|
if (!existsSync4(skillMd)) continue;
|
|
2493
2656
|
let description = "";
|
|
2494
2657
|
try {
|
|
@@ -2500,7 +2663,7 @@ var init_engine2 = __esm({
|
|
|
2500
2663
|
const newEntry = {
|
|
2501
2664
|
name: entry.name,
|
|
2502
2665
|
description,
|
|
2503
|
-
sourcePath:
|
|
2666
|
+
sourcePath: join8(skillsRoot, entry.name),
|
|
2504
2667
|
sourceAgent: agent
|
|
2505
2668
|
};
|
|
2506
2669
|
const existing = seen.get(entry.name);
|
|
@@ -2537,7 +2700,7 @@ var init_engine2 = __esm({
|
|
|
2537
2700
|
}
|
|
2538
2701
|
for (const skill of skills) {
|
|
2539
2702
|
if (skill.sourceAgent === target) continue;
|
|
2540
|
-
const dest =
|
|
2703
|
+
const dest = join8(targetDir, skill.name);
|
|
2541
2704
|
if (existsSync4(dest)) {
|
|
2542
2705
|
skipped.push(`${skill.name} (already exists in ${target})`);
|
|
2543
2706
|
continue;
|
|
@@ -2553,13 +2716,13 @@ var init_engine2 = __esm({
|
|
|
2553
2716
|
}
|
|
2554
2717
|
scanWorkflows() {
|
|
2555
2718
|
const workflows = [];
|
|
2556
|
-
const wfDir =
|
|
2719
|
+
const wfDir = join8(this.projectRoot, ".windsurf", "workflows");
|
|
2557
2720
|
if (!existsSync4(wfDir)) return workflows;
|
|
2558
2721
|
try {
|
|
2559
2722
|
const files = readdirSync(wfDir).filter((f) => f.endsWith(".md"));
|
|
2560
2723
|
for (const file of files) {
|
|
2561
2724
|
try {
|
|
2562
|
-
const content = readFileSync2(
|
|
2725
|
+
const content = readFileSync2(join8(wfDir, file), "utf-8");
|
|
2563
2726
|
workflows.push(this.workflowSyncer.parseWindsurfWorkflow(file, content));
|
|
2564
2727
|
} catch {
|
|
2565
2728
|
}
|
|
@@ -2646,7 +2809,8 @@ var init_engine2 = __esm({
|
|
|
2646
2809
|
"claude-code": "claude-code",
|
|
2647
2810
|
codex: "codex",
|
|
2648
2811
|
windsurf: "windsurf",
|
|
2649
|
-
copilot: "windsurf"
|
|
2812
|
+
copilot: "windsurf",
|
|
2813
|
+
antigravity: "antigravity"
|
|
2650
2814
|
};
|
|
2651
2815
|
return map[target] ?? null;
|
|
2652
2816
|
}
|
|
@@ -3583,12 +3747,12 @@ Entity: ${entityName} | Type: ${type} | Project: ${project.id}${enrichment}`
|
|
|
3583
3747
|
};
|
|
3584
3748
|
}
|
|
3585
3749
|
);
|
|
3586
|
-
const RULE_SOURCES = ["cursor", "claude-code", "codex", "windsurf"];
|
|
3750
|
+
const RULE_SOURCES = ["cursor", "claude-code", "codex", "windsurf", "antigravity"];
|
|
3587
3751
|
server.registerTool(
|
|
3588
3752
|
"memorix_rules_sync",
|
|
3589
3753
|
{
|
|
3590
3754
|
title: "Rules Sync",
|
|
3591
|
-
description: "Scan project for agent rule files (Cursor, Claude Code, Codex, Windsurf), deduplicate, detect conflicts, and optionally generate rules for a target agent format. Without target: returns sync status report. With target: generates converted rule files.",
|
|
3755
|
+
description: "Scan project for agent rule files (Cursor, Claude Code, Codex, Windsurf, Antigravity), deduplicate, detect conflicts, and optionally generate rules for a target agent format. Without target: returns sync status report. With target: generates converted rule files.",
|
|
3592
3756
|
inputSchema: {
|
|
3593
3757
|
action: z.enum(["status", "generate"]).describe('Action: "status" for report, "generate" to produce target files'),
|
|
3594
3758
|
target: z.enum(RULE_SOURCES).optional().describe("Target agent format for generation (required when action=generate)")
|
|
@@ -3638,7 +3802,7 @@ Entity: ${entityName} | Type: ${type} | Project: ${project.id}${enrichment}`
|
|
|
3638
3802
|
};
|
|
3639
3803
|
}
|
|
3640
3804
|
);
|
|
3641
|
-
const AGENT_TARGETS = ["windsurf", "cursor", "claude-code", "codex", "copilot"];
|
|
3805
|
+
const AGENT_TARGETS = ["windsurf", "cursor", "claude-code", "codex", "copilot", "antigravity"];
|
|
3642
3806
|
server.registerTool(
|
|
3643
3807
|
"memorix_workspace_sync",
|
|
3644
3808
|
{
|
|
@@ -3882,7 +4046,8 @@ var init_sync = __esm({
|
|
|
3882
4046
|
cursor: "Cursor (.cursor/rules/*.mdc, .cursorrules)",
|
|
3883
4047
|
"claude-code": "Claude Code (CLAUDE.md, .claude/rules/*.md)",
|
|
3884
4048
|
codex: "Codex (SKILL.md, AGENTS.md)",
|
|
3885
|
-
windsurf: "Windsurf (.windsurfrules, .windsurf/rules/*.md)"
|
|
4049
|
+
windsurf: "Windsurf (.windsurfrules, .windsurf/rules/*.md)",
|
|
4050
|
+
antigravity: "Antigravity (.agent/rules/*.md, GEMINI.md)"
|
|
3886
4051
|
};
|
|
3887
4052
|
sync_default = defineCommand3({
|
|
3888
4053
|
meta: {
|
|
@@ -3892,7 +4057,7 @@ var init_sync = __esm({
|
|
|
3892
4057
|
args: {
|
|
3893
4058
|
target: {
|
|
3894
4059
|
type: "string",
|
|
3895
|
-
description: "Target agent format (cursor, claude-code, codex, windsurf)",
|
|
4060
|
+
description: "Target agent format (cursor, claude-code, codex, windsurf, antigravity)",
|
|
3896
4061
|
required: false
|
|
3897
4062
|
},
|
|
3898
4063
|
dry: {
|
|
@@ -3935,11 +4100,11 @@ var init_sync = __esm({
|
|
|
3935
4100
|
}
|
|
3936
4101
|
let target = args.target;
|
|
3937
4102
|
if (!target) {
|
|
3938
|
-
const available = ["cursor", "claude-code", "codex", "windsurf"].filter(
|
|
4103
|
+
const available = ["cursor", "claude-code", "codex", "windsurf", "antigravity"].filter(
|
|
3939
4104
|
(t) => !sources.includes(t)
|
|
3940
4105
|
);
|
|
3941
4106
|
if (available.length === 0) {
|
|
3942
|
-
available.push("cursor", "claude-code", "codex", "windsurf");
|
|
4107
|
+
available.push("cursor", "claude-code", "codex", "windsurf", "antigravity");
|
|
3943
4108
|
}
|
|
3944
4109
|
const selected = await p2.select({
|
|
3945
4110
|
message: "Generate rules for which agent?",
|
|
@@ -4706,7 +4871,7 @@ import { defineCommand as defineCommand9, runMain } from "citty";
|
|
|
4706
4871
|
var main = defineCommand9({
|
|
4707
4872
|
meta: {
|
|
4708
4873
|
name: "memorix",
|
|
4709
|
-
version: "0.3.
|
|
4874
|
+
version: "0.3.9",
|
|
4710
4875
|
description: "Cross-Agent Memory Bridge \u2014 Universal memory layer for AI coding agents via MCP"
|
|
4711
4876
|
},
|
|
4712
4877
|
subCommands: {
|