@remixmate/cli 0.9.22 → 0.9.23
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/README.md +18 -6
- package/README.zh-CN.md +18 -7
- package/dist/doctor.js +3 -1
- package/dist/install.d.ts +8 -4
- package/dist/install.js +175 -38
- package/dist/manifest.json +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,15 +16,27 @@ npm install -g @remixmate/cli && remixmate install
|
|
|
16
16
|
|
|
17
17
|
`npm install` gives you the `remixmate` binary. `remixmate install` is what makes an
|
|
18
18
|
agent *discover* the skills on its own: it copies the bundled `skills/` into every
|
|
19
|
-
agent home it finds
|
|
20
|
-
|
|
19
|
+
agent home it finds. All of these hosts read the same `SKILL.md` format, so one
|
|
20
|
+
`skills/` directory serves all of them:
|
|
21
|
+
|
|
22
|
+
| Host | User-level | Project-level | Override |
|
|
23
|
+
| --- | --- | --- | --- |
|
|
24
|
+
| Claude Code | `~/.claude/skills` | `./.claude/skills` | `CLAUDE_CONFIG_DIR` |
|
|
25
|
+
| Codex | `~/.codex/skills` | — | `CODEX_HOME` |
|
|
26
|
+
| WorkBuddy | `~/.workbuddy/skills` | `./.workbuddy/skills` | — |
|
|
27
|
+
| CodeBuddy | `~/.codebuddy/skills` | `./.codebuddy/skills` | — |
|
|
28
|
+
| Trae / TraeWork | — | `./.trae/skills` | — |
|
|
29
|
+
|
|
30
|
+
Trae CN and TraeWork CN share `~/.trae-cn` and only define a workspace location (`.trae/skills/<name>/`, per its own built-in
|
|
31
|
+
`skill-creator`), so it is installed per project — a plain `remixmate install` reports
|
|
32
|
+
it and tells you to re-run with `--project` inside the repo. Restart the agent
|
|
21
33
|
afterwards.
|
|
22
34
|
|
|
23
35
|
```bash
|
|
24
|
-
remixmate install --host
|
|
25
|
-
remixmate install --project
|
|
26
|
-
remixmate install --dir <path>
|
|
27
|
-
remixmate uninstall
|
|
36
|
+
remixmate install --host workbuddy # only one host
|
|
37
|
+
remixmate install --project # ./<config-dir>/skills (not Codex — it has none)
|
|
38
|
+
remixmate install --dir <path> # explicit target, for a host not listed above
|
|
39
|
+
remixmate uninstall # remove exactly what was installed
|
|
28
40
|
```
|
|
29
41
|
|
|
30
42
|
The install is *managed*, not a `cp -R`: each skills directory gets a
|
package/README.zh-CN.md
CHANGED
|
@@ -15,15 +15,26 @@ npm install -g @remixmate/cli && remixmate install
|
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
`npm install` 装的是 `remixmate` 这个命令;`remixmate install` 才让 agent **自己发现**
|
|
18
|
-
这些 skill —— 它把内置的 `skills/` 铺进检测到的每个 agent
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
这些 skill —— 它把内置的 `skills/` 铺进检测到的每个 agent 目录。下面这些宿主用的是
|
|
19
|
+
同一套 `SKILL.md` 格式,所以一份 `skills/` 全都能喂:
|
|
20
|
+
|
|
21
|
+
| 宿主 | 用户级 | 项目级 | 可用环境变量改位置 |
|
|
22
|
+
| --- | --- | --- | --- |
|
|
23
|
+
| Claude Code | `~/.claude/skills` | `./.claude/skills` | `CLAUDE_CONFIG_DIR` |
|
|
24
|
+
| Codex | `~/.codex/skills` | — | `CODEX_HOME` |
|
|
25
|
+
| WorkBuddy | `~/.workbuddy/skills` | `./.workbuddy/skills` | — |
|
|
26
|
+
| CodeBuddy | `~/.codebuddy/skills` | `./.codebuddy/skills` | — |
|
|
27
|
+
| Trae / TraeWork | — | `./.trae/skills` | — |
|
|
28
|
+
|
|
29
|
+
Trae CN 与 TraeWork CN 共用 `~/.trae-cn`,且只定义了工作区位置(`.trae/skills/<name>/`,依据是它自带的 `skill-creator`),
|
|
30
|
+
所以只能按项目装 —— 直接跑 `remixmate install` 会提示你进项目目录加 `--project` 重跑。
|
|
31
|
+
装完重启 agent 生效。
|
|
21
32
|
|
|
22
33
|
```bash
|
|
23
|
-
remixmate install --host
|
|
24
|
-
remixmate install --project
|
|
25
|
-
remixmate install --dir <path>
|
|
26
|
-
remixmate uninstall
|
|
34
|
+
remixmate install --host workbuddy # 只装某一个宿主
|
|
35
|
+
remixmate install --project # 装到 ./<配置目录>/skills(Codex 没有项目级目录)
|
|
36
|
+
remixmate install --dir <path> # 指定目录,用于上表之外的宿主
|
|
37
|
+
remixmate uninstall # 按装机记录精确卸载
|
|
27
38
|
```
|
|
28
39
|
|
|
29
40
|
这里的安装是**受管**的,不是 `cp -R`:每个 skills 目录下会写一份
|
package/dist/doctor.js
CHANGED
|
@@ -166,7 +166,9 @@ export async function runDoctor(opts = {}) {
|
|
|
166
166
|
if (!opts.skipNetwork)
|
|
167
167
|
checks.push(await checkBackend(apiBaseUrl));
|
|
168
168
|
for (const c of checks) {
|
|
169
|
-
|
|
169
|
+
// 16 而不是 14:宿主检查名最长是「WorkBuddy skill」,窄一格就会把那两行的
|
|
170
|
+
// detail 列顶出去,报告看起来像是漏了对齐。
|
|
171
|
+
process.stdout.write(`${ICON[c.status]} ${padDisplay(c.name, 16)}${c.detail}\n`);
|
|
170
172
|
}
|
|
171
173
|
const failed = checks.filter((c) => c.status === 'fail');
|
|
172
174
|
if (failed.length === 0) {
|
package/dist/install.d.ts
CHANGED
|
@@ -21,18 +21,22 @@
|
|
|
21
21
|
*/
|
|
22
22
|
export declare const INSTALL_VERB = "install";
|
|
23
23
|
export declare const UNINSTALL_VERB = "uninstall";
|
|
24
|
-
export type HostId = 'claude' | 'codex';
|
|
24
|
+
export type HostId = 'claude' | 'codex' | 'workbuddy' | 'codebuddy' | 'trae';
|
|
25
25
|
interface Host {
|
|
26
26
|
id: HostId | 'custom';
|
|
27
27
|
label: string;
|
|
28
28
|
/** skill 的父目录 —— 安装写到 <skillsDir>/<skill-name>/。 */
|
|
29
29
|
skillsDir: string;
|
|
30
30
|
}
|
|
31
|
+
/** 已检测到、且**有用户级位置**的宿主。 */
|
|
32
|
+
export declare function detectHosts(): Host[];
|
|
31
33
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
+
* 检测到了、但只能项目级安装的宿主(当前只有 Trae)。
|
|
35
|
+
*
|
|
36
|
+
* 单独拎出来是为了别把它们**静默**跳过:用户装了 Trae 却在全局 install 的输出里
|
|
37
|
+
* 完全看不到它,只会以为这个 CLI 不支持 —— 正是这次 WorkBuddy 的翻车方式。
|
|
34
38
|
*/
|
|
35
|
-
export declare function
|
|
39
|
+
export declare function projectOnlyHosts(): HostId[];
|
|
36
40
|
export declare function installUsage(): void;
|
|
37
41
|
export declare function uninstallUsage(): void;
|
|
38
42
|
export declare function runInstall(argv: string[]): number;
|
package/dist/install.js
CHANGED
|
@@ -34,27 +34,118 @@ const PKG_ROOT = path.resolve(__dirname, '..');
|
|
|
34
34
|
const RECEIPT = '.remixmate-install.json';
|
|
35
35
|
const PACKAGE_NAME = '@remixmate/cli';
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
37
|
+
* 支持的 agent 宿主。
|
|
38
|
+
*
|
|
39
|
+
* 共同点是 skill 的格式:`<某个目录>/skills/<name>/SKILL.md`,frontmatter 都是
|
|
40
|
+
* name + description —— 一份 skills/ 能喂给所有宿主。这张表记的是各家把那个「某个
|
|
41
|
+
* 目录」放在哪、能不能被环境变量改、有没有用户级 / 项目级。
|
|
42
|
+
*
|
|
43
|
+
* 每一条的依据:
|
|
44
|
+
* - Claude Code / Codex:各自的官方安装位置(Codex 见其内置 skill-installer,
|
|
45
|
+
* 原话是装到 $CODEX_HOME/skills)。
|
|
46
|
+
* - WorkBuddy / CodeBuddy:WorkBuddy 内置的 find-skills skill 给了两条路径,
|
|
47
|
+
* 它按 __CFBundleIdentifier 区分。这里不做那个区分 —— 检测到哪个装哪个,
|
|
48
|
+
* 两个都在就都装,比猜「当前跑在哪个客户端里」稳。
|
|
49
|
+
* - Trae:内置的 skill-creator skill 只给了一个位置 —— 工作区的
|
|
50
|
+
* `.trae/skills/<name>/`。注意它的应用数据目录叫 ~/.trae-cn(国内版),
|
|
51
|
+
* 跟 skill 目录名 .trae 不是一个东西,而且 ~/.trae-cn/skills 并不存在。
|
|
52
|
+
* 没有任何证据表明存在用户级位置,所以 userDirName 留空:Trae 只能项目级装。
|
|
53
|
+
*/
|
|
54
|
+
const HOSTS = [
|
|
55
|
+
{
|
|
56
|
+
id: 'claude',
|
|
57
|
+
label: 'Claude Code',
|
|
58
|
+
detectDirNames: ['.claude'],
|
|
59
|
+
homeEnv: 'CLAUDE_CONFIG_DIR',
|
|
60
|
+
userDirName: '.claude',
|
|
61
|
+
projectDirName: '.claude',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'codex',
|
|
65
|
+
label: 'Codex',
|
|
66
|
+
detectDirNames: ['.codex'],
|
|
67
|
+
homeEnv: 'CODEX_HOME',
|
|
68
|
+
userDirName: '.codex',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'workbuddy',
|
|
72
|
+
label: 'WorkBuddy',
|
|
73
|
+
detectDirNames: ['.workbuddy'],
|
|
74
|
+
userDirName: '.workbuddy',
|
|
75
|
+
projectDirName: '.workbuddy',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'codebuddy',
|
|
79
|
+
label: 'CodeBuddy',
|
|
80
|
+
detectDirNames: ['.codebuddy'],
|
|
81
|
+
userDirName: '.codebuddy',
|
|
82
|
+
projectDirName: '.codebuddy',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: 'trae',
|
|
86
|
+
// Trae CN 与 TraeWork CN(安装出来叫 TRAE SOLO CN.app,bundle id cn.trae.solo.app)
|
|
87
|
+
// 共用 ~/.trae-cn —— 后者的内置 skill(dynamic-ui 等)就躺在那底下的
|
|
88
|
+
// builtin/*/skills/,所以一条 host 覆盖两个客户端。
|
|
89
|
+
label: 'Trae / TraeWork',
|
|
90
|
+
detectDirNames: ['.trae-cn', '.trae'],
|
|
91
|
+
projectDirName: '.trae',
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
const HOST_IDS = HOSTS.map((h) => h.id);
|
|
95
|
+
function spec(id) {
|
|
96
|
+
return HOSTS.find((h) => h.id === id);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 用户级 skills 目录;宿主没有用户级位置时返回 null。声明了环境变量的宿主要跟着
|
|
100
|
+
* 变量走 —— 否则把 CODEX_HOME 指到别处的用户会看到「未检测到 Codex」。
|
|
39
101
|
*/
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
102
|
+
function userSkillsDir(id) {
|
|
103
|
+
const h = spec(id);
|
|
104
|
+
if (!h.userDirName)
|
|
105
|
+
return null;
|
|
106
|
+
const override = h.homeEnv ? process.env[h.homeEnv] : undefined;
|
|
107
|
+
return path.join(override || path.join(os.homedir(), h.userDirName), 'skills');
|
|
108
|
+
}
|
|
109
|
+
/** 检测用的候选目录 —— 存在任意一个就算这台机器上装了这个 agent。 */
|
|
110
|
+
function detectDirs(id) {
|
|
111
|
+
const h = spec(id);
|
|
112
|
+
const override = h.homeEnv ? process.env[h.homeEnv] : undefined;
|
|
113
|
+
if (override)
|
|
114
|
+
return [override];
|
|
115
|
+
return h.detectDirNames.map((d) => path.join(os.homedir(), d));
|
|
116
|
+
}
|
|
117
|
+
function isInstalled(id) {
|
|
118
|
+
return detectDirs(id).some((d) => existsSync(d));
|
|
44
119
|
}
|
|
45
|
-
const HOST_LABEL = {
|
|
46
|
-
claude: 'Claude Code',
|
|
47
|
-
codex: 'Codex',
|
|
48
|
-
};
|
|
49
120
|
function hostOf(id) {
|
|
50
|
-
|
|
121
|
+
const dir = userSkillsDir(id);
|
|
122
|
+
return dir ? { id, label: spec(id).label, skillsDir: dir } : null;
|
|
123
|
+
}
|
|
124
|
+
/** 项目级安装目标:当前目录下的 ./<projectDirName>/skills。 */
|
|
125
|
+
function projectHostOf(id) {
|
|
126
|
+
const h = spec(id);
|
|
127
|
+
if (!h.projectDirName)
|
|
128
|
+
return null;
|
|
129
|
+
return {
|
|
130
|
+
id,
|
|
131
|
+
label: `${h.label}(项目级)`,
|
|
132
|
+
skillsDir: path.join(process.cwd(), h.projectDirName, 'skills'),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** 已检测到、且**有用户级位置**的宿主。 */
|
|
136
|
+
export function detectHosts() {
|
|
137
|
+
return HOST_IDS.filter(isInstalled)
|
|
138
|
+
.map(hostOf)
|
|
139
|
+
.filter((h) => h !== null);
|
|
51
140
|
}
|
|
52
141
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
142
|
+
* 检测到了、但只能项目级安装的宿主(当前只有 Trae)。
|
|
143
|
+
*
|
|
144
|
+
* 单独拎出来是为了别把它们**静默**跳过:用户装了 Trae 却在全局 install 的输出里
|
|
145
|
+
* 完全看不到它,只会以为这个 CLI 不支持 —— 正是这次 WorkBuddy 的翻车方式。
|
|
55
146
|
*/
|
|
56
|
-
export function
|
|
57
|
-
return
|
|
147
|
+
export function projectOnlyHosts() {
|
|
148
|
+
return HOST_IDS.filter((id) => isInstalled(id) && !spec(id).userDirName);
|
|
58
149
|
}
|
|
59
150
|
function packageVersion() {
|
|
60
151
|
try {
|
|
@@ -91,9 +182,11 @@ function readReceipt(skillsDir) {
|
|
|
91
182
|
return null;
|
|
92
183
|
}
|
|
93
184
|
}
|
|
185
|
+
const nonNull = (h) => h !== null;
|
|
94
186
|
function parseArgs(argv, verb) {
|
|
95
187
|
const out = { hosts: [], force: false, help: false };
|
|
96
188
|
const picked = [];
|
|
189
|
+
let all = false;
|
|
97
190
|
let dir = '';
|
|
98
191
|
let project = false;
|
|
99
192
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -105,12 +198,14 @@ function parseArgs(argv, verb) {
|
|
|
105
198
|
switch (key) {
|
|
106
199
|
case '--host': {
|
|
107
200
|
const v = next();
|
|
201
|
+
// `all` 是「所有**适用**的宿主」,不是「表里每一行」—— 展开成后者会让
|
|
202
|
+
// `--host all` 撞上 Trae 这种只有项目级的宿主而整条命令失败。
|
|
108
203
|
if (v === 'all')
|
|
109
|
-
|
|
110
|
-
else if (v
|
|
204
|
+
all = true;
|
|
205
|
+
else if (HOST_IDS.includes(v))
|
|
111
206
|
picked.push(v);
|
|
112
207
|
else {
|
|
113
|
-
out.
|
|
208
|
+
out.error = `未知参数: --host ${v}`;
|
|
114
209
|
return out;
|
|
115
210
|
}
|
|
116
211
|
break;
|
|
@@ -129,35 +224,64 @@ function parseArgs(argv, verb) {
|
|
|
129
224
|
out.help = true;
|
|
130
225
|
return out;
|
|
131
226
|
default:
|
|
132
|
-
out.
|
|
227
|
+
out.error = `未知参数: ${a}`;
|
|
133
228
|
return out;
|
|
134
229
|
}
|
|
135
230
|
}
|
|
136
231
|
if (dir) {
|
|
137
232
|
out.hosts = [{ id: 'custom', label: '自定义目录', skillsDir: path.resolve(dir) }];
|
|
233
|
+
return out;
|
|
138
234
|
}
|
|
139
|
-
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
|
|
235
|
+
if (project) {
|
|
236
|
+
// Codex 的官方安装位置只有 $CODEX_HOME/skills(见其内置 skill-installer),
|
|
237
|
+
// 没有项目级约定,不臆造一个 —— 点名 --host codex --project 直接报错,
|
|
238
|
+
// 不声不响装到一个宿主永远不会读的目录才是最糟的。
|
|
239
|
+
const chosen = all
|
|
240
|
+
? HOST_IDS.filter((id) => spec(id).projectDirName)
|
|
241
|
+
: picked.length > 0
|
|
242
|
+
? [...new Set(picked)]
|
|
243
|
+
: HOST_IDS.filter((id) => isInstalled(id) && spec(id).projectDirName);
|
|
244
|
+
const unsupported = chosen.filter((id) => !spec(id).projectDirName);
|
|
245
|
+
if (unsupported.length > 0) {
|
|
246
|
+
out.error = `${unsupported.map((id) => spec(id).label).join('、')} 没有项目级 skill 目录,不能和 --project 一起用`;
|
|
247
|
+
return out;
|
|
248
|
+
}
|
|
249
|
+
out.hosts = chosen.map(projectHostOf).filter(nonNull);
|
|
250
|
+
return out;
|
|
251
|
+
}
|
|
252
|
+
if (all) {
|
|
253
|
+
out.hosts = HOST_IDS.map(hostOf).filter(nonNull);
|
|
254
|
+
return out;
|
|
143
255
|
}
|
|
144
|
-
|
|
145
|
-
|
|
256
|
+
if (picked.length > 0) {
|
|
257
|
+
const chosen = [...new Set(picked)];
|
|
258
|
+
// 点名了一个只有项目级的宿主(Trae)却没给 --project:报错而不是默默装到别处。
|
|
259
|
+
const userless = chosen.filter((id) => !spec(id).userDirName);
|
|
260
|
+
if (userless.length > 0) {
|
|
261
|
+
out.error =
|
|
262
|
+
`${userless.map((id) => spec(id).label).join('、')} 只有项目级 skill 目录 —— ` +
|
|
263
|
+
'进到项目根目录后加 --project 重跑。';
|
|
264
|
+
return out;
|
|
265
|
+
}
|
|
266
|
+
out.hosts = chosen.map(hostOf).filter(nonNull);
|
|
146
267
|
}
|
|
147
268
|
else {
|
|
148
|
-
|
|
269
|
+
// 卸载时不做检测:配置目录可能已经随 agent 一起被删掉,而我们铺出去的副本还在。
|
|
270
|
+
out.hosts = verb === UNINSTALL_VERB ? HOST_IDS.map(hostOf).filter(nonNull) : detectHosts();
|
|
149
271
|
}
|
|
150
272
|
return out;
|
|
151
273
|
}
|
|
152
274
|
export function installUsage() {
|
|
153
275
|
process.stdout.write('Usage: remixmate install [options]\n' +
|
|
154
276
|
'\n' +
|
|
155
|
-
'把本包自带的 skill 装进已检测到的 agent
|
|
156
|
-
'
|
|
277
|
+
'把本包自带的 skill 装进已检测到的 agent 宿主,让它们能自动发现这些能力。\n' +
|
|
278
|
+
'重复运行即升级。支持的宿主:\n' +
|
|
279
|
+
HOSTS.map((h) => ` ${padDisplay(h.label, 14)}${h.userDirName ? `~/${h.userDirName}/skills` : '(仅项目级)'}${h.projectDirName ? ` 项目级 ./${h.projectDirName}/skills` : ''}\n`).join('') +
|
|
157
280
|
'\n' +
|
|
158
281
|
'Options:\n' +
|
|
159
|
-
|
|
160
|
-
'
|
|
282
|
+
` --host <${HOST_IDS.join('|')}|all>\n` +
|
|
283
|
+
' 只装指定宿主(默认:装到所有检测到的宿主)\n' +
|
|
284
|
+
' --project 装到当前目录 ./<配置目录>/skills(Codex 不支持)\n' +
|
|
161
285
|
' --dir <path> 自定义 skills 父目录(覆盖上面两者)\n' +
|
|
162
286
|
' --force 覆盖同名的、非本 CLI 安装的 skill 目录\n');
|
|
163
287
|
}
|
|
@@ -167,7 +291,8 @@ export function uninstallUsage() {
|
|
|
167
291
|
'按装机回执删除本 CLI 装过的 skill —— 只删回执里列出的目录,不碰其它 skill。\n' +
|
|
168
292
|
'\n' +
|
|
169
293
|
'Options:\n' +
|
|
170
|
-
|
|
294
|
+
` --host <${HOST_IDS.join('|')}|all>\n` +
|
|
295
|
+
' 只卸载指定宿主(默认:所有宿主都查)\n' +
|
|
171
296
|
' --project 卸载当前目录 ./.claude/skills 下的安装\n' +
|
|
172
297
|
' --dir <path> 自定义 skills 父目录\n');
|
|
173
298
|
}
|
|
@@ -210,8 +335,8 @@ export function runInstall(argv) {
|
|
|
210
335
|
installUsage();
|
|
211
336
|
return EXIT.OK;
|
|
212
337
|
}
|
|
213
|
-
if (opts.
|
|
214
|
-
process.stderr.write(`❌
|
|
338
|
+
if (opts.error) {
|
|
339
|
+
process.stderr.write(`❌ ${opts.error}\n`);
|
|
215
340
|
installUsage();
|
|
216
341
|
return EXIT.USAGE;
|
|
217
342
|
}
|
|
@@ -220,10 +345,17 @@ export function runInstall(argv) {
|
|
|
220
345
|
process.stderr.write(`❌ 包内没有可安装的 skill(${SKILLS_DIR})\n`);
|
|
221
346
|
return EXIT.ERROR;
|
|
222
347
|
}
|
|
348
|
+
const projectOnly = projectOnlyHosts();
|
|
223
349
|
if (opts.hosts.length === 0) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
350
|
+
// 只检测到项目级宿主(比如只装了 Trae)时,这不是「没检测到」,而是「装法不同」。
|
|
351
|
+
if (projectOnly.length > 0) {
|
|
352
|
+
process.stderr.write(`❌ 只检测到 ${projectOnly.map((id) => spec(id).label).join('、')},` +
|
|
353
|
+
'它只有项目级 skill 目录。\n' +
|
|
354
|
+
' 进到项目根目录后运行:remixmate install --project\n');
|
|
355
|
+
return EXIT.USAGE;
|
|
356
|
+
}
|
|
357
|
+
process.stderr.write('❌ 没有检测到任何 agent 宿主。找过这些位置:\n' +
|
|
358
|
+
HOST_IDS.map((id) => ` ${padDisplay(spec(id).label, 14)}${detectDirs(id).join('、')}\n`).join('') +
|
|
227
359
|
' 先把 agent 装好再重跑,或用 --dir <path> 指定目录。\n');
|
|
228
360
|
return EXIT.USAGE;
|
|
229
361
|
}
|
|
@@ -240,6 +372,11 @@ export function runInstall(argv) {
|
|
|
240
372
|
}
|
|
241
373
|
if (failures > 0)
|
|
242
374
|
return EXIT.ERROR;
|
|
375
|
+
// 检测到了但这一轮装不了的宿主要说出来 —— 静默跳过会让用户以为不支持。
|
|
376
|
+
if (projectOnly.length > 0 && !opts.hosts.some((h) => projectOnly.includes(h.id))) {
|
|
377
|
+
process.stdout.write(`\nℹ️ 还检测到 ${projectOnly.map((id) => spec(id).label).join('、')},` +
|
|
378
|
+
'它只有项目级 skill 目录 —— 在项目根目录里运行 remixmate install --project 即可。\n');
|
|
379
|
+
}
|
|
243
380
|
process.stdout.write('\n重启 agent 后即可生效。升级后重跑 remixmate install 覆盖即可。\n');
|
|
244
381
|
return EXIT.OK;
|
|
245
382
|
}
|
|
@@ -249,8 +386,8 @@ export function runUninstall(argv) {
|
|
|
249
386
|
uninstallUsage();
|
|
250
387
|
return EXIT.OK;
|
|
251
388
|
}
|
|
252
|
-
if (opts.
|
|
253
|
-
process.stderr.write(`❌
|
|
389
|
+
if (opts.error) {
|
|
390
|
+
process.stderr.write(`❌ ${opts.error}\n`);
|
|
254
391
|
uninstallUsage();
|
|
255
392
|
return EXIT.USAGE;
|
|
256
393
|
}
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remixmate/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.23",
|
|
4
4
|
"description": "AI media generation skills for Claude Code / Codex — 12 skills covering image, video, voice, digital human, web screenshot, web recording, script, template registry, rendering, Jianying export, and video deconstruction.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|