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 +38 -18
- package/package.json +1 -1
- package/src/omni_skill/README.md +46 -0
- package/src/omni_skill/cli.py +98 -3
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
|
|
25
|
+
# 初始化技能(从 npm 包安装所有 skills)
|
|
26
|
+
omni-skill init --ai windsurf
|
|
27
27
|
|
|
28
|
-
#
|
|
29
|
-
skill
|
|
28
|
+
# 手动安装本地创建的 skill
|
|
29
|
+
omni-skill install ./skills/my-new-skill
|
|
30
30
|
|
|
31
|
-
#
|
|
32
|
-
skill
|
|
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
|
|
97
|
+
# 安装单个 skill
|
|
98
|
+
omni-skill install ./skills/my-new-skill
|
|
90
99
|
|
|
91
|
-
#
|
|
92
|
-
skill
|
|
100
|
+
# 或安装整个 skills 目录
|
|
101
|
+
omni-skill install ./skills
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
这会:
|
|
105
|
+
- 复制 skill 到当前目录的 skills/ 文件夹
|
|
106
|
+
- 为该 skill 生成所有 AI 助手的输出文件
|
|
93
107
|
|
|
94
|
-
|
|
95
|
-
|
|
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
package/src/omni_skill/README.md
CHANGED
|
@@ -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
|
package/src/omni_skill/cli.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|