agentsmesh 0.27.0 → 0.29.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,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.29.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 663f0e6: Strip elevated artifacts from remote `extends` sources by default
8
+
9
+ `hooks`, `permissions`, and `mcp` contributed by a **remote** `extends` source (`github:`, `gitlab:`, `git+…`, including `git+file://`) are now stripped during config load unless the entry opts in with `accept: [hooks, permissions, mcp]`. This closes a gap where a remote `extends` could inject shell-executing config (settings hooks, MCP launch specs) without the per-artifact consent that `agentsmesh install` already requires. Local `extends` remain trusted as-is, and a warning reports anything that was stripped.
10
+
11
+ ### Patch Changes
12
+
13
+ - 11f90bc: Harden plugin source containment against intermediate-symlink escapes
14
+
15
+ The plugin loader now canonicalizes an unresolvable source path against its nearest existing ancestor instead of falling back to the raw path. This closes a gap where a local plugin `source` routed through a symlinked directory that resolves outside the project root could slip past the trust-boundary check when its entry file did not exist yet. Legitimate in-project plugins are unaffected.
16
+
17
+ - c647c9b: Docs: the README now leads with lessons (the shared agent memory), adds a head-to-head comparison with Ruler and rulesync, embeds demo GIFs, leads the quickstart with the import-first path for existing repos, and documents the new `extends` `accept:` consent. Documentation-only — no behavior change.
18
+
19
+ ## 0.28.0
20
+
21
+ ### Minor Changes
22
+
23
+ - e148490: Deterministic pre-edit lesson recall via a `PreToolUse` hook.
24
+
25
+ `agentsmesh init --lessons` now wires the recall hook under **both** `PreToolUse` and `PostToolUse`, and `agentsmesh lessons hook` is event-aware (it echoes the harness `hook_event_name`). On targets whose hooks can inject context before a tool call (e.g. Claude Code), matching lessons are now surfaced **before the first edit/command** — guarding the "first touch" the previous PostToolUse-only design left unguarded — with no extra model turn and no compliance dependence. Session dedup keeps each lesson injected at most once per session, and `PostToolUse` remains as the fallback for harnesses that support only post-call context injection. Existing projects pick this up by re-running `agentsmesh init --lessons` (idempotent) and `agentsmesh generate`; behavior is unchanged when no `hook_event_name` is supplied (defaults to `PostToolUse`).
26
+
3
27
  ## 0.27.0
4
28
 
5
29
  ### Minor Changes
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  <div align="center">
2
2
 
3
- # AgentsMesh — One `.agentsmesh/` Directory for Every AI Coding Tool
3
+ # AgentsMesh
4
4
 
5
- <img src="https://raw.githubusercontent.com/sampleXbro/agentsmesh/master/assets/agentsmesh-banner.jpeg" alt="AgentsMesh — One source. Every AI coding tool. Always in sync." width="100%" />
5
+ ### One source for every AI coding tool with a shared agent memory that learns from your repo.
6
+
7
+ <img src="https://raw.githubusercontent.com/sampleXbro/agentsmesh/master/assets/agentsmesh-banner.jpeg" alt="AgentsMesh — One source. Every AI coding tool. Agents that learn." width="100%" />
6
8
 
7
9
  [![CI](https://github.com/sampleXbro/agentsmesh/actions/workflows/ci.yml/badge.svg)](https://github.com/sampleXbro/agentsmesh/actions/workflows/ci.yml)
8
10
  [![npm version](https://img.shields.io/npm/v/agentsmesh.svg)](https://www.npmjs.com/package/agentsmesh)
@@ -23,6 +25,28 @@ Every AI coding assistant has its own config format — `CLAUDE.md`, `AGENTS.md`
23
25
  > [!NOTE]
24
26
  > Full documentation, guides, and the per-tool reference live at **[samplexbro.github.io/agentsmesh](https://samplexbro.github.io/agentsmesh/)**.
25
27
 
28
+ ## How AgentsMesh compares
29
+
30
+ Most config tools stop at copying rule files into each assistant's folder. AgentsMesh is the only one that also gives your agents a **shared memory that learns**, round-trips **losslessly** in both directions, and lets anyone **add a new tool as a plugin** — no release required.
31
+
32
+ | Capability | AgentsMesh | [Ruler](https://github.com/intellectronica/ruler) | [rulesync](https://github.com/dyoshikawa/rulesync) |
33
+ |---|:---:|:---:|:---:|
34
+ | Generate native config for many tools | ✅ | ✅ | ✅ |
35
+ | Import existing tool config back to source | ✅ | — | ✅ |
36
+ | **Lossless round-trip** (re-import restores originals) | ✅ | — | partial |
37
+ | Convert one tool's config directly to another | ✅ | — | ✅ |
38
+ | **Automatic cross-tool link rebasing** | ✅ | — | — |
39
+ | **Lessons — a shared agent memory that learns** | ✅ | — | — |
40
+ | **Plugins — add a target without a release** | ✅ | — | — |
41
+ | Cross-target lint (warn before silent data loss) | ✅ | — | — |
42
+ | CI drift gate + git-merge recovery | ✅ | partial | partial |
43
+ | Self-serve MCP server (agent-operable config) | ✅ | — | — |
44
+ | `--json` everywhere + typed programmatic API | ✅ | — | partial |
45
+
46
+ <sub>Reflects the public projects as of June 2026 — see the [alternatives guide](https://samplexbro.github.io/agentsmesh/reference/alternatives/) for sources and detail. Corrections welcome.</sub>
47
+
48
+ Built to be depended on: **8,000+ tests** run on Linux, macOS, and Windows CI (Node 22 & 24), configs are JSON-Schema-validated, npm releases ship with [provenance](https://docs.npmjs.com/generating-provenance-statements), and standalone binaries are published with SHA-256 checksums.
49
+
26
50
  ## Install
27
51
 
28
52
  Every install method ships the same CLI (`agentsmesh`, plus the shorter `amsh` alias) and the same TypeScript library.
@@ -45,11 +69,14 @@ Standalone binaries are also on [GitHub Releases](https://github.com/sampleXbro/
45
69
 
46
70
  ## 60-second quickstart
47
71
 
48
- Works on Linux, macOS, and Windows. After [installing](#install):
72
+ Works on Linux, macOS, and Windows. After [installing](#install), `agentsmesh init` adapts to your repo:
73
+
74
+ - **Already using AI tools?** It detects your existing `.cursor/`, `.claude/`, `.github/copilot-instructions.md`, and more, and offers to import them all into one `.agentsmesh/` source — nothing rewritten by hand. (`agentsmesh init --yes` does it non-interactively.)
75
+ - **Starting fresh?** It scaffolds a minimal `.agentsmesh/` to grow from.
49
76
 
50
77
  ```bash
51
- agentsmesh init # scaffold .agentsmesh/ + agentsmesh.yaml
52
- agentsmesh generate # write native configs for every enabled tool
78
+ agentsmesh init # detect & import existing configs, or scaffold fresh
79
+ agentsmesh generate # write each tool's native config from the one source
53
80
  agentsmesh check # CI-friendly drift gate against .agentsmesh/.lock
54
81
  ```
55
82
 
@@ -99,20 +126,40 @@ AGENTS.md
99
126
 
100
127
  Edit canonical sources, run `agentsmesh generate`, and every native file above is (re)written for you — always in sync. Alongside the directory, `agentsmesh.yaml` selects which targets and features are enabled, `agentsmesh.local.yaml` holds per-developer overrides (gitignored), and `.agentsmesh/.lock` records the checksums that `agentsmesh check` enforces.
101
128
 
129
+ <div align="center">
130
+ <img src="https://raw.githubusercontent.com/sampleXbro/agentsmesh/master/assets/generate-demo.gif" alt="agentsmesh detects existing tool configs, imports them into one source, and generates native config for every tool" width="100%" />
131
+ </div>
132
+
102
133
  ## Teach your agents: lessons
103
134
 
104
- Lessons give your AI agents a **memory of past mistakes** — read *before* they touch anything, written *after* something goes wrong, so the same mistake doesn't happen twice in any tool.
135
+ This is the part no other config-sync tool has. Lessons give your AI agents a **memory of past mistakes** — read *before* they touch anything, written *after* something goes wrong, so the same mistake doesn't happen twice in any tool. It's what turns a static pile of rules into an agent that gets better at *your* codebase over time.
136
+
137
+ <div align="center">
138
+ <img src="https://raw.githubusercontent.com/sampleXbro/agentsmesh/master/assets/lessons-demo.gif" alt="an AI agent captures a lesson after a failure, then recalls it before editing the same file — triggered by file, command, or keyword" width="100%" />
139
+ </div>
105
140
 
106
141
  The memory is one git-tracked file, `.agentsmesh/lessons/lessons.json`, and every agent talks to it through two commands:
107
142
 
108
143
  - **Recall** — before an edit or a state-changing command, the agent runs `agentsmesh lessons query --file <path> --cmd <command>` and follows the rules that match.
109
144
  - **Capture** — right after a failure (red test, lint error, review comment, wrong assumption), it saves the rule with `agentsmesh lessons add "<rule>" --topic <id> --trigger-file <glob>`.
110
145
 
146
+ In practice:
147
+
148
+ ```bash
149
+ # An agent breaks the Windows build, finds the cause, and writes the lesson down:
150
+ agentsmesh lessons add "Normalize CLI display paths to forward slashes" \
151
+ --topic windows-paths --trigger-file "src/cli/**/*.ts"
152
+
153
+ # Days later, any agent — in any tool — about to touch that path recalls it first:
154
+ agentsmesh lessons query --file src/cli/output.ts
155
+ # → "Normalize CLI display paths to forward slashes"
156
+ ```
157
+
111
158
  ```bash
112
159
  agentsmesh init --lessons && agentsmesh generate # wire the recall/capture loop once
113
160
  ```
114
161
 
115
- `init --lessons` drops a small always-on rule into `.agentsmesh/rules/_root.md` (so every target gets the habit), seeds the full operating manual as a `lessons` skill where supported, and wires a `PostToolUse` recall hook on hook-capable tools; agents without shell access use the matching MCP tools (`lessons_query` / `lessons_add`). Because the graph is a normal git-tracked file, a lesson one agent learns today helps every teammate's agent tomorrow, and every change is reviewable like any other diff.
162
+ `init --lessons` drops a small always-on rule into `.agentsmesh/rules/_root.md` (so every target gets the habit), seeds the full operating manual as a `lessons` skill where supported, and wires a recall hook (a `PreToolUse` first-touch guard plus a `PostToolUse` fallback) on hook-capable tools; agents without shell access use the matching MCP tools (`lessons_query` / `lessons_add`). Because the graph is a normal git-tracked file, a lesson one agent learns today helps every teammate's agent tomorrow, and every change is reviewable like any other diff.
116
163
 
117
164
  Full walkthrough: [Teach your AI agents with lessons](https://samplexbro.github.io/agentsmesh/guides/lessons/) · [`agentsmesh lessons` reference](https://samplexbro.github.io/agentsmesh/cli/lessons/).
118
165
 
@@ -125,8 +172,8 @@ Full walkthrough: [Teach your AI agents with lessons](https://samplexbro.github.
125
172
  - **Migrate between tools** — `convert --from <a> --to <b>` rewrites one tool's config directly into another's native format. [convert →](https://samplexbro.github.io/agentsmesh/cli/convert/)
126
173
  - **Global mode** — `~/.agentsmesh/` syncs your personal config to `~/.claude/`, `~/.cursor/`, `~/.codex/`, and more. Every command accepts `--global`. [Global paths →](https://samplexbro.github.io/agentsmesh/reference/supported-tools/#global-mode)
127
174
  - **Team-safe and CI-ready** — `check` is a drift gate against `.agentsmesh/.lock`, `diff` previews changes, `merge` rebuilds the lock after a 3-way Git conflict, and `lock_features` + per-feature `strategy` prevent accidental overrides. `lint` adds cross-target warnings (`silent-drop-guard`, `hook-script-references`, `rule-scope-inversion`) for content a tool would silently mishandle. [check →](https://samplexbro.github.io/agentsmesh/cli/check/) · [lint →](https://samplexbro.github.io/agentsmesh/cli/lint/)
128
- - **Community packs and `extends`** — install shared rules, skills, agents, and commands from any git repo (`install`, `--sync`, `refresh`, remote `extends`); a multi-signal classifier auto-detects Anthropic-style skill packs. Elevated artifacts (hooks, permissions, MCP) from remote sources are stripped unless you opt in with `--accept-*`. [Install reference →](https://samplexbro.github.io/agentsmesh/cli/install/)
129
- - **Plugins** — ship support for a new tool as a standalone npm package, with full parity to built-in targets (project + global, conversions, lint hooks, hook post-processing). [Build a plugin →](https://samplexbro.github.io/agentsmesh/guides/building-plugins/)
175
+ - **Community packs and `extends`** — install shared rules, skills, agents, and commands from any git repo (`install`, `--sync`, `refresh`, remote `extends`); a multi-signal classifier auto-detects Anthropic-style skill packs. Elevated artifacts (hooks, permissions, MCP) from remote sources are stripped unless you opt in with `--accept-*` on `install`, or `accept:` on a remote `extends` entry. [Install reference →](https://samplexbro.github.io/agentsmesh/cli/install/)
176
+ - **Plugins — add a tool without waiting for a release** — ship support for a new AI tool as a standalone npm package, with full parity to built-in targets (project + global, conversions, lint hooks, hook post-processing). When a tool ships or changes its format, you don't file an issue and wait on the maintainer — you publish a plugin. [Build a plugin →](https://samplexbro.github.io/agentsmesh/guides/building-plugins/)
130
177
  - **Schema-validated configs** — each config ships a JSON Schema, so editors give you autocomplete and validation out of the box. [JSON schemas →](https://samplexbro.github.io/agentsmesh/reference/json-schemas/)
131
178
  - **Typed programmatic API** — drive `generate` / `import` / `lint` / `diff` / `check` from scripts or CI via `agentsmesh`, `/engine`, `/canonical`, `/targets`, `/lessons`. [API reference →](https://samplexbro.github.io/agentsmesh/reference/programmatic-api/)
132
179
  - **Self-serve MCP server** — `agentsmesh mcp` (seeded by `init`) exposes canonical config as MCP tools so agents can introspect rules, commands, and skills and trigger `generate` in-conversation. [MCP server →](https://samplexbro.github.io/agentsmesh/reference/mcp-server/)
@@ -135,9 +182,11 @@ Full walkthrough: [Teach your AI agents with lessons](https://samplexbro.github.
135
182
  > [!TIP]
136
183
  > Commit **both** `.agentsmesh/` and the generated tool files, the same way you commit `package-lock.json`: they're deterministic build output that the AI tools read directly, and `agentsmesh check` guards the two from drifting.
137
184
 
138
- ## Why not just `AGENTS.md`?
185
+ ## Why not Ruler, rulesync, or just `AGENTS.md`?
186
+
187
+ **vs. `AGENTS.md`** — [`AGENTS.md`](https://agents.md) is a great shared instruction file, and AgentsMesh emits it natively wherever a tool supports it. But a single markdown file isn't enough on its own: most assistants expose configuration *beyond* it — Cursor's `.cursor/rules/*.mdc` and MCP config, Claude Code's agents/skills/commands/hooks/permissions, Copilot's `.github/instructions/`, Gemini's `.gemini/settings.json`, and so on — and those surfaces don't overlap. AgentsMesh canonicalizes all of them so you never have to pick one tool's surface as the lowest common denominator.
139
188
 
140
- [`AGENTS.md`](https://agents.md) is a great shared instruction file, and AgentsMesh emits it natively wherever a tool supports it. But a single markdown file isn't enough on its own: most assistants expose configuration *beyond* it — Cursor's `.cursor/rules/*.mdc` and MCP config, Claude Code's agents/skills/commands/hooks/permissions, Copilot's `.github/instructions/`, Gemini's `.gemini/settings.json`, and so on and those surfaces don't overlap. AgentsMesh canonicalizes all of them so you never have to pick one tool's surface as the lowest common denominator.
189
+ **vs. other sync tools** — [Ruler](https://github.com/intellectronica/ruler) and [rulesync](https://github.com/dyoshikawa/rulesync) solve the rules-distribution half well. AgentsMesh goes further on the parts that are hardest to keep in sync: a shared [lessons](#teach-your-agents-lessons) memory your agents learn from, lossless two-way [import](https://samplexbro.github.io/agentsmesh/cli/import/), automatic cross-tool [link rebasing](https://samplexbro.github.io/agentsmesh/reference/generation-pipeline/), [plugins](https://samplexbro.github.io/agentsmesh/guides/building-plugins/) so a new tool ships without a release, and [lint](https://samplexbro.github.io/agentsmesh/cli/lint/) that warns before a tool would silently drop content. See the [full comparison](#how-agentsmesh-compares) and the [alternatives guide](https://samplexbro.github.io/agentsmesh/reference/alternatives/).
141
190
 
142
191
  ## Commands
143
192
 
@@ -1,5 +1,5 @@
1
- import { b as CanonicalFiles, V as ValidatedConfig } from './schema-CzaoYJlG.js';
2
- export { C as CanonicalAgent, a as CanonicalCommand, c as CanonicalRule, d as CanonicalSkill, H as HookEntry, e as Hooks, I as IgnorePatterns, M as McpConfig, f as McpServer, P as Permissions, S as SkillSupportingFile, g as StdioMcpServer, U as UrlMcpServer } from './schema-CzaoYJlG.js';
1
+ import { b as CanonicalFiles, V as ValidatedConfig } from './schema-CH_JJep8.js';
2
+ export { C as CanonicalAgent, a as CanonicalCommand, c as CanonicalRule, d as CanonicalSkill, H as HookEntry, e as Hooks, I as IgnorePatterns, M as McpConfig, f as McpServer, P as Permissions, S as SkillSupportingFile, g as StdioMcpServer, U as UrlMcpServer } from './schema-CH_JJep8.js';
3
3
  import 'zod';
4
4
 
5
5
  interface UnrecognizedFormatsWarningOptions {
package/dist/canonical.js CHANGED
@@ -20874,7 +20874,9 @@ async function resolveExtendPaths(config, configDir, options = {}) {
20874
20874
  as: ext.as,
20875
20875
  version: fetched.version,
20876
20876
  path: ext.path,
20877
- pick: ext.pick
20877
+ pick: ext.pick,
20878
+ isRemote: true,
20879
+ accept: ext.accept
20878
20880
  });
20879
20881
  continue;
20880
20882
  }
@@ -20891,7 +20893,9 @@ async function resolveExtendPaths(config, configDir, options = {}) {
20891
20893
  target: ext.target,
20892
20894
  as: ext.as,
20893
20895
  path: ext.path,
20894
- pick: ext.pick
20896
+ pick: ext.pick,
20897
+ isRemote: false,
20898
+ accept: ext.accept
20895
20899
  });
20896
20900
  }
20897
20901
  return result;
@@ -22421,6 +22425,47 @@ function applyExtendPick(canonical, features, pick, extendName) {
22421
22425
  return next;
22422
22426
  }
22423
22427
 
22428
+ // src/install/core/elevated-artifacts.ts
22429
+ function stripUntrustedElevatedArtifacts(canonical, options) {
22430
+ if (options.sourceKind === "local") {
22431
+ return { canonical, stripped: [] };
22432
+ }
22433
+ const stripped = [];
22434
+ let hooks = canonical.hooks;
22435
+ let permissions = canonical.permissions;
22436
+ let mcp = canonical.mcp;
22437
+ if (hooks !== null && !options.acceptHooks) {
22438
+ hooks = null;
22439
+ stripped.push("hooks");
22440
+ }
22441
+ if (permissions !== null && !options.acceptPermissions) {
22442
+ permissions = null;
22443
+ stripped.push("permissions");
22444
+ }
22445
+ if (mcp !== null && !options.acceptMcp) {
22446
+ mcp = null;
22447
+ stripped.push("mcp");
22448
+ }
22449
+ if (stripped.length === 0) {
22450
+ return { canonical, stripped: [] };
22451
+ }
22452
+ return {
22453
+ canonical: { ...canonical, hooks, permissions, mcp },
22454
+ stripped
22455
+ };
22456
+ }
22457
+
22458
+ // src/canonical/extends/extend-elevated.ts
22459
+ function gateExtendElevatedArtifacts(canonical, ext) {
22460
+ const accept = ext.accept ?? [];
22461
+ return stripUntrustedElevatedArtifacts(canonical, {
22462
+ sourceKind: ext.isRemote ? "git" : "local",
22463
+ acceptHooks: accept.includes("hooks"),
22464
+ acceptPermissions: accept.includes("permissions"),
22465
+ acceptMcp: accept.includes("mcp")
22466
+ });
22467
+ }
22468
+
22424
22469
  // src/install/pack/pack-reader.ts
22425
22470
  init_fs();
22426
22471
 
@@ -22454,7 +22499,14 @@ var extendSourceSchema = z.object({
22454
22499
  features: z.array(featureSchema),
22455
22500
  /** Repo-relative POSIX path for discovery (skill packs, nested .agentsmesh). */
22456
22501
  path: z.string().optional(),
22457
- pick: extendPickSchema.optional()
22502
+ pick: extendPickSchema.optional(),
22503
+ /**
22504
+ * Per-entry consent for "elevated" artifacts (`hooks`, `permissions`, `mcp`)
22505
+ * from a remote source. These control local code execution at generate time,
22506
+ * so for non-local extends they are stripped by default and only merged for
22507
+ * the artifacts listed here. Local extends are trusted and ignore this field.
22508
+ */
22509
+ accept: z.array(z.enum(["hooks", "permissions", "mcp"])).optional()
22458
22510
  });
22459
22511
  var collaborationSchema = z.object({
22460
22512
  strategy: z.enum(["merge", "lock", "last-wins"]).default("merge"),
@@ -22646,7 +22698,14 @@ async function loadCanonicalWithExtends(config, configDir, options = {}, canonic
22646
22698
  for (const ext of resolvedExtends) {
22647
22699
  const extCanonical = await loadCanonicalForExtend(ext);
22648
22700
  const filtered = filterCanonicalByFeatures(extCanonical, ext.features);
22649
- const picked = applyExtendPick(filtered, ext.features, ext.pick, ext.name);
22701
+ const gated = gateExtendElevatedArtifacts(filtered, ext);
22702
+ if (gated.stripped.length > 0) {
22703
+ const list = gated.stripped.join(", ");
22704
+ logger.warn(
22705
+ `[agentsmesh] Extend "${ext.name}": stripped elevated artifacts from a remote source: ${list}. Add \`accept: [${list}]\` to this extends entry in agentsmesh.yaml to keep them.`
22706
+ );
22707
+ }
22708
+ const picked = applyExtendPick(gated.canonical, ext.features, ext.pick, ext.name);
22650
22709
  merged = mergeCanonicalFiles(merged, picked);
22651
22710
  }
22652
22711
  const packsCanonical = await loadPacksCanonical(canonicalDir);