agentsmesh 0.12.0 → 0.14.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 16a7f0d: Self-serve MCP server. `agentsmesh mcp` boots a stdio MCP server exposing 41 tools and 16 resources for canonical config introspection, CRUD on rules/commands/agents/skills, settings management (config/mcp-servers/permissions/hooks/ignore), capability matrix queries, and orchestration verbs (generate/lint/check/diff/import/convert). Auto-registered in `.agentsmesh/mcp.json` on `init` and `import`. See the MCP server reference page.
8
+
9
+ ## 0.13.0
10
+
11
+ ### Minor Changes
12
+
13
+ - f68ab67: feat(cli): add convert command for direct tool-to-tool migration
14
+
15
+ Adds `agentsmesh convert --from <source> --to <target>` for direct tool-to-tool conversion without going through canonical setup. Internally chains the existing import and generate pipelines via a temporary directory, producing destination tool files from source tool files in a single command. Supports `--dry-run` and `--json` flags.
16
+
17
+ - c8d58c0: feat(cli): add structured JSON output mode
18
+
19
+ Adds `--json` support across CLI commands so automation and CI can consume stable machine-readable command results. JSON mode returns structured success/error envelopes while keeping the existing human-readable output as the default.
20
+
3
21
  ## 0.12.0
4
22
 
5
23
  ### Minor Changes
package/README.md CHANGED
@@ -85,7 +85,7 @@ Prefer a local install? `npm install -D agentsmesh` (also `pnpm add -D` / `yarn
85
85
  If your repo already has `.cursor/`, `.claude/`, `.github/copilot-instructions.md`, or other native files, you don't have to delete them. The recommended flow imports them into `.agentsmesh/` first, lets you preview the projection, and only then trusts `generate`.
86
86
 
87
87
  ```bash
88
- npx agentsmesh import --from cursor # or claude-code, copilot, codex-cli, gemini-cli, windsurf, ...
88
+ npx agentsmesh import --from cursor # or claude-code, copilot, codex-cli, gemini-cli, windsurf, amp, zed, warp, ...
89
89
  npx agentsmesh diff # patch-style preview of what generate would change
90
90
  npx agentsmesh generate # write native configs (back) from canonical
91
91
  npx agentsmesh check # add to CI to detect drift
@@ -121,7 +121,7 @@ On macOS/Linux you can also run `tree .agentsmesh` if you have `tree` installed.
121
121
 
122
122
  ## Supported AI coding tools
123
123
 
124
- AgentsMesh currently generates native config for every major AI coding assistant — Claude Code, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Continue, Cline, Kiro, Codex CLI, Junie, Roo Code, Antigravity — plus plugin targets you can ship as standalone npm packages. Each tool's native vs. embedded support per feature is tracked in the [supported tools matrix](https://samplexbro.github.io/agentsmesh/reference/supported-tools/). The full matrix table is also embedded [further down this README](#supported-tools--feature-matrix).
124
+ AgentsMesh currently generates native config for every major AI coding assistant — Claude Code, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Continue, Cline, Kiro, Codex CLI, Junie, Roo Code, Antigravity, Amp, Zed, Warp — plus plugin targets you can ship as standalone npm packages. Each tool's native vs. embedded support per feature is tracked in the [supported tools matrix](https://samplexbro.github.io/agentsmesh/reference/supported-tools/). The full matrix table is also embedded [further down this README](#supported-tools--feature-matrix).
125
125
 
126
126
  ---
127
127
 
@@ -133,6 +133,7 @@ AgentsMesh currently generates native config for every major AI coding assistant
133
133
  - **Team-safe collaboration** — `agentsmesh check` is a CI drift gate against `.agentsmesh/.lock`, `agentsmesh diff` previews changes, `agentsmesh merge` rebuilds the lock after three-way Git conflicts, and `lock_features` + per-feature `strategy` prevent accidental overrides.
134
134
  - **Global mode** — `~/.agentsmesh/` syncs personal AI config to `~/.claude/`, `~/.cursor/`, `~/.codex/`, `~/.windsurf/`, and other user-level folders. Every CLI command accepts `--global`.
135
135
  - **Extensible** — community packs (`agentsmesh install ...`), remote `extends`, runtime plugins (`agentsmesh plugin add`), schema-validated config files, and a typed programmatic API for scripts, IDE extensions, and CI.
136
+ - **Self-serve MCP server** — `agentsmesh mcp` exposes canonical configuration as an MCP tool so AI agents can introspect rules, commands, agents, and skills, and trigger `generate` — all within the conversation. Seeded automatically by `agentsmesh init`.
136
137
 
137
138
  ---
138
139
 
@@ -147,7 +148,7 @@ The reason `AGENTS.md` alone is not enough: most AI coding assistants expose con
147
148
  - **GitHub Copilot** has `.github/copilot-instructions.md`, `.github/instructions/*.instructions.md`, agents, prompts, and (partial) hooks.
148
149
  - **Gemini CLI** has `GEMINI.md`, `.gemini/settings.json` (MCP + hooks), `.gemini/commands/*.toml`, and agents.
149
150
  - **Codex CLI** has `AGENTS.md` plus `.codex/config.toml`, `.codex/agents/*.toml`, and `.codex/rules/`.
150
- - **Windsurf**, **Continue**, **Cline**, **Kiro**, **Junie**, **Roo Code**, **Antigravity** each have their own native rules, workflows, MCP servers, skills, and ignore files.
151
+ - **Windsurf**, **Continue**, **Cline**, **Kiro**, **Junie**, **Roo Code**, **Antigravity**, **Amp**, **Zed**, **Warp** each have their own native rules, workflows, MCP servers, skills, and ignore files.
151
152
 
152
153
  AgentsMesh canonicalizes all of these — rules, commands, agents, skills, MCP servers, hooks, ignore patterns, permissions — so you don't pick one tool's surface as the lowest common denominator. When a tool has no native slot for a feature, AgentsMesh embeds it with round-trip metadata instead of dropping it.
153
154
 
@@ -183,6 +184,7 @@ Detailed contracts: [Canonical Config](https://samplexbro.github.io/agentsmesh/c
183
184
  agentsmesh init [--global] [--yes]
184
185
  agentsmesh generate [--global] [--targets <csv>] [--check] [--dry-run] [--force] [--refresh-cache]
185
186
  agentsmesh import --from <target> [--global]
187
+ agentsmesh convert --from <target> --to <target> [--global] [--dry-run]
186
188
  agentsmesh diff [--global] [--targets <csv>]
187
189
  agentsmesh lint [--global] [--targets <csv>]
188
190
  agentsmesh watch [--global] [--targets <csv>]
@@ -196,6 +198,20 @@ agentsmesh target scaffold <id> [--name <displayName>] [--force]
196
198
 
197
199
  `agentsmesh --help` prints the same surface; `agentsmesh <cmd> --help` is also supported.
198
200
 
201
+ ### Machine-readable output
202
+
203
+ All commands support `--json` for CI pipelines and scripting:
204
+
205
+ ```bash
206
+ agentsmesh lint --json
207
+ # {"success":true,"command":"lint","data":{"diagnostics":[],"summary":{"errors":0,"warnings":0}}}
208
+
209
+ agentsmesh generate --check --json
210
+ # {"success":false,"command":"generate","error":"Command 'generate' failed","data":{"scope":"project","mode":"check","files":[...],...}}
211
+ ```
212
+
213
+ Every command emits a single JSON envelope to stdout: `{ success, command, data?, error? }`. Human output is fully suppressed. Exit codes are preserved. `--json` is not supported with `watch`.
214
+
199
215
  ### Global mode (personal AI assistant config)
200
216
 
201
217
  `.agentsmesh/` at the project level is for teams. `~/.agentsmesh/` at the home level is for personal setup across every repo you touch:
@@ -375,7 +391,7 @@ See the [full feature matrix docs](https://samplexbro.github.io/agentsmesh/refer
375
391
 
376
392
  - **[Getting Started](https://samplexbro.github.io/agentsmesh/getting-started/installation/)** — installation, quick start
377
393
  - **[Canonical Config](https://samplexbro.github.io/agentsmesh/canonical-config/)** — rules, commands, agents, skills, MCP, hooks, ignore, permissions
378
- - **[CLI Reference](https://samplexbro.github.io/agentsmesh/cli/)** — `init`, `generate`, `import`, `install`, `diff`, `lint`, `watch`, `check`, `merge`, `matrix`, `plugin`, `target`
394
+ - **[CLI Reference](https://samplexbro.github.io/agentsmesh/cli/)** — `init`, `generate`, `import`, `convert`, `install`, `diff`, `lint`, `watch`, `check`, `merge`, `matrix`, `plugin`, `target`
379
395
  - **[Configuration](https://samplexbro.github.io/agentsmesh/configuration/agentsmesh-yaml/)** — `agentsmesh.yaml`, local overrides, extends, collaboration, conversions
380
396
  - **[Guides](https://samplexbro.github.io/agentsmesh/guides/existing-project/)** — adopting in existing projects · multi-tool teams · sharing config · CI drift detection · community packs · **building plugins**
381
397
  - **[Reference](https://samplexbro.github.io/agentsmesh/reference/generation-pipeline/)** — supported tools matrix · generation pipeline · managed embedding
package/dist/canonical.js CHANGED
@@ -1166,12 +1166,12 @@ async function readExistingServers(path) {
1166
1166
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
1167
1167
  const raw = parsed.mcpServers;
1168
1168
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
1169
- const out = {};
1169
+ const out2 = {};
1170
1170
  for (const [name, value] of Object.entries(raw)) {
1171
1171
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
1172
- out[name] = value;
1172
+ out2[name] = value;
1173
1173
  }
1174
- return out;
1174
+ return out2;
1175
1175
  }
1176
1176
  var init_mcp_merge = __esm({
1177
1177
  "src/targets/import/mcp-merge.ts"() {
@@ -1454,13 +1454,13 @@ function parseMcpJson(content) {
1454
1454
  if (!parsed || typeof parsed !== "object") return {};
1455
1455
  const raw = parsed.mcpServers;
1456
1456
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
1457
- const out = {};
1457
+ const out2 = {};
1458
1458
  for (const [name, value] of Object.entries(raw)) {
1459
1459
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
1460
1460
  const server = value;
1461
1461
  const description = typeof server.description === "string" ? server.description : void 0;
1462
1462
  if (typeof server.command === "string") {
1463
- out[name] = {
1463
+ out2[name] = {
1464
1464
  type: typeof server.type === "string" ? server.type : "stdio",
1465
1465
  command: server.command,
1466
1466
  args: toStringArray5(server.args),
@@ -1470,7 +1470,7 @@ function parseMcpJson(content) {
1470
1470
  continue;
1471
1471
  }
1472
1472
  if (typeof server.url === "string") {
1473
- out[name] = {
1473
+ out2[name] = {
1474
1474
  type: typeof server.type === "string" ? server.type : "http",
1475
1475
  url: server.url,
1476
1476
  headers: toStringRecord(server.headers),
@@ -1479,7 +1479,7 @@ function parseMcpJson(content) {
1479
1479
  };
1480
1480
  }
1481
1481
  }
1482
- return out;
1482
+ return out2;
1483
1483
  }
1484
1484
  async function runMcpJson(spec, sources, projectRoot, fromTool) {
1485
1485
  if (!spec.canonicalFilename) {
@@ -9549,18 +9549,18 @@ function generateRules11(canonical) {
9549
9549
  return outputs;
9550
9550
  }
9551
9551
  function toJunieMcpServer(server) {
9552
- const out = {};
9553
- if (server.description) out.description = server.description;
9554
- if (server.type !== "stdio") out.type = server.type;
9552
+ const out2 = {};
9553
+ if (server.description) out2.description = server.description;
9554
+ if (server.type !== "stdio") out2.type = server.type;
9555
9555
  if (isStdioMcpServer(server)) {
9556
- out.command = server.command;
9557
- out.args = server.args;
9556
+ out2.command = server.command;
9557
+ out2.args = server.args;
9558
9558
  } else {
9559
- out.url = server.url;
9560
- if (Object.keys(server.headers).length > 0) out.headers = server.headers;
9559
+ out2.url = server.url;
9560
+ if (Object.keys(server.headers).length > 0) out2.headers = server.headers;
9561
9561
  }
9562
- if (Object.keys(server.env).length > 0) out.env = server.env;
9563
- return out;
9562
+ if (Object.keys(server.env).length > 0) out2.env = server.env;
9563
+ return out2;
9564
9564
  }
9565
9565
  function generateMcp7(canonical) {
9566
9566
  if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
@@ -11029,11 +11029,11 @@ var init_generator17 = __esm({
11029
11029
  });
11030
11030
  function toStringRecord2(value) {
11031
11031
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
11032
- const out = {};
11032
+ const out2 = {};
11033
11033
  for (const [k, v] of Object.entries(value)) {
11034
- if (typeof v === "string") out[k] = v;
11034
+ if (typeof v === "string") out2[k] = v;
11035
11035
  }
11036
- return out;
11036
+ return out2;
11037
11037
  }
11038
11038
  function parseOpenCodeMcp(content) {
11039
11039
  let parsed;
@@ -11045,12 +11045,12 @@ function parseOpenCodeMcp(content) {
11045
11045
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
11046
11046
  const raw = parsed.mcp;
11047
11047
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
11048
- const out = {};
11048
+ const out2 = {};
11049
11049
  for (const [name, value] of Object.entries(raw)) {
11050
11050
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
11051
11051
  const entry = value;
11052
11052
  if (typeof entry.url === "string") {
11053
- out[name] = {
11053
+ out2[name] = {
11054
11054
  type: "url",
11055
11055
  url: entry.url,
11056
11056
  headers: toStringRecord2(entry.headers),
@@ -11064,7 +11064,7 @@ function parseOpenCodeMcp(content) {
11064
11064
  const command = cmdArr[0];
11065
11065
  if (command === void 0) continue;
11066
11066
  const args = cmdArr.slice(1);
11067
- out[name] = {
11067
+ out2[name] = {
11068
11068
  type: "stdio",
11069
11069
  command,
11070
11070
  args,
@@ -11073,7 +11073,7 @@ function parseOpenCodeMcp(content) {
11073
11073
  };
11074
11074
  }
11075
11075
  }
11076
- return out;
11076
+ return out2;
11077
11077
  }
11078
11078
  async function importMcp4(projectRoot, scope, results) {
11079
11079
  const configFile = scope === "global" ? OPENCODE_GLOBAL_CONFIG_FILE : OPENCODE_CONFIG_FILE;
@@ -13495,12 +13495,12 @@ function topLevelDotfilePrefixes(descriptor19) {
13495
13495
  ...layouts.flatMap((l) => l.managedOutputs?.dirs ?? []),
13496
13496
  ...layouts.flatMap((l) => l.managedOutputs?.files ?? [])
13497
13497
  ];
13498
- const out = /* @__PURE__ */ new Set();
13498
+ const out2 = /* @__PURE__ */ new Set();
13499
13499
  for (const candidate of candidates) {
13500
13500
  const top = candidate.split("/")[0];
13501
- if (top && top.startsWith(".") && top.length > 1) out.add(`${top}/`);
13501
+ if (top && top.startsWith(".") && top.length > 1) out2.add(`${top}/`);
13502
13502
  }
13503
- return out;
13503
+ return out2;
13504
13504
  }
13505
13505
  function buildDefaultRootRelativePrefixes() {
13506
13506
  const set = /* @__PURE__ */ new Set([".agentsmesh/"]);
@@ -15076,12 +15076,60 @@ function parseServer(raw) {
15076
15076
  env
15077
15077
  };
15078
15078
  }
15079
+ function stripJsonComments(text) {
15080
+ let result = "";
15081
+ let i = 0;
15082
+ const len = text.length;
15083
+ while (i < len) {
15084
+ const ch = text[i];
15085
+ if (ch === '"') {
15086
+ result += ch;
15087
+ i++;
15088
+ while (i < len) {
15089
+ const sc = text[i];
15090
+ result += sc;
15091
+ if (sc === "\\") {
15092
+ i++;
15093
+ if (i < len) {
15094
+ result += text[i];
15095
+ }
15096
+ } else if (sc === '"') {
15097
+ break;
15098
+ }
15099
+ i++;
15100
+ }
15101
+ i++;
15102
+ continue;
15103
+ }
15104
+ if (ch === "/" && text[i + 1] === "*") {
15105
+ i += 2;
15106
+ while (i < len) {
15107
+ if (text[i] === "*" && text[i + 1] === "/") {
15108
+ i += 2;
15109
+ break;
15110
+ }
15111
+ i++;
15112
+ }
15113
+ continue;
15114
+ }
15115
+ if (ch === "/" && text[i + 1] === "/") {
15116
+ i += 2;
15117
+ while (i < len && text[i] !== "\n") {
15118
+ i++;
15119
+ }
15120
+ continue;
15121
+ }
15122
+ result += ch;
15123
+ i++;
15124
+ }
15125
+ return result;
15126
+ }
15079
15127
  async function parseMcp(mcpPath) {
15080
15128
  const content = await readFileSafe(mcpPath);
15081
15129
  if (!content) return null;
15082
15130
  let parsed;
15083
15131
  try {
15084
- parsed = JSON.parse(content);
15132
+ parsed = JSON.parse(stripJsonComments(content));
15085
15133
  } catch {
15086
15134
  return null;
15087
15135
  }
@@ -15283,14 +15331,14 @@ function mergeHooks(base, overlay) {
15283
15331
  }
15284
15332
  function mergeIgnore(base, overlay) {
15285
15333
  const seen = new Set(base);
15286
- const out = [...base];
15334
+ const out2 = [...base];
15287
15335
  for (const p of overlay) {
15288
15336
  if (!seen.has(p)) {
15289
15337
  seen.add(p);
15290
- out.push(p);
15338
+ out2.push(p);
15291
15339
  }
15292
15340
  }
15293
- return out;
15341
+ return out2;
15294
15342
  }
15295
15343
 
15296
15344
  // src/config/resolve/native-format-detector.ts
@@ -15398,6 +15446,11 @@ var C = {
15398
15446
  cyan: "\x1B[36m",
15399
15447
  reset: "\x1B[0m"
15400
15448
  };
15449
+ function out(text) {
15450
+ {
15451
+ process.stdout.write(text);
15452
+ }
15453
+ }
15401
15454
  function noColor() {
15402
15455
  return process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "";
15403
15456
  }
@@ -15410,7 +15463,7 @@ function pad(str, width) {
15410
15463
  }
15411
15464
  var logger = {
15412
15465
  info(msg) {
15413
- process.stdout.write(c(C.cyan, msg) + "\n");
15466
+ out(c(C.cyan, msg) + "\n");
15414
15467
  },
15415
15468
  warn(msg) {
15416
15469
  process.stderr.write(c(C.yellow, "\u26A0 ") + msg + "\n");
@@ -15419,11 +15472,11 @@ var logger = {
15419
15472
  process.stderr.write(c(C.red, "\u2717 ") + msg + "\n");
15420
15473
  },
15421
15474
  success(msg) {
15422
- process.stdout.write(c(C.green, "\u2713 ") + msg + "\n");
15475
+ out(c(C.green, "\u2713 ") + msg + "\n");
15423
15476
  },
15424
15477
  debug(msg) {
15425
15478
  if (process.env.AGENTSMESH_DEBUG === "1") {
15426
- process.stdout.write(c(C.cyan, "[debug] ") + msg + "\n");
15479
+ out(c(C.cyan, "[debug] ") + msg + "\n");
15427
15480
  }
15428
15481
  },
15429
15482
  table(rows) {
@@ -15439,13 +15492,13 @@ var logger = {
15439
15492
  widths[j] = max;
15440
15493
  }
15441
15494
  const border = "+" + widths.map((w) => "-".repeat(w + 2)).join("+") + "+";
15442
- process.stdout.write(border + "\n");
15495
+ out(border + "\n");
15443
15496
  for (let i = 0; i < rows.length; i++) {
15444
15497
  const row = rows[i];
15445
15498
  const line = "| " + row.map((cell, j) => pad(cell, widths[j])).join(" | ") + " |";
15446
- process.stdout.write(line + "\n");
15499
+ out(line + "\n");
15447
15500
  }
15448
- process.stdout.write(border + "\n");
15501
+ out(border + "\n");
15449
15502
  }
15450
15503
  };
15451
15504