@heihei0299/matt-skills 3.0.9 → 3.0.10

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 CHANGED
@@ -12,11 +12,11 @@ template/
12
12
  └── .pi/ pi prompts、docs 与项目自定义 skills 占位
13
13
  ```
14
14
 
15
- 共享 Skills 不作为 Template Snapshot 的持久化副本;`init`、`sync` 和 `install` 根据 distribution boundary 从 Workspace 的 canonical source 分发到目标项目的 `.agents/skills/`。
15
+ 共享 Skills 不作为 Template Snapshot 的持久化副本;`init`、普通 `sync` 和 `install` 从 Workspace 的 canonical source 分发到各工具的默认项目目录:Codex `.agents/skills/`、pi 为 `.pi/skills/`、opencode 为 `.opencode/skills/`、Claude 为 `.claude/skills/`。
16
16
 
17
17
  - `PROJECT.md` 描述项目是什么;操作规则放在 `AGENTS.md`。
18
18
  - `.opencode/CONTEXT.md` / `.pi/CONTEXT.md` 保存领域术语与边界。
19
- - `.opencode/skills/` `.pi/skills/` 仅用于项目自定义 skills。
19
+ - 各工具默认项目目录承载共享 skills;同步只处理可分发 skill 名称,不删除额外的项目自定义 skills。
20
20
  - `ci-guard`、`commit-check` 是本仓库维护用的 repo-local skills,不会分发到目标项目。
21
21
 
22
22
  ## 独有 skill 分发边界
@@ -73,13 +73,13 @@ npx @heihei0299/matt-skills check [--all] [--json] [--upstream <url>] [--ref <re
73
73
 
74
74
  - `--all`:包含全部可分发 skills,默认范围只包含 programming skills。
75
75
  - `--dest <dir>`:指定目标目录。
76
- - `--tools <list>`:选择 `codex`、`pi`、`opencode` 或 `claude`;项目级共享 skills 统一写入 `.agents/skills/`。
76
+ - `--tools <list>`:选择 `codex`、`pi`、`opencode` 或 `claude`;项目级 skills 写入所选工具的默认目录。
77
77
  - `--global`:写入用户级 skills 目录。
78
78
  - `--dry-run`:只检查差异,不写入;`--json` 输出机器可读结果。
79
79
 
80
80
  ## Codex CLI 支持
81
81
 
82
- Codex 与其他 harness 共用项目级 `.agents/skills/` 唯一共享源;全局 skills 位于 `~/.codex/skills`。
82
+ Codex 的项目级 skills 位于 `.agents/skills/`;全局 skills 位于 `~/.codex/skills`。`init` 和普通 `sync` 默认同时分发到四个工具的项目目录。
83
83
 
84
84
  ```sh
85
85
  npm run codex:smoke
package/bin/cli.js CHANGED
@@ -33,10 +33,12 @@ process.stdout.on('error', (err) => {
33
33
  throw err;
34
34
  });
35
35
 
36
+ const PROJECT_SKILL_DIRS = '.agents/skills、.pi/skills、.opencode/skills、.claude/skills';
37
+
36
38
  const HELP_GLOBAL = `matt-skills — install and manage this skill collection
37
39
 
38
40
  Usage:
39
- matt-skills init [options] Initialize a project: template + skills (.agents/skills)
41
+ matt-skills init [options] Initialize a project: template + skills (${PROJECT_SKILL_DIRS})
40
42
  matt-skills sync [--all|--dry-run] [--dest <path>] Sync existing project to latest template + skills
41
43
  matt-skills list [--all] [--json] List available skills and their descriptions
42
44
  matt-skills install [options] Install skills (interactive by default)
@@ -46,7 +48,7 @@ Usage:
46
48
  matt-skills --version | -v Show version
47
49
  `;
48
50
 
49
- const HELP_INIT = `matt-skills init [options] — Initialize a project: template + skills (.agents/skills)
51
+ const HELP_INIT = `matt-skills init [options] — Initialize a project: template + skills (${PROJECT_SKILL_DIRS})
50
52
 
51
53
  Usage:
52
54
  matt-skills init [options]
@@ -70,6 +72,7 @@ Sync options:
70
72
  --dry-run 预演:只比对不写盘
71
73
  --dest <path> Target directory (default: current directory)
72
74
  --help, -h Show this help
75
+ 项目 skills:${PROJECT_SKILL_DIRS}
73
76
 
74
77
  说明:默认不带 --all 增量同步默认 programming skill,并只更新 AGENTS.md 的 matt-skills 受管区块;没有受管标记的现有 AGENTS.md 原样保留。--all 时同步全部可分发 skill 并强制刷新 AGENTS.md。
75
78
 
@@ -110,7 +113,7 @@ Usage:
110
113
  matt-skills install [options]
111
114
 
112
115
  Install options:
113
- --tools <a,b> Install for the given tools (codex, pi, opencode, claude); skips tool selection — 共享技能统一指向 .agents/skills,.pi/skills/.opencode/skills 仅用于项目自定义
116
+ --tools <a,b> Install for the given tools (codex, pi, opencode, claude); skips tool selection
114
117
  --all Install all distributable skills (default only default programming); skips skill selection
115
118
  --force Overwrite existing skills
116
119
  --global Install to the user's global skill directories
@@ -217,15 +220,17 @@ async function syncManagedAgents(targetFile) {
217
220
 
218
221
  const TOOLS = ['codex', 'pi', 'opencode', 'claude'];
219
222
 
220
- // 统一源:共享技能全部在 .agents/skills,harness 的 .pi/skills/.opencode/skills 仅用于项目自定义
221
- // 为兼容历史,pi/opencode/claude 的项目安装仍解析但统一指向 .agents/skills,并给出提示
222
223
  const PROJECT_DIRS = {
223
224
  codex: '.agents/skills',
224
- pi: '.agents/skills',
225
- opencode: '.agents/skills',
226
- claude: '.agents/skills',
225
+ pi: '.pi/skills',
226
+ opencode: '.opencode/skills',
227
+ claude: '.claude/skills',
227
228
  };
228
229
 
230
+ function projectSkillTargets(target) {
231
+ return TOOLS.map((tool) => ({ tool, dir: path.resolve(target, PROJECT_DIRS[tool]) }));
232
+ }
233
+
229
234
  const GLOBAL_DIRS = {
230
235
  codex: '.codex/skills',
231
236
  pi: '.pi/agent/skills',
@@ -275,13 +280,8 @@ async function installCommand({ dest, all, force, tools, global }) {
275
280
  process.stdout.write('未选择任何工具,未安装任何技能\n');
276
281
  return;
277
282
  }
278
- // 共享技能统一源提示:pi/opencode 的项目目录已改为 .agents/skills
279
- const needsHint = selectedTools.some((t) => t === 'pi' || t === 'opencode');
280
- if (needsHint && !global) {
281
- process.stdout.write('提示:共享技能统一在 .agents/skills,.pi/skills/.opencode/skills 仅用于项目自定义技能\n');
282
- }
283
283
  targets = selectedTools.map((tool) => ({ tool, dir: toolDir(tool, global) }));
284
- // 去重:多个工具可能映射到同一目录(如 pi/opencode/codex 都指向 .agents/skills),合并去重避免重复计数
284
+ // 去重:保留对自定义 PROJECT_DIRS 映射的兼容。
285
285
  const seen = new Map();
286
286
  for (const t of targets) {
287
287
  if (!seen.has(t.dir)) seen.set(t.dir, t);
@@ -330,15 +330,16 @@ async function initCommand({ dest, all }) {
330
330
  filter: shouldCopyTemplatePath,
331
331
  });
332
332
  const selectedSkills = await listSkillNames({ onlyProgramming });
333
- const skillsDir = path.join(target, '.agents', 'skills');
334
- await mkdir(skillsDir, { recursive: true });
335
- for (const name of selectedSkills) {
336
- const source = path.join(SKILLS_DIR, name);
337
- const destination = path.join(skillsDir, name);
338
- if (path.resolve(source) === path.resolve(destination)) continue;
339
- await cp(source, destination, { recursive: true, force: true });
333
+ for (const { dir } of projectSkillTargets(target)) {
334
+ await mkdir(dir, { recursive: true });
335
+ for (const name of selectedSkills) {
336
+ const source = path.join(SKILLS_DIR, name);
337
+ const destination = path.join(dir, name);
338
+ if (path.resolve(source) === path.resolve(destination)) continue;
339
+ await cp(source, destination, { recursive: true, force: true });
340
+ }
340
341
  }
341
- process.stdout.write('模板:已复制(AGENTS.md、.opencode/、.pi/)\n');
342
+ process.stdout.write(`模板:已复制(AGENTS.md、skills:${PROJECT_SKILL_DIRS})\n`);
342
343
  }
343
344
  // 统计(区分编程 vs 全量)
344
345
  const skillsDir = path.join(target, '.agents', 'skills');
@@ -407,7 +408,7 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
407
408
  force: true,
408
409
  filter: shouldCopyTemplatePath,
409
410
  });
410
- process.stdout.write('模板:已复制(AGENTS.md、.opencode/、.pi/)\n');
411
+ process.stdout.write(`模板:已复制(AGENTS.md、skills:${PROJECT_SKILL_DIRS})\n`);
411
412
  } else {
412
413
  process.stdout.write('同步:检测到现有项目,将增量更新\n');
413
414
  if (all) {
@@ -416,7 +417,7 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
416
417
  force: true,
417
418
  filter: shouldCopyTemplatePath,
418
419
  });
419
- process.stdout.write('模板:已同步(AGENTS.md 整体刷新、.opencode/、.pi/)\n');
420
+ process.stdout.write(`模板:已同步(AGENTS.md 整体刷新、skills:${PROJECT_SKILL_DIRS})\n`);
420
421
  } else {
421
422
  let agentsManaged = false;
422
423
  try {
@@ -425,26 +426,23 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
425
426
  await cp(path.join(TEMPLATE_DIR, '.opencode'), path.join(target, '.opencode'), { recursive: true, force: true });
426
427
  await cp(path.join(TEMPLATE_DIR, '.pi'), path.join(target, '.pi'), { recursive: true, force: true });
427
428
  if (agentsManaged) {
428
- process.stdout.write('模板:已同步(AGENTS.md 受管区块已更新,项目自定义内容已保留)\n');
429
+ process.stdout.write(`模板:已同步(AGENTS.md 受管区块已更新、skills:${PROJECT_SKILL_DIRS},项目自定义内容已保留)\n`);
429
430
  } else {
430
- process.stdout.write('模板:已同步(AGENTS.md 未受管,已原样保留)\n');
431
+ process.stdout.write(`模板:已同步(AGENTS.md 未受管、skills:${PROJECT_SKILL_DIRS},已原样保留)\n`);
431
432
  }
432
433
  }
433
434
  }
434
435
  // 技能同步:--all 仅更新同名可分发技能内容,存在则覆盖,不存在则新增,并更新 AGENTS.md(由上一步已处理);默认范围为默认 programming,不删多余
435
436
  const allSkills = await listSkillNames({ onlyProgramming });
436
- const skillsDir = path.join(target, '.agents', 'skills');
437
- await mkdir(skillsDir, { recursive: true });
437
+ const skillTargets = projectSkillTargets(target);
438
+ const skillsDir = path.resolve(target, PROJECT_DIRS.codex);
438
439
  const preservedRepoLocal = [];
439
- const preserveLocations = [
440
- {
441
- dir: skillsDir,
442
- label: '.agents/skills',
443
- isWorkspaceSource: path.resolve(skillsDir) === path.resolve(SKILLS_DIR),
444
- },
445
- { dir: path.join(target, '.pi', 'skills'), label: '.pi/skills', isWorkspaceSource: false },
446
- { dir: path.join(target, '.opencode', 'skills'), label: '.opencode/skills', isWorkspaceSource: false },
447
- ];
440
+ const preserveLocations = skillTargets.map(({ tool, dir }) => ({
441
+ dir,
442
+ label: PROJECT_DIRS[tool],
443
+ isWorkspaceSource: path.resolve(dir) === path.resolve(SKILLS_DIR),
444
+ }));
445
+ for (const { dir } of skillTargets) await mkdir(dir, { recursive: true });
448
446
  for (const name of REPO_LOCAL_SKILLS) {
449
447
  for (const location of preserveLocations) {
450
448
  if (!location.isWorkspaceSource && await pathExists(path.join(location.dir, name))) {
@@ -454,24 +452,26 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
454
452
  }
455
453
  let installed = 0;
456
454
  let updated = 0;
457
- for (const name of allSkills) {
458
- const src = path.join(SKILLS_DIR, name);
459
- const dst = path.join(skillsDir, name);
460
- if (path.resolve(src) === path.resolve(dst)) {
461
- updated++;
462
- continue;
463
- }
464
- const exists = await pathExists(dst);
465
- if (exists) {
466
- await rm(dst, { recursive: true, force: true });
467
- await cp(src, dst, { recursive: true, force: true });
468
- updated++;
469
- } else {
470
- await cp(src, dst, { recursive: true, force: true });
471
- installed++;
455
+ for (const { dir } of skillTargets) {
456
+ for (const name of allSkills) {
457
+ const src = path.join(SKILLS_DIR, name);
458
+ const dst = path.join(dir, name);
459
+ if (path.resolve(src) === path.resolve(dst)) {
460
+ if (path.resolve(dir) === skillsDir) updated++;
461
+ continue;
462
+ }
463
+ const exists = await pathExists(dst);
464
+ if (exists) {
465
+ await rm(dst, { recursive: true, force: true });
466
+ await cp(src, dst, { recursive: true, force: true });
467
+ if (path.resolve(dir) === skillsDir) updated++;
468
+ } else {
469
+ await cp(src, dst, { recursive: true, force: true });
470
+ if (path.resolve(dir) === skillsDir) installed++;
471
+ }
472
472
  }
473
473
  }
474
- // Harness skill directories may contain project-local Skills. Preserve them because
474
+ // Project skill directories may contain project-local Skills. Preserve them because
475
475
  // their origin cannot be distinguished safely from a historical shared mirror.
476
476
  // 清理过时的 .pi/settings.json 指向
477
477
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heihei0299/matt-skills",
3
- "version": "3.0.9",
3
+ "version": "3.0.10",
4
4
  "description": "Agent skills + 项目配置模板:一条命令初始化 opencode / pi-agent 项目(含 mattpocock/skills 上游技能)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,4 +1,4 @@
1
1
  # 项目技能(opencode)
2
2
 
3
- 此目录用于存放项目自定义技能(project-local skills)。
4
- 共享技能统一在 `.agents/skills/`。
3
+ 此目录用于存放项目 skills(共享或 project-local)。
4
+ 共享技能默认在 `.opencode/skills/`;同步不会删除额外的项目自定义 skills。
@@ -1,4 +1,4 @@
1
1
  # 项目技能(pi)
2
2
 
3
- 此目录用于存放项目自定义技能(project-local skills)。
4
- 共享技能统一在 `.agents/skills/`。
3
+ 此目录用于存放项目 skills(共享或 project-local)。
4
+ 共享技能默认在 `.pi/skills/`;同步不会删除额外的项目自定义 skills。