neo-skill 0.1.17 → 0.1.18

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
@@ -22,14 +22,17 @@ pip install neo-skill
22
22
  ### 命令行工具(安装后)
23
23
 
24
24
  ```bash
25
- # 初始化技能
26
- omni-skill init --ai claude
25
+ # 初始化技能(从 npm 包安装所有 skills)
26
+ omni-skill init --ai windsurf
27
27
 
28
- # 生成技能输出
29
- skill-creator generate skills/skill-name/skillspec.json
28
+ # 手动安装本地创建的 skill
29
+ omni-skill install ./skills/my-new-skill
30
30
 
31
- # 验证技能
32
- skill-creator validate skills/skill-name/skillspec.json
31
+ # 更新 npm 包并重新初始化
32
+ omni-skill update
33
+
34
+ # 查看帮助
35
+ omni-skill --help
33
36
  ```
34
37
 
35
38
  ### 直接运行 Python 模块(开发模式)
@@ -72,29 +75,46 @@ python -m skill_creator.cli validate skills/skill-name/skillspec.json
72
75
 
73
76
  ### 使用场景
74
77
 
75
- **初始化技能文件**
78
+ **1. 初始化技能(首次使用)**
76
79
  ```bash
77
80
  # 初始化指定 AI 助手的技能文件
78
- omni-skill init --ai claude
79
81
  omni-skill init --ai windsurf
82
+ omni-skill init --ai claude
80
83
  omni-skill init --ai all # 初始化所有支持的 AI 助手
81
-
82
- # 更新(基于上次 init 的配置)
83
- omni-skill update
84
84
  ```
85
85
 
86
- **生成和验证技能**
86
+ 这会:
87
+ - 从 npm 包同步 skills/ 和 .shared/ 到当前目录
88
+ - 为所有 skills 生成 AI 助手的输出文件(.windsurf, .claude, .cursor, .github)
89
+ - 保存初始化状态到 .neo-skill.json
90
+
91
+ **2. 使用 skill-creator 创建新 skill**
92
+
93
+ 在 IDE 中输入 `/skill-creator`(Windsurf)或使用其他 AI 助手的触发方式,按照对话式流程创建新 skill。
94
+
95
+ **3. 安装刚创建的 skill**
87
96
  ```bash
88
- # 生成技能输出
89
- skill-creator generate skills/skill-name/skillspec.json
97
+ # 安装单个 skill
98
+ omni-skill install ./skills/my-new-skill
90
99
 
91
- # 验证技能
92
- skill-creator validate skills/skill-name/skillspec.json
100
+ # 或安装整个 skills 目录
101
+ omni-skill install ./skills
102
+ ```
103
+
104
+ 这会:
105
+ - 复制 skill 到当前目录的 skills/ 文件夹
106
+ - 为该 skill 生成所有 AI 助手的输出文件
93
107
 
94
- # 打包 Claude 技能
95
- skill-creator package --target claude --skill skill-name
108
+ **4. 更新 npm 包**
109
+ ```bash
110
+ # 更新到最新版本并重新初始化
111
+ omni-skill update
96
112
  ```
97
113
 
114
+ 这会:
115
+ - 运行 `npm install neo-skill@latest`
116
+ - 重新执行 `omni-skill init`(使用保存的 AI 目标)
117
+
98
118
  **在其他项目中使用**
99
119
  将 neo-skill 仓库克隆到你的项目中(例如 `vendor/neo-skill/`),然后:
100
120
  1. 设置 PYTHONPATH:`export PYTHONPATH=$PWD/vendor/neo-skill/src:$PYTHONPATH`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo-skill",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "A multi-assistant skill generator (Claude/Windsurf/Cursor/GitHub Skills) driven by a canonical SkillSpec.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -10,3 +10,49 @@
10
10
  ## 约定
11
11
 
12
12
  - 同步规则与生成行为应保持确定性(同输入得到同输出)。
13
+
14
+ ## Commands
15
+
16
+ ### `omni-skill init --ai <target>`
17
+ Initialize skills for target AI assistants.
18
+
19
+ **Usage:**
20
+ ```bash
21
+ omni-skill init --ai windsurf
22
+ omni-skill init --ai claude
23
+ omni-skill init --ai all
24
+ ```
25
+
26
+ **What it does:**
27
+ 1. Syncs skills/ and .shared/ from npm package to current directory
28
+ 2. Installs all skills (generates outputs for all AI targets)
29
+ 3. Writes VERSION files for each AI target
30
+ 4. Saves init state to .neo-skill.json
31
+
32
+ ### `omni-skill install <path>`
33
+ Install skill(s) from a local directory.
34
+
35
+ **Usage:**
36
+ ```bash
37
+ # Install a single skill
38
+ omni-skill install ./skills/my-new-skill
39
+
40
+ # Install all skills from a directory
41
+ omni-skill install ./skills
42
+ ```
43
+
44
+ **What it does:**
45
+ 1. Copies skill(s) to current directory's skills/ folder
46
+ 2. Generates outputs for all AI targets (.windsurf, .claude, .cursor, .github)
47
+
48
+ ### `omni-skill update`
49
+ Update npm package and re-initialize skills.
50
+
51
+ **Usage:**
52
+ ```bash
53
+ omni-skill update
54
+ ```
55
+
56
+ **What it does:**
57
+ 1. Runs `npm install neo-skill@latest`
58
+ 2. Re-runs `omni-skill init` with saved AI targets
@@ -185,13 +185,53 @@ def _generate_outputs_best_effort(pkg_root: Path, cwd: Path) -> None:
185
185
  print("\nGenerating skill outputs from skillspec.json ...")
186
186
  for spec_path in specs:
187
187
  try:
188
- ns = argparse.Namespace(repo_root=str(cwd), spec=str(spec_path))
188
+ ns = argparse.Namespace(repo_root=str(cwd), spec=str(spec_path), all=True)
189
189
  cmd_generate(ns)
190
190
  except SystemExit as e:
191
191
  rel = spec_path.relative_to(cwd) if spec_path.is_relative_to(cwd) else spec_path
192
192
  print(f" Skipping generator for {rel} (exit {e.code})")
193
193
 
194
194
 
195
+ def _install_skills_from_dir(skills_dir: Path, cwd: Path) -> int:
196
+ """
197
+ Install skills from a directory (either from npm package or local path).
198
+ Generates outputs for all AI targets.
199
+ """
200
+ if not skills_dir.exists():
201
+ print(f"Skills directory not found: {skills_dir}")
202
+ return 1
203
+
204
+ specs = sorted(skills_dir.glob("*/skillspec.json"))
205
+ if not specs:
206
+ print(f"No skillspec.json found in: {skills_dir}")
207
+ return 1
208
+
209
+ print(f"\nInstalling {len(specs)} skill(s) from {skills_dir} ...")
210
+ for spec_path in specs:
211
+ skill_name = spec_path.parent.name
212
+ print(f" Installing skill: {skill_name}")
213
+
214
+ # Copy skill to cwd/skills if not already there
215
+ dest_skill_dir = cwd / "skills" / skill_name
216
+ if spec_path.parent.resolve() != dest_skill_dir.resolve():
217
+ dest_skill_dir.parent.mkdir(parents=True, exist_ok=True)
218
+ if dest_skill_dir.exists():
219
+ import shutil
220
+ shutil.rmtree(dest_skill_dir)
221
+ shutil.copytree(spec_path.parent, dest_skill_dir)
222
+ print(f" Copied to: {dest_skill_dir}")
223
+
224
+ # Generate outputs for all targets
225
+ try:
226
+ ns = argparse.Namespace(repo_root=str(cwd), spec=str(cwd / "skills" / skill_name / "skillspec.json"), all=True)
227
+ cmd_generate(ns)
228
+ print(f" Generated outputs for all targets")
229
+ except SystemExit as e:
230
+ print(f" Warning: Generator failed (exit {e.code})")
231
+
232
+ return 0
233
+
234
+
195
235
  def _handle_init(selected_ais: List[str], mode: str) -> int:
196
236
  pkg_root = _get_pkg_root()
197
237
  cwd = Path.cwd().resolve()
@@ -201,7 +241,12 @@ def _handle_init(selected_ais: List[str], mode: str) -> int:
201
241
  sync_pairs = _build_sync_pairs(effective_ais)
202
242
  print("Initializing skills in:", cwd)
203
243
  _perform_sync(pkg_root, cwd, sync_pairs)
204
- _generate_outputs_best_effort(pkg_root, cwd)
244
+
245
+ # Install all skills from npm package
246
+ pkg_skills_dir = pkg_root / "skills"
247
+ if pkg_skills_dir.exists():
248
+ _install_skills_from_dir(pkg_skills_dir, cwd)
249
+
205
250
  _write_version_files(cwd, effective_ais, version)
206
251
  print("\nDone! neo-skill initialized.")
207
252
 
@@ -222,11 +267,57 @@ def _cmd_init(args: argparse.Namespace) -> int:
222
267
  return _handle_init(resolved["selected"], "init")
223
268
 
224
269
 
270
+ def _cmd_install(args: argparse.Namespace) -> int:
271
+ """
272
+ Install skill(s) from a local directory.
273
+ Usage: omni-skill install <path-to-skill-or-skills-dir>
274
+ """
275
+ cwd = Path.cwd().resolve()
276
+ skill_path = Path(args.path).resolve()
277
+
278
+ if not skill_path.exists():
279
+ raise SystemExit(f"Path not found: {skill_path}")
280
+
281
+ # Check if it's a single skill directory (contains skillspec.json)
282
+ if (skill_path / "skillspec.json").exists():
283
+ # Single skill
284
+ temp_skills_dir = skill_path.parent
285
+ return _install_skills_from_dir(temp_skills_dir, cwd)
286
+
287
+ # Check if it's a skills directory (contains subdirs with skillspec.json)
288
+ elif skill_path.is_dir():
289
+ return _install_skills_from_dir(skill_path, cwd)
290
+
291
+ else:
292
+ raise SystemExit(f"Invalid path: {skill_path}. Must be a skill directory or skills directory.")
293
+
294
+
225
295
  def _cmd_update(args: argparse.Namespace) -> int:
296
+ """
297
+ Update npm package and re-initialize skills.
298
+ """
299
+ import subprocess
300
+
226
301
  cwd = Path.cwd().resolve()
227
302
  state = _read_init_state(cwd)
228
303
  if not state["ok"]:
229
304
  raise SystemExit(state["error"])
305
+
306
+ print("Updating neo-skill npm package...")
307
+ result = subprocess.run(
308
+ ["npm", "install", "neo-skill@latest"],
309
+ cwd=cwd,
310
+ capture_output=True,
311
+ text=True
312
+ )
313
+
314
+ if result.returncode != 0:
315
+ print(f"Warning: npm install failed: {result.stderr}")
316
+ print("Continuing with re-initialization...")
317
+ else:
318
+ print("Package updated successfully.")
319
+
320
+ print("\nRe-initializing skills...")
230
321
  return _handle_init(state["selected"], "update")
231
322
 
232
323
 
@@ -253,7 +344,11 @@ def build_parser() -> argparse.ArgumentParser:
253
344
  p_init.add_argument("--ai", action="append", help="Target AI (can be repeated)")
254
345
  p_init.set_defaults(func=_cmd_init)
255
346
 
256
- p_update = sub.add_parser("update", help="Update skills based on previous init state")
347
+ p_install = sub.add_parser("install", help="Install skill(s) from a local directory")
348
+ p_install.add_argument("path", help="Path to skill directory or skills directory")
349
+ p_install.set_defaults(func=_cmd_install)
350
+
351
+ p_update = sub.add_parser("update", help="Update npm package and re-initialize skills")
257
352
  p_update.set_defaults(func=_cmd_update)
258
353
 
259
354
  return p