mnueron 0.1.1 → 0.2.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.
@@ -0,0 +1,59 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ /**
5
+ * Aider (aider.chat) — pair-programming AI in the terminal.
6
+ *
7
+ * As of late-2026 Aider doesn't natively speak MCP — it talks to LLM APIs
8
+ * directly via LiteLLM. So we DETECT Aider's presence (so `mnueron setup`
9
+ * can report it as "found, manual integration only") but we don't write
10
+ * a config that Aider wouldn't read.
11
+ *
12
+ * If/when Aider adds MCP server support upstream, we'll switch this to
13
+ * extend JsonMcpDetector and target the right config key.
14
+ *
15
+ * Detection signals (any one is enough):
16
+ * - ~/.aider.conf.yml exists (Aider's main config file)
17
+ * - ~/.aider.input.history exists (Aider's prompt-history cache)
18
+ * - .aider.* files in CWD (project-local Aider state)
19
+ */
20
+ export class AiderDetector {
21
+ id = 'aider';
22
+ displayName = 'Aider';
23
+ isInstalled() {
24
+ const home = homedir();
25
+ if (existsSync(join(home, '.aider.conf.yml')))
26
+ return true;
27
+ if (existsSync(join(home, '.aider.input.history')))
28
+ return true;
29
+ if (existsSync(join(home, '.aider.chat.history.md')))
30
+ return true;
31
+ return false;
32
+ }
33
+ status() {
34
+ const installed = this.isInstalled();
35
+ return {
36
+ id: this.id,
37
+ displayName: this.displayName,
38
+ installed,
39
+ configPath: null,
40
+ configExists: false,
41
+ alreadyConfigured: false,
42
+ };
43
+ }
44
+ install(_serverName, _entry) {
45
+ const installed = this.isInstalled();
46
+ if (!installed) {
47
+ return { ok: false, changed: false, message: `${this.displayName} not detected` };
48
+ }
49
+ return {
50
+ ok: true, changed: false,
51
+ message: 'Aider does not yet speak MCP natively — install the mnueron Python SDK and call ' +
52
+ 'mem.recall() inside an Aider /run hook, or wait for upstream MCP support.',
53
+ };
54
+ }
55
+ uninstall(_serverName) {
56
+ return { ok: true, removed: false, message: 'no config to remove (Aider has no MCP support yet)' };
57
+ }
58
+ }
59
+ //# sourceMappingURL=aider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aider.js","sourceRoot":"","sources":["../../src/detectors/aider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAKjC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,aAAa;IACxB,EAAE,GAAG,OAAO,CAAC;IACb,WAAW,GAAG,OAAO,CAAC;IAEd,WAAW;QACjB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3D,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAChE,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAClE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM;QACJ,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS;YACT,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,KAAK;YACnB,iBAAiB,EAAE,KAAK;SACzB,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,WAAmB,EAAE,MAAsB;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,WAAW,eAAe,EAAE,CAAC;QACpF,CAAC;QACD,OAAO;YACL,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK;YACxB,OAAO,EACL,kFAAkF;gBAClF,2EAA2E;SAC9E,CAAC;IACJ,CAAC;IAED,SAAS,CAAC,WAAmB;QAC3B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,oDAAoD,EAAE,CAAC;IACrG,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { JsonMcpDetector } from './json_detector.js';
5
+ /**
6
+ * Continue (continue.dev) — open-source AI coding assistant for VS Code,
7
+ * JetBrains, and standalone. Stores its global config at:
8
+ *
9
+ * ~/.continue/config.json (legacy, still supported)
10
+ * ~/.continue/config.yaml (newer, default for fresh installs)
11
+ *
12
+ * MCP servers go under `experimental.modelContextProtocolServers` in JSON
13
+ * or `mcpServers` in YAML. We target the JSON config path because we ship
14
+ * JsonMcpDetector and most existing users still have the JSON variant. If
15
+ * a user only has the YAML config we surface that as "detected but not
16
+ * configured" so they know to wire it manually.
17
+ */
18
+ export class ContinueDetector extends JsonMcpDetector {
19
+ id = 'continue';
20
+ displayName = 'Continue';
21
+ configPath() {
22
+ return join(homedir(), '.continue', 'config.json');
23
+ }
24
+ isInstalled() {
25
+ // The .continue/ directory exists if the user has installed any Continue
26
+ // edition (VS Code, JetBrains, CLI). Presence of EITHER config.json or
27
+ // config.yaml is the strongest signal.
28
+ return existsSync(join(homedir(), '.continue'));
29
+ }
30
+ }
31
+ //# sourceMappingURL=continue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"continue.js","sourceRoot":"","sources":["../../src/detectors/continue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,gBAAiB,SAAQ,eAAe;IACnD,EAAE,GAAG,UAAU,CAAC;IAChB,WAAW,GAAG,UAAU,CAAC;IAEf,UAAU;QAClB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IACrD,CAAC;IAES,WAAW;QACnB,yEAAyE;QACzE,uEAAuE;QACvE,uCAAuC;QACvC,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;IAClD,CAAC;CACF"}
@@ -0,0 +1,48 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { homedir, platform } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { JsonMcpDetector } from './json_detector.js';
5
+ /**
6
+ * Goose (block.xyz/goose) — an MCP-native open-source AI agent. Goose's
7
+ * config is YAML by default, but it ALSO honours a JSON config at the
8
+ * same path if you choose it explicitly. We write the JSON variant so we
9
+ * can lean on JsonMcpDetector — users with the YAML config will see
10
+ * "configPath exists but not yet wired" and can copy the JSON in.
11
+ *
12
+ * Config locations:
13
+ * macOS / Linux: ~/.config/goose/config.json (or config.yaml)
14
+ * Windows: %APPDATA%\Block\goose\config.json
15
+ *
16
+ * Goose stores MCP servers under the `extensions` key in YAML, or under
17
+ * `mcpServers` in JSON config (mirroring Cursor / Claude Desktop). Our
18
+ * JsonMcpDetector writes to mcpServers, which Goose accepts.
19
+ */
20
+ export class GooseDetector extends JsonMcpDetector {
21
+ id = 'goose';
22
+ displayName = 'Goose';
23
+ configPath() {
24
+ const home = homedir();
25
+ switch (platform()) {
26
+ case 'win32': {
27
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
28
+ return join(appdata, 'Block', 'goose', 'config.json');
29
+ }
30
+ default:
31
+ return join(home, '.config', 'goose', 'config.json');
32
+ }
33
+ }
34
+ isInstalled() {
35
+ const home = homedir();
36
+ // Either the config dir exists or a Goose binary is on PATH (we don't
37
+ // try to resolve PATH to avoid spawning a child process at detect time).
38
+ switch (platform()) {
39
+ case 'win32': {
40
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
41
+ return existsSync(join(appdata, 'Block', 'goose'));
42
+ }
43
+ default:
44
+ return existsSync(join(home, '.config', 'goose'));
45
+ }
46
+ }
47
+ }
48
+ //# sourceMappingURL=goose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goose.js","sourceRoot":"","sources":["../../src/detectors/goose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,aAAc,SAAQ,eAAe;IAChD,EAAE,GAAG,OAAO,CAAC;IACb,WAAW,GAAG,OAAO,CAAC;IAEZ,UAAU;QAClB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,QAAQ,QAAQ,EAAE,EAAE,CAAC;YACnB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBACxE,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;YACxD,CAAC;YACD;gBACE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAES,WAAW;QACnB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,sEAAsE;QACtE,yEAAyE;QACzE,QAAQ,QAAQ,EAAE,EAAE,CAAC;YACnB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBACxE,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YACrD,CAAC;YACD;gBACE,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;CACF"}
@@ -2,6 +2,17 @@ import { ClaudeDesktopDetector } from './claude_desktop.js';
2
2
  import { ClaudeCodeDetector } from './claude_code.js';
3
3
  import { CursorDetector } from './cursor.js';
4
4
  import { WindsurfDetector, ClineDetector } from './extra.js';
5
+ // v0.2.7 — additional MCP-speaking editors and agents.
6
+ import { ContinueDetector } from './continue.js';
7
+ import { ZedDetector } from './zed.js';
8
+ import { AiderDetector } from './aider.js';
9
+ import { GooseDetector } from './goose.js';
10
+ import { OpenCodeDetector } from './opencode.js';
11
+ /**
12
+ * Order matters for the setup wizard output. The first five (Claude-family +
13
+ * Cursor + Windsurf + Cline) are the original tier-1 tools. The v0.2.7
14
+ * additions come after — they're real but lower-density in our user base.
15
+ */
5
16
  export function allDetectors() {
6
17
  return [
7
18
  new ClaudeDesktopDetector(),
@@ -9,6 +20,11 @@ export function allDetectors() {
9
20
  new CursorDetector(),
10
21
  new WindsurfDetector(),
11
22
  new ClineDetector(),
23
+ new ContinueDetector(),
24
+ new ZedDetector(),
25
+ new GooseDetector(),
26
+ new OpenCodeDetector(),
27
+ new AiderDetector(),
12
28
  ];
13
29
  }
14
30
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/detectors/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,IAAI,qBAAqB,EAAE;QAC3B,IAAI,kBAAkB,EAAE;QACxB,IAAI,cAAc,EAAE;QACpB,IAAI,gBAAgB,EAAE;QACtB,IAAI,aAAa,EAAE;KACpB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/detectors/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC7D,uDAAuD;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,IAAI,qBAAqB,EAAE;QAC3B,IAAI,kBAAkB,EAAE;QACxB,IAAI,cAAc,EAAE;QACpB,IAAI,gBAAgB,EAAE;QACtB,IAAI,aAAa,EAAE;QACnB,IAAI,gBAAgB,EAAE;QACtB,IAAI,WAAW,EAAE;QACjB,IAAI,aAAa,EAAE;QACnB,IAAI,gBAAgB,EAAE;QACtB,IAAI,aAAa,EAAE;KACpB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { homedir, platform } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { JsonMcpDetector } from './json_detector.js';
5
+ /**
6
+ * OpenCode (sst.dev/opencode) — open-source terminal AI coding agent.
7
+ * Speaks MCP natively. Config lives at:
8
+ *
9
+ * macOS / Linux: ~/.config/opencode/config.json
10
+ * Windows: %APPDATA%\opencode\config.json
11
+ *
12
+ * Schema: standard `mcpServers` map — same shape as Cursor / Claude Desktop,
13
+ * so we inherit JsonMcpDetector directly. OpenCode auto-reloads MCP servers
14
+ * when the config changes; users don't have to restart.
15
+ */
16
+ export class OpenCodeDetector extends JsonMcpDetector {
17
+ id = 'opencode';
18
+ displayName = 'OpenCode';
19
+ configPath() {
20
+ const home = homedir();
21
+ switch (platform()) {
22
+ case 'win32': {
23
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
24
+ return join(appdata, 'opencode', 'config.json');
25
+ }
26
+ default:
27
+ return join(home, '.config', 'opencode', 'config.json');
28
+ }
29
+ }
30
+ isInstalled() {
31
+ const home = homedir();
32
+ switch (platform()) {
33
+ case 'win32': {
34
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
35
+ return existsSync(join(appdata, 'opencode'));
36
+ }
37
+ default:
38
+ return existsSync(join(home, '.config', 'opencode'));
39
+ }
40
+ }
41
+ }
42
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/detectors/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;GAUG;AACH,MAAM,OAAO,gBAAiB,SAAQ,eAAe;IACnD,EAAE,GAAG,UAAU,CAAC;IAChB,WAAW,GAAG,UAAU,CAAC;IAEf,UAAU;QAClB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,QAAQ,QAAQ,EAAE,EAAE,CAAC;YACnB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBACxE,OAAO,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;YAClD,CAAC;YACD;gBACE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAES,WAAW;QACnB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,QAAQ,QAAQ,EAAE,EAAE,CAAC;YACnB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBACxE,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD;gBACE,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,138 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, } from 'node:fs';
2
+ import { homedir, platform } from 'node:os';
3
+ import { dirname, join } from 'node:path';
4
+ /**
5
+ * Zed (zed.dev) — Rust-based collaborative editor. MCP servers are
6
+ * declared under the `context_servers` key in Zed's settings.json (NOT
7
+ * the standard `mcpServers` key our other detectors use), so we can't
8
+ * inherit JsonMcpDetector — we need a custom install/uninstall path.
9
+ *
10
+ * Locations:
11
+ * macOS: ~/.config/zed/settings.json (preferred) OR
12
+ * ~/Library/Application Support/Zed/settings.json
13
+ * Windows: %APPDATA%\Zed\settings.json
14
+ * Linux: ~/.config/zed/settings.json
15
+ *
16
+ * Zed reads settings.json with comments + trailing commas (JSONC). We
17
+ * use plain JSON.parse, which works for any human-edited file that
18
+ * doesn't actively have comments. If parsing fails we leave the file
19
+ * alone and surface a message — safer than corrupting a config.
20
+ */
21
+ export class ZedDetector {
22
+ id = 'zed';
23
+ displayName = 'Zed';
24
+ lastServerName;
25
+ settingsPath() {
26
+ const home = homedir();
27
+ switch (platform()) {
28
+ case 'win32': {
29
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
30
+ return join(appdata, 'Zed', 'settings.json');
31
+ }
32
+ default:
33
+ return join(home, '.config', 'zed', 'settings.json');
34
+ }
35
+ }
36
+ isInstalled() {
37
+ const home = homedir();
38
+ if (existsSync(this.settingsPath()))
39
+ return true;
40
+ switch (platform()) {
41
+ case 'darwin':
42
+ return (existsSync(join(home, 'Library', 'Application Support', 'Zed')) ||
43
+ existsSync(join(home, '.config', 'zed')));
44
+ case 'win32': {
45
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
46
+ return existsSync(join(appdata, 'Zed'));
47
+ }
48
+ case 'linux':
49
+ return existsSync(join(home, '.config', 'zed'));
50
+ default:
51
+ return false;
52
+ }
53
+ }
54
+ status() {
55
+ const path = this.settingsPath();
56
+ const installed = this.isInstalled();
57
+ if (!installed) {
58
+ return {
59
+ id: this.id, displayName: this.displayName,
60
+ installed: false, configPath: null,
61
+ configExists: false, alreadyConfigured: false,
62
+ };
63
+ }
64
+ const configExists = existsSync(path);
65
+ let alreadyConfigured = false;
66
+ if (configExists) {
67
+ try {
68
+ const cfg = JSON.parse(readFileSync(path, 'utf8'));
69
+ alreadyConfigured = !!cfg?.context_servers?.[this.lastServerName ?? 'mnueron'];
70
+ }
71
+ catch { /* malformed or JSONC — leave alone */ }
72
+ }
73
+ return {
74
+ id: this.id, displayName: this.displayName,
75
+ installed: true, configPath: path,
76
+ configExists, alreadyConfigured,
77
+ };
78
+ }
79
+ install(serverName, entry) {
80
+ const path = this.settingsPath();
81
+ if (!this.isInstalled()) {
82
+ return { ok: false, changed: false, message: `${this.displayName} not detected` };
83
+ }
84
+ mkdirSync(dirname(path), { recursive: true });
85
+ let cfg = {};
86
+ if (existsSync(path)) {
87
+ try {
88
+ const raw = readFileSync(path, 'utf8');
89
+ cfg = raw.trim() ? JSON.parse(raw) : {};
90
+ }
91
+ catch {
92
+ return {
93
+ ok: false, changed: false,
94
+ message: `${path} contains JSONC / comments / trailing commas — we can't parse it. ` +
95
+ `Add the following to context_servers manually: { ${serverName}: ${JSON.stringify(entry)} }`,
96
+ };
97
+ }
98
+ }
99
+ const cs = cfg.context_servers ?? {};
100
+ const before = JSON.stringify(cs[serverName] ?? null);
101
+ cs[serverName] = entry;
102
+ cfg.context_servers = cs;
103
+ const after = JSON.stringify(cs[serverName]);
104
+ const changed = before !== after;
105
+ writeFileSync(path, JSON.stringify(cfg, null, 2));
106
+ this.lastServerName = serverName;
107
+ return {
108
+ ok: true, changed, configPath: path,
109
+ message: changed
110
+ ? (before === 'null' ? 'added' : 'updated existing entry')
111
+ : 'already up to date',
112
+ };
113
+ }
114
+ uninstall(serverName) {
115
+ const path = this.settingsPath();
116
+ if (!existsSync(path)) {
117
+ return { ok: true, removed: false, message: 'nothing to remove' };
118
+ }
119
+ try {
120
+ const cfg = JSON.parse(readFileSync(path, 'utf8'));
121
+ const cs = cfg.context_servers ?? {};
122
+ if (cs[serverName]) {
123
+ delete cs[serverName];
124
+ cfg.context_servers = cs;
125
+ writeFileSync(path, JSON.stringify(cfg, null, 2));
126
+ return { ok: true, removed: true, message: 'removed' };
127
+ }
128
+ return { ok: true, removed: false, message: 'not registered' };
129
+ }
130
+ catch (e) {
131
+ return {
132
+ ok: false, removed: false,
133
+ message: `failed: ${e instanceof Error ? e.message : String(e)}`,
134
+ };
135
+ }
136
+ }
137
+ }
138
+ //# sourceMappingURL=zed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zed.js","sourceRoot":"","sources":["../../src/detectors/zed.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnueron",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "MNUERON — persistent memory for Claude Desktop, Claude Code, Cursor, and any AI dev tool or app. Local-first, free, with optional hosted multi-tenant backend.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",