allagents 0.1.5 → 0.2.1

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 EntityProcess
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 EntityProcess
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,281 +1,281 @@
1
- # AllAgents
2
-
3
- CLI tool for managing multi-repo AI agent workspaces with plugin synchronization across multiple AI clients.
4
-
5
- > **Attribution:** AllAgents is inspired by [dotagents](https://github.com/iannuttall/dotagents) by Ian Nuttall. While rewritten from scratch, we share the vision of unified AI agent configuration management. Thank you Ian for the inspiration!
6
-
7
- ## Why AllAgents?
8
-
9
- **The Problem:** AI coding assistants (Claude, Copilot, Cursor, Codex, etc.) each have their own configuration formats and directory structures. If you want to share skills, commands, or prompts across multiple projects or use multiple AI clients, you need to manually copy and transform files.
10
-
11
- **AllAgents solves this by:**
12
-
13
- | Feature | Claude Code Plugins | AllAgents |
14
- |---------|--------------------|-----------|
15
- | Scope | Single project | Multi-repo workspace |
16
- | Client support | Claude only | 8 AI clients |
17
- | File location | Runtime lookup from cache | Copied to workspace (git-versioned) |
18
- | Project structure | AI config mixed with code | Separate workspace repo |
19
-
20
- ### Key Differentiators
21
-
22
- 1. **Multi-repo workspaces** - One workspace references multiple project repositories. Your AI tooling lives separately from your application code.
23
-
24
- 2. **Multi-client distribution** - Write plugins once, sync to all clients. AllAgents transforms and copies files to each client's expected paths.
25
-
26
- 3. **Workspace is a git repo** - Unlike Claude's runtime plugin system, AllAgents copies files into your workspace. Team members get the same AI tooling via git.
27
-
28
- 4. **Clean separation** - Project repos stay clean. AI configuration lives in the workspace.
29
-
30
- ```
31
- ┌─────────────────┐
32
- │ Marketplace │ (plugin source - GitHub repos)
33
- └────────┬────────┘
34
-
35
-
36
- ┌─────────────────┐
37
- │ AllAgents │ (sync & transform)
38
- │ workspace sync │
39
- └────────┬────────┘
40
-
41
- ┌────┴────┬────────┬─────────┐
42
- ▼ ▼ ▼ ▼
43
- .claude/ .github/ .cursor/ .codex/ (client-specific paths)
44
- ```
45
-
46
- ## Installation
47
-
48
- ```bash
49
- # Using bun
50
- bun install -g allagents
51
-
52
- # Or run directly
53
- bunx allagents
54
- ```
55
-
56
- ## Quick Start
57
-
58
- ```bash
59
- # Create a new workspace
60
- allagents workspace init my-workspace
61
- cd my-workspace
62
-
63
- # Add a marketplace (or let auto-registration handle it)
64
- allagents plugin marketplace add anthropics/claude-plugins-official
65
-
66
- # Add plugins to workspace
67
- allagents workspace plugin add code-review@claude-plugins-official
68
- allagents workspace plugin add my-plugin@someuser/their-repo
69
-
70
- # Sync plugins to workspace
71
- allagents workspace sync
72
- ```
73
-
74
- ## Commands
75
-
76
- ### Workspace Commands
77
-
78
- ```bash
79
- # Initialize a new workspace from template
80
- allagents workspace init <path>
81
-
82
- # Sync all plugins to workspace (non-destructive)
83
- allagents workspace sync [options]
84
- --force Force re-fetch of remote plugins even if cached
85
- --dry-run Preview changes without applying
86
-
87
- # Non-destructive sync: your files are safe
88
- # - First sync overlays without deleting existing files
89
- # - Subsequent syncs only remove files AllAgents previously synced
90
- # - Tracked in .allagents/sync-state.json
91
-
92
- # Show status of workspace and plugins
93
- allagents workspace status
94
-
95
- # Add a plugin to .allagents/workspace.yaml (auto-registers marketplace if needed)
96
- allagents workspace plugin add <plugin@marketplace>
97
-
98
- # Remove a plugin from .allagents/workspace.yaml
99
- allagents workspace plugin remove <plugin>
100
- ```
101
-
102
- ### Plugin Marketplace Commands
103
-
104
- ```bash
105
- # List registered marketplaces
106
- allagents plugin marketplace list
107
-
108
- # Add a marketplace from GitHub or local path
109
- allagents plugin marketplace add <source>
110
- # Examples:
111
- # allagents plugin marketplace add anthropics/claude-plugins-official
112
- # allagents plugin marketplace add /path/to/local/marketplace
113
-
114
- # Remove a marketplace
115
- allagents plugin marketplace remove <name>
116
-
117
- # Update marketplace(s) from remote
118
- allagents plugin marketplace update [name]
119
- ```
120
-
121
- ### Plugin Commands
122
-
123
- ```bash
124
- # List available plugins from marketplaces
125
- allagents plugin list [marketplace]
126
-
127
- # Validate a plugin or marketplace structure
128
- allagents plugin validate <path>
129
- ```
130
-
131
- ## .allagents/workspace.yaml
132
-
133
- The workspace configuration file lives in `.allagents/workspace.yaml` and defines repositories, plugins, and target clients:
134
-
135
- ```yaml
136
- repositories:
137
- - path: ../my-project
138
- owner: myorg
139
- repo: my-project
140
- description: Main project repository
141
- - path: ../my-api
142
- owner: myorg
143
- repo: my-api
144
- description: API service
145
-
146
- plugins:
147
- - code-review@claude-plugins-official # plugin@marketplace format
148
- - context7@claude-plugins-official
149
- - my-plugin@someuser/their-repo # fully qualified for custom marketplaces
150
-
151
- clients:
152
- - claude
153
- - copilot
154
- - cursor
155
- ```
156
-
157
- ### Plugin Spec Format
158
-
159
- Plugins use the `plugin@marketplace` format:
160
-
161
- | Format | Example | Description |
162
- |--------|---------|-------------|
163
- | Well-known | `code-review@claude-plugins-official` | Uses known marketplace mapping |
164
- | owner/repo | `my-plugin@owner/repo` | Auto-registers GitHub repo, looks in `plugins/` |
165
- | owner/repo/subpath | `my-plugin@owner/repo/extensions` | Looks in custom subdirectory |
166
-
167
- The subpath format is useful when plugins aren't in the standard `plugins/` directory:
168
-
169
- ```yaml
170
- plugins:
171
- - feature-dev@anthropics/claude-plugins-official/plugins # explicit plugins/ dir
172
- - my-addon@someuser/repo/addons # custom addons/ dir
173
- - tool@org/monorepo/packages/tools # nested path
174
- ```
175
-
176
- ### Well-Known Marketplaces
177
-
178
- These marketplace names auto-resolve to their GitHub repos:
179
-
180
- - `claude-plugins-official` → `anthropics/claude-plugins-official`
181
-
182
- ### Supported Clients
183
-
184
- | Client | Commands | Skills | Agent File | Hooks |
185
- |--------|----------|--------|------------|-------|
186
- | claude | `.claude/commands/` | `.claude/skills/` | `CLAUDE.md` | `.claude/hooks/` |
187
- | copilot | `.github/prompts/*.prompt.md` | `.github/skills/` | `AGENTS.md` | No |
188
- | codex | `.codex/prompts/` | `.codex/skills/` | `AGENTS.md` | No |
189
- | cursor | `.cursor/commands/` | `.cursor/skills/` | No | No |
190
- | opencode | `.opencode/commands/` | `.opencode/skills/` | `AGENTS.md` | No |
191
- | gemini | `.gemini/commands/` | `.gemini/skills/` | `GEMINI.md` | No |
192
- | factory | `.factory/commands/` | `.factory/skills/` | `AGENTS.md` | `.factory/hooks/` |
193
- | ampcode | N/A | N/A | `AGENTS.md` | No |
194
-
195
- ## Marketplace Structure
196
-
197
- Marketplaces contain multiple plugins:
198
-
199
- ```
200
- my-marketplace/
201
- ├── plugins/
202
- │ ├── code-review/
203
- │ │ ├── plugin.json
204
- ├── commands/
205
- │ │ └── skills/
206
- │ └── debugging/
207
- ├── plugin.json
208
- │ ├── commands/
209
- │ └── skills/
210
- └── README.md
211
- ```
212
-
213
- ## Plugin Structure
214
-
215
- Each plugin follows this structure:
216
-
217
- ```
218
- my-plugin/
219
- ├── plugin.json # Plugin metadata
220
- ├── commands/ # Command files (.md)
221
- ├── build.md
222
- └── deploy.md
223
- ├── skills/ # Skill directories with SKILL.md
224
- └── debugging/
225
- └── SKILL.md
226
- ├── hooks/ # Hook files (for Claude/Factory)
227
- │ └── pre-commit.md
228
- └── AGENTS.md # Agent configuration (optional)
229
- ```
230
-
231
- ### Skill Validation
232
-
233
- Skills must have a valid `SKILL.md` file with YAML frontmatter:
234
-
235
- ```yaml
236
- ---
237
- name: my-skill # Required: lowercase, alphanumeric + hyphens, max 64 chars
238
- description: Description of the skill # Required
239
- allowed-tools: # Optional
240
- - Read
241
- - Write
242
- model: claude-3-opus # Optional
243
- ---
244
-
245
- # Skill Content
246
-
247
- Skill instructions go here...
248
- ```
249
-
250
- ## Storage Locations
251
-
252
- ```
253
- ~/.allagents/
254
- ├── marketplaces.json # Registry of marketplaces
255
- └── marketplaces/ # Cloned marketplace repos
256
- ├── claude-plugins-official/
257
- └── someuser-their-repo/
258
- ```
259
-
260
- ## Development
261
-
262
- ```bash
263
- # Install dependencies
264
- bun install
265
-
266
- # Run in development
267
- bun run dev workspace init test-ws
268
-
269
- # Run tests
270
- bun run test
271
-
272
- # Type check
273
- bun run typecheck
274
-
275
- # Build
276
- bun run build
277
- ```
278
-
279
- ## License
280
-
281
- MIT
1
+ # AllAgents
2
+
3
+ CLI tool for managing multi-repo AI agent workspaces with plugin synchronization across multiple AI clients.
4
+
5
+ > **Attribution:** AllAgents is inspired by [dotagents](https://github.com/iannuttall/dotagents) by Ian Nuttall. While rewritten from scratch, we share the vision of unified AI agent configuration management. Thank you Ian for the inspiration!
6
+
7
+ ## Why AllAgents?
8
+
9
+ **The Problem:** AI coding assistants (Claude, Copilot, Cursor, Codex, etc.) each have their own configuration formats and directory structures. If you want to share skills across multiple projects or use multiple AI clients, you need to manually copy and transform files.
10
+
11
+ **AllAgents solves this by:**
12
+
13
+ | Feature | Claude Code Plugins | AllAgents |
14
+ |---------|--------------------|-----------|
15
+ | Scope | Single project | Multi-repo workspace |
16
+ | Client support | Claude only | 8 AI clients |
17
+ | File location | Runtime lookup from cache | Copied to workspace (git-versioned) |
18
+ | Project structure | AI config mixed with code | Separate workspace repo |
19
+
20
+ ### Key Differentiators
21
+
22
+ 1. **Multi-repo workspaces** - One workspace references multiple project repositories. Your AI tooling lives separately from your application code.
23
+
24
+ 2. **Multi-client distribution** - Write plugins once, sync to all clients. AllAgents transforms and copies files to each client's expected paths.
25
+
26
+ 3. **Workspace is a git repo** - Unlike Claude's runtime plugin system, AllAgents copies files into your workspace. Team members get the same AI tooling via git.
27
+
28
+ 4. **Clean separation** - Project repos stay clean. AI configuration lives in the workspace.
29
+
30
+ ```
31
+ ┌─────────────────┐
32
+ │ Marketplace │ (plugin source - GitHub repos)
33
+ └────────┬────────┘
34
+
35
+
36
+ ┌─────────────────┐
37
+ │ AllAgents │ (sync & transform)
38
+ │ workspace sync │
39
+ └────────┬────────┘
40
+
41
+ ┌────┴────┬────────┬─────────┐
42
+ ▼ ▼ ▼ ▼
43
+ .claude/ .github/ .cursor/ .codex/ (client-specific paths)
44
+ ```
45
+
46
+ ## Installation
47
+
48
+ ```bash
49
+ # Using bun
50
+ bun install -g allagents
51
+
52
+ # Or run directly
53
+ bunx allagents
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```bash
59
+ # Create a new workspace
60
+ allagents workspace init my-workspace
61
+ cd my-workspace
62
+
63
+ # Add a marketplace (or let auto-registration handle it)
64
+ allagents plugin marketplace add anthropics/claude-plugins-official
65
+
66
+ # Add plugins to workspace
67
+ allagents workspace plugin add code-review@claude-plugins-official
68
+ allagents workspace plugin add my-plugin@someuser/their-repo
69
+
70
+ # Sync plugins to workspace
71
+ allagents workspace sync
72
+ ```
73
+
74
+ ## Commands
75
+
76
+ ### Workspace Commands
77
+
78
+ ```bash
79
+ # Initialize a new workspace from template
80
+ allagents workspace init <path>
81
+
82
+ # Sync all plugins to workspace (non-destructive)
83
+ allagents workspace sync [options]
84
+ --force Force re-fetch of remote plugins even if cached
85
+ --dry-run Preview changes without applying
86
+
87
+ # Non-destructive sync: your files are safe
88
+ # - First sync overlays without deleting existing files
89
+ # - Subsequent syncs only remove files AllAgents previously synced
90
+ # - Tracked in .allagents/sync-state.json
91
+
92
+ # Show status of workspace and plugins
93
+ allagents workspace status
94
+
95
+ # Add a plugin to .allagents/workspace.yaml (auto-registers marketplace if needed)
96
+ allagents workspace plugin add <plugin@marketplace>
97
+
98
+ # Remove a plugin from .allagents/workspace.yaml
99
+ allagents workspace plugin remove <plugin>
100
+ ```
101
+
102
+ ### Plugin Marketplace Commands
103
+
104
+ ```bash
105
+ # List registered marketplaces
106
+ allagents plugin marketplace list
107
+
108
+ # Add a marketplace from GitHub or local path
109
+ allagents plugin marketplace add <source>
110
+ # Examples:
111
+ # allagents plugin marketplace add anthropics/claude-plugins-official
112
+ # allagents plugin marketplace add /path/to/local/marketplace
113
+
114
+ # Remove a marketplace
115
+ allagents plugin marketplace remove <name>
116
+
117
+ # Update marketplace(s) from remote
118
+ allagents plugin marketplace update [name]
119
+ ```
120
+
121
+ ### Plugin Commands
122
+
123
+ ```bash
124
+ # List available plugins from marketplaces
125
+ allagents plugin list [marketplace]
126
+
127
+ # Validate a plugin or marketplace structure
128
+ allagents plugin validate <path>
129
+ ```
130
+
131
+ ## .allagents/workspace.yaml
132
+
133
+ The workspace configuration file lives in `.allagents/workspace.yaml` and defines repositories, plugins, and target clients:
134
+
135
+ ```yaml
136
+ repositories:
137
+ - path: ../my-project
138
+ owner: myorg
139
+ repo: my-project
140
+ description: Main project repository
141
+ - path: ../my-api
142
+ owner: myorg
143
+ repo: my-api
144
+ description: API service
145
+
146
+ plugins:
147
+ - code-review@claude-plugins-official # plugin@marketplace format
148
+ - context7@claude-plugins-official
149
+ - my-plugin@someuser/their-repo # fully qualified for custom marketplaces
150
+
151
+ clients:
152
+ - claude
153
+ - copilot
154
+ - cursor
155
+ ```
156
+
157
+ ### Plugin Spec Format
158
+
159
+ Plugins use the `plugin@marketplace` format:
160
+
161
+ | Format | Example | Description |
162
+ |--------|---------|-------------|
163
+ | Well-known | `code-review@claude-plugins-official` | Uses known marketplace mapping |
164
+ | owner/repo | `my-plugin@owner/repo` | Auto-registers GitHub repo, looks in `plugins/` |
165
+ | owner/repo/subpath | `my-plugin@owner/repo/extensions` | Looks in custom subdirectory |
166
+
167
+ The subpath format is useful when plugins aren't in the standard `plugins/` directory:
168
+
169
+ ```yaml
170
+ plugins:
171
+ - feature-dev@anthropics/claude-plugins-official/plugins # explicit plugins/ dir
172
+ - my-addon@someuser/repo/addons # custom addons/ dir
173
+ - tool@org/monorepo/packages/tools # nested path
174
+ ```
175
+
176
+ ### Well-Known Marketplaces
177
+
178
+ These marketplace names auto-resolve to their GitHub repos:
179
+
180
+ - `claude-plugins-official` → `anthropics/claude-plugins-official`
181
+
182
+ ### Supported Clients
183
+
184
+ | Client | Skills | Agent File | Hooks | Commands |
185
+ |--------|--------|------------|-------|----------|
186
+ | claude | `.claude/skills/` | `CLAUDE.md` | `.claude/hooks/` | `.claude/commands/` |
187
+ | copilot | `.github/skills/` | `AGENTS.md` | No | No |
188
+ | codex | `.codex/skills/` | `AGENTS.md` | No | No |
189
+ | cursor | `.cursor/skills/` | `AGENTS.md` | No | No |
190
+ | opencode | `.opencode/skills/` | `AGENTS.md` | No | No |
191
+ | gemini | `.gemini/skills/` | `GEMINI.md` | No | No |
192
+ | factory | `.factory/skills/` | `AGENTS.md` | `.factory/hooks/` | No |
193
+ | ampcode | No | `AGENTS.md` | No | No |
194
+
195
+ > **Note:** Commands are a Claude-specific feature. Skills are the cross-client way to share reusable prompts.
196
+
197
+ ## Marketplace Structure
198
+
199
+ Marketplaces contain multiple plugins:
200
+
201
+ ```
202
+ my-marketplace/
203
+ ├── plugins/
204
+ │ ├── code-review/
205
+ │ │ ├── plugin.json
206
+ └── skills/
207
+ └── debugging/
208
+ │ ├── plugin.json
209
+ │ └── skills/
210
+ └── README.md
211
+ ```
212
+
213
+ ## Plugin Structure
214
+
215
+ Each plugin follows this structure:
216
+
217
+ ```
218
+ my-plugin/
219
+ ├── plugin.json # Plugin metadata
220
+ ├── skills/ # Skill directories with SKILL.md (all clients)
221
+ └── debugging/
222
+ └── SKILL.md
223
+ ├── commands/ # Command files (.md) - Claude only
224
+ ├── build.md
225
+ └── deploy.md
226
+ ├── hooks/ # Hook files (Claude/Factory only)
227
+ │ └── pre-commit.md
228
+ └── AGENTS.md # Agent configuration (optional)
229
+ ```
230
+
231
+ ### Skill Validation
232
+
233
+ Skills must have a valid `SKILL.md` file with YAML frontmatter:
234
+
235
+ ```yaml
236
+ ---
237
+ name: my-skill # Required: lowercase, alphanumeric + hyphens, max 64 chars
238
+ description: Description of the skill # Required
239
+ allowed-tools: # Optional
240
+ - Read
241
+ - Write
242
+ model: claude-3-opus # Optional
243
+ ---
244
+
245
+ # Skill Content
246
+
247
+ Skill instructions go here...
248
+ ```
249
+
250
+ ## Storage Locations
251
+
252
+ ```
253
+ ~/.allagents/
254
+ ├── marketplaces.json # Registry of marketplaces
255
+ └── marketplaces/ # Cloned marketplace repos
256
+ ├── claude-plugins-official/
257
+ └── someuser-their-repo/
258
+ ```
259
+
260
+ ## Development
261
+
262
+ ```bash
263
+ # Install dependencies
264
+ bun install
265
+
266
+ # Run in development
267
+ bun run dev workspace init test-ws
268
+
269
+ # Run tests
270
+ bun run test
271
+
272
+ # Type check
273
+ bun run typecheck
274
+
275
+ # Build
276
+ bun run build
277
+ ```
278
+
279
+ ## License
280
+
281
+ MIT
package/dist/index.js CHANGED
@@ -1893,12 +1893,12 @@ var require_isexe = __commonJS((exports, module) => {
1893
1893
  if (typeof Promise !== "function") {
1894
1894
  throw new TypeError("callback not provided");
1895
1895
  }
1896
- return new Promise(function(resolve2, reject) {
1896
+ return new Promise(function(resolve, reject) {
1897
1897
  isexe(path, options2 || {}, function(er, is) {
1898
1898
  if (er) {
1899
1899
  reject(er);
1900
1900
  } else {
1901
- resolve2(is);
1901
+ resolve(is);
1902
1902
  }
1903
1903
  });
1904
1904
  });
@@ -1960,27 +1960,27 @@ var require_which = __commonJS((exports, module) => {
1960
1960
  opt = {};
1961
1961
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
1962
1962
  const found = [];
1963
- const step = (i2) => new Promise((resolve2, reject) => {
1963
+ const step = (i2) => new Promise((resolve, reject) => {
1964
1964
  if (i2 === pathEnv.length)
1965
- return opt.all && found.length ? resolve2(found) : reject(getNotFoundError(cmd));
1965
+ return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
1966
1966
  const ppRaw = pathEnv[i2];
1967
1967
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
1968
1968
  const pCmd = path.join(pathPart, cmd);
1969
1969
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
1970
- resolve2(subStep(p, i2, 0));
1970
+ resolve(subStep(p, i2, 0));
1971
1971
  });
1972
- const subStep = (p, i2, ii) => new Promise((resolve2, reject) => {
1972
+ const subStep = (p, i2, ii) => new Promise((resolve, reject) => {
1973
1973
  if (ii === pathExt.length)
1974
- return resolve2(step(i2 + 1));
1974
+ return resolve(step(i2 + 1));
1975
1975
  const ext = pathExt[ii];
1976
1976
  isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
1977
1977
  if (!er && is) {
1978
1978
  if (opt.all)
1979
1979
  found.push(p + ext);
1980
1980
  else
1981
- return resolve2(p + ext);
1981
+ return resolve(p + ext);
1982
1982
  }
1983
- return resolve2(subStep(p, i2, ii + 1));
1983
+ return resolve(subStep(p, i2, ii + 1));
1984
1984
  });
1985
1985
  });
1986
1986
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -11053,8 +11053,13 @@ var {
11053
11053
  Help
11054
11054
  } = import__.default;
11055
11055
 
11056
+ // src/cli/index.ts
11057
+ import { readFileSync as readFileSync2 } from "node:fs";
11058
+ import { dirname as dirname6, join as join11 } from "node:path";
11059
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
11060
+
11056
11061
  // src/core/workspace.ts
11057
- import { mkdir as mkdir5, cp as cp2, readFile as readFile6, writeFile as writeFile4 } from "node:fs/promises";
11062
+ import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile4 } from "node:fs/promises";
11058
11063
  import { existsSync as existsSync7 } from "node:fs";
11059
11064
  import { join as join8, resolve as resolve5, dirname as dirname5, relative as relative2, sep } from "node:path";
11060
11065
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -11071,8 +11076,6 @@ var WORKSPACE_CONFIG_FILE = "workspace.yaml";
11071
11076
  var WORKSPACE_CONFIG_PATH = `${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE}`;
11072
11077
  var WORKSPACE_RULES = `
11073
11078
  <!-- WORKSPACE-RULES:START -->
11074
- # Workspace Rules
11075
-
11076
11079
  ## Rule: Workspace Discovery
11077
11080
  TRIGGER: Any task
11078
11081
  ACTION: Read \`.allagents/workspace.yaml\` to get repository paths and project domains
@@ -17779,122 +17782,6 @@ ${errors2.join(`
17779
17782
 
17780
17783
  // src/utils/plugin-path.ts
17781
17784
  import { resolve, isAbsolute } from "node:path";
17782
- function isGitHubUrl(source) {
17783
- const explicitPatterns = [
17784
- /^https?:\/\/github\.com\//,
17785
- /^https?:\/\/www\.github\.com\//,
17786
- /^github\.com\//,
17787
- /^gh:/
17788
- ];
17789
- if (explicitPatterns.some((pattern) => pattern.test(source))) {
17790
- return true;
17791
- }
17792
- if (!source.startsWith(".") && !source.startsWith("/") && !source.includes("\\") && !/^[a-zA-Z]:/.test(source) && source.includes("/")) {
17793
- const parts = source.split("/");
17794
- if (parts.length >= 2 && parts[0] && parts[1]) {
17795
- const validOwnerRepo = /^[a-zA-Z0-9_-]+$/;
17796
- if (validOwnerRepo.test(parts[0]) && validOwnerRepo.test(parts[1])) {
17797
- return true;
17798
- }
17799
- }
17800
- }
17801
- return false;
17802
- }
17803
- function parseGitHubUrl(url) {
17804
- let normalized = url;
17805
- if (normalized.startsWith("gh:")) {
17806
- normalized = normalized.replace(/^gh:/, "https://github.com/");
17807
- }
17808
- if (normalized.startsWith("github.com/")) {
17809
- normalized = `https://${normalized}`;
17810
- }
17811
- if (!normalized.includes("://") && !normalized.startsWith("github.com")) {
17812
- const parts = normalized.split("/");
17813
- if (parts.length >= 2) {
17814
- const owner = parts[0];
17815
- const repo = parts[1];
17816
- const validOwnerRepo = /^[a-zA-Z0-9_-]+$/;
17817
- if (owner && repo && validOwnerRepo.test(owner) && validOwnerRepo.test(repo)) {
17818
- if (parts.length > 2) {
17819
- const subpath = parts.slice(2).join("/");
17820
- return { owner, repo, subpath };
17821
- }
17822
- return { owner, repo };
17823
- }
17824
- }
17825
- return null;
17826
- }
17827
- const subpathPattern = /^https?:\/\/(?:www\.)?github\.com\/([^/]+)\/([^/]+?)\/tree\/[^/]+\/(.+)$/;
17828
- const subpathMatch = normalized.match(subpathPattern);
17829
- if (subpathMatch) {
17830
- const owner = subpathMatch[1];
17831
- const repo = subpathMatch[2]?.replace(/\.git$/, "");
17832
- const subpath = subpathMatch[3];
17833
- if (owner && repo && subpath) {
17834
- return { owner, repo, subpath };
17835
- }
17836
- }
17837
- const basicPattern = /^https?:\/\/(?:www\.)?github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/.*)?$/;
17838
- const basicMatch = normalized.match(basicPattern);
17839
- if (basicMatch) {
17840
- const owner = basicMatch[1];
17841
- const repo = basicMatch[2]?.replace(/\.git$/, "");
17842
- if (owner && repo) {
17843
- return { owner, repo };
17844
- }
17845
- }
17846
- return null;
17847
- }
17848
- function normalizePluginPath(source, baseDir = process.cwd()) {
17849
- if (isGitHubUrl(source)) {
17850
- return source;
17851
- }
17852
- if (isAbsolute(source)) {
17853
- return source;
17854
- }
17855
- return resolve(baseDir, source);
17856
- }
17857
- function parsePluginSource(source, baseDir = process.cwd()) {
17858
- if (isGitHubUrl(source)) {
17859
- const parsed = parseGitHubUrl(source);
17860
- return {
17861
- type: "github",
17862
- original: source,
17863
- normalized: source,
17864
- ...parsed?.owner && { owner: parsed.owner },
17865
- ...parsed?.repo && { repo: parsed.repo }
17866
- };
17867
- }
17868
- return {
17869
- type: "local",
17870
- original: source,
17871
- normalized: normalizePluginPath(source, baseDir)
17872
- };
17873
- }
17874
- function getPluginCachePath(owner, repo) {
17875
- const homeDir = process.env.HOME || process.env.USERPROFILE || "~";
17876
- return resolve(homeDir, ".allagents", "plugins", "marketplaces", `${owner}-${repo}`);
17877
- }
17878
- function validatePluginSource(source) {
17879
- if (!source || source.trim() === "") {
17880
- return { valid: false, error: "Plugin source cannot be empty" };
17881
- }
17882
- if (isGitHubUrl(source)) {
17883
- const parsed = parseGitHubUrl(source);
17884
- if (!parsed) {
17885
- return {
17886
- valid: false,
17887
- error: "Invalid GitHub URL format. Expected: https://github.com/owner/repo"
17888
- };
17889
- }
17890
- }
17891
- return { valid: true };
17892
- }
17893
-
17894
- // src/core/plugin.ts
17895
- import { mkdir, readdir, stat } from "node:fs/promises";
17896
- import { existsSync } from "node:fs";
17897
- import { dirname, join, resolve as resolve2 } from "node:path";
17898
17785
 
17899
17786
  // node_modules/execa/index.js
17900
17787
  var import_cross_spawn = __toESM(require_cross_spawn(), 1);
@@ -18769,7 +18656,7 @@ var setupTimeout = (spawned, { timeout, killSignal = "SIGTERM" }, spawnedPromise
18769
18656
  return spawnedPromise;
18770
18657
  }
18771
18658
  let timeoutId;
18772
- const timeoutPromise = new Promise((resolve2, reject) => {
18659
+ const timeoutPromise = new Promise((resolve, reject) => {
18773
18660
  timeoutId = setTimeout(() => {
18774
18661
  timeoutKill(spawned, killSignal, reject);
18775
18662
  }, timeout);
@@ -19133,9 +19020,9 @@ var mergePromise = (spawned, promise) => {
19133
19020
  Reflect.defineProperty(spawned, property, { ...descriptor, value });
19134
19021
  }
19135
19022
  };
19136
- var getSpawnedPromise = (spawned) => new Promise((resolve2, reject) => {
19023
+ var getSpawnedPromise = (spawned) => new Promise((resolve, reject) => {
19137
19024
  spawned.on("exit", (exitCode, signal) => {
19138
- resolve2({ exitCode, signal });
19025
+ resolve({ exitCode, signal });
19139
19026
  });
19140
19027
  spawned.on("error", (error) => {
19141
19028
  reject(error);
@@ -19431,7 +19318,188 @@ function create$(options2) {
19431
19318
  }
19432
19319
  var $ = create$();
19433
19320
 
19321
+ // src/utils/plugin-path.ts
19322
+ function isGitHubUrl(source) {
19323
+ const explicitPatterns = [
19324
+ /^https?:\/\/github\.com\//,
19325
+ /^https?:\/\/www\.github\.com\//,
19326
+ /^github\.com\//,
19327
+ /^gh:/
19328
+ ];
19329
+ if (explicitPatterns.some((pattern) => pattern.test(source))) {
19330
+ return true;
19331
+ }
19332
+ if (!source.startsWith(".") && !source.startsWith("/") && !source.includes("\\") && !/^[a-zA-Z]:/.test(source) && source.includes("/")) {
19333
+ const parts = source.split("/");
19334
+ if (parts.length >= 2 && parts[0] && parts[1]) {
19335
+ const validOwnerRepo = /^[a-zA-Z0-9_.-]+$/;
19336
+ if (validOwnerRepo.test(parts[0]) && validOwnerRepo.test(parts[1])) {
19337
+ return true;
19338
+ }
19339
+ }
19340
+ }
19341
+ return false;
19342
+ }
19343
+ function parseGitHubUrl(url) {
19344
+ let normalized = url;
19345
+ if (normalized.startsWith("gh:")) {
19346
+ normalized = normalized.replace(/^gh:/, "https://github.com/");
19347
+ }
19348
+ if (normalized.startsWith("github.com/")) {
19349
+ normalized = `https://${normalized}`;
19350
+ }
19351
+ if (!normalized.includes("://") && !normalized.startsWith("github.com")) {
19352
+ const parts = normalized.split("/");
19353
+ if (parts.length >= 2) {
19354
+ const owner = parts[0];
19355
+ const repo = parts[1];
19356
+ const validOwnerRepo = /^[a-zA-Z0-9_.-]+$/;
19357
+ if (owner && repo && validOwnerRepo.test(owner) && validOwnerRepo.test(repo)) {
19358
+ if (parts.length > 2) {
19359
+ const subpath = parts.slice(2).join("/");
19360
+ return { owner, repo, subpath };
19361
+ }
19362
+ return { owner, repo };
19363
+ }
19364
+ }
19365
+ return null;
19366
+ }
19367
+ const subpathPattern = /^https?:\/\/(?:www\.)?github\.com\/([^/]+)\/([^/]+?)\/tree\/[^/]+\/(.+)$/;
19368
+ const subpathMatch = normalized.match(subpathPattern);
19369
+ if (subpathMatch) {
19370
+ const owner = subpathMatch[1];
19371
+ const repo = subpathMatch[2]?.replace(/\.git$/, "");
19372
+ const subpath = subpathMatch[3];
19373
+ if (owner && repo && subpath) {
19374
+ return { owner, repo, subpath };
19375
+ }
19376
+ }
19377
+ const basicPattern = /^https?:\/\/(?:www\.)?github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/.*)?$/;
19378
+ const basicMatch = normalized.match(basicPattern);
19379
+ if (basicMatch) {
19380
+ const owner = basicMatch[1];
19381
+ const repo = basicMatch[2]?.replace(/\.git$/, "");
19382
+ if (owner && repo) {
19383
+ return { owner, repo };
19384
+ }
19385
+ }
19386
+ return null;
19387
+ }
19388
+ function normalizePluginPath(source, baseDir = process.cwd()) {
19389
+ if (isGitHubUrl(source)) {
19390
+ return source;
19391
+ }
19392
+ if (isAbsolute(source)) {
19393
+ return source;
19394
+ }
19395
+ return resolve(baseDir, source);
19396
+ }
19397
+ function parsePluginSource(source, baseDir = process.cwd()) {
19398
+ if (isGitHubUrl(source)) {
19399
+ const parsed = parseGitHubUrl(source);
19400
+ return {
19401
+ type: "github",
19402
+ original: source,
19403
+ normalized: source,
19404
+ ...parsed?.owner && { owner: parsed.owner },
19405
+ ...parsed?.repo && { repo: parsed.repo }
19406
+ };
19407
+ }
19408
+ return {
19409
+ type: "local",
19410
+ original: source,
19411
+ normalized: normalizePluginPath(source, baseDir)
19412
+ };
19413
+ }
19414
+ function getPluginCachePath(owner, repo) {
19415
+ const homeDir = process.env.HOME || process.env.USERPROFILE || "~";
19416
+ return resolve(homeDir, ".allagents", "plugins", "marketplaces", `${owner}-${repo}`);
19417
+ }
19418
+ function validatePluginSource(source) {
19419
+ if (!source || source.trim() === "") {
19420
+ return { valid: false, error: "Plugin source cannot be empty" };
19421
+ }
19422
+ if (isGitHubUrl(source)) {
19423
+ const parsed = parseGitHubUrl(source);
19424
+ if (!parsed) {
19425
+ return {
19426
+ valid: false,
19427
+ error: "Invalid GitHub URL format. Expected: https://github.com/owner/repo"
19428
+ };
19429
+ }
19430
+ }
19431
+ return { valid: true };
19432
+ }
19433
+ async function verifyGitHubUrlExists(source) {
19434
+ const parsed = parseGitHubUrl(source);
19435
+ if (!parsed) {
19436
+ return {
19437
+ exists: false,
19438
+ error: "Invalid GitHub URL format. Expected: https://github.com/owner/repo"
19439
+ };
19440
+ }
19441
+ const { owner, repo, subpath } = parsed;
19442
+ try {
19443
+ await execa("gh", ["--version"]);
19444
+ } catch {
19445
+ return {
19446
+ exists: false,
19447
+ error: "gh CLI not installed. Install from: https://cli.github.com"
19448
+ };
19449
+ }
19450
+ try {
19451
+ await execa("gh", ["repo", "view", `${owner}/${repo}`, "--json", "name"]);
19452
+ } catch (error) {
19453
+ if (error instanceof Error) {
19454
+ const errorMessage = error.message.toLowerCase();
19455
+ if (errorMessage.includes("not found") || errorMessage.includes("404") || errorMessage.includes("could not resolve to a repository")) {
19456
+ return {
19457
+ exists: false,
19458
+ error: `Repository not found: ${owner}/${repo}`
19459
+ };
19460
+ }
19461
+ if (errorMessage.includes("auth") || errorMessage.includes("authentication")) {
19462
+ return {
19463
+ exists: false,
19464
+ error: "GitHub authentication required. Run: gh auth login"
19465
+ };
19466
+ }
19467
+ }
19468
+ return {
19469
+ exists: false,
19470
+ error: `Failed to verify repository: ${error instanceof Error ? error.message : String(error)}`
19471
+ };
19472
+ }
19473
+ if (subpath) {
19474
+ try {
19475
+ await execa("gh", [
19476
+ "api",
19477
+ `repos/${owner}/${repo}/contents/${subpath}`,
19478
+ "--silent"
19479
+ ]);
19480
+ } catch (error) {
19481
+ if (error instanceof Error) {
19482
+ const errorMessage = error.message.toLowerCase();
19483
+ if (errorMessage.includes("not found") || errorMessage.includes("404")) {
19484
+ return {
19485
+ exists: false,
19486
+ error: `Path not found in repository: ${owner}/${repo}/${subpath}`
19487
+ };
19488
+ }
19489
+ }
19490
+ return {
19491
+ exists: false,
19492
+ error: `Failed to verify path: ${error instanceof Error ? error.message : String(error)}`
19493
+ };
19494
+ }
19495
+ }
19496
+ return { exists: true };
19497
+ }
19498
+
19434
19499
  // src/core/plugin.ts
19500
+ import { mkdir, readdir, stat } from "node:fs/promises";
19501
+ import { existsSync } from "node:fs";
19502
+ import { dirname, join, resolve as resolve2 } from "node:path";
19435
19503
  async function fetchPlugin(url, options2 = {}) {
19436
19504
  const { force = false } = options2;
19437
19505
  const validation = validatePluginSource(url);
@@ -19579,7 +19647,6 @@ async function resolveGlobPatterns(sourceRoot, patterns) {
19579
19647
  var CLIENT_MAPPINGS = {
19580
19648
  claude: {
19581
19649
  commandsPath: ".claude/commands/",
19582
- commandsExt: ".md",
19583
19650
  skillsPath: ".claude/skills/",
19584
19651
  agentsPath: ".claude/agents/",
19585
19652
  agentFile: "CLAUDE.md",
@@ -19587,46 +19654,32 @@ var CLIENT_MAPPINGS = {
19587
19654
  hooksPath: ".claude/hooks/"
19588
19655
  },
19589
19656
  copilot: {
19590
- commandsPath: ".github/prompts/",
19591
- commandsExt: ".prompt.md",
19592
19657
  skillsPath: ".github/skills/",
19593
19658
  agentFile: "AGENTS.md"
19594
19659
  },
19595
19660
  codex: {
19596
- commandsPath: ".codex/prompts/",
19597
- commandsExt: ".md",
19598
19661
  skillsPath: ".codex/skills/",
19599
19662
  agentFile: "AGENTS.md"
19600
19663
  },
19601
19664
  cursor: {
19602
- commandsPath: ".cursor/commands/",
19603
- commandsExt: ".md",
19604
19665
  skillsPath: ".cursor/skills/",
19605
19666
  agentFile: "AGENTS.md"
19606
19667
  },
19607
19668
  opencode: {
19608
- commandsPath: ".opencode/commands/",
19609
- commandsExt: ".md",
19610
19669
  skillsPath: ".opencode/skills/",
19611
19670
  agentFile: "AGENTS.md"
19612
19671
  },
19613
19672
  gemini: {
19614
- commandsPath: ".gemini/commands/",
19615
- commandsExt: ".md",
19616
19673
  skillsPath: ".gemini/skills/",
19617
19674
  agentFile: "GEMINI.md",
19618
19675
  agentFileFallback: "AGENTS.md"
19619
19676
  },
19620
19677
  factory: {
19621
- commandsPath: ".factory/commands/",
19622
- commandsExt: ".md",
19623
19678
  skillsPath: ".factory/skills/",
19624
19679
  agentFile: "AGENTS.md",
19625
19680
  hooksPath: ".factory/hooks/"
19626
19681
  },
19627
19682
  ampcode: {
19628
- commandsPath: "",
19629
- commandsExt: ".md",
19630
19683
  skillsPath: "",
19631
19684
  agentFile: "AGENTS.md"
19632
19685
  }
@@ -19698,20 +19751,27 @@ async function validateSkill(skillDir) {
19698
19751
  }
19699
19752
 
19700
19753
  // src/core/transform.ts
19701
- async function injectWorkspaceRules(filePath) {
19702
- const content = await readFile3(filePath, "utf-8");
19754
+ async function ensureWorkspaceRules(filePath, rules) {
19755
+ const rulesContent = rules ?? WORKSPACE_RULES;
19703
19756
  const startMarker = "<!-- WORKSPACE-RULES:START -->";
19704
19757
  const endMarker = "<!-- WORKSPACE-RULES:END -->";
19758
+ if (!existsSync3(filePath)) {
19759
+ await writeFile(filePath, `${rulesContent.trim()}
19760
+ `, "utf-8");
19761
+ return;
19762
+ }
19763
+ const content = await readFile3(filePath, "utf-8");
19705
19764
  const startIndex = content.indexOf(startMarker);
19706
19765
  const endIndex = content.indexOf(endMarker);
19707
19766
  if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
19708
19767
  const before = content.substring(0, startIndex);
19709
19768
  const after = content.substring(endIndex + endMarker.length);
19710
- await writeFile(filePath, before + WORKSPACE_RULES.trim() + after, "utf-8");
19769
+ await writeFile(filePath, before + rulesContent.trim() + after, "utf-8");
19711
19770
  } else {
19712
- await writeFile(filePath, content + WORKSPACE_RULES, "utf-8");
19771
+ await writeFile(filePath, content + rulesContent, "utf-8");
19713
19772
  }
19714
19773
  }
19774
+ var injectWorkspaceRules = ensureWorkspaceRules;
19715
19775
  async function copyCommands(pluginPath, workspacePath, client, options2 = {}) {
19716
19776
  const { dryRun = false } = options2;
19717
19777
  const mapping = CLIENT_MAPPINGS[client];
@@ -19731,11 +19791,7 @@ async function copyCommands(pluginPath, workspacePath, client, options2 = {}) {
19731
19791
  const mdFiles = files.filter((f) => f.endsWith(".md"));
19732
19792
  const copyPromises = mdFiles.map(async (file) => {
19733
19793
  const sourcePath = join4(sourceDir, file);
19734
- let destFileName = file;
19735
- if (mapping.commandsExt === ".prompt.md" && !file.endsWith(".prompt.md")) {
19736
- destFileName = file.replace(/\.md$/, ".prompt.md");
19737
- }
19738
- const destPath = join4(destDir, destFileName);
19794
+ const destPath = join4(destDir, file);
19739
19795
  if (dryRun) {
19740
19796
  return { source: sourcePath, destination: destPath, action: "copied" };
19741
19797
  }
@@ -20744,11 +20800,8 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
20744
20800
  workspaceYamlContent = await readFile6(defaultYamlPath, "utf-8");
20745
20801
  }
20746
20802
  await writeFile4(configPath, workspaceYamlContent, "utf-8");
20747
- const defaultAgentsPath = join8(defaultTemplatePath, "AGENTS.md");
20748
20803
  const targetAgentsPath = join8(absoluteTarget, "AGENTS.md");
20749
- if (existsSync7(defaultAgentsPath) && !existsSync7(targetAgentsPath)) {
20750
- await cp2(defaultAgentsPath, targetAgentsPath);
20751
- }
20804
+ await ensureWorkspaceRules(targetAgentsPath);
20752
20805
  console.log(`✓ Workspace created at: ${absoluteTarget}`);
20753
20806
  console.log(`
20754
20807
  Syncing plugins...`);
@@ -20883,6 +20936,13 @@ async function addPlugin(plugin, workspacePath = process.cwd()) {
20883
20936
  error: validation.error || "Invalid GitHub URL"
20884
20937
  };
20885
20938
  }
20939
+ const verifyResult = await verifyGitHubUrlExists(plugin);
20940
+ if (!verifyResult.exists) {
20941
+ return {
20942
+ success: false,
20943
+ error: verifyResult.error || `GitHub URL not found: ${plugin}`
20944
+ };
20945
+ }
20886
20946
  } else {
20887
20947
  const fullPath = join10(workspacePath, plugin);
20888
20948
  if (!existsSync9(fullPath) && !existsSync9(plugin)) {
@@ -21332,9 +21392,81 @@ pluginCommand.command("validate <path>").description("Validate plugin structure
21332
21392
  console.log("(validation not yet implemented)");
21333
21393
  });
21334
21394
 
21395
+ // src/cli/commands/update.ts
21396
+ function detectPackageManagerFromPath(scriptPath) {
21397
+ if (scriptPath.includes(".bun")) {
21398
+ return "bun";
21399
+ }
21400
+ return "npm";
21401
+ }
21402
+ function detectPackageManager() {
21403
+ return detectPackageManagerFromPath(process.argv[1] ?? "");
21404
+ }
21405
+ async function getCurrentVersion() {
21406
+ try {
21407
+ const { createRequire: createRequire2 } = await import("node:module");
21408
+ const require2 = createRequire2(import.meta.url);
21409
+ const pkg = require2("../../../package.json");
21410
+ return pkg.version;
21411
+ } catch {
21412
+ return "unknown";
21413
+ }
21414
+ }
21415
+ var updateCommand = new Command("update").description("Update allagents to the latest version").option("--npm", "Force update using npm").option("--bun", "Force update using bun").action(async (options2) => {
21416
+ try {
21417
+ let packageManager;
21418
+ if (options2.npm && options2.bun) {
21419
+ console.error("Error: Cannot specify both --npm and --bun");
21420
+ process.exit(1);
21421
+ }
21422
+ if (options2.npm) {
21423
+ packageManager = "npm";
21424
+ } else if (options2.bun) {
21425
+ packageManager = "bun";
21426
+ } else {
21427
+ packageManager = detectPackageManager();
21428
+ }
21429
+ const currentVersion = await getCurrentVersion();
21430
+ console.log(`Current version: ${currentVersion}`);
21431
+ console.log(`Updating allagents using ${packageManager}...
21432
+ `);
21433
+ const args = packageManager === "npm" ? ["install", "-g", "allagents@latest"] : ["add", "-g", "allagents@latest"];
21434
+ const result = await execa(packageManager, args, {
21435
+ stdio: "inherit"
21436
+ });
21437
+ if (result.exitCode === 0) {
21438
+ try {
21439
+ const versionResult = await execa("allagents", ["--version"]);
21440
+ const newVersion = versionResult.stdout.trim();
21441
+ console.log(`
21442
+ Update complete: ${currentVersion} → ${newVersion}`);
21443
+ } catch {
21444
+ console.log(`
21445
+ Update complete.`);
21446
+ }
21447
+ }
21448
+ } catch (error) {
21449
+ if (error instanceof Error) {
21450
+ if (error.message.includes("ENOENT") || error.message.includes("not found")) {
21451
+ const detected = detectPackageManager();
21452
+ const alternative = detected === "npm" ? "bun" : "npm";
21453
+ console.error(`Error: ${detected} not found. Try using --${alternative} flag.`);
21454
+ } else {
21455
+ console.error(`Error: ${error.message}`);
21456
+ }
21457
+ process.exit(1);
21458
+ }
21459
+ throw error;
21460
+ }
21461
+ });
21462
+
21335
21463
  // src/cli/index.ts
21464
+ var __dirname2 = dirname6(fileURLToPath3(import.meta.url));
21465
+ var packageJsonPath = join11(__dirname2, "..", "package.json");
21466
+ var packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
21336
21467
  var program2 = new Command;
21337
- program2.name("allagents").description("CLI tool for managing multi-repo AI agent workspaces with plugin synchronization").version("0.1.0");
21468
+ program2.name("allagents").description("CLI tool for managing multi-repo AI agent workspaces with plugin synchronization").version(packageJson.version);
21338
21469
  program2.addCommand(workspaceCommand);
21339
21470
  program2.addCommand(pluginCommand);
21471
+ program2.addCommand(updateCommand);
21340
21472
  program2.parse();
@@ -1,15 +1,15 @@
1
- # Workspace root files (optional)
2
- # workspace:
3
- # source: ./path/to/config # local path, GitHub URL, or plugin@marketplace
4
- # files:
5
- # - CLAUDE.md
6
- # - AGENTS.md
7
- # - source: docs/CLAUDE.md # explicit source/dest mapping
8
- # dest: CLAUDE.md
9
-
10
- repositories: []
11
-
12
- plugins: []
13
-
14
- clients:
15
- - claude
1
+ # Workspace root files (optional)
2
+ # workspace:
3
+ # source: ./path/to/config # local path, GitHub URL, or plugin@marketplace
4
+ # files:
5
+ # - CLAUDE.md
6
+ # - AGENTS.md
7
+ # - source: docs/CLAUDE.md # explicit source/dest mapping
8
+ # dest: CLAUDE.md
9
+
10
+ repositories: []
11
+
12
+ plugins: []
13
+
14
+ clients:
15
+ - claude
@@ -1,14 +1,14 @@
1
- # Workspace
2
-
3
- ## Development
4
-
5
- To run tests:
6
- ```bash
7
- npm test
8
- ```
9
-
10
- ## Guidelines
11
-
12
- - Add project-specific coding conventions here
13
- - Document architectural decisions
14
- - Include workflow preferences
1
+ # Workspace
2
+
3
+ ## Development
4
+
5
+ To run tests:
6
+ ```bash
7
+ npm test
8
+ ```
9
+
10
+ ## Guidelines
11
+
12
+ - Add project-specific coding conventions here
13
+ - Document architectural decisions
14
+ - Include workflow preferences
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "0.1.5",
3
+ "version": "0.2.1",
4
4
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,7 +24,7 @@
24
24
  "format": "biome format --write src",
25
25
  "check": "biome check src",
26
26
  "check:fix": "biome check --write src",
27
- "prepare": "bun run build && bunx prek install -t pre-push"
27
+ "prepare": "bun run build && (test -d .git && bunx prek install -t pre-push || true)"
28
28
  },
29
29
  "keywords": [
30
30
  "cli",
@@ -53,6 +53,7 @@
53
53
  "@types/bun": "latest",
54
54
  "@types/js-yaml": "^4.0.9",
55
55
  "@types/node": "^20.11.5",
56
+ "shx": "^0.4.0",
56
57
  "typescript": "^5.3.3"
57
58
  },
58
59
  "engines": {