@mhmdreza-rafiei/agentry 0.2.1 → 0.2.2
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 +21 -21
- package/README.md +249 -198
- package/dist/_chunks/theme2.mjs +3 -3
- package/dist/cli.mjs +226 -32
- package/package.json +61 -53
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 comprehensive-skills contributors
|
|
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 comprehensive-skills contributors
|
|
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,198 +1,249 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
# Agentry
|
|
4
|
-
|
|
5
|
-
**Install agents, skills, rules, scripts, and profiles onto coding agents — from any Git repo.**
|
|
6
|
-
|
|
7
|
-
Supports **Cursor**, **Claude Code**, **Codex**, **OpenCode**, and [70+ more](#supported-agents).
|
|
8
|
-
|
|
9
|
-
[](https://www.npmjs.com/package/@mhmdreza-rafiei/agentry)
|
|
10
|
-
[](#install)
|
|
11
|
-
[](LICENSE)
|
|
12
|
-
[](https://github.com/mhmdreza-rafiei/agentry)
|
|
13
|
-
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
## Install
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install -g @mhmdreza-rafiei/agentry
|
|
20
|
-
# or
|
|
21
|
-
npx @mhmdreza-rafiei/agentry@latest --help
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Quick start
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
# Browse + install skills from a repo
|
|
28
|
-
agentry add skills mhmdreza-rafiei/agent-tools
|
|
29
|
-
|
|
30
|
-
# Install one skill to Cursor
|
|
31
|
-
agentry add skills mhmdreza-rafiei/agent-tools enhance-prompt -a cursor
|
|
32
|
-
|
|
33
|
-
# See what is installed
|
|
34
|
-
agentry list
|
|
35
|
-
agentry list skills
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
##
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
agentry list
|
|
96
|
-
agentry list
|
|
97
|
-
agentry list
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
agentry
|
|
101
|
-
agentry
|
|
102
|
-
agentry
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
#
|
|
110
|
-
agentry
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
agentry
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Agentry
|
|
4
|
+
|
|
5
|
+
**Install agents, skills, rules, scripts, and profiles onto coding agents — from any Git repo.**
|
|
6
|
+
|
|
7
|
+
Supports **Cursor**, **Claude Code**, **Codex**, **OpenCode**, and [70+ more](#supported-agents).
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@mhmdreza-rafiei/agentry)
|
|
10
|
+
[](#install)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](https://github.com/mhmdreza-rafiei/agentry)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @mhmdreza-rafiei/agentry
|
|
20
|
+
# or
|
|
21
|
+
npx @mhmdreza-rafiei/agentry@latest --help
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick start
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Browse + install skills from a repo
|
|
28
|
+
agentry add skills mhmdreza-rafiei/agent-tools
|
|
29
|
+
|
|
30
|
+
# Install one skill to Cursor
|
|
31
|
+
agentry add skills mhmdreza-rafiei/agent-tools enhance-prompt -a cursor
|
|
32
|
+
|
|
33
|
+
# See what is installed
|
|
34
|
+
agentry list
|
|
35
|
+
agentry list skills
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## What it looks like
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
█████╗ ██████╗ ███████╗███╗ ██╗████████╗██████╗ ██╗ ██╗
|
|
42
|
+
██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝██╔══██╗╚██╗ ██╔╝
|
|
43
|
+
███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██████╔╝ ╚████╔╝
|
|
44
|
+
██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██╔══██╗ ╚██╔╝
|
|
45
|
+
██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ██║ ██║ ██║
|
|
46
|
+
╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
47
|
+
Install agents, skills, rules & profiles
|
|
48
|
+
|
|
49
|
+
◇ Cloning mhmdreza-rafiei/agent-tools
|
|
50
|
+
◇ Found 12 skills
|
|
51
|
+
|
|
52
|
+
◆ Select skills to install
|
|
53
|
+
│ Search: enhance
|
|
54
|
+
│ ◼ All
|
|
55
|
+
│ ◼ prompt/enhance-prompt
|
|
56
|
+
│ ◻ quick-start
|
|
57
|
+
│
|
|
58
|
+
◇ Which agents do you want to install to?
|
|
59
|
+
│ Universal (.agents/skills) · Cursor, Codex, …
|
|
60
|
+
│ ◼ Claude Code
|
|
61
|
+
|
|
62
|
+
◆ Installation scope
|
|
63
|
+
│
|
|
64
|
+
│ ● Project
|
|
65
|
+
│ Install in the current directory (committed with your project)
|
|
66
|
+
│ → /path/to/your-project
|
|
67
|
+
│ lock /path/to/your-project/.agentry/lock.json
|
|
68
|
+
│
|
|
69
|
+
│ ○ Global
|
|
70
|
+
│ Install in your home directory (available across all projects)
|
|
71
|
+
│ → /home/you
|
|
72
|
+
│ lock /home/you/.agentry/lock.json
|
|
73
|
+
└ ↑/↓ select · enter confirm
|
|
74
|
+
|
|
75
|
+
◆ Install summary
|
|
76
|
+
│ Scope project
|
|
77
|
+
│ Targets 4 agents · 3 universal · 1 additional
|
|
78
|
+
│ Cursor, Codex, OpenCode, Claude Code
|
|
79
|
+
│
|
|
80
|
+
│ Artifacts 1 selected
|
|
81
|
+
│ • skill/prompt/enhance-prompt
|
|
82
|
+
│ Rewrite prompts for clarity and fidelity
|
|
83
|
+
│
|
|
84
|
+
└ Review before use — artifacts run with full agent permissions.
|
|
85
|
+
|
|
86
|
+
◇ Installed skill/prompt/enhance-prompt
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Commands
|
|
90
|
+
|
|
91
|
+
| Command | Description |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `agentry add <kind> <source> [selector]` | Discover and install artifacts |
|
|
94
|
+
| `agentry add profile <name> [source]` | Apply a local `profile/<name>.yaml` bundle |
|
|
95
|
+
| `agentry list` | List installed artifacts |
|
|
96
|
+
| `agentry list <kind>` | List installed artifacts of one kind |
|
|
97
|
+
| `agentry list <source> [kind] [selector]` | List what a repo/path contains |
|
|
98
|
+
| `agentry remove <kind> [source] [selector]` | Remove installs (files + lock) |
|
|
99
|
+
| `agentry update [kind] [source] [selector]` | Re-install from source or lockfile |
|
|
100
|
+
| `agentry init <kind> [name] [category]` | Scaffold a new artifact |
|
|
101
|
+
| `agentry update` | Update the Agentry CLI itself |
|
|
102
|
+
| `agentry uninstall` | Uninstall the Agentry CLI |
|
|
103
|
+
|
|
104
|
+
`<kind>` is `skill | rule | agent | profile | script` (plurals accepted).
|
|
105
|
+
|
|
106
|
+
### Source formats
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# GitHub shorthand
|
|
110
|
+
agentry add skills mhmdreza-rafiei/agent-tools
|
|
111
|
+
|
|
112
|
+
# Full GitHub URL
|
|
113
|
+
agentry add skills https://github.com/mhmdreza-rafiei/agent-tools
|
|
114
|
+
|
|
115
|
+
# Tree URL (subdir + ref)
|
|
116
|
+
agentry add skills https://github.com/mhmdreza-rafiei/agent-tools/tree/main/skills
|
|
117
|
+
|
|
118
|
+
# Local path
|
|
119
|
+
agentry add skills ./my-skills
|
|
120
|
+
|
|
121
|
+
# Any git URL
|
|
122
|
+
agentry add skills git@github.com:mhmdreza-rafiei/agent-tools.git
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Options
|
|
126
|
+
|
|
127
|
+
| Option | Description |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| `-g, --global` | Install into `~` (all projects) |
|
|
130
|
+
| `-p, --project` | Install into the current folder |
|
|
131
|
+
| `-d, --dir <path>` | Install into a specific folder |
|
|
132
|
+
| `-a, --agent <name>` | Target provider(s); repeatable; `*` = all |
|
|
133
|
+
| `-l, --list` | Preview only — write nothing |
|
|
134
|
+
| `--copy` | Copy instead of symlink for non-universal agents |
|
|
135
|
+
| `--all` | Install everything to all agents, no prompts |
|
|
136
|
+
| `-y, --yes` | Skip prompts (scope defaults to project) |
|
|
137
|
+
| `--description <text>` | `init`: frontmatter description |
|
|
138
|
+
| `--alwaysApply` | `init` rule: `alwaysApply: true` |
|
|
139
|
+
| `--reference` / `--no-reference` | `init` skill: include `references/TEMPLATE.md` |
|
|
140
|
+
| `--skills` / `--agents` / `--rules` / `--scripts` `[src]` | `init` profile: include kinds (optional source) |
|
|
141
|
+
|
|
142
|
+
## Examples
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# List everything in a catalog repo
|
|
146
|
+
agentry list mhmdreza-rafiei/agent-tools
|
|
147
|
+
agentry list mhmdreza-rafiei/agent-tools skills
|
|
148
|
+
agentry list mhmdreza-rafiei/agent-tools skills enhance-prompt
|
|
149
|
+
|
|
150
|
+
# Install
|
|
151
|
+
agentry add skills mhmdreza-rafiei/agent-tools
|
|
152
|
+
agentry add skills mhmdreza-rafiei/agent-tools enhance-prompt -a cursor -a claude-code
|
|
153
|
+
agentry add rules mhmdreza-rafiei/agent-tools ask-dont-guess
|
|
154
|
+
agentry add agents mhmdreza-rafiei/agent-tools frontend-developer
|
|
155
|
+
|
|
156
|
+
# Inventory
|
|
157
|
+
agentry list
|
|
158
|
+
agentry list skills
|
|
159
|
+
|
|
160
|
+
# Update / remove by selector or by install source
|
|
161
|
+
agentry update skills mhmdreza-rafiei/agent-tools
|
|
162
|
+
agentry remove skills enhance-prompt
|
|
163
|
+
agentry remove skills mhmdreza-rafiei/agent-tools
|
|
164
|
+
|
|
165
|
+
# Scaffold
|
|
166
|
+
agentry init skill enhance-prompt prompt --reference
|
|
167
|
+
agentry init rule ask-dont-guess --alwaysApply --description "Ask before guessing"
|
|
168
|
+
agentry init profile frontend --skills mhmdreza-rafiei/agent-tools -a cursor
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Example catalog used throughout this README: [`mhmdreza-rafiei/agent-tools`](https://github.com/mhmdreza-rafiei/agent-tools).
|
|
172
|
+
|
|
173
|
+
## How it works
|
|
174
|
+
|
|
175
|
+
1. Resolve a source (local path or shallow git clone).
|
|
176
|
+
2. Discover artifacts under `<kind>s/` **and** root markers (`SKILL.md`, `.mdc`).
|
|
177
|
+
3. Let you pick what to install (searchable list + `All`).
|
|
178
|
+
4. Install once to `.agents/skills/<id>` for universal providers; symlink (or `--copy`) for others.
|
|
179
|
+
5. Track installs in `.agentry/lock.json` for remove/update.
|
|
180
|
+
|
|
181
|
+
If a clone fails and a prior cache exists, Agentry asks whether to load from cache (`~/.cache/agentry/repos`).
|
|
182
|
+
|
|
183
|
+
## Artifact layouts
|
|
184
|
+
|
|
185
|
+
Author installable tools in a source repo like this:
|
|
186
|
+
|
|
187
|
+
### Skills
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
skills/
|
|
191
|
+
enhance-prompt/
|
|
192
|
+
SKILL.md
|
|
193
|
+
references/
|
|
194
|
+
TEMPLATE.md
|
|
195
|
+
prompt/
|
|
196
|
+
rewrite/
|
|
197
|
+
SKILL.md
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Agents / rules
|
|
201
|
+
|
|
202
|
+
```text
|
|
203
|
+
agents/
|
|
204
|
+
frontend-developer.mdc
|
|
205
|
+
rules/
|
|
206
|
+
ask-dont-guess.mdc
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Scripts / profiles
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
scripts/
|
|
213
|
+
deploy/
|
|
214
|
+
README.md
|
|
215
|
+
profiles/
|
|
216
|
+
frontend.yaml
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Local install profiles (consumed by `agentry add profile`) live at `profile/<name>.yaml`.
|
|
220
|
+
|
|
221
|
+
## Supported agents
|
|
222
|
+
|
|
223
|
+
Agentry targets **70+** providers. Universal providers share `.agents/skills/`; others get a symlink or copy.
|
|
224
|
+
|
|
225
|
+
| Agent | Skills path |
|
|
226
|
+
| --- | --- |
|
|
227
|
+
| Cursor | `.agents/skills` |
|
|
228
|
+
| Codex | `.agents/skills` |
|
|
229
|
+
| OpenCode | `.agents/skills` |
|
|
230
|
+
| Gemini CLI | `.agents/skills` |
|
|
231
|
+
| Claude Code | `.claude/skills` |
|
|
232
|
+
| Windsurf | `.windsurf/skills` |
|
|
233
|
+
| … | see `src/registry/agents.ts` |
|
|
234
|
+
|
|
235
|
+
## Development
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
npm install
|
|
239
|
+
npm run typecheck
|
|
240
|
+
npm test
|
|
241
|
+
npm run build
|
|
242
|
+
node dist/cli.mjs --help
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Requires **Node ≥ 22.20**.
|
|
246
|
+
|
|
247
|
+
## License
|
|
248
|
+
|
|
249
|
+
[MIT](LICENSE)
|
package/dist/_chunks/theme2.mjs
CHANGED
|
@@ -122,13 +122,13 @@ function printHelp() {
|
|
|
122
122
|
"",
|
|
123
123
|
h("Options"),
|
|
124
124
|
` ${flag("-g, --global")} ${dim("Install into ~ (all projects)")}`,
|
|
125
|
-
`
|
|
126
|
-
`
|
|
125
|
+
` ${flag("-p, --project")} ${dim("Install into the current folder")}`,
|
|
126
|
+
` ${flag("-d, --dir")} ${dim("<p>")} ${dim("Install into a specific folder")}`,
|
|
127
127
|
` ${flag("-a, --agent")} ${dim("<n>")} ${dim("Target provider(s); repeatable; '*' = all")}`,
|
|
128
128
|
` ${flag("-l, --list")} ${dim("Preview only — write nothing")}`,
|
|
129
129
|
` ${flag("--copy")} ${dim("Copy files instead of symlinking")}`,
|
|
130
130
|
` ${flag("--all")} ${dim("Install everything to all agents, no prompts")}`,
|
|
131
|
-
` ${flag("-y, --yes")} ${dim("Don't prompt")}`,
|
|
131
|
+
` ${flag("-y, --yes")} ${dim("Don't prompt (scope defaults to project)")}`,
|
|
132
132
|
` ${flag("--description")} ${dim("<t>")} ${dim("init: frontmatter description")}`,
|
|
133
133
|
` ${flag("--alwaysApply")} ${dim("init rule: alwaysApply: true")}`,
|
|
134
134
|
` ${flag("--reference")} ${dim("init skill: add references/TEMPLATE.md")}`,
|
package/dist/cli.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { animateLogo, badge, delay, printHelp, sky, theme } from "./_chunks/theme2.mjs";
|
|
3
|
-
import { execFileSync
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
4
|
import https from "node:https";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
|
-
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { homedir, tmpdir } from "node:os";
|
|
8
8
|
import { dirname, join, resolve, sep } from "node:path";
|
|
9
9
|
import { xdgCache, xdgConfig } from "xdg-basedir";
|
|
@@ -16,7 +16,7 @@ import { determineAgent } from "@vercel/detect-agent";
|
|
|
16
16
|
import { stripVTControlCharacters } from "node:util";
|
|
17
17
|
import { Writable } from "node:stream";
|
|
18
18
|
var name = "@mhmdreza-rafiei/agentry";
|
|
19
|
-
var version = "0.2.
|
|
19
|
+
var version = "0.2.2";
|
|
20
20
|
const ARTIFACT_KINDS = [
|
|
21
21
|
"skill",
|
|
22
22
|
"rule",
|
|
@@ -34,15 +34,21 @@ function isLocalPath(source) {
|
|
|
34
34
|
return false;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
const SAFE_REF$1 = /^[a-zA-Z0-9][\w./-]*$/;
|
|
37
38
|
function parseGithubTreeUrl(url) {
|
|
38
39
|
const m = url.match(/^https?:\/\/github\.com\/([\w.-]+\/[\w.-]+?)\/tree\/([^/]+)\/(.+)$/);
|
|
39
40
|
if (!m) return null;
|
|
41
|
+
const ref = m[2];
|
|
42
|
+
if (!SAFE_REF$1.test(ref)) throw new Error(`Invalid git ref in source URL: "${ref}"`);
|
|
40
43
|
return {
|
|
41
44
|
ownerRepo: m[1],
|
|
42
|
-
ref
|
|
45
|
+
ref,
|
|
43
46
|
subpath: m[3].replace(/\/+$/, "")
|
|
44
47
|
};
|
|
45
48
|
}
|
|
49
|
+
function redactUrl(url) {
|
|
50
|
+
return url.replace(/:\/\/([^/@]+)@/g, "://***@");
|
|
51
|
+
}
|
|
46
52
|
function parseSource(source) {
|
|
47
53
|
if (!source || typeof source !== "string") throw new Error("Empty source.");
|
|
48
54
|
const raw = source;
|
|
@@ -140,7 +146,9 @@ function saveToCache(parsed, clonedRoot) {
|
|
|
140
146
|
cpSync(clonedRoot, dest, { recursive: true });
|
|
141
147
|
} catch {}
|
|
142
148
|
}
|
|
149
|
+
const SAFE_REF = /^[a-zA-Z0-9][\w./-]*$/;
|
|
143
150
|
function cloneTo(url, dest, ref) {
|
|
151
|
+
if (ref && !SAFE_REF.test(ref)) throw new Error(`Invalid git ref: "${ref}"`);
|
|
144
152
|
execFileSync("git", [
|
|
145
153
|
"clone",
|
|
146
154
|
"--quiet",
|
|
@@ -158,28 +166,39 @@ function cloneTo(url, dest, ref) {
|
|
|
158
166
|
"pipe"
|
|
159
167
|
] });
|
|
160
168
|
}
|
|
169
|
+
function assertInsideRoot(root, candidate) {
|
|
170
|
+
const base = resolve(root);
|
|
171
|
+
const resolved = resolve(candidate);
|
|
172
|
+
const prefix = base.endsWith(sep) ? base : base + sep;
|
|
173
|
+
const a = resolved.toLowerCase();
|
|
174
|
+
const b = base.toLowerCase();
|
|
175
|
+
const p = prefix.toLowerCase();
|
|
176
|
+
if (a !== b && !a.startsWith(p)) throw new Error(`Path escapes source root: "${candidate}"`);
|
|
177
|
+
return resolved;
|
|
178
|
+
}
|
|
161
179
|
function withSubpath(root, subpath, cleanupRoot) {
|
|
180
|
+
const cleanup = () => rmSync(cleanupRoot, {
|
|
181
|
+
recursive: true,
|
|
182
|
+
force: true
|
|
183
|
+
});
|
|
162
184
|
if (!subpath) return {
|
|
163
185
|
root,
|
|
164
|
-
cleanup
|
|
165
|
-
recursive: true,
|
|
166
|
-
force: true
|
|
167
|
-
})
|
|
186
|
+
cleanup
|
|
168
187
|
};
|
|
169
|
-
|
|
188
|
+
let sub;
|
|
189
|
+
try {
|
|
190
|
+
sub = assertInsideRoot(root, join(root, subpath));
|
|
191
|
+
} catch (e) {
|
|
192
|
+
cleanup();
|
|
193
|
+
throw e;
|
|
194
|
+
}
|
|
170
195
|
if (!existsSync(sub)) {
|
|
171
|
-
|
|
172
|
-
recursive: true,
|
|
173
|
-
force: true
|
|
174
|
-
});
|
|
196
|
+
cleanup();
|
|
175
197
|
throw new Error(`Subpath "${subpath}" not found.`);
|
|
176
198
|
}
|
|
177
199
|
return {
|
|
178
200
|
root: sub,
|
|
179
|
-
cleanup
|
|
180
|
-
recursive: true,
|
|
181
|
-
force: true
|
|
182
|
-
})
|
|
201
|
+
cleanup
|
|
183
202
|
};
|
|
184
203
|
}
|
|
185
204
|
async function resolveSource(source, opts = {}) {
|
|
@@ -193,6 +212,7 @@ async function resolveSource(source, opts = {}) {
|
|
|
193
212
|
}
|
|
194
213
|
const url = parsed.url;
|
|
195
214
|
if (!url) throw new Error(`Cannot resolve source "${parsed.raw}".`);
|
|
215
|
+
const safeUrl = redactUrl(url);
|
|
196
216
|
const tmp = mkdtempSync(join(tmpdir(), "agentry-src-"));
|
|
197
217
|
try {
|
|
198
218
|
cloneTo(url, tmp, parsed.ref);
|
|
@@ -206,7 +226,7 @@ async function resolveSource(source, opts = {}) {
|
|
|
206
226
|
const cacheOk = existsSync(cached) && existsSync(join(cached, ".git"));
|
|
207
227
|
if (cacheOk && opts.confirmCache) {
|
|
208
228
|
if (await opts.confirmCache({
|
|
209
|
-
url,
|
|
229
|
+
url: safeUrl,
|
|
210
230
|
cacheDir: cached,
|
|
211
231
|
error: detail
|
|
212
232
|
})) {
|
|
@@ -218,7 +238,7 @@ async function resolveSource(source, opts = {}) {
|
|
|
218
238
|
};
|
|
219
239
|
}
|
|
220
240
|
}
|
|
221
|
-
throw new Error(`git clone failed for ${
|
|
241
|
+
throw new Error(`git clone failed for ${safeUrl}\n${detail}${cacheOk ? "\n(A local cache exists — re-run interactively to load it, or pass -y to auto-use cache.)" : ""}`);
|
|
222
242
|
}
|
|
223
243
|
saveToCache(parsed, tmp);
|
|
224
244
|
return withSubpath(tmp, parsed.subpath, tmp);
|
|
@@ -563,6 +583,38 @@ function getNonUniversalAgents() {
|
|
|
563
583
|
return listAgents().filter((a) => a.skillsDir !== ".agents/skills");
|
|
564
584
|
}
|
|
565
585
|
const home = homedir();
|
|
586
|
+
function copyTreeDereferenced(src, dest, seen = /* @__PURE__ */ new Set()) {
|
|
587
|
+
const st = lstatSync(src);
|
|
588
|
+
if (st.isSymbolicLink()) {
|
|
589
|
+
let real;
|
|
590
|
+
try {
|
|
591
|
+
real = realpathSync(src);
|
|
592
|
+
} catch {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (seen.has(real)) return;
|
|
596
|
+
seen.add(real);
|
|
597
|
+
copyTreeDereferenced(real, dest, seen);
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
if (st.isDirectory()) {
|
|
601
|
+
let real;
|
|
602
|
+
try {
|
|
603
|
+
real = realpathSync(src);
|
|
604
|
+
} catch {
|
|
605
|
+
real = resolve(src);
|
|
606
|
+
}
|
|
607
|
+
if (seen.has(real)) return;
|
|
608
|
+
seen.add(real);
|
|
609
|
+
mkdirSync(dest, { recursive: true });
|
|
610
|
+
for (const name of readdirSync(src)) copyTreeDereferenced(join(src, name), join(dest, name), seen);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (st.isFile()) {
|
|
614
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
615
|
+
copyFileSync(src, dest);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
566
618
|
function lockBase(opts) {
|
|
567
619
|
return opts.scope === "global" ? home : opts.dir || process.cwd();
|
|
568
620
|
}
|
|
@@ -690,7 +742,7 @@ function installOne(artifact, opts, agentList, source) {
|
|
|
690
742
|
force: true
|
|
691
743
|
});
|
|
692
744
|
mkdirSync(join(canonical, ".."), { recursive: true });
|
|
693
|
-
|
|
745
|
+
copyTreeDereferenced(artifact.dir, canonical);
|
|
694
746
|
for (const a of list) if (a.skillsDir === ".agents/skills") dests.push({
|
|
695
747
|
agent: a.name,
|
|
696
748
|
dir: canonical
|
|
@@ -703,7 +755,7 @@ function installOne(artifact, opts, agentList, source) {
|
|
|
703
755
|
});
|
|
704
756
|
mkdirSync(join(dir, ".."), { recursive: true });
|
|
705
757
|
if (opts.copy) {
|
|
706
|
-
|
|
758
|
+
copyTreeDereferenced(canonical, dir);
|
|
707
759
|
dests.push({
|
|
708
760
|
agent: a.name,
|
|
709
761
|
dir
|
|
@@ -716,7 +768,7 @@ function installOne(artifact, opts, agentList, source) {
|
|
|
716
768
|
symlinked: true
|
|
717
769
|
});
|
|
718
770
|
} catch {
|
|
719
|
-
|
|
771
|
+
copyTreeDereferenced(canonical, dir);
|
|
720
772
|
dests.push({
|
|
721
773
|
agent: a.name,
|
|
722
774
|
dir
|
|
@@ -730,7 +782,7 @@ function installOne(artifact, opts, agentList, source) {
|
|
|
730
782
|
force: true
|
|
731
783
|
});
|
|
732
784
|
mkdirSync(join(dir, ".."), { recursive: true });
|
|
733
|
-
|
|
785
|
+
copyTreeDereferenced(artifact.dir, dir);
|
|
734
786
|
dests.push({
|
|
735
787
|
agent: a.name,
|
|
736
788
|
dir
|
|
@@ -1417,6 +1469,98 @@ function agentsPrompt(action) {
|
|
|
1417
1469
|
if (action === "update") return "Which agents do you want to update for?";
|
|
1418
1470
|
return "Which agents do you want to install to?";
|
|
1419
1471
|
}
|
|
1472
|
+
function scopePrompt(action) {
|
|
1473
|
+
if (action === "remove") return "Removal scope";
|
|
1474
|
+
if (action === "update") return "Update scope";
|
|
1475
|
+
return "Installation scope";
|
|
1476
|
+
}
|
|
1477
|
+
async function selectInstallScope(message, paths) {
|
|
1478
|
+
if (isQuiet()) return "project";
|
|
1479
|
+
return new Promise((resolve) => {
|
|
1480
|
+
if (!process.stdin.isTTY) {
|
|
1481
|
+
resolve("project");
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
const rl = readline.createInterface({
|
|
1485
|
+
input: process.stdin,
|
|
1486
|
+
output: process.stdout
|
|
1487
|
+
});
|
|
1488
|
+
process.stdin.setRawMode(true);
|
|
1489
|
+
readline.emitKeypressEvents(process.stdin, rl);
|
|
1490
|
+
let value = "project";
|
|
1491
|
+
let lastH = 0;
|
|
1492
|
+
const joinRel = (base, rel) => {
|
|
1493
|
+
const sep = base.includes("\\") ? "\\" : "/";
|
|
1494
|
+
return `${base.replace(/[\\/]+$/, "")}${sep}${rel.replace(/\//g, sep)}`;
|
|
1495
|
+
};
|
|
1496
|
+
const optionBlock = (key, selected, done) => {
|
|
1497
|
+
const active = done ? done === key : selected;
|
|
1498
|
+
const bullet = active ? sky(c.bold("●")) : c.dim("○");
|
|
1499
|
+
const title = key === "project" ? "Project" : "Global";
|
|
1500
|
+
const hint = key === "project" ? "Install in the current directory (committed with your project)" : "Install in your home directory (available across all projects)";
|
|
1501
|
+
const path = key === "project" ? paths.projectDir : paths.homeDir;
|
|
1502
|
+
const lock = key === "project" ? joinRel(paths.projectDir, ".agentry/lock.json") : joinRel(paths.homeDir, ".agentry/lock.json");
|
|
1503
|
+
const lines = [];
|
|
1504
|
+
if (done === "cancel") lines.push(`${c.dim("│")} ${c.strikethrough(c.dim(title))}`);
|
|
1505
|
+
else {
|
|
1506
|
+
lines.push(`${c.dim("│")} ${bullet} ${active ? c.bold(title) : title}`);
|
|
1507
|
+
lines.push(`${c.dim("│")} ${c.dim(hint)}`);
|
|
1508
|
+
lines.push(`${c.dim("│")} ${sky("→")} ${c.dim(path)}`);
|
|
1509
|
+
lines.push(`${c.dim("│")} ${c.dim(`lock ${lock}`)}`);
|
|
1510
|
+
}
|
|
1511
|
+
return lines;
|
|
1512
|
+
};
|
|
1513
|
+
const paint = (done) => {
|
|
1514
|
+
const lines = [];
|
|
1515
|
+
if (done === "cancel") {
|
|
1516
|
+
lines.push(`${sky("■")} ${c.bold(message)}`);
|
|
1517
|
+
lines.push(`${c.dim("│")} ${c.strikethrough(c.dim("Cancelled"))}`);
|
|
1518
|
+
} else if (done === "project" || done === "global") {
|
|
1519
|
+
lines.push(`${sky("◇")} ${c.bold(message)}`);
|
|
1520
|
+
lines.push(...optionBlock(done, true, done).slice(0, 2));
|
|
1521
|
+
lines.push(`${c.dim("│")} ${sky("→")} ${c.dim(done === "project" ? paths.projectDir : paths.homeDir)}`);
|
|
1522
|
+
} else {
|
|
1523
|
+
lines.push(`${sky("◆")} ${c.bold(message)}`);
|
|
1524
|
+
lines.push(`${c.dim("│")}`);
|
|
1525
|
+
lines.push(...optionBlock("project", value === "project"));
|
|
1526
|
+
lines.push(`${c.dim("│")}`);
|
|
1527
|
+
lines.push(...optionBlock("global", value === "global"));
|
|
1528
|
+
lines.push(`${c.dim("└")} ${c.dim("↑/↓ select · enter confirm")}`);
|
|
1529
|
+
}
|
|
1530
|
+
if (lastH > 0) for (let i = 0; i < lastH; i++) process.stdout.write("\x1B[1A\x1B[2K");
|
|
1531
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
1532
|
+
lastH = lines.length;
|
|
1533
|
+
};
|
|
1534
|
+
const cleanup = () => {
|
|
1535
|
+
process.stdin.removeListener("keypress", onKey);
|
|
1536
|
+
process.stdin.setRawMode(false);
|
|
1537
|
+
rl.close();
|
|
1538
|
+
};
|
|
1539
|
+
const onKey = (_s, key) => {
|
|
1540
|
+
if (!key) return;
|
|
1541
|
+
if (key.name === "up" || key.name === "down" || key.name === "tab") {
|
|
1542
|
+
value = value === "project" ? "global" : "project";
|
|
1543
|
+
paint();
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
if (key.name === "return") {
|
|
1547
|
+
paint(value);
|
|
1548
|
+
cleanup();
|
|
1549
|
+
blank();
|
|
1550
|
+
resolve(value);
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
if (key.name === "escape" || key.ctrl && key.name === "c") {
|
|
1554
|
+
paint("cancel");
|
|
1555
|
+
cleanup();
|
|
1556
|
+
resolve(null);
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
process.stdin.on("keypress", onKey);
|
|
1560
|
+
blank();
|
|
1561
|
+
paint();
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1420
1564
|
function isQuiet() {
|
|
1421
1565
|
return isCI() || !process.stdout.isTTY;
|
|
1422
1566
|
}
|
|
@@ -1814,7 +1958,10 @@ async function cmdAdd(kind, source, selector, opts) {
|
|
|
1814
1958
|
blank();
|
|
1815
1959
|
}
|
|
1816
1960
|
const agentList = await resolveAgentList(opts, "install");
|
|
1817
|
-
|
|
1961
|
+
const askScope = !opts.scopeExplicit && !opts.yes && !isQuiet();
|
|
1962
|
+
if (!isQuiet() && !opts.agents.length && !opts.all && !opts.yes) await sectionTransition(`${agentList.length} agent${agentList.length === 1 ? "" : "s"} selected`, askScope ? "installation scope" : "install summary");
|
|
1963
|
+
if (!await ensureInstallScope(opts, "install")) return;
|
|
1964
|
+
if (askScope) await sectionTransition("scope set", "install summary");
|
|
1818
1965
|
installAll(chosen, opts, agentList, source);
|
|
1819
1966
|
} finally {
|
|
1820
1967
|
cleanup();
|
|
@@ -1833,6 +1980,7 @@ async function cmdAddProfile(name, source, opts) {
|
|
|
1833
1980
|
const repo = source || (profile.artifacts.skills[0]?.source ?? profile.artifacts.rules[0]?.source);
|
|
1834
1981
|
if (!repo) throw new Error(`No source given and ${file} lists none. Try: agentry add profile ${name} author/repo`);
|
|
1835
1982
|
const agentList = await resolveAgentList(opts, "install");
|
|
1983
|
+
if (!await ensureInstallScope(opts, "install")) return;
|
|
1836
1984
|
const { root, cleanup } = await resolveSourceWithUi(repo, opts);
|
|
1837
1985
|
try {
|
|
1838
1986
|
const artifacts = [];
|
|
@@ -1878,6 +2026,23 @@ async function resolveAgentList(opts, action = "install") {
|
|
|
1878
2026
|
if (isCancelLike(selected)) throw new Error("Cancelled.");
|
|
1879
2027
|
return selected;
|
|
1880
2028
|
}
|
|
2029
|
+
async function ensureInstallScope(opts, action) {
|
|
2030
|
+
if (opts.scopeExplicit) return true;
|
|
2031
|
+
if (opts.yes || isQuiet()) return true;
|
|
2032
|
+
const { homedir } = await import("node:os");
|
|
2033
|
+
if (!isQuiet()) await sectionTransition(`${action === "install" ? "agents" : action} ready`, scopePrompt(action).toLowerCase());
|
|
2034
|
+
const picked = await selectInstallScope(scopePrompt(action), {
|
|
2035
|
+
projectDir: opts.dir || process.cwd(),
|
|
2036
|
+
homeDir: homedir()
|
|
2037
|
+
});
|
|
2038
|
+
if (picked == null || isCancelLike(picked)) {
|
|
2039
|
+
outro("Cancelled.");
|
|
2040
|
+
return false;
|
|
2041
|
+
}
|
|
2042
|
+
opts.scope = picked;
|
|
2043
|
+
opts.scopeExplicit = true;
|
|
2044
|
+
return true;
|
|
2045
|
+
}
|
|
1881
2046
|
function installAll(artifacts, opts, agentList, source) {
|
|
1882
2047
|
if (!artifacts.length) {
|
|
1883
2048
|
warn("Nothing matched - nothing installed.");
|
|
@@ -1904,8 +2069,22 @@ function resolveSourceOrSelector(arg1, arg2, opts) {
|
|
|
1904
2069
|
if (!arg1) return {};
|
|
1905
2070
|
if (isExplicitSource(arg1)) return { source: arg1 };
|
|
1906
2071
|
if (isOwnerRepoShape(arg1)) {
|
|
1907
|
-
const
|
|
1908
|
-
|
|
2072
|
+
const bases = [{
|
|
2073
|
+
scope: "project",
|
|
2074
|
+
dir: opts.dir,
|
|
2075
|
+
agents: opts.agents,
|
|
2076
|
+
copy: opts.copy,
|
|
2077
|
+
dryRun: opts.dryRun
|
|
2078
|
+
}, {
|
|
2079
|
+
scope: "global",
|
|
2080
|
+
agents: opts.agents,
|
|
2081
|
+
copy: opts.copy,
|
|
2082
|
+
dryRun: opts.dryRun
|
|
2083
|
+
}];
|
|
2084
|
+
for (const base of bases) {
|
|
2085
|
+
const lock = readLock(base);
|
|
2086
|
+
if (Object.values(lock.items).some((e) => e.source && sourcesEqual(e.source, arg1))) return { source: arg1 };
|
|
2087
|
+
}
|
|
1909
2088
|
}
|
|
1910
2089
|
return { selector: arg1 };
|
|
1911
2090
|
}
|
|
@@ -1918,6 +2097,7 @@ async function cmdRemove(kind, arg1, arg2, opts) {
|
|
|
1918
2097
|
}, 420);
|
|
1919
2098
|
if (!isQuiet() && !opts.agents.length && !opts.all && !opts.yes) await sectionTransition("prepare remove", "choose agents to remove from");
|
|
1920
2099
|
const agentList = await resolveAgentList(opts, "remove");
|
|
2100
|
+
if (!await ensureInstallScope(opts, "remove")) return;
|
|
1921
2101
|
const installOpts = toInstallOpts(opts);
|
|
1922
2102
|
const scope = [
|
|
1923
2103
|
kind,
|
|
@@ -2051,7 +2231,6 @@ function printArtifactList(artifacts, meta) {
|
|
|
2051
2231
|
async function cmdUpdateAssets(kind, arg1, arg2, opts) {
|
|
2052
2232
|
intro();
|
|
2053
2233
|
const { source, selector } = resolveSourceOrSelector(arg1, arg2, opts);
|
|
2054
|
-
const installOpts = toInstallOpts(opts);
|
|
2055
2234
|
if (source) {
|
|
2056
2235
|
await spinner("Parsing source…", () => parseSource(source), (p) => {
|
|
2057
2236
|
const where = p.url || p.local || source;
|
|
@@ -2076,6 +2255,7 @@ async function cmdUpdateAssets(kind, arg1, arg2, opts) {
|
|
|
2076
2255
|
await sectionTransition(`${chosen.length} ${kind}${chosen.length === 1 ? "" : "s"} selected`, "choose target agents");
|
|
2077
2256
|
} else if (!isQuiet() && !opts.agents.length && !opts.all && !opts.yes) await sectionTransition(`${chosen.length} ${kind}${chosen.length === 1 ? "" : "s"} ready`, "choose target agents");
|
|
2078
2257
|
const agentList = await resolveAgentList(opts, "update");
|
|
2258
|
+
if (!await ensureInstallScope(opts, "update")) return;
|
|
2079
2259
|
if (!isQuiet() && !opts.agents.length && !opts.all && !opts.yes) await sectionTransition(`${agentList.length} agent${agentList.length === 1 ? "" : "s"} selected`, "update summary");
|
|
2080
2260
|
installAll(chosen, opts, agentList, source);
|
|
2081
2261
|
} finally {
|
|
@@ -2083,7 +2263,8 @@ async function cmdUpdateAssets(kind, arg1, arg2, opts) {
|
|
|
2083
2263
|
}
|
|
2084
2264
|
return;
|
|
2085
2265
|
}
|
|
2086
|
-
|
|
2266
|
+
if (!await ensureInstallScope(opts, "update")) return;
|
|
2267
|
+
let installed = listInstalled(toInstallOpts(opts)).filter((it) => kind === "all" || it.id.startsWith(kind + "/"));
|
|
2087
2268
|
if (selector) {
|
|
2088
2269
|
const rel = `${kind}/${selector}`;
|
|
2089
2270
|
installed = installed.filter((it) => it.id === rel || it.id.startsWith(rel + "/") || it.id.endsWith("/" + selector));
|
|
@@ -2308,6 +2489,7 @@ function takeOptValue(argv, i) {
|
|
|
2308
2489
|
function parseArgs(argv) {
|
|
2309
2490
|
const opts = {
|
|
2310
2491
|
scope: "project",
|
|
2492
|
+
scopeExplicit: false,
|
|
2311
2493
|
agents: [],
|
|
2312
2494
|
copy: false,
|
|
2313
2495
|
dryRun: false,
|
|
@@ -2321,15 +2503,19 @@ function parseArgs(argv) {
|
|
|
2321
2503
|
const a = argv[i];
|
|
2322
2504
|
if (a === "-g" || a === "--global") {
|
|
2323
2505
|
opts.scope = "global";
|
|
2506
|
+
opts.scopeExplicit = true;
|
|
2324
2507
|
flags.global = true;
|
|
2325
|
-
} else if (a === "--project") {
|
|
2508
|
+
} else if (a === "-p" || a === "--project") {
|
|
2326
2509
|
opts.scope = "project";
|
|
2510
|
+
opts.scopeExplicit = true;
|
|
2327
2511
|
flags.project = true;
|
|
2328
2512
|
} else if (a === "-y" || a === "--yes") {
|
|
2329
2513
|
opts.yes = true;
|
|
2330
2514
|
flags.yes = true;
|
|
2331
|
-
} else if (a === "--dir") {
|
|
2515
|
+
} else if (a === "-d" || a === "--dir") {
|
|
2332
2516
|
opts.dir = argv[++i];
|
|
2517
|
+
opts.scope = "project";
|
|
2518
|
+
opts.scopeExplicit = true;
|
|
2333
2519
|
flags.dir = opts.dir;
|
|
2334
2520
|
} else if (a === "-a" || a === "--agent") {
|
|
2335
2521
|
opts.agents.push(argv[++i]);
|
|
@@ -2420,7 +2606,11 @@ async function runUpdateSelf() {
|
|
|
2420
2606
|
function runNpmInstall(spec) {
|
|
2421
2607
|
spinner(`Updating agentry CLI`, () => {
|
|
2422
2608
|
try {
|
|
2423
|
-
|
|
2609
|
+
execFileSync("npm", [
|
|
2610
|
+
"install",
|
|
2611
|
+
"-g",
|
|
2612
|
+
spec
|
|
2613
|
+
], { stdio: "inherit" });
|
|
2424
2614
|
} catch {
|
|
2425
2615
|
err("Update failed. Once published, run: npm install -g " + spec);
|
|
2426
2616
|
process.exit(1);
|
|
@@ -2430,7 +2620,11 @@ function runNpmInstall(spec) {
|
|
|
2430
2620
|
function runUninstall() {
|
|
2431
2621
|
spinner("Uninstalling agentry CLI", () => {
|
|
2432
2622
|
try {
|
|
2433
|
-
|
|
2623
|
+
execFileSync("npm", [
|
|
2624
|
+
"uninstall",
|
|
2625
|
+
"-g",
|
|
2626
|
+
name
|
|
2627
|
+
], { stdio: "inherit" });
|
|
2434
2628
|
} catch {
|
|
2435
2629
|
err("Uninstall failed. Try: npm uninstall -g " + name);
|
|
2436
2630
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,53 +1,61 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@mhmdreza-rafiei/agentry",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "One CLI to install agents, skills, rules, and profiles onto AI coding agents — portable AI/agent tooling.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"agentry": "
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"dist",
|
|
11
|
-
"README.md",
|
|
12
|
-
"LICENSE"
|
|
13
|
-
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"dev": "tsx src/cli.ts",
|
|
16
|
-
"build": "obuild",
|
|
17
|
-
"test": "vitest run",
|
|
18
|
-
"test:watch": "vitest",
|
|
19
|
-
"typecheck": "tsc --noEmit"
|
|
20
|
-
},
|
|
21
|
-
"engines": {
|
|
22
|
-
"node": ">=22.20.0"
|
|
23
|
-
},
|
|
24
|
-
"keywords": [
|
|
25
|
-
"ai",
|
|
26
|
-
"agents",
|
|
27
|
-
"skills",
|
|
28
|
-
"rules",
|
|
29
|
-
"profiles",
|
|
30
|
-
"cli",
|
|
31
|
-
"cursor",
|
|
32
|
-
"claude-code",
|
|
33
|
-
"codex",
|
|
34
|
-
"agentic",
|
|
35
|
-
"scaffold"
|
|
36
|
-
],
|
|
37
|
-
"license": "MIT",
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"@
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@mhmdreza-rafiei/agentry",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "One CLI to install agents, skills, rules, and profiles onto AI coding agents — portable AI/agent tooling.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentry": "dist/cli.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"dev": "tsx src/cli.ts",
|
|
16
|
+
"build": "obuild",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:watch": "vitest",
|
|
19
|
+
"typecheck": "tsc --noEmit"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=22.20.0"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"ai",
|
|
26
|
+
"agents",
|
|
27
|
+
"skills",
|
|
28
|
+
"rules",
|
|
29
|
+
"profiles",
|
|
30
|
+
"cli",
|
|
31
|
+
"cursor",
|
|
32
|
+
"claude-code",
|
|
33
|
+
"codex",
|
|
34
|
+
"agentic",
|
|
35
|
+
"scaffold"
|
|
36
|
+
],
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/mhmdreza-rafiei/agentry.git"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/mhmdreza-rafiei/agentry/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://github.com/mhmdreza-rafiei/agentry#readme",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@clack/prompts": "^0.7.0",
|
|
48
|
+
"@vercel/detect-agent": "^1.2.1",
|
|
49
|
+
"picocolors": "^1.1.1",
|
|
50
|
+
"xdg-basedir": "^5.1.0",
|
|
51
|
+
"yaml": "^2.8.3",
|
|
52
|
+
"zod": "^3.23.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^22.10.0",
|
|
56
|
+
"obuild": "^0.4.22",
|
|
57
|
+
"tsx": "^4.19.0",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"vitest": "^4.1.10"
|
|
60
|
+
}
|
|
61
|
+
}
|