skills-manifest 0.3.0 → 0.3.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.
@@ -0,0 +1,32 @@
1
+ import fs from "node:fs/promises";
2
+ import { loadConfig } from "c12";
3
+ import { defineCommand } from "citty";
4
+
5
+ //#region src/cli/add.ts
6
+ const add = defineCommand({
7
+ meta: {
8
+ name: "add",
9
+ description: "Add repo and skills to manifest"
10
+ },
11
+ args: { repo: {
12
+ type: "positional",
13
+ description: "Repository (e.g. owner/repo or full URL)",
14
+ required: true
15
+ } },
16
+ async run({ args }) {
17
+ const { config, configFile } = await loadConfig({ configFile: "skills-manifest" });
18
+ if (!configFile) throw new Error("skills-manifest.json not found. Run `skills-manifest init` first.");
19
+ const repo = args.repo;
20
+ const skills = (args._ ?? []).slice(1);
21
+ const existing = config.skills[repo];
22
+ const existingList = Array.isArray(existing) ? existing : typeof existing === "object" && existing !== null ? Object.keys(existing).filter((k) => existing[k]) : [];
23
+ const skillsToAdd = [...new Set([...existingList, ...skills])];
24
+ config.skills[repo] = skillsToAdd;
25
+ const content = JSON.stringify(config, null, 2);
26
+ await fs.writeFile(configFile, content);
27
+ console.log(`Added ${repo} to skills-manifest.json`);
28
+ }
29
+ });
30
+
31
+ //#endregion
32
+ export { add as t };
@@ -0,0 +1,12 @@
1
+ import * as citty0 from "citty";
2
+
3
+ //#region src/cli/add.d.ts
4
+ declare const add: citty0.CommandDef<{
5
+ readonly repo: {
6
+ readonly type: "positional";
7
+ readonly description: "Repository (e.g. owner/repo or full URL)";
8
+ readonly required: true;
9
+ };
10
+ }>;
11
+ //#endregion
12
+ export { add };
@@ -0,0 +1,3 @@
1
+ import { t as add } from "../add-CmzBK4br.mjs";
2
+
3
+ export { add };
@@ -1,186 +1,15 @@
1
- import { createRequire } from "node:module";
2
- import fs from "node:fs/promises";
3
- import path from "node:path";
4
- import process from "node:process";
5
- import { loadConfig } from "c12";
1
+ import { t as add } from "../add-CmzBK4br.mjs";
2
+ import { t as init } from "../init-4enI_4o6.mjs";
3
+ import { t as install } from "../install-CmdQl0XL.mjs";
4
+ import { t as remove } from "../remove-ByCBLakw.mjs";
5
+ import { t as sync } from "../sync-1OE33hei.mjs";
6
6
  import { defineCommand, runMain } from "citty";
7
- import { addDevDependency, installDependencies } from "nypm";
8
- import { x } from "tinyexec";
9
7
 
10
8
  //#region package.json
11
- var version = "0.3.0";
9
+ var version = "0.3.2";
12
10
 
13
11
  //#endregion
14
12
  //#region src/cli/index.ts
15
- const require = createRequire(import.meta.url);
16
- async function patchSkillsCli() {
17
- const cwd = process.cwd();
18
- const cliPath = path.join(cwd, "node_modules", "skills", "bin", "cli.mjs");
19
- try {
20
- if (!(await fs.stat(cliPath)).isFile()) return;
21
- } catch {
22
- return;
23
- }
24
- if ((await fs.readFile(cliPath, "utf-8").catch(() => "")).includes("Injected by skills-manifest")) return;
25
- let wrapperPath;
26
- try {
27
- const pkgJsonPath = require.resolve("skills-manifest/package.json");
28
- wrapperPath = path.join(path.dirname(pkgJsonPath), "patches", "skills-cli.mjs");
29
- } catch {
30
- return;
31
- }
32
- try {
33
- const wrapper = await fs.readFile(wrapperPath, "utf-8");
34
- await fs.writeFile(cliPath, wrapper, "utf-8");
35
- } catch {
36
- console.warn("skills-manifest: failed to inject wrapper. Sync add/remove with manifest will not run.");
37
- }
38
- }
39
- const DEFAULT_MANIFEST = {
40
- agents: ["cursor", "claude-code"],
41
- skills: {}
42
- };
43
- const init = defineCommand({
44
- meta: {
45
- name: "init",
46
- description: "Initialize skills configuration"
47
- },
48
- async run() {
49
- const cwd = process.cwd();
50
- await addDevDependency(["skills", "skills-manifest"], { cwd });
51
- await installDependencies({ cwd });
52
- await patchSkillsCli();
53
- const manifestPath = path.join(cwd, "skills-manifest.json");
54
- if (!await fs.stat(manifestPath).catch(() => null)) {
55
- const content = {
56
- $schema: "https://raw.githubusercontent.com/hairyf/skills-manifest/main/skills-manifest.schema.json",
57
- ...DEFAULT_MANIFEST
58
- };
59
- await fs.writeFile(manifestPath, JSON.stringify(content, null, 2));
60
- }
61
- const gitignorePath = path.join(cwd, ".gitignore");
62
- const gitignore = await fs.readFile(gitignorePath, "utf-8").catch(() => "");
63
- if (!gitignore.split("\n").includes("skills")) await fs.appendFile(gitignorePath, gitignore.endsWith("\n") ? "skills\n" : "\nskills\n");
64
- const pkgPath = path.join(cwd, "package.json");
65
- const pkg = JSON.parse(await fs.readFile(pkgPath, "utf-8"));
66
- const prepare = pkg.scripts?.prepare;
67
- const cmd = "skills-manifest install";
68
- if (!prepare) pkg.scripts = {
69
- ...pkg.scripts,
70
- prepare: cmd
71
- };
72
- else if (!prepare.includes(cmd)) pkg.scripts.prepare = `${prepare} && ${cmd}`;
73
- await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2));
74
- }
75
- });
76
- const add = defineCommand({
77
- meta: {
78
- name: "add",
79
- description: "Add repo and skills to manifest"
80
- },
81
- args: { repo: {
82
- type: "positional",
83
- description: "Repository (e.g. owner/repo or full URL)",
84
- required: true
85
- } },
86
- async run({ args }) {
87
- const { config, configFile } = await loadConfig({ configFile: "skills-manifest" });
88
- if (!configFile) throw new Error("skills-manifest.json not found. Run `skills-manifest init` first.");
89
- const repo = args.repo;
90
- const skills = (args._ ?? []).slice(1);
91
- const existing = config.skills[repo];
92
- const existingList = Array.isArray(existing) ? existing : typeof existing === "object" && existing !== null ? Object.keys(existing).filter((k) => existing[k]) : [];
93
- const skillsToAdd = [...new Set([...existingList, ...skills])];
94
- config.skills[repo] = skillsToAdd;
95
- const content = JSON.stringify(config, null, 2);
96
- await fs.writeFile(configFile, content);
97
- console.log(`Added ${repo} to skills-manifest.json`);
98
- }
99
- });
100
- const remove = defineCommand({
101
- meta: {
102
- name: "remove",
103
- description: "Remove repo or skills from manifest"
104
- },
105
- args: { repo: {
106
- type: "positional",
107
- description: "Repository (e.g. owner/repo or full URL)",
108
- required: true
109
- } },
110
- async run({ args }) {
111
- const { config, configFile } = await loadConfig({ configFile: "skills-manifest" });
112
- if (!configFile) throw new Error("skills-manifest.json not found. Run `skills-manifest init` first.");
113
- const repo = args.repo;
114
- const skillsToRemove = (args._ ?? []).slice(1);
115
- if (!(repo in config.skills)) throw new Error(`Repo ${repo} not found in manifest`);
116
- if (skillsToRemove.length === 0) {
117
- delete config.skills[repo];
118
- console.log(`Removed ${repo} from skills-manifest.json`);
119
- } else {
120
- const existing = config.skills[repo];
121
- const skillsToKeep = (Array.isArray(existing) ? existing : typeof existing === "object" && existing !== null ? Object.keys(existing).filter((k) => existing[k]) : []).filter((s) => !skillsToRemove.includes(s));
122
- if (skillsToKeep.length === 0) {
123
- delete config.skills[repo];
124
- console.log(`Removed ${repo} from skills-manifest.json`);
125
- } else {
126
- config.skills[repo] = skillsToKeep;
127
- console.log(`Removed skills from ${repo} in skills-manifest.json`);
128
- }
129
- }
130
- const content = JSON.stringify(config, null, 2);
131
- await fs.writeFile(configFile, content);
132
- }
133
- });
134
- const install = defineCommand({
135
- meta: {
136
- name: "install",
137
- description: "Install skills"
138
- },
139
- async run() {
140
- const { config } = await loadConfig({ configFile: "skills-manifest" });
141
- const repos = Object.keys(config.skills);
142
- for (const repo of repos) {
143
- if (typeof config.skills[repo] === "boolean") {
144
- await x("skills", [
145
- "add",
146
- repo,
147
- "--agent",
148
- ...config.agents,
149
- "--all",
150
- "--yes"
151
- ], { nodeOptions: { stdio: "inherit" } });
152
- continue;
153
- }
154
- await x("skills", [
155
- "add",
156
- repo,
157
- "--skill",
158
- ...Array.isArray(config.skills[repo]) ? config.skills[repo] : Object.keys(config.skills[repo]).filter((skill) => config.skills[repo][skill] === true),
159
- "--agent",
160
- ...config.agents,
161
- "--yes"
162
- ], { nodeOptions: { stdio: "inherit" } });
163
- }
164
- const TARGET_MAP = {
165
- cursor: ".cursor",
166
- opencode: ".opencode"
167
- };
168
- const agents = path.join(process.cwd(), ".agents");
169
- const fixedAgents = config.agents.filter((a) => a in TARGET_MAP);
170
- for (const agent of fixedAgents) {
171
- const dest = path.join(process.cwd(), TARGET_MAP[agent]);
172
- await fs.rm(dest, {
173
- recursive: true,
174
- force: true
175
- });
176
- await fs.cp(agents, dest, {
177
- recursive: true,
178
- verbatimSymlinks: false
179
- });
180
- }
181
- await patchSkillsCli();
182
- }
183
- });
184
13
  runMain(defineCommand({
185
14
  meta: {
186
15
  name: "skills-manifest",
@@ -191,7 +20,8 @@ runMain(defineCommand({
191
20
  add,
192
21
  init,
193
22
  install,
194
- remove
23
+ remove,
24
+ sync
195
25
  }
196
26
  }));
197
27
 
@@ -0,0 +1,6 @@
1
+ import * as citty2 from "citty";
2
+
3
+ //#region src/cli/init.d.ts
4
+ declare const init: citty2.CommandDef<citty2.ArgsDef>;
5
+ //#endregion
6
+ export { init };
@@ -0,0 +1,3 @@
1
+ import { t as init } from "../init-4enI_4o6.mjs";
2
+
3
+ export { init };
@@ -0,0 +1,6 @@
1
+ import * as citty5 from "citty";
2
+
3
+ //#region src/cli/install.d.ts
4
+ declare const install: citty5.CommandDef<citty5.ArgsDef>;
5
+ //#endregion
6
+ export { install };
@@ -0,0 +1,3 @@
1
+ import { t as install } from "../install-CmdQl0XL.mjs";
2
+
3
+ export { install };
@@ -0,0 +1,5 @@
1
+ //#region src/cli/patch.d.ts
2
+ /** Replace node_modules/skills/bin/cli.mjs with wrapper (add/remove sync with skills-manifest.json, add --skip-manifest) */
3
+ declare function patchSkillsCli(): Promise<void>;
4
+ //#endregion
5
+ export { patchSkillsCli };
@@ -0,0 +1,3 @@
1
+ import { t as patchSkillsCli } from "../patch-C3hgBcHP.mjs";
2
+
3
+ export { patchSkillsCli };
@@ -0,0 +1,12 @@
1
+ import * as citty4 from "citty";
2
+
3
+ //#region src/cli/remove.d.ts
4
+ declare const remove: citty4.CommandDef<{
5
+ readonly repo: {
6
+ readonly type: "positional";
7
+ readonly description: "Repository (e.g. owner/repo or full URL)";
8
+ readonly required: true;
9
+ };
10
+ }>;
11
+ //#endregion
12
+ export { remove };
@@ -0,0 +1,3 @@
1
+ import { t as remove } from "../remove-ByCBLakw.mjs";
2
+
3
+ export { remove };
@@ -0,0 +1,6 @@
1
+ import * as citty0 from "citty";
2
+
3
+ //#region src/cli/sync.d.ts
4
+ declare const sync: citty0.CommandDef<citty0.ArgsDef>;
5
+ //#endregion
6
+ export { sync };
@@ -0,0 +1,3 @@
1
+ import { t as sync } from "../sync-1OE33hei.mjs";
2
+
3
+ export { sync };
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as Skills, r as SkillsManifest, t as Repo } from "./index-OGqMIJuf.mjs";
1
+ import { n as Skills, r as SkillsManifest, t as Repo } from "./index-DeyN5X2A.mjs";
2
2
  export { Repo, Skills, SkillsManifest };
@@ -0,0 +1,48 @@
1
+ import { t as patchSkillsCli } from "./patch-C3hgBcHP.mjs";
2
+ import fs from "node:fs/promises";
3
+ import { defineCommand } from "citty";
4
+ import path from "node:path";
5
+ import process from "node:process";
6
+ import { addDevDependency, installDependencies } from "nypm";
7
+
8
+ //#region src/cli/init.ts
9
+ const DEFAULT_MANIFEST = {
10
+ agents: ["cursor", "claude-code"],
11
+ skills: {}
12
+ };
13
+ const init = defineCommand({
14
+ meta: {
15
+ name: "init",
16
+ description: "Initialize skills configuration"
17
+ },
18
+ async run() {
19
+ const cwd = process.cwd();
20
+ await addDevDependency(["skills", "skills-manifest"], { cwd });
21
+ await installDependencies({ cwd });
22
+ await patchSkillsCli();
23
+ const manifestPath = path.join(cwd, "skills-manifest.json");
24
+ if (!await fs.stat(manifestPath).catch(() => null)) {
25
+ const content = {
26
+ $schema: "https://raw.githubusercontent.com/hairyf/skills-manifest/main/skills-manifest.schema.json",
27
+ ...DEFAULT_MANIFEST
28
+ };
29
+ await fs.writeFile(manifestPath, JSON.stringify(content, null, 2));
30
+ }
31
+ const gitignorePath = path.join(cwd, ".gitignore");
32
+ const gitignore = await fs.readFile(gitignorePath, "utf-8").catch(() => "");
33
+ if (!gitignore.split("\n").includes("skills")) await fs.appendFile(gitignorePath, gitignore.endsWith("\n") ? "skills\n" : "\nskills\n");
34
+ const pkgPath = path.join(cwd, "package.json");
35
+ const pkg = JSON.parse(await fs.readFile(pkgPath, "utf-8"));
36
+ const prepare = pkg.scripts?.prepare;
37
+ const cmd = "skills-manifest install";
38
+ if (!prepare) pkg.scripts = {
39
+ ...pkg.scripts,
40
+ prepare: cmd
41
+ };
42
+ else if (!prepare.includes(cmd)) pkg.scripts.prepare = `${prepare} && ${cmd}`;
43
+ await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2));
44
+ }
45
+ });
46
+
47
+ //#endregion
48
+ export { init as t };
@@ -0,0 +1,62 @@
1
+ import { t as patchSkillsCli } from "./patch-C3hgBcHP.mjs";
2
+ import fs from "node:fs/promises";
3
+ import { loadConfig } from "c12";
4
+ import { defineCommand } from "citty";
5
+ import path from "node:path";
6
+ import process from "node:process";
7
+ import { x } from "tinyexec";
8
+
9
+ //#region src/cli/install.ts
10
+ const TARGET_MAP = {
11
+ cursor: ".cursor",
12
+ opencode: ".opencode"
13
+ };
14
+ const install = defineCommand({
15
+ meta: {
16
+ name: "install",
17
+ description: "Install skills"
18
+ },
19
+ async run() {
20
+ const { config } = await loadConfig({ configFile: "skills-manifest" });
21
+ const repos = Object.keys(config.skills);
22
+ for (const repo of repos) {
23
+ if (typeof config.skills[repo] === "boolean") {
24
+ await x("skills", [
25
+ "add",
26
+ repo,
27
+ "--agent",
28
+ ...config.agents,
29
+ "--all",
30
+ "--yes"
31
+ ], { nodeOptions: { stdio: "inherit" } });
32
+ continue;
33
+ }
34
+ await x("skills", [
35
+ "add",
36
+ repo,
37
+ "--skill",
38
+ ...Array.isArray(config.skills[repo]) ? config.skills[repo] : Object.keys(config.skills[repo]).filter((skill) => config.skills[repo][skill] === true),
39
+ "--agent",
40
+ ...config.agents,
41
+ "--yes"
42
+ ], { nodeOptions: { stdio: "inherit" } });
43
+ }
44
+ const agents = path.join(process.cwd(), ".agents");
45
+ const fixedAgents = config.agents.filter((a) => a in TARGET_MAP);
46
+ for (const agent of fixedAgents) {
47
+ const dest = path.join(process.cwd(), TARGET_MAP[agent]);
48
+ await fs.rm(dest, {
49
+ recursive: true,
50
+ force: true
51
+ });
52
+ await fs.cp(agents, dest, {
53
+ recursive: true,
54
+ verbatimSymlinks: false
55
+ });
56
+ }
57
+ await patchSkillsCli();
58
+ }
59
+ });
60
+
61
+ //#endregion
62
+ export { install as t };
@@ -0,0 +1,34 @@
1
+ import { createRequire } from "node:module";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import process from "node:process";
5
+
6
+ //#region src/cli/patch.ts
7
+ const require = createRequire(import.meta.url);
8
+ /** Replace node_modules/skills/bin/cli.mjs with wrapper (add/remove sync with skills-manifest.json, add --skip-manifest) */
9
+ async function patchSkillsCli() {
10
+ const cwd = process.cwd();
11
+ const cliPath = path.join(cwd, "node_modules", "skills", "bin", "cli.mjs");
12
+ try {
13
+ if (!(await fs.stat(cliPath)).isFile()) return;
14
+ } catch {
15
+ return;
16
+ }
17
+ if ((await fs.readFile(cliPath, "utf-8").catch(() => "")).includes("Injected by skills-manifest")) return;
18
+ let wrapperPath;
19
+ try {
20
+ const pkgJsonPath = require.resolve("skills-manifest/package.json");
21
+ wrapperPath = path.join(path.dirname(pkgJsonPath), "patches", "skills-cli.mjs");
22
+ } catch {
23
+ return;
24
+ }
25
+ try {
26
+ const wrapper = await fs.readFile(wrapperPath, "utf-8");
27
+ await fs.writeFile(cliPath, wrapper, "utf-8");
28
+ } catch {
29
+ console.warn("skills-manifest: failed to inject wrapper. Sync add/remove with manifest will not run.");
30
+ }
31
+ }
32
+
33
+ //#endregion
34
+ export { patchSkillsCli as t };
@@ -0,0 +1,42 @@
1
+ import fs from "node:fs/promises";
2
+ import { loadConfig } from "c12";
3
+ import { defineCommand } from "citty";
4
+
5
+ //#region src/cli/remove.ts
6
+ const remove = defineCommand({
7
+ meta: {
8
+ name: "remove",
9
+ description: "Remove repo or skills from manifest"
10
+ },
11
+ args: { repo: {
12
+ type: "positional",
13
+ description: "Repository (e.g. owner/repo or full URL)",
14
+ required: true
15
+ } },
16
+ async run({ args }) {
17
+ const { config, configFile } = await loadConfig({ configFile: "skills-manifest" });
18
+ if (!configFile) throw new Error("skills-manifest.json not found. Run `skills-manifest init` first.");
19
+ const repo = args.repo;
20
+ const skillsToRemove = (args._ ?? []).slice(1);
21
+ if (!(repo in config.skills)) throw new Error(`Repo ${repo} not found in manifest`);
22
+ if (skillsToRemove.length === 0) {
23
+ delete config.skills[repo];
24
+ console.log(`Removed ${repo} from skills-manifest.json`);
25
+ } else {
26
+ const existing = config.skills[repo];
27
+ const skillsToKeep = (Array.isArray(existing) ? existing : typeof existing === "object" && existing !== null ? Object.keys(existing).filter((k) => existing[k]) : []).filter((s) => !skillsToRemove.includes(s));
28
+ if (skillsToKeep.length === 0) {
29
+ delete config.skills[repo];
30
+ console.log(`Removed ${repo} from skills-manifest.json`);
31
+ } else {
32
+ config.skills[repo] = skillsToKeep;
33
+ console.log(`Removed skills from ${repo} in skills-manifest.json`);
34
+ }
35
+ }
36
+ const content = JSON.stringify(config, null, 2);
37
+ await fs.writeFile(configFile, content);
38
+ }
39
+ });
40
+
41
+ //#endregion
42
+ export { remove as t };
@@ -0,0 +1,18 @@
1
+ import { t as syncFromSkills } from "./utils-m5dGqHGZ.mjs";
2
+ import { defineCommand } from "citty";
3
+ import process from "node:process";
4
+
5
+ //#region src/cli/sync.ts
6
+ const sync = defineCommand({
7
+ meta: {
8
+ name: "sync",
9
+ description: "Sync manifest from skills CLI argv (internal)"
10
+ },
11
+ async run() {
12
+ const idx = process.argv.indexOf("sync");
13
+ await syncFromSkills(idx < 0 ? [] : process.argv.slice(idx + 1));
14
+ }
15
+ });
16
+
17
+ //#endregion
18
+ export { sync as t };
@@ -1,2 +1,2 @@
1
- import { n as Skills, r as SkillsManifest, t as Repo } from "../index-OGqMIJuf.mjs";
1
+ import { n as Skills, r as SkillsManifest, t as Repo } from "../index-DeyN5X2A.mjs";
2
2
  export { Repo, Skills, SkillsManifest };
@@ -0,0 +1,8 @@
1
+ //#region src/utils/index.d.ts
2
+ interface SyncFromSkillsOptions {
3
+ cwd?: string;
4
+ }
5
+ /** Parse skills CLI-style argv and sync manifest (used by skills-cli patch). */
6
+ declare function syncFromSkills(argv: string[], options?: SyncFromSkillsOptions): Promise<void>;
7
+ //#endregion
8
+ export { SyncFromSkillsOptions, syncFromSkills };
@@ -0,0 +1,3 @@
1
+ import { t as syncFromSkills } from "../utils-m5dGqHGZ.mjs";
2
+
3
+ export { syncFromSkills };
@@ -0,0 +1,58 @@
1
+ import fs from "node:fs/promises";
2
+ import { loadConfig } from "c12";
3
+ import path from "node:path";
4
+ import process from "node:process";
5
+
6
+ //#region src/utils/index.ts
7
+ /** Parse skills CLI-style argv and sync manifest (used by skills-cli patch). */
8
+ async function syncFromSkills(argv, options = {}) {
9
+ const cmd = argv[0];
10
+ if (cmd !== "add" && cmd !== "remove") return;
11
+ const cwd = options.cwd ?? process.cwd();
12
+ const configPath = path.join(cwd, "skills-manifest.json");
13
+ try {
14
+ await fs.access(configPath);
15
+ } catch {
16
+ return;
17
+ }
18
+ const { config, configFile } = await loadConfig({
19
+ configFile: "skills-manifest",
20
+ cwd
21
+ });
22
+ if (!configFile) return;
23
+ if (cmd === "add") {
24
+ const rest = argv.slice(1);
25
+ let repo = "";
26
+ const skills = [];
27
+ for (let i = 0; i < rest.length; i++) {
28
+ if (rest[i] === "--skill" && rest[i + 1]) {
29
+ skills.push(rest[i + 1]);
30
+ i++;
31
+ continue;
32
+ }
33
+ if (!rest[i].startsWith("-") && !repo) {
34
+ repo = rest[i];
35
+ continue;
36
+ }
37
+ }
38
+ if (!repo) return;
39
+ const existing = config.skills[repo];
40
+ const existingList = Array.isArray(existing) ? existing : typeof existing === "object" && existing !== null ? Object.keys(existing).filter((k) => existing[k]) : [];
41
+ config.skills[repo] = [...new Set([...existingList, ...skills])];
42
+ } else {
43
+ const skillNames = argv.slice(1).filter((a) => !a.startsWith("-"));
44
+ if (skillNames.length === 0) return;
45
+ for (const [repo, list] of Object.entries(config.skills)) {
46
+ const arr = Array.isArray(list) ? list : typeof list === "object" && list !== null ? Object.keys(list).filter((k) => list[k]) : [];
47
+ const toRemove = skillNames.filter((s) => arr.includes(s));
48
+ if (toRemove.length === 0) continue;
49
+ const kept = arr.filter((s) => !toRemove.includes(s));
50
+ if (kept.length === 0) delete config.skills[repo];
51
+ else config.skills[repo] = kept;
52
+ }
53
+ }
54
+ await fs.writeFile(configFile, JSON.stringify(config, null, 2));
55
+ }
56
+
57
+ //#endregion
58
+ export { syncFromSkills as t };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "skills-manifest",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.3.2",
5
5
  "description": "A lightweight manifest manager for skills, enabling project-level skill synchronization and collaborative configuration.",
6
6
  "author": "Hairyf <wwu710632@gmail.com>",
7
7
  "license": "MIT",
@@ -32,7 +32,7 @@
32
32
  "patches"
33
33
  ],
34
34
  "peerDependencies": {
35
- "skills": "^1.2.0"
35
+ "skills": "^1.3.4"
36
36
  },
37
37
  "dependencies": {
38
38
  "c12": "^3.3.3",
@@ -50,7 +50,7 @@
50
50
  "lint-staged": "^16.2.7",
51
51
  "publint": "^0.3.16",
52
52
  "simple-git-hooks": "^2.13.1",
53
- "skills": "^1.2.0",
53
+ "skills": "^1.3.4",
54
54
  "tsdown": "^0.17.3",
55
55
  "tsx": "^4.21.0",
56
56
  "typescript": "^5.9.3",
@@ -58,7 +58,7 @@
58
58
  "vitest": "^4.0.15",
59
59
  "vitest-package-exports": "^0.1.1",
60
60
  "yaml": "^2.8.2",
61
- "skills-manifest": "0.3.0"
61
+ "skills-manifest": "0.3.2"
62
62
  },
63
63
  "simple-git-hooks": {
64
64
  "pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && npx lint-staged"
@@ -1,54 +1,22 @@
1
1
  #!/usr/bin/env node
2
- // Injected by skills-manifest install: sync add/remove with skills-manifest.json
3
- import { spawnSync } from 'node:child_process'
4
- import { existsSync, readFileSync } from 'node:fs'
5
- import { fileURLToPath } from 'node:url'
6
- import { dirname, join } from 'node:path'
2
+ import { enableCompileCache } from 'node:module';
3
+ import { spawnSync } from 'node:child_process';
4
+ import { createRequire } from 'node:module';
5
+ import { join, dirname } from 'node:path';
7
6
 
8
- const __dirname = dirname(fileURLToPath(import.meta.url))
9
- const originalCli = join(__dirname, '..', 'dist', 'cli.mjs')
10
- const cwd = process.cwd()
7
+ if (enableCompileCache)
8
+ try { enableCompileCache(); } catch {}
11
9
 
12
- function runSkillsManifest(args) {
13
- const inNodeModules = join(cwd, 'node_modules', 'skills-manifest', 'bin')
14
- const inCwd = join(cwd, 'bin')
15
- const binDir = existsSync(inNodeModules) ? inNodeModules : inCwd
16
- const entry = existsSync(join(binDir, 'index.dev.mjs')) ? join(binDir, 'index.dev.mjs') : join(binDir, 'index.mjs')
17
- if (!existsSync(entry)) return
18
- const r = spawnSync(process.execPath, [entry, ...args], { stdio: 'inherit', cwd })
19
- if (r.status !== 0) process.exit(r.status ?? 1)
20
- }
21
-
22
- const argv = process.argv.slice(2)
23
- const skipManifest = argv.includes('--skip-manifest')
24
- const forwardArgs = argv.filter(a => a !== '--skip-manifest')
25
- const cmd = forwardArgs[0]
10
+ const argv = process.argv.slice(2);
11
+ const skipManifest = argv.includes('--skip-manifest');
12
+ const forwardArgs = argv.filter(arg => arg !== '--skip-manifest');
13
+ const [cmd] = forwardArgs;
26
14
 
27
- const result = spawnSync(process.execPath, [originalCli, ...forwardArgs], { stdio: 'inherit', cwd })
28
- if (result.status !== 0) process.exit(result.status ?? 1)
29
-
30
- if (cmd === 'add' && !skipManifest) {
31
- const rest = forwardArgs.slice(1)
32
- let repo = ''
33
- const skills = []
34
- for (let i = 0; i < rest.length; i++) {
35
- if (rest[i] === '--skill' && rest[i + 1]) { skills.push(rest[i + 1]); i++; continue }
36
- if (!rest[i].startsWith('-') && !repo) { repo = rest[i]; continue }
37
- }
38
- if (repo) runSkillsManifest(['add', repo, ...skills])
39
- } else if (cmd === 'remove') {
40
- const rest = forwardArgs.slice(1)
41
- const skillNames = []
42
- for (const a of rest) { if (a.startsWith('-')) break; skillNames.push(a) }
43
- if (skillNames.length === 0) process.exit(0)
44
- const manifestPath = join(cwd, 'skills-manifest.json')
45
- if (!existsSync(manifestPath)) process.exit(0)
46
- const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'))
47
- const repos = manifest.skills || {}
48
- for (const [repo, list] of Object.entries(repos)) {
49
- const arr = Array.isArray(list) ? list : (typeof list === 'object' && list !== null ? Object.keys(list).filter(k => list[k]) : [])
50
- const toRemove = skillNames.filter(s => arr.includes(s))
51
- if (toRemove.length > 0) runSkillsManifest(['remove', repo, ...toRemove])
52
- }
15
+ if (!skipManifest && ['add', 'remove'].includes(cmd)) {
16
+ const require = createRequire(import.meta.url);
17
+ const manifestPkg = require.resolve('skills-manifest/package.json', { paths: [process.cwd()] });
18
+ const binPath = join(dirname(manifestPkg), 'bin/index.mjs');
19
+ spawnSync(process.execPath, [binPath, 'sync', ...forwardArgs], { stdio: 'inherit' });
53
20
  }
54
- process.exit(0)
21
+
22
+ await import('../dist/cli.mjs');