agentsmesh 0.8.0 → 0.9.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 +43 -0
- package/README.md +190 -107
- package/dist/canonical.js +56 -14
- package/dist/canonical.js.map +1 -1
- package/dist/cli.js +117 -117
- package/dist/engine.d.ts +1 -1
- package/dist/engine.js +68 -28
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +69 -28
- package/dist/index.js.map +1 -1
- package/dist/{target-descriptor-Cb9PXaxr.d.ts → target-descriptor-CkH4Z43u.d.ts} +2 -1
- package/dist/targets.d.ts +21 -3
- package/dist/targets.js +43 -13
- package/dist/targets.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b3f702d: Adds three new `agentsmesh lint` diagnostics, a recommended `.gitignore` policy for materialized packs, and a one-step `agentsmesh target-scaffold` workflow.
|
|
8
|
+
|
|
9
|
+
Added:
|
|
10
|
+
- New lint diagnostics, all emitted as warnings (do not change `lint`'s exit code):
|
|
11
|
+
- `silent-drop-guard` flags canonical content a target would otherwise drop without trace based on its capability map.
|
|
12
|
+
- `hook-script-references` warns when a hook command references a script path for any target whose generator does not copy hook scripts into its output. **All built-in targets except Copilot fall under this rule today.** Existing hook configs that reference local script paths (e.g. `./scripts/pre-commit.sh`) will surface a new warning per matching target on the first lint after upgrade. The script must already exist relative to the hook execution directory or the generated config will fail at runtime — the diagnostic just makes the gap visible.
|
|
13
|
+
- `rule-scope-inversion` catches manual-activation rules whose scope contradicts the target's projection rules.
|
|
14
|
+
All three are wired into `runLint` for every target via descriptor capabilities; no existing rule has been removed and no diagnostic is upgraded to error severity.
|
|
15
|
+
- `agentsmesh init` now writes `.agentsmesh/packs/` into `.gitignore` alongside `agentsmesh.local.yaml`, `.agentsmeshcache`, and `.agentsmesh/.lock.tmp`, and skips entries already covered by a broader pre-existing pattern (e.g. an existing `.agentsmesh/` line covers `.agentsmesh/packs/`). Materialized packs are treated like `node_modules` — `installs.yaml` is committed and `agentsmesh install --sync` reproduces the tree deterministically post-clone.
|
|
16
|
+
- `agentsmesh target-scaffold` post-steps collapse the previous three-edit sequence into one `pnpm catalog:generate` invocation, backed by a new auto-discovered builtin-target catalog (`scripts/generate-target-catalog.ts` + `pnpm catalog:verify` drift guard in CI).
|
|
17
|
+
|
|
18
|
+
Changed:
|
|
19
|
+
- The `agentsmesh.json` and `pack.json` schemas now list `targets` enums alphabetically. Schema consumers that pin order will see a one-time diff; values are unchanged.
|
|
20
|
+
- README documents the commit-vs-gitignore convention for generated tool folders and clarifies native Windows support (no WSL).
|
|
21
|
+
|
|
22
|
+
Internal:
|
|
23
|
+
- Per-target importers (`antigravity`, `claude-code`, `continue`, `copilot`, `cursor`, `gemini-cli`, `junie`, `kiro`, `roo-code`) migrated to the descriptor-driven import runner with mapper functions extracted into `import-mappers.ts` to keep `index.ts` ↔ `importer.ts` cycles out of the TDZ.
|
|
24
|
+
- New shared link-format registry (`src/core/reference/link-format-registry.ts`) consolidates per-target link rendering rules.
|
|
25
|
+
- `writeFileAtomic` now refuses to follow a pre-existing symlink at the target path (closes a TOCTOU window where a swapped symlink could redirect writes outside the project tree).
|
|
26
|
+
- `agentsmesh plugin add` now warns that plugins load as trusted Node.js modules with full process privileges.
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- 08ef1b0: Security hardening and correctness fixes across install, generate, reference rewriting, plugin loading, and caching subsystems.
|
|
31
|
+
|
|
32
|
+
Fixed:
|
|
33
|
+
- `agentsmesh install --path` now rejects paths that traverse outside the install source root, closing a directory-escape vulnerability where `--path ../../outside` could read files outside the fetched source.
|
|
34
|
+
- Pack names are validated as single directory segments before materialization — values containing path separators (e.g. `../../escape`) are rejected, preventing writes outside `.agentsmesh/packs/`.
|
|
35
|
+
- `writeFileAtomic` now checks the `.tmp` staging path for symlinks before writing, closing a TOCTOU window where a symlink at `${path}.tmp` could redirect writes to an attacker-controlled location.
|
|
36
|
+
- `agentsmesh generate --targets` now validates filter values against configured targets and errors on unknown names. Previously a misspelled target silently produced zero outputs and `--check` reported success, allowing CI to pass while checking nothing.
|
|
37
|
+
- Project-scope skill mirrors now receive source-map entries for reference rewriting. Previously only global-scope mirrors were mapped, leaving Markdown links inside project-mirrored skill files unrewritten.
|
|
38
|
+
- Plugin targets declaring `sharedArtifacts` are now recognized during global reference rewriting. Previously only builtin target descriptors were consulted, so plugin-owned shared paths could be rebased through the wrong artifact map.
|
|
39
|
+
- `runDescriptorImport` is now exported from `agentsmesh/targets` as documented in the plugin guide.
|
|
40
|
+
- Importer fallback sources are now tried when configured primary files are absent on disk, not only when the primary source list is empty.
|
|
41
|
+
- `flatFile` and `mcpJson` import modes now honor `canonicalDir` when `canonicalFilename` is a bare filename, matching the documented directory-plus-filename contract for plugin descriptor authors.
|
|
42
|
+
- Rule path mapping uses POSIX `basename` with backslash normalization instead of host `node:path`, preventing broken slugs when Windows-shaped canonical paths appear on a POSIX host.
|
|
43
|
+
- Relative `file:` plugin sources now resolve against `projectRoot` instead of the filesystem root.
|
|
44
|
+
- Remote cache keys now preserve dots and use double-separator delimiters so distinct refs like `v1.0.0` and `v1_0_0` no longer collide. Existing cached entries will be re-fetched once after upgrade.
|
|
45
|
+
|
|
3
46
|
## 0.8.0
|
|
4
47
|
|
|
5
48
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
# AgentsMesh —
|
|
3
|
+
# AgentsMesh — One `.agentsmesh/` Directory for Every AI Coding Tool
|
|
4
4
|
|
|
5
5
|
[](https://github.com/sampleXbro/agentsmesh/actions/workflows/ci.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/agentsmesh)
|
|
@@ -12,99 +12,189 @@
|
|
|
12
12
|
[](https://samplexbro.github.io/agentsmesh)
|
|
13
13
|
[](https://github.com/sampleXbro/agentsmesh/pulls)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Edit once and generate `CLAUDE.md`, `AGENTS.md`, `.cursor/rules`, `.github/copilot-instructions.md`, `.gemini/settings.json`, `.windsurf/rules`, `.codex/config.toml`, `.kiro/steering`, and more from the same source. Import existing Claude Code, Cursor, Copilot, Gemini CLI, Windsurf, Codex CLI, and other configs back into canonical form without losing round-trip metadata.
|
|
15
|
+
</div>
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
AI coding assistants now ship with their own configuration formats — `CLAUDE.md`, `AGENTS.md`, `.cursor/rules/*.mdc`, `.github/copilot-instructions.md`, `.gemini/settings.json`, `.windsurf/rules/*.md`, `.codex/config.toml`, `.kiro/steering/*.md`, and more. Maintaining the same rules, prompts, MCP servers, hooks, and permissions across all of them by hand causes config drift fast.
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
**AgentsMesh** is an open-source CLI and TypeScript library that fixes this. You write canonical rules, commands, agents, skills, MCP, hooks, ignore files, and permissions once in `.agentsmesh/`, then `agentsmesh generate` projects them out as native config for every supported assistant. `agentsmesh import` brings existing tool configs back into canonical form, and `agentsmesh check` catches drift in CI.
|
|
22
20
|
|
|
23
21
|
> **Full documentation: [samplexbro.github.io/agentsmesh](https://samplexbro.github.io/agentsmesh)**
|
|
24
22
|
|
|
25
23
|
---
|
|
26
24
|
|
|
27
|
-
##
|
|
25
|
+
## Before / After
|
|
26
|
+
|
|
27
|
+
**Before — fragmented assistant-native config in one repo:**
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
CLAUDE.md
|
|
31
|
+
AGENTS.md
|
|
32
|
+
.cursor/rules/*.mdc
|
|
33
|
+
.github/copilot-instructions.md
|
|
34
|
+
.gemini/settings.json
|
|
35
|
+
.windsurf/rules/*.md
|
|
36
|
+
.codex/config.toml
|
|
37
|
+
.kiro/steering/*.md
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**After — one canonical source, generated everywhere:**
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
.agentsmesh/
|
|
44
|
+
rules/
|
|
45
|
+
_root.md
|
|
46
|
+
commands/
|
|
47
|
+
agents/
|
|
48
|
+
skills/
|
|
49
|
+
mcp.json
|
|
50
|
+
hooks.yaml
|
|
51
|
+
permissions.yaml
|
|
52
|
+
ignore
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx agentsmesh generate
|
|
57
|
+
```
|
|
28
58
|
|
|
29
|
-
|
|
30
|
-
- **Adopt existing projects safely** with bidirectional `import` and `generate` instead of rewriting every tool config by hand.
|
|
31
|
-
- **Sync personal global config** from `~/.agentsmesh/` to user-level assistant folders such as `~/.claude/`, `~/.cursor/`, and `~/.codex/`.
|
|
32
|
-
- **Standardize MCP, hooks, permissions, skills, and agents** where tools support them natively, with metadata-backed projections where they do not.
|
|
33
|
-
- **Catch config drift in CI** with lock-file checks, diffs, linting, and merge recovery built for team workflows.
|
|
34
|
-
- **Share and extend configuration** with community packs, remote `extends`, runtime plugins, and a typed programmatic API.
|
|
59
|
+
The native files above are still emitted — AgentsMesh writes them for you from `.agentsmesh/`. Edit canonical sources, regenerate, and every tool stays in sync.
|
|
35
60
|
|
|
36
61
|
---
|
|
37
62
|
|
|
38
|
-
##
|
|
63
|
+
## 60-second quickstart
|
|
39
64
|
|
|
40
|
-
Requires
|
|
65
|
+
Requires Node.js 20+. Works on Linux, macOS, and Windows (native, not WSL).
|
|
41
66
|
|
|
42
67
|
```bash
|
|
43
|
-
|
|
44
|
-
npx agentsmesh
|
|
68
|
+
npx agentsmesh init # scaffold .agentsmesh/ + agentsmesh.yaml
|
|
69
|
+
npx agentsmesh generate # produce native configs for every enabled tool
|
|
70
|
+
npx agentsmesh check # CI-friendly drift gate against .agentsmesh/.lock
|
|
45
71
|
```
|
|
46
72
|
|
|
47
|
-
|
|
73
|
+
- **`init`** — creates `agentsmesh.yaml`, `agentsmesh.local.yaml`, and the canonical `.agentsmesh/` directory.
|
|
74
|
+
- **`generate`** — writes `CLAUDE.md`, `AGENTS.md`, `.cursor/`, `.github/copilot-instructions.md`, etc. from canonical sources.
|
|
75
|
+
- **`check`** — exits non-zero if generated files have drifted from `.agentsmesh/.lock`. Drop into CI.
|
|
48
76
|
|
|
49
|
-
|
|
77
|
+
Prefer a local install? `npm install -D agentsmesh` (also `pnpm add -D` / `yarn add -D`). The CLI ships as `agentsmesh` and the shorter alias `amsh`.
|
|
50
78
|
|
|
51
79
|
---
|
|
52
80
|
|
|
53
|
-
##
|
|
81
|
+
## Safe adoption in an existing repository
|
|
54
82
|
|
|
55
|
-
|
|
83
|
+
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`.
|
|
56
84
|
|
|
57
85
|
```bash
|
|
58
|
-
agentsmesh
|
|
59
|
-
#
|
|
60
|
-
agentsmesh generate
|
|
86
|
+
npx agentsmesh import --from cursor # or claude-code, copilot, codex-cli, gemini-cli, windsurf, ...
|
|
87
|
+
npx agentsmesh diff # patch-style preview of what generate would change
|
|
88
|
+
npx agentsmesh generate # write native configs (back) from canonical
|
|
89
|
+
npx agentsmesh check # add to CI to detect drift
|
|
61
90
|
```
|
|
62
91
|
|
|
63
|
-
|
|
92
|
+
What this gets you:
|
|
64
93
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
agentsmesh
|
|
68
|
-
```
|
|
94
|
+
- `import` reads existing tool configs and writes equivalent canonical files into `.agentsmesh/` — round-trip metadata is preserved so re-import doesn't lose information.
|
|
95
|
+
- `diff` shows the unified patch every output file would receive, so you can review before any write.
|
|
96
|
+
- `check` reads `.agentsmesh/.lock` and fails the build if the canonical sources and the generated files disagree.
|
|
69
97
|
|
|
70
|
-
|
|
98
|
+
`import --from` accepts the built-in target IDs: `claude-code`, `cursor`, `copilot`, `codex-cli`, `gemini-cli`, `windsurf`, `continue`, `cline`, `kiro`, `junie`, `roo-code`, `antigravity`. Plugin targets are valid too.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Demo
|
|
103
|
+
|
|
104
|
+
<!-- TODO: Add terminal demo GIF showing init → generate → diff → check. -->
|
|
105
|
+
|
|
106
|
+
A quick sample of the canonical → native projection:
|
|
71
107
|
|
|
72
108
|
```bash
|
|
73
|
-
agentsmesh init
|
|
74
|
-
agentsmesh
|
|
75
|
-
agentsmesh generate
|
|
109
|
+
npx agentsmesh init
|
|
110
|
+
find .agentsmesh -maxdepth 2 -type f # see the canonical scaffold
|
|
111
|
+
npx agentsmesh generate
|
|
112
|
+
npx agentsmesh diff # preview future changes
|
|
113
|
+
npx agentsmesh check # CI-style drift gate
|
|
76
114
|
```
|
|
77
115
|
|
|
116
|
+
On macOS/Linux you can also run `tree .agentsmesh` if you have `tree` installed.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Supported AI coding tools
|
|
121
|
+
|
|
122
|
+
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).
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Why developers use AgentsMesh
|
|
127
|
+
|
|
128
|
+
- **Bidirectional sync** — `import` reads existing tool configs into `.agentsmesh/`; `generate` projects them back out. Round-trips are loss-free, so adopting AgentsMesh in an existing repo never throws away data.
|
|
129
|
+
- **Automatic link rebasing** — references like `.agentsmesh/skills/foo/SKILL.md` are rewritten to target-relative paths in every generated artifact, so cross-file links stay valid from `.claude/`, `.cursor/`, `.github/`, `.codex/`, and the rest.
|
|
130
|
+
- **Managed embedding with round-trip metadata** — when a target has no native slot for a feature (e.g. commands in Codex CLI, agents in Cline), AgentsMesh embeds it with frontmatter that survives the next `import`. No silent data loss; the full feature-by-feature breakdown lives in the [supported tools matrix](https://samplexbro.github.io/agentsmesh/reference/supported-tools/).
|
|
131
|
+
- **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.
|
|
132
|
+
- **Global mode** — `~/.agentsmesh/` syncs personal AI config to `~/.claude/`, `~/.cursor/`, `~/.codex/`, `~/.windsurf/`, and other user-level folders. Every CLI command accepts `--global`.
|
|
133
|
+
- **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.
|
|
134
|
+
|
|
78
135
|
---
|
|
79
136
|
|
|
80
|
-
##
|
|
137
|
+
## Why not just `AGENTS.md`?
|
|
81
138
|
|
|
82
|
-
|
|
139
|
+
[`AGENTS.md`](https://agents.md) is great as a shared, human-readable instruction file. AgentsMesh uses `AGENTS.md` natively where the target supports it (Codex CLI, Cursor, Copilot, Junie, Windsurf, …) and treats it as a first-class output, not a competitor.
|
|
83
140
|
|
|
84
|
-
|
|
141
|
+
The reason `AGENTS.md` alone is not enough: most AI coding assistants expose configuration surfaces beyond a single instruction markdown file, and those surfaces don't all overlap.
|
|
85
142
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
| **Windsurf** | `.windsurf/rules/*.md`, `.windsurf/workflows/`, `.windsurf/mcp_config.json`, `.windsurf/hooks.json` |
|
|
93
|
-
| **Continue** | `.continue/rules/`, `.continue/prompts/`, `.continue/mcpServers/`, `.continue/config.yaml` |
|
|
94
|
-
| **Cline** | `.clinerules/`, `.cline/skills/`, `.cline/cline_mcp_settings.json`, hooks |
|
|
95
|
-
| **Kiro** | `.kiro/steering/`, `.kiro/skills/`, `.kiro/hooks/*.kiro.hook`, `.kiro/settings/mcp.json` |
|
|
96
|
-
| **Codex CLI** | `AGENTS.md`, `.codex/config.toml`, `.codex/agents/*.toml`, `.codex/rules/` |
|
|
97
|
-
| **Junie** | `AGENTS.md`, `.junie/agents/`, `.junie/commands/`, `.junie/skills/`, `.junie/mcp/mcp.json` |
|
|
98
|
-
| **Roo Code** | `.roo/rules/`, `.roomodes` (agents → custom modes), `.roo/commands/`, `.roo/skills/` |
|
|
99
|
-
| **Antigravity** | `.agents/rules/general.md`, `.agents/skills/`, `.agents/workflows/`, `.agents/mcp_config.json` |
|
|
143
|
+
- **Cursor** has `.cursor/rules/*.mdc` (with frontmatter scopes), `.cursorignore`, MCP config, and hooks.
|
|
144
|
+
- **Claude Code** has `CLAUDE.md`, `.claude/agents/`, `.claude/skills/`, `.claude/commands/`, `.claude/settings.json`, hooks, and permissions.
|
|
145
|
+
- **GitHub Copilot** has `.github/copilot-instructions.md`, `.github/instructions/*.instructions.md`, agents, prompts, and (partial) hooks.
|
|
146
|
+
- **Gemini CLI** has `GEMINI.md`, `.gemini/settings.json` (MCP + hooks), `.gemini/commands/*.toml`, and agents.
|
|
147
|
+
- **Codex CLI** has `AGENTS.md` plus `.codex/config.toml`, `.codex/agents/*.toml`, and `.codex/rules/`.
|
|
148
|
+
- **Windsurf**, **Continue**, **Cline**, **Kiro**, **Junie**, **Roo Code**, **Antigravity** each have their own native rules, workflows, MCP servers, skills, and ignore files.
|
|
100
149
|
|
|
101
|
-
|
|
150
|
+
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.
|
|
102
151
|
|
|
103
|
-
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Core concepts
|
|
155
|
+
|
|
156
|
+
`.agentsmesh/` is the canonical source of truth. Generated tool files are artifacts. The directory contains:
|
|
157
|
+
|
|
158
|
+
- `rules/_root.md` — the root rule every target projects (typically becomes `CLAUDE.md`, `AGENTS.md`, `.cursor/rules/_root.mdc`, etc.).
|
|
159
|
+
- `rules/*.md` — additional scoped rules.
|
|
160
|
+
- `commands/*.md` — reusable slash-style prompts/commands.
|
|
161
|
+
- `agents/*.md` — agent definitions (where the target supports them).
|
|
162
|
+
- `skills/<name>/SKILL.md` (+ supporting files) — composable skills.
|
|
163
|
+
- `mcp.json` — MCP server definitions.
|
|
164
|
+
- `hooks.yaml` — pre/post tool hooks.
|
|
165
|
+
- `permissions.yaml` — allow/deny rules where the target supports them.
|
|
166
|
+
- `ignore` — paths the assistant should not read or modify.
|
|
167
|
+
|
|
168
|
+
Configuration:
|
|
169
|
+
|
|
170
|
+
- `agentsmesh.yaml` — selects which targets and features are enabled.
|
|
171
|
+
- `agentsmesh.local.yaml` — per-developer overrides (gitignored by default).
|
|
172
|
+
- `.agentsmesh/.lock` — drift-detection lock file consumed by `agentsmesh check`.
|
|
173
|
+
|
|
174
|
+
Detailed contracts: [Canonical Config](https://samplexbro.github.io/agentsmesh/canonical-config/) · [Generation pipeline](https://samplexbro.github.io/agentsmesh/reference/generation-pipeline/).
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## CLI usage
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
agentsmesh init [--global] [--yes]
|
|
182
|
+
agentsmesh generate [--global] [--targets <csv>] [--check] [--dry-run] [--force] [--refresh-cache]
|
|
183
|
+
agentsmesh import --from <target> [--global]
|
|
184
|
+
agentsmesh diff [--global] [--targets <csv>]
|
|
185
|
+
agentsmesh lint [--global] [--targets <csv>]
|
|
186
|
+
agentsmesh watch [--global] [--targets <csv>]
|
|
187
|
+
agentsmesh check [--global]
|
|
188
|
+
agentsmesh merge [--global]
|
|
189
|
+
agentsmesh matrix [--global] [--targets <csv>] [--verbose]
|
|
190
|
+
agentsmesh install <source> [--sync] [--path <dir>] [--target <id>] [--as <kind>] [--name <id>] [--extends] [--dry-run] [--global] [--force]
|
|
191
|
+
agentsmesh plugin add|list|remove|info [--version <v>] [--id <id>]
|
|
192
|
+
agentsmesh target scaffold <id> [--name <displayName>] [--force]
|
|
193
|
+
```
|
|
104
194
|
|
|
105
|
-
|
|
195
|
+
`agentsmesh --help` prints the same surface; `agentsmesh <cmd> --help` is also supported.
|
|
106
196
|
|
|
107
|
-
### Global mode
|
|
197
|
+
### Global mode (personal AI assistant config)
|
|
108
198
|
|
|
109
199
|
`.agentsmesh/` at the project level is for teams. `~/.agentsmesh/` at the home level is for personal setup across every repo you touch:
|
|
110
200
|
|
|
@@ -114,7 +204,7 @@ agentsmesh import --global --from claude-code
|
|
|
114
204
|
agentsmesh generate --global # writes ~/.claude/CLAUDE.md, ~/.cursor/, ~/.codex/, ~/.windsurf/, etc.
|
|
115
205
|
```
|
|
116
206
|
|
|
117
|
-
Every built-in target
|
|
207
|
+
Every built-in target with a global layout supports global mode. Every CLI command (`diff`, `lint`, `watch`, `check`, `merge`, `matrix`) accepts `--global`. [Global mode paths per tool →](https://samplexbro.github.io/agentsmesh/reference/supported-tools/#global-mode)
|
|
118
208
|
|
|
119
209
|
### Plugins for new AI coding tools
|
|
120
210
|
|
|
@@ -130,12 +220,12 @@ Plugins have full parity with built-in targets: project + global layouts, featur
|
|
|
130
220
|
|
|
131
221
|
### Team-safe collaboration & CI drift detection
|
|
132
222
|
|
|
133
|
-
- **`agentsmesh check`** — CI gate that exits 1 if generated files drifted from the lock
|
|
134
|
-
- **`agentsmesh diff`** — preview what the next `generate` would change
|
|
135
|
-
- **`agentsmesh lint`** — validate canonical config against target-specific constraints
|
|
136
|
-
- **`agentsmesh watch`** — regenerate target files on save during local editing
|
|
137
|
-
- **`agentsmesh merge`** — recover from three-way `.lock` conflicts after `git merge
|
|
138
|
-
- **Collaboration config** — `lock_features` and `strategy` prevent accidental overrides
|
|
223
|
+
- **`agentsmesh check`** — CI gate that exits 1 if generated files drifted from the lock.
|
|
224
|
+
- **`agentsmesh diff`** — preview what the next `generate` would change.
|
|
225
|
+
- **`agentsmesh lint`** — validate canonical config against target-specific constraints; also surfaces cross-target warnings (`silent-drop-guard`, `hook-script-references`, `rule-scope-inversion`) for content a target would silently drop or mishandle. [Lint reference →](https://samplexbro.github.io/agentsmesh/cli/lint/)
|
|
226
|
+
- **`agentsmesh watch`** — regenerate target files on save during local editing.
|
|
227
|
+
- **`agentsmesh merge`** — recover from three-way `.lock` conflicts after `git merge`.
|
|
228
|
+
- **Collaboration config** — `lock_features` and `strategy` prevent accidental overrides.
|
|
139
229
|
|
|
140
230
|
### Community packs and shared config
|
|
141
231
|
|
|
@@ -167,13 +257,6 @@ Why generated configs stay committed: the same reason `package-lock.json` does.
|
|
|
167
257
|
|
|
168
258
|
If your team has a strong reason to gitignore generated configs (e.g., monorepo size concerns, regenerate-on-checkout hooks), add the target-specific entries manually — but expect to wire `agentsmesh generate` into your post-checkout flow.
|
|
169
259
|
|
|
170
|
-
### Extending AgentsMesh
|
|
171
|
-
|
|
172
|
-
- **`agentsmesh target scaffold foo-ide`** — generate a built-in target skeleton (10 files: descriptor, generators, importer, linter, tests, fixtures) with global mode, conversion support, and lint hooks pre-wired. The catalog is auto-discovered at build time (`pnpm catalog:generate`) — no manual edits to `target-ids.ts`, `builtin-targets.ts`, or the import-map barrel.
|
|
173
|
-
- **`agentsmesh plugin add <pkg>`** — load third-party npm packages as runtime targets with full built-in parity. Supports `agentsmesh plugin list`, `info`, and `remove`.
|
|
174
|
-
|
|
175
|
-
[Extending guide →](https://samplexbro.github.io/agentsmesh/guides/extending/) · [Building plugins →](https://samplexbro.github.io/agentsmesh/guides/building-plugins/)
|
|
176
|
-
|
|
177
260
|
### Schema-validated configs (IDE autocomplete)
|
|
178
261
|
|
|
179
262
|
Every config file ships with a generated JSON Schema, so VS Code, JetBrains, and other editors give you autocomplete and validation out of the box:
|
|
@@ -190,45 +273,7 @@ Every config file ships with a generated JSON Schema, so VS Code, JetBrains, and
|
|
|
190
273
|
|
|
191
274
|
---
|
|
192
275
|
|
|
193
|
-
##
|
|
194
|
-
|
|
195
|
-
### Project scope (`agentsmesh generate`)
|
|
196
|
-
|
|
197
|
-
<!-- agentsmesh:support-matrix:project -->
|
|
198
|
-
| Feature | Antigravity | Claude Code | Cline | Codex CLI | Continue | Copilot | Cursor | Gemini CLI | Junie | Kiro | Roo Code | Windsurf |
|
|
199
|
-
|---|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|
|
|
200
|
-
| Rules | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native |
|
|
201
|
-
| Additional Rules | Native | Native | Native | Native | Native | Native | Embedded | Embedded | Native | Native | Native | Native |
|
|
202
|
-
| Commands | Partial (workflows) | Native | Native (workflows) | Embedded | Embedded | Native | Native | Native | Native | — | Native | Native (workflows) |
|
|
203
|
-
| Agents | — | Native | Embedded | Native | — | Native | Native | Native | Native | Native | Partial | Embedded |
|
|
204
|
-
| Skills | Native | Native | Native | Native | Embedded | Native | Native | Native | Native | Native | Native | Native |
|
|
205
|
-
| MCP Servers | — | Native | Native | Native | Native | — | Native | Native | Native | Native | Native | Partial |
|
|
206
|
-
| Hooks | — | Native | Native | — | — | Partial | Native | Partial | — | Native | — | Native |
|
|
207
|
-
| Ignore | — | Native | Native | — | — | — | Native | Native (settings-embedded) | Native | Native | Native | Native |
|
|
208
|
-
| Permissions | — | Native | — | — | — | — | Partial | Partial | — | — | — | — |
|
|
209
|
-
<!-- /agentsmesh:support-matrix:project -->
|
|
210
|
-
|
|
211
|
-
### Global scope (`agentsmesh generate --global`)
|
|
212
|
-
|
|
213
|
-
<!-- agentsmesh:support-matrix:global -->
|
|
214
|
-
| Feature | Antigravity | Claude Code | Cline | Codex CLI | Continue | Copilot | Cursor | Gemini CLI | Junie | Kiro | Roo Code | Windsurf |
|
|
215
|
-
|---|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|
|
|
216
|
-
| Rules | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native |
|
|
217
|
-
| Additional Rules | Embedded | Native | Native | Embedded | Native | Native | Embedded | Embedded | Embedded | Native | Native | Partial |
|
|
218
|
-
| Commands | Partial (workflows) | Native | Native (workflows) | Embedded | Native | Native | Native | Native | Native | — | Native | Native (workflows) |
|
|
219
|
-
| Agents | — | Native | Embedded | Native | — | Native | Native | Native | Native | Native | Partial | Embedded |
|
|
220
|
-
| Skills | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native |
|
|
221
|
-
| MCP Servers | Native | Native | Native | Native | Native | — | Native | Native | Native | Native | Native | Partial |
|
|
222
|
-
| Hooks | — | Native | Native | — | — | — | Native | Partial | — | — | — | Native |
|
|
223
|
-
| Ignore | — | Native | Native | — | — | — | Native | — | — | Native | Native | Native |
|
|
224
|
-
| Permissions | — | Native | — | — | — | — | — | — | — | — | — | — |
|
|
225
|
-
<!-- /agentsmesh:support-matrix:global -->
|
|
226
|
-
|
|
227
|
-
See the [full feature matrix docs](https://samplexbro.github.io/agentsmesh/reference/supported-tools/) for native vs. embedded support details and per-tool global paths.
|
|
228
|
-
|
|
229
|
-
---
|
|
230
|
-
|
|
231
|
-
## Programmatic API
|
|
276
|
+
## TypeScript / Programmatic API
|
|
232
277
|
|
|
233
278
|
AgentsMesh is also importable as a typed ESM library, so you can drive every CLI capability — `generate`, `import`, `lint`, `diff`, `check` — from scripts, IDE extensions, MCP servers, or CI without spawning the CLI. Public entrypoints: `agentsmesh` (full surface), `agentsmesh/engine`, `agentsmesh/canonical`, `agentsmesh/targets`.
|
|
234
279
|
|
|
@@ -286,6 +331,44 @@ Every public symbol resolves to a real `.d.ts` under strict TypeScript. Full ref
|
|
|
286
331
|
|
|
287
332
|
---
|
|
288
333
|
|
|
334
|
+
## Supported tools — feature matrix
|
|
335
|
+
|
|
336
|
+
### Project scope (`agentsmesh generate`)
|
|
337
|
+
|
|
338
|
+
<!-- agentsmesh:support-matrix:project -->
|
|
339
|
+
| Feature | Antigravity | Claude Code | Cline | Codex CLI | Continue | Copilot | Cursor | Gemini CLI | Junie | Kiro | Roo Code | Windsurf |
|
|
340
|
+
|---|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|
|
|
341
|
+
| Rules | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native |
|
|
342
|
+
| Additional Rules | Native | Native | Native | Native | Native | Native | Embedded | Embedded | Native | Native | Native | Native |
|
|
343
|
+
| Commands | Partial (workflows) | Native | Native (workflows) | Embedded | Embedded | Native | Native | Native | Native | — | Native | Native (workflows) |
|
|
344
|
+
| Agents | — | Native | Embedded | Native | — | Native | Native | Native | Native | Native | Partial | Embedded |
|
|
345
|
+
| Skills | Native | Native | Native | Native | Embedded | Native | Native | Native | Native | Native | Native | Native |
|
|
346
|
+
| MCP Servers | — | Native | Native | Native | Native | — | Native | Native | Native | Native | Native | Partial |
|
|
347
|
+
| Hooks | — | Native | Native | — | — | Partial | Native | Partial | — | Native | — | Native |
|
|
348
|
+
| Ignore | — | Native | Native | — | — | — | Native | Native (settings-embedded) | Native | Native | Native | Native |
|
|
349
|
+
| Permissions | — | Native | — | — | — | — | Partial | Partial | — | — | — | — |
|
|
350
|
+
<!-- /agentsmesh:support-matrix:project -->
|
|
351
|
+
|
|
352
|
+
### Global scope (`agentsmesh generate --global`)
|
|
353
|
+
|
|
354
|
+
<!-- agentsmesh:support-matrix:global -->
|
|
355
|
+
| Feature | Antigravity | Claude Code | Cline | Codex CLI | Continue | Copilot | Cursor | Gemini CLI | Junie | Kiro | Roo Code | Windsurf |
|
|
356
|
+
|---|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|:-----------:|
|
|
357
|
+
| Rules | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native |
|
|
358
|
+
| Additional Rules | Embedded | Native | Native | Embedded | Native | Native | Embedded | Embedded | Embedded | Native | Native | Partial |
|
|
359
|
+
| Commands | Partial (workflows) | Native | Native (workflows) | Embedded | Native | Native | Native | Native | Native | — | Native | Native (workflows) |
|
|
360
|
+
| Agents | — | Native | Embedded | Native | — | Native | Native | Native | Native | Native | Partial | Embedded |
|
|
361
|
+
| Skills | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native | Native |
|
|
362
|
+
| MCP Servers | Native | Native | Native | Native | Native | — | Native | Native | Native | Native | Native | Partial |
|
|
363
|
+
| Hooks | — | Native | Native | — | — | — | Native | Partial | — | — | — | Native |
|
|
364
|
+
| Ignore | — | Native | Native | — | — | — | Native | — | — | Native | Native | Native |
|
|
365
|
+
| Permissions | — | Native | — | — | — | — | — | — | — | — | — | — |
|
|
366
|
+
<!-- /agentsmesh:support-matrix:global -->
|
|
367
|
+
|
|
368
|
+
See the [full feature matrix docs](https://samplexbro.github.io/agentsmesh/reference/supported-tools/) for native vs. embedded support details and per-tool global paths.
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
289
372
|
## Documentation
|
|
290
373
|
|
|
291
374
|
- **[Getting Started](https://samplexbro.github.io/agentsmesh/getting-started/installation/)** — installation, quick start
|
package/dist/canonical.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { access, readdir, realpath, stat, readFile, rm, mkdir, writeFile, rename, lstat } from 'fs/promises';
|
|
1
|
+
import { access, readdir, realpath, stat, readFile, rm, mkdir, writeFile, rename, lstat, unlink } from 'fs/promises';
|
|
2
2
|
import { join, basename, dirname, resolve, relative, normalize, extname, win32, isAbsolute, posix } from 'path';
|
|
3
3
|
import { constants, existsSync, realpathSync, statSync } from 'fs';
|
|
4
4
|
import { parse, stringify } from 'yaml';
|
|
@@ -6,6 +6,7 @@ import { parse as parse$1 } from 'smol-toml';
|
|
|
6
6
|
import { Buffer } from 'buffer';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { homedir } from 'os';
|
|
9
|
+
import { createHash } from 'crypto';
|
|
9
10
|
import { execFile } from 'child_process';
|
|
10
11
|
import { URL } from 'url';
|
|
11
12
|
import { promisify } from 'util';
|
|
@@ -104,6 +105,11 @@ async function writeFileAtomic(path, content) {
|
|
|
104
105
|
{ errnoCode: "EISDIR" }
|
|
105
106
|
);
|
|
106
107
|
}
|
|
108
|
+
if (info.isSymbolicLink()) {
|
|
109
|
+
await unlink(path).catch((e) => {
|
|
110
|
+
if (e.code !== "ENOENT") throw e;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
107
113
|
} catch (err) {
|
|
108
114
|
if (err instanceof FileSystemError) throw err;
|
|
109
115
|
const e = err;
|
|
@@ -112,7 +118,15 @@ async function writeFileAtomic(path, content) {
|
|
|
112
118
|
const tmpPath = `${path}.tmp`;
|
|
113
119
|
const payload = shouldNormalizeLineEndings(path) ? normalizeLineEndings(content) : content;
|
|
114
120
|
try {
|
|
115
|
-
|
|
121
|
+
try {
|
|
122
|
+
const tmpInfo = await lstat(tmpPath);
|
|
123
|
+
if (tmpInfo.isSymbolicLink()) {
|
|
124
|
+
await unlink(tmpPath);
|
|
125
|
+
}
|
|
126
|
+
} catch (tmpErr) {
|
|
127
|
+
if (tmpErr.code !== "ENOENT") throw tmpErr;
|
|
128
|
+
}
|
|
129
|
+
await writeFile(tmpPath, payload, { encoding: "utf-8", flag: "w" });
|
|
116
130
|
await rename(tmpPath, path);
|
|
117
131
|
} catch (err) {
|
|
118
132
|
await rm(tmpPath, { force: true }).catch(() => {
|
|
@@ -1136,18 +1150,24 @@ async function runDirectory(spec, sources, projectRoot, fromTool, normalize) {
|
|
|
1136
1150
|
}
|
|
1137
1151
|
return results;
|
|
1138
1152
|
}
|
|
1153
|
+
function resolveCanonicalFilePath(spec) {
|
|
1154
|
+
const filename = spec.canonicalFilename;
|
|
1155
|
+
if (filename.includes("/") || filename.includes("\\")) return filename;
|
|
1156
|
+
return posix.join(spec.canonicalDir, filename);
|
|
1157
|
+
}
|
|
1139
1158
|
async function runFlatFile(spec, sources, projectRoot, fromTool) {
|
|
1140
1159
|
if (!spec.canonicalFilename) {
|
|
1141
1160
|
throw new Error(`flatFile spec for ${spec.feature} must set canonicalFilename`);
|
|
1142
1161
|
}
|
|
1162
|
+
const canonicalPath = resolveCanonicalFilePath(spec);
|
|
1143
1163
|
for (const rel2 of sources) {
|
|
1144
1164
|
const srcPath = join(projectRoot, rel2);
|
|
1145
1165
|
const content = await readFileSafe(srcPath);
|
|
1146
1166
|
if (content === null) continue;
|
|
1147
|
-
const destPath = join(projectRoot,
|
|
1167
|
+
const destPath = join(projectRoot, canonicalPath);
|
|
1148
1168
|
await mkdirp(dirname(destPath));
|
|
1149
1169
|
await writeFileAtomic(destPath, content.trimEnd());
|
|
1150
|
-
return [{ fromTool, fromPath: srcPath, toPath:
|
|
1170
|
+
return [{ fromTool, fromPath: srcPath, toPath: canonicalPath, feature: spec.feature }];
|
|
1151
1171
|
}
|
|
1152
1172
|
return [];
|
|
1153
1173
|
}
|
|
@@ -1192,24 +1212,21 @@ async function runMcpJson(spec, sources, projectRoot, fromTool) {
|
|
|
1192
1212
|
if (!spec.canonicalFilename) {
|
|
1193
1213
|
throw new Error(`mcpJson spec for ${spec.feature} must set canonicalFilename`);
|
|
1194
1214
|
}
|
|
1215
|
+
const canonicalPath = resolveCanonicalFilePath(spec);
|
|
1195
1216
|
for (const rel2 of sources) {
|
|
1196
1217
|
const srcPath = join(projectRoot, rel2);
|
|
1197
1218
|
const content = await readFileSafe(srcPath);
|
|
1198
1219
|
if (content === null) continue;
|
|
1199
1220
|
const servers = parseMcpJson(content);
|
|
1200
1221
|
if (Object.keys(servers).length === 0) return [];
|
|
1201
|
-
const destPath = join(projectRoot,
|
|
1222
|
+
const destPath = join(projectRoot, canonicalPath);
|
|
1202
1223
|
await mkdirp(dirname(destPath));
|
|
1203
1224
|
await writeFileAtomic(destPath, JSON.stringify({ mcpServers: servers }, null, 2));
|
|
1204
|
-
return [{ fromTool, fromPath: srcPath, toPath:
|
|
1225
|
+
return [{ fromTool, fromPath: srcPath, toPath: canonicalPath, feature: spec.feature }];
|
|
1205
1226
|
}
|
|
1206
1227
|
return [];
|
|
1207
1228
|
}
|
|
1208
|
-
|
|
1209
|
-
const primary = resolveScopedSources(spec.source, scope);
|
|
1210
|
-
const fallback = resolveScopedSources(spec.fallbacks, scope);
|
|
1211
|
-
const sources = primary.length > 0 ? primary : fallback;
|
|
1212
|
-
if (sources.length === 0) return [];
|
|
1229
|
+
function dispatchSpec(spec, sources, projectRoot, fromTool, normalize) {
|
|
1213
1230
|
switch (spec.mode) {
|
|
1214
1231
|
case "singleFile":
|
|
1215
1232
|
return runSingleFile(spec, sources, projectRoot, fromTool, normalize);
|
|
@@ -1221,6 +1238,19 @@ async function runSpec(spec, scope, projectRoot, fromTool, normalize) {
|
|
|
1221
1238
|
return runMcpJson(spec, sources, projectRoot, fromTool);
|
|
1222
1239
|
}
|
|
1223
1240
|
}
|
|
1241
|
+
async function runSpec(spec, scope, projectRoot, fromTool, normalize) {
|
|
1242
|
+
const primary = resolveScopedSources(spec.source, scope);
|
|
1243
|
+
const fallback = resolveScopedSources(spec.fallbacks, scope);
|
|
1244
|
+
if (primary.length === 0 && fallback.length === 0) return [];
|
|
1245
|
+
if (primary.length > 0) {
|
|
1246
|
+
const results = await dispatchSpec(spec, primary, projectRoot, fromTool, normalize);
|
|
1247
|
+
if (results.length > 0) return results;
|
|
1248
|
+
}
|
|
1249
|
+
if (fallback.length > 0) {
|
|
1250
|
+
return dispatchSpec(spec, fallback, projectRoot, fromTool, normalize);
|
|
1251
|
+
}
|
|
1252
|
+
return [];
|
|
1253
|
+
}
|
|
1224
1254
|
function specsForFeature(importer, feature) {
|
|
1225
1255
|
const value = importer[feature];
|
|
1226
1256
|
if (!value) return [];
|
|
@@ -12098,13 +12128,25 @@ async function sweepStaleCache(cacheDir, maxAgeMs) {
|
|
|
12098
12128
|
}
|
|
12099
12129
|
|
|
12100
12130
|
// src/config/remote/remote-fetcher.ts
|
|
12131
|
+
var MAX_CACHE_KEY_LENGTH = 80;
|
|
12101
12132
|
function buildCacheKey(provider, identifier, ref) {
|
|
12102
|
-
const safe = (value) => value.replace(/[^a-zA-Z0-9_
|
|
12133
|
+
const safe = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_").replace(/^\.+/, "_");
|
|
12134
|
+
let key;
|
|
12103
12135
|
if (provider === "github") {
|
|
12104
12136
|
const [org, repo] = identifier.split("/", 2);
|
|
12105
|
-
if (org && repo)
|
|
12137
|
+
if (org && repo) {
|
|
12138
|
+
key = `${safe(org)}--${safe(repo)}--${safe(ref)}`;
|
|
12139
|
+
} else {
|
|
12140
|
+
key = `${safe(provider)}__${safe(identifier)}__${safe(ref)}`;
|
|
12141
|
+
}
|
|
12142
|
+
} else {
|
|
12143
|
+
key = `${safe(provider)}__${safe(identifier)}__${safe(ref)}`;
|
|
12144
|
+
}
|
|
12145
|
+
if (key.length > MAX_CACHE_KEY_LENGTH) {
|
|
12146
|
+
const hash = createHash("sha256").update(key).digest("hex").slice(0, 16);
|
|
12147
|
+
key = `${key.slice(0, MAX_CACHE_KEY_LENGTH - 18)}--${hash}`;
|
|
12106
12148
|
}
|
|
12107
|
-
return
|
|
12149
|
+
return key;
|
|
12108
12150
|
}
|
|
12109
12151
|
function getCacheDir() {
|
|
12110
12152
|
const env = process.env.AGENTSMESH_CACHE;
|