@softspark/ai-toolkit 4.5.1 → 4.7.0
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/AGENTS.md +50 -0
- package/CHANGELOG.md +46 -0
- package/README.md +13 -13
- package/app/.claude-plugin/plugin.json +1 -1
- package/benchmarks/ecosystem-doctor-snapshot.json +76 -54
- package/bin/ai-toolkit.js +2 -5
- package/kb/procedures/maintenance-sop.md +9 -8
- package/kb/procedures/release-preparation-sop.md +24 -16
- package/kb/procedures/release-verification-sop.md +4 -6
- package/kb/reference/architecture-overview.md +5 -6
- package/kb/reference/cli-reference.md +2 -3
- package/kb/reference/global-install-model.md +3 -3
- package/kb/reference/opencode-compatibility.md +2 -2
- package/kb/reference/supported-tools-registry.md +40 -33
- package/llms-full.txt +89 -77
- package/manifest.json +1 -1
- package/package.json +2 -3
- package/scripts/ecosystem_tools.json +74 -20
- package/scripts/generate_antigravity.py +32 -21
- package/scripts/generate_augment_agents.py +9 -10
- package/scripts/generate_augment_commands.py +4 -17
- package/scripts/generate_augment_hooks.py +7 -5
- package/scripts/generate_codex.py +28 -0
- package/scripts/generate_codex_hooks.py +23 -1
- package/scripts/generate_cursor_agents.py +13 -29
- package/scripts/generate_cursor_mdc.py +4 -3
- package/scripts/generate_opencode_commands.py +9 -9
- package/scripts/generate_windsurf_hooks.py +6 -0
- package/scripts/generate_windsurf_rules.py +39 -24
- package/scripts/generate_windsurf_skills.py +14 -4
- package/scripts/install.py +1 -1
- package/scripts/install_steps/ai_tools.py +68 -30
- package/scripts/plugin.py +2 -2
- package/scripts/validate.py +1 -0
- package/scripts/generate_codex_rules.py +0 -52
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"description": "Authoritative registry of tools ai-toolkit integrates with. Consumed by scripts/ecosystem_doctor.py to detect upstream doc/version drift.",
|
|
4
|
-
"last_updated": "2026-
|
|
4
|
+
"last_updated": "2026-06-10",
|
|
5
5
|
"tools": [
|
|
6
6
|
{
|
|
7
7
|
"id": "claude-code",
|
|
8
8
|
"display_name": "Claude Code",
|
|
9
9
|
"kind": "primary",
|
|
10
10
|
"urls": {
|
|
11
|
-
"docs": "https://
|
|
11
|
+
"docs": "https://code.claude.com/docs",
|
|
12
12
|
"release_notes": "https://github.com/anthropics/claude-code/releases",
|
|
13
|
-
"changelog":
|
|
13
|
+
"changelog": "https://code.claude.com/docs/en/changelog"
|
|
14
14
|
},
|
|
15
15
|
"config_paths": [
|
|
16
16
|
"~/.claude/settings.json",
|
|
17
|
+
".claude/settings.json",
|
|
17
18
|
".claude/settings.local.json",
|
|
18
19
|
"CLAUDE.md",
|
|
20
|
+
".claude/rules/*.md",
|
|
19
21
|
".claude/agents/*.md",
|
|
20
22
|
".claude/skills/*/SKILL.md",
|
|
21
23
|
"~/.claude/themes/*.json"
|
|
@@ -60,7 +62,8 @@
|
|
|
60
62
|
"hook handler: command",
|
|
61
63
|
"hook handler: prompt",
|
|
62
64
|
"hook handler: agent",
|
|
63
|
-
"hook handler: mcp_tool"
|
|
65
|
+
"hook handler: mcp_tool",
|
|
66
|
+
"hook handler: http"
|
|
64
67
|
],
|
|
65
68
|
"version_probe": {
|
|
66
69
|
"kind": "command",
|
|
@@ -79,7 +82,6 @@
|
|
|
79
82
|
"config_paths": [
|
|
80
83
|
".cursorrules",
|
|
81
84
|
".cursor/rules/*.mdc",
|
|
82
|
-
".cursor/rules/*.md",
|
|
83
85
|
"AGENTS.md",
|
|
84
86
|
".cursor/mcp.json",
|
|
85
87
|
"~/.cursor/mcp.json",
|
|
@@ -92,11 +94,18 @@
|
|
|
92
94
|
".codex/skills/*/SKILL.md",
|
|
93
95
|
"~/.codex/skills/*/SKILL.md",
|
|
94
96
|
".cursor/agents/*.md",
|
|
97
|
+
"~/.cursor/agents/*.md",
|
|
98
|
+
".claude/agents/*.md",
|
|
99
|
+
"~/.claude/agents/*.md",
|
|
100
|
+
".codex/agents/*.md",
|
|
101
|
+
"~/.codex/agents/*.md",
|
|
95
102
|
".cursor/hooks.json"
|
|
96
103
|
],
|
|
97
104
|
"our_generators": [
|
|
98
105
|
"scripts/generate_cursor_rules.py",
|
|
99
106
|
"scripts/generate_cursor_mdc.py",
|
|
107
|
+
"scripts/generate_cursor_hooks.py",
|
|
108
|
+
"scripts/generate_cursor_agents.py",
|
|
100
109
|
"scripts/generate_cursor_skills.py"
|
|
101
110
|
],
|
|
102
111
|
"capability_markers": [
|
|
@@ -118,11 +127,17 @@
|
|
|
118
127
|
"display_name": "Windsurf",
|
|
119
128
|
"kind": "editor",
|
|
120
129
|
"urls": {
|
|
121
|
-
"docs": "https://docs.
|
|
122
|
-
"release_notes": "https://
|
|
123
|
-
"changelog": "https://
|
|
130
|
+
"docs": "https://docs.devin.ai/desktop",
|
|
131
|
+
"release_notes": "https://docs.devin.ai/desktop/changelog",
|
|
132
|
+
"changelog": "https://docs.devin.ai/desktop/changelog"
|
|
124
133
|
},
|
|
125
134
|
"config_paths": [
|
|
135
|
+
".devin/rules/*.md",
|
|
136
|
+
".devin/workflows/*.md",
|
|
137
|
+
".devin/skills/*/SKILL.md",
|
|
138
|
+
".devin/config.json",
|
|
139
|
+
".devin/config.local.json",
|
|
140
|
+
"~/.config/devin/config.json",
|
|
126
141
|
".windsurfrules",
|
|
127
142
|
".windsurf/rules/*.md",
|
|
128
143
|
".windsurf/workflows/*.md",
|
|
@@ -136,8 +151,10 @@
|
|
|
136
151
|
"our_generators": [
|
|
137
152
|
"scripts/generate_windsurf.py",
|
|
138
153
|
"scripts/generate_windsurf_rules.py",
|
|
139
|
-
"scripts/generate_windsurf_skills.py"
|
|
154
|
+
"scripts/generate_windsurf_skills.py",
|
|
155
|
+
"scripts/generate_windsurf_hooks.py"
|
|
140
156
|
],
|
|
157
|
+
"status_note": "Windsurf rebranded to Devin Desktop on 2026-06-02. .devin/ is the primary read+write workspace tree; .windsurfrules, .windsurf/* and ~/.codeium/windsurf/* are legacy read-only fallbacks. Our generators dual-emit .devin/* + .windsurf/*. Cascade agent is available only through 2026-07-01 (Devin Local is the default agent since 2026-06-02); the .windsurf/hooks.json surface emitted by generate_windsurf_hooks.py is Cascade-scoped and dies with Cascade — migrate to the Devin CLI lifecycle-hooks surface (docs.devin.ai/cli/extensibility/hooks/*) before that date. Devin CLI ('Devin for Terminal', launched 2026-04-29) shares the Devin Local harness, reads AGENTS.md and the same SKILL.md standard; not yet tracked as a separate registry entry.",
|
|
141
158
|
"capability_markers": [
|
|
142
159
|
"Cascade",
|
|
143
160
|
"windsurfrules",
|
|
@@ -202,6 +219,7 @@
|
|
|
202
219
|
".gemini/skills/*/SKILL.md",
|
|
203
220
|
".agents/skills/*/SKILL.md",
|
|
204
221
|
"~/.gemini/skills/*/SKILL.md",
|
|
222
|
+
"~/.agents/skills/*/SKILL.md",
|
|
205
223
|
".gemini/extensions/gemini-extension.json"
|
|
206
224
|
],
|
|
207
225
|
"our_generators": [
|
|
@@ -214,17 +232,21 @@
|
|
|
214
232
|
"settings.json",
|
|
215
233
|
"BeforeTool",
|
|
216
234
|
"AfterTool",
|
|
235
|
+
"BeforeToolSelection",
|
|
217
236
|
"BeforeAgent",
|
|
218
237
|
"AfterAgent",
|
|
219
238
|
"BeforeModel",
|
|
239
|
+
"AfterModel",
|
|
240
|
+
"Notification",
|
|
241
|
+
"PreCompress",
|
|
220
242
|
"SessionStart",
|
|
221
243
|
"SessionEnd",
|
|
222
|
-
"Stop",
|
|
223
244
|
"SKILL.md",
|
|
224
245
|
"activate_skill",
|
|
225
246
|
"custom commands",
|
|
226
247
|
"gemini-extension.json"
|
|
227
248
|
],
|
|
249
|
+
"status_note": "Gemini CLI drops free + paid (AI Pro/Ultra) tiers on 2026-06-18 in favor of the new Antigravity CLI (we ship generate_antigravity.py); enterprise Gemini Code Assist Standard/Enterprise keeps full Gemini CLI support. The .gemini/* generators remain valid for the enterprise audience.",
|
|
228
250
|
"version_probe": {
|
|
229
251
|
"kind": "command",
|
|
230
252
|
"command": "gemini --version"
|
|
@@ -242,14 +264,21 @@
|
|
|
242
264
|
"config_paths": [
|
|
243
265
|
".clinerules/*.md",
|
|
244
266
|
".clinerules/workflows/*.md",
|
|
267
|
+
".clinerules/skills/*/SKILL.md",
|
|
268
|
+
".clinerules/hooks/",
|
|
245
269
|
".cline/rules/*.md",
|
|
246
270
|
".cline/hooks/",
|
|
271
|
+
".cline/plugins/",
|
|
247
272
|
".cline/skills/*/SKILL.md",
|
|
248
|
-
"~/.cline/rules
|
|
273
|
+
"~/.cline/rules/",
|
|
249
274
|
"~/.cline/hooks/",
|
|
275
|
+
"~/.cline/plugins/",
|
|
250
276
|
"~/.cline/skills/*/SKILL.md",
|
|
277
|
+
"~/Documents/Cline/Rules/Hooks/",
|
|
251
278
|
"~/.cline/data/settings/cline_mcp_settings.json",
|
|
252
|
-
".claude/skills/*/SKILL.md"
|
|
279
|
+
".claude/skills/*/SKILL.md",
|
|
280
|
+
"AGENTS.md",
|
|
281
|
+
"~/.agents/AGENTS.md"
|
|
253
282
|
],
|
|
254
283
|
"our_generators": [
|
|
255
284
|
"scripts/generate_cline.py",
|
|
@@ -266,7 +295,9 @@
|
|
|
266
295
|
"hooks",
|
|
267
296
|
"skills",
|
|
268
297
|
"subagents",
|
|
269
|
-
"conditional rules"
|
|
298
|
+
"conditional rules",
|
|
299
|
+
"AGENTS.md",
|
|
300
|
+
"plugins"
|
|
270
301
|
],
|
|
271
302
|
"version_probe": null
|
|
272
303
|
},
|
|
@@ -275,10 +306,12 @@
|
|
|
275
306
|
"display_name": "Roo Code",
|
|
276
307
|
"kind": "editor",
|
|
277
308
|
"urls": {
|
|
278
|
-
"docs": "https://
|
|
309
|
+
"docs": "https://roocodeinc.github.io/Roo-Code",
|
|
279
310
|
"release_notes": "https://github.com/RooCodeInc/Roo-Code/releases",
|
|
280
311
|
"changelog": null
|
|
281
312
|
},
|
|
313
|
+
"status": "archived",
|
|
314
|
+
"status_note": "Upstream RooCodeInc/Roo-Code repo archived/read-only as of 2026-05-15, frozen at v3.54.0; docs.roocode.com 301-redirects to roocodeinc.github.io/Roo-Code. A community fork reportedly continues maintenance. JSON .roomodes is NOT deprecated; both generators remain valid.",
|
|
282
315
|
"config_paths": [
|
|
283
316
|
".roomodes",
|
|
284
317
|
".roo/rules/*.md",
|
|
@@ -354,11 +387,16 @@
|
|
|
354
387
|
},
|
|
355
388
|
"config_paths": [
|
|
356
389
|
".augment/rules/*.md",
|
|
357
|
-
".augment
|
|
390
|
+
".augment-guidelines",
|
|
358
391
|
".augment/agents/*.md",
|
|
359
392
|
".augment/commands/*.md",
|
|
360
393
|
".augment/skills/*/SKILL.md",
|
|
394
|
+
".augment/settings.json",
|
|
395
|
+
".augment/settings.local.json",
|
|
396
|
+
".claude/skills/*/SKILL.md",
|
|
397
|
+
".agents/skills/*/SKILL.md",
|
|
361
398
|
"~/.augment/rules/*.md",
|
|
399
|
+
"~/.augment/user-guidelines.md",
|
|
362
400
|
"~/.augment/agents/*.md",
|
|
363
401
|
"~/.augment/commands/*.md",
|
|
364
402
|
"~/.augment/settings.json",
|
|
@@ -366,7 +404,11 @@
|
|
|
366
404
|
],
|
|
367
405
|
"our_generators": [
|
|
368
406
|
"scripts/generate_augment.py",
|
|
369
|
-
"scripts/generate_augment_rules.py"
|
|
407
|
+
"scripts/generate_augment_rules.py",
|
|
408
|
+
"scripts/generate_augment_agents.py",
|
|
409
|
+
"scripts/generate_augment_commands.py",
|
|
410
|
+
"scripts/generate_augment_skills.py",
|
|
411
|
+
"scripts/generate_augment_hooks.py"
|
|
370
412
|
],
|
|
371
413
|
"capability_markers": [
|
|
372
414
|
".augment",
|
|
@@ -385,6 +427,7 @@
|
|
|
385
427
|
"SessionStart",
|
|
386
428
|
"SessionEnd",
|
|
387
429
|
"Stop",
|
|
430
|
+
"Notification",
|
|
388
431
|
"ACP Mode"
|
|
389
432
|
],
|
|
390
433
|
"version_probe": null
|
|
@@ -399,6 +442,11 @@
|
|
|
399
442
|
"changelog": null
|
|
400
443
|
},
|
|
401
444
|
"config_paths": [
|
|
445
|
+
".agents/rules/*.md",
|
|
446
|
+
".agents/workflows/*.md",
|
|
447
|
+
".agents/skills/*/SKILL.md",
|
|
448
|
+
".agents/hooks.json",
|
|
449
|
+
".agents/mcp_config.json",
|
|
402
450
|
".agent/rules/*.md",
|
|
403
451
|
".agent/workflows/*.md",
|
|
404
452
|
".agent/skills/*/SKILL.md",
|
|
@@ -408,6 +456,7 @@
|
|
|
408
456
|
"our_generators": [
|
|
409
457
|
"scripts/generate_antigravity.py"
|
|
410
458
|
],
|
|
459
|
+
"status_note": "Antigravity CLI (GA 2026-05-19) reads workspace skills from .agents/skills/ (plural); the IDE still uses .agent/skills/ (singular) — our generator dual-emits the skill pointer to both. CLI hooks live in .agents/hooks.json with Claude-style event names (PreToolUse, not BeforeTool) and a JSON stdin/stdout decision contract. CLI MCP config is .agents/mcp_config.json with a required serverUrl field (url/httpUrl rejected silently); the GLOBAL MCP config path is reported inconsistently across sources (~/.gemini/antigravity-cli/ vs ~/.gemini/config/), so only the workspace path is registered until verified via agy inspect. Official docs are fully JS-rendered — the doctor is blind to them; verify changes manually each sync.",
|
|
411
460
|
"capability_markers": [
|
|
412
461
|
"Antigravity",
|
|
413
462
|
"agent manager",
|
|
@@ -416,6 +465,7 @@
|
|
|
416
465
|
"workflows",
|
|
417
466
|
"rules",
|
|
418
467
|
"skills",
|
|
468
|
+
"hooks",
|
|
419
469
|
"AGENTS.md",
|
|
420
470
|
"GEMINI.md",
|
|
421
471
|
"agent permissions"
|
|
@@ -427,20 +477,19 @@
|
|
|
427
477
|
"display_name": "Codex CLI",
|
|
428
478
|
"kind": "editor",
|
|
429
479
|
"urls": {
|
|
430
|
-
"docs": "https://
|
|
480
|
+
"docs": "https://developers.openai.com/codex",
|
|
431
481
|
"release_notes": "https://github.com/openai/codex/releases",
|
|
432
482
|
"changelog": null
|
|
433
483
|
},
|
|
434
484
|
"config_paths": [
|
|
435
485
|
"AGENTS.md",
|
|
436
|
-
".agents/rules/*.md",
|
|
437
486
|
".agents/skills/*/SKILL.md",
|
|
438
487
|
".codex/hooks.json",
|
|
488
|
+
".codex/config.toml",
|
|
439
489
|
"~/.codex/config.toml"
|
|
440
490
|
],
|
|
441
491
|
"our_generators": [
|
|
442
492
|
"scripts/generate_codex.py",
|
|
443
|
-
"scripts/generate_codex_rules.py",
|
|
444
493
|
"scripts/generate_codex_hooks.py",
|
|
445
494
|
"scripts/generate_codex_skills.py"
|
|
446
495
|
],
|
|
@@ -486,8 +535,13 @@
|
|
|
486
535
|
".opencode/plugins/*",
|
|
487
536
|
".opencode/skills/*/SKILL.md",
|
|
488
537
|
"AGENTS.md",
|
|
489
|
-
".claude/skills/*/SKILL.md"
|
|
538
|
+
".claude/skills/*/SKILL.md",
|
|
539
|
+
".agents/skills/*/SKILL.md",
|
|
540
|
+
"~/.config/opencode/skills/*/SKILL.md",
|
|
541
|
+
"~/.claude/skills/*/SKILL.md",
|
|
542
|
+
"~/.agents/skills/*/SKILL.md"
|
|
490
543
|
],
|
|
544
|
+
"status_note": "opencode v1.16.0 (2026-06-05) ships an experimental v2 skill registry with flat-file skills and a 'slash' frontmatter key; undocumented as of 2026-06-09. Watch item: re-check next sync whether the v2 format reaches the documented SKILL.md spec before touching generate_opencode*.py. Note sst/opencode redirects to anomalyco/opencode.",
|
|
491
545
|
"our_generators": [
|
|
492
546
|
"scripts/generate_opencode.py",
|
|
493
547
|
"scripts/generate_opencode_agents.py",
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Generate Antigravity IDE ``.
|
|
2
|
+
"""Generate Antigravity IDE ``.agents/rules/``, ``.agents/workflows/``, and
|
|
3
3
|
skill pointer files.
|
|
4
4
|
|
|
5
|
+
Antigravity 2.0 reads rules/workflows from the plural ``.agents/`` directory by
|
|
6
|
+
default; singular ``.agent/`` is still accepted as a backward-compatible
|
|
7
|
+
fallback (Antigravity checks plural first, then singular). We emit plural.
|
|
5
8
|
Antigravity reads rules from:
|
|
6
9
|
* ``GEMINI.md`` (highest priority) — generated by ``generate_gemini.py``
|
|
7
10
|
* ``AGENTS.md`` (cross-tool) — generated by ``generate_agents_md.py``
|
|
8
|
-
* ``.
|
|
9
|
-
* ``.
|
|
10
|
-
|
|
11
|
-
Antigravity also supports the Agent Skills standard
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
that teaches Antigravity to look up the real
|
|
16
|
-
``~/.softspark/ai-toolkit/app/skills/`` (global install) or
|
|
11
|
+
* ``.agents/rules/*.md`` — per-category rule files (this generator)
|
|
12
|
+
* ``.agents/workflows/*.md`` — workflow templates (this generator)
|
|
13
|
+
|
|
14
|
+
Antigravity also supports the Agent Skills standard. The IDE reads
|
|
15
|
+
``.agent/skills/<skill-name>/SKILL.md`` (singular), while the Antigravity CLI
|
|
16
|
+
(GA 2026-05-19) reads ``.agents/skills/`` (plural) — so the skill pointer is
|
|
17
|
+
dual-emitted to both. We do not duplicate our full skill catalogue; instead we
|
|
18
|
+
emit a single pointer skill that teaches Antigravity to look up the real
|
|
19
|
+
catalogue in ``~/.softspark/ai-toolkit/app/skills/`` (global install) or
|
|
17
20
|
``.claude/skills/`` (local install).
|
|
18
21
|
|
|
19
22
|
Usage:
|
|
20
23
|
python3 scripts/generate_antigravity.py [target-dir]
|
|
21
24
|
|
|
22
|
-
Writes
|
|
25
|
+
Writes rules/workflows to target-dir/.agents/{rules,workflows}/ and the skill
|
|
26
|
+
pointer to target-dir/.agent/skills/ (IDE) + target-dir/.agents/skills/ (CLI).
|
|
23
27
|
"""
|
|
24
28
|
from __future__ import annotations
|
|
25
29
|
|
|
@@ -78,11 +82,17 @@ def _pointer_skill_md() -> str:
|
|
|
78
82
|
|
|
79
83
|
|
|
80
84
|
def _write_skill_pointer(target_dir: Path) -> None:
|
|
81
|
-
"""Write the pointer SKILL.md
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
"""Write the pointer SKILL.md for both the IDE and the CLI surface.
|
|
86
|
+
|
|
87
|
+
The IDE reads ``.agent/skills/`` (singular); the Antigravity CLI reads
|
|
88
|
+
``.agents/skills/`` (plural).
|
|
89
|
+
"""
|
|
90
|
+
content = _pointer_skill_md()
|
|
91
|
+
for tree in (".agent", ".agents"):
|
|
92
|
+
skill_dir = target_dir / tree / "skills" / POINTER_SKILL_NAME
|
|
93
|
+
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
94
|
+
(skill_dir / "SKILL.md").write_text(content, encoding="utf-8")
|
|
95
|
+
print(f" Generated: {tree}/skills/{POINTER_SKILL_NAME}/SKILL.md")
|
|
86
96
|
|
|
87
97
|
|
|
88
98
|
# ---------------------------------------------------------------------------
|
|
@@ -93,16 +103,17 @@ def generate(target_dir: Path, *,
|
|
|
93
103
|
language_modules: list[str] | None = None,
|
|
94
104
|
rules_dir: Path | None = None,
|
|
95
105
|
emit_skill_pointer: bool = True) -> None:
|
|
96
|
-
"""Write ``.
|
|
106
|
+
"""Write ``.agents/{rules,workflows}/`` and the dual skill pointers.
|
|
97
107
|
|
|
98
|
-
``emit_skill_pointer`` controls whether the pointer SKILL.md is written
|
|
99
|
-
|
|
108
|
+
``emit_skill_pointer`` controls whether the pointer SKILL.md is written
|
|
109
|
+
to ``.agent/skills/`` (IDE) and ``.agents/skills/`` (CLI). Set to
|
|
110
|
+
``False`` if you manage those directories yourself.
|
|
100
111
|
"""
|
|
101
112
|
rules = dict(STANDARD_RULES)
|
|
102
113
|
rules.update(build_language_rules(language_modules))
|
|
103
114
|
rules.update(build_registered_rules(rules_dir))
|
|
104
|
-
write_rules(target_dir, rules, ".
|
|
105
|
-
write_rules(target_dir, STANDARD_WORKFLOWS, ".
|
|
115
|
+
write_rules(target_dir, rules, ".agents/rules")
|
|
116
|
+
write_rules(target_dir, STANDARD_WORKFLOWS, ".agents/workflows")
|
|
106
117
|
if emit_skill_pointer:
|
|
107
118
|
_write_skill_pointer(target_dir)
|
|
108
119
|
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"""Generate ``.augment/agents/ai-toolkit-*.md`` files for Augment Code.
|
|
3
3
|
|
|
4
4
|
Each ai-toolkit agent in ``app/agents/`` is mirrored as an Augment native
|
|
5
|
-
subagent. Augment's subagent frontmatter (per docs.augmentcode.com)
|
|
5
|
+
subagent. Augment's subagent frontmatter (per docs.augmentcode.com/cli/subagents)
|
|
6
|
+
documents: name, description, color, model, tools, disabled_tools.
|
|
6
7
|
|
|
7
8
|
---
|
|
8
9
|
name: <slug>
|
|
9
10
|
description: "<single-line description>"
|
|
10
|
-
model: inherit # or explicit model id
|
|
11
11
|
color: <color-name> # optional UI hint
|
|
12
12
|
tools: [Read, Write, ...]
|
|
13
13
|
disabled_tools: []
|
|
@@ -17,9 +17,10 @@ subagent. Augment's subagent frontmatter (per docs.augmentcode.com) supports:
|
|
|
17
17
|
|
|
18
18
|
Design choices:
|
|
19
19
|
|
|
20
|
-
* ``model
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
* ``model`` is omitted. The docs state "If not specified, the CLI default model
|
|
21
|
+
is used" and do not document ``inherit`` as a value. ai-toolkit stores short
|
|
22
|
+
aliases (``opus``/``sonnet``/``haiku``) that do not map to Augment's full
|
|
23
|
+
model ids, so we omit the field to defer to the CLI default.
|
|
23
24
|
* ``tools`` are passed through verbatim from the source file, normalized into
|
|
24
25
|
YAML flow-list form (``[Read, Write, ...]``) so Augment parses them as a
|
|
25
26
|
native list.
|
|
@@ -79,11 +80,9 @@ def _render_augment_agent(agent_file: Path) -> str:
|
|
|
79
80
|
lines: list[str] = ["---"]
|
|
80
81
|
lines.append(f"name: {name}")
|
|
81
82
|
lines.append(f'description: "{safe_desc}"')
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
# we deliberately emit ``inherit`` instead of translating.
|
|
86
|
-
lines.append("model: inherit")
|
|
83
|
+
# `model` is omitted: Augment's docs say the CLI default model is used when
|
|
84
|
+
# absent, and `inherit` is not a documented value. Our short aliases do not
|
|
85
|
+
# map to Augment's provider-qualified ids, so we defer to the CLI default.
|
|
87
86
|
if color:
|
|
88
87
|
lines.append(f"color: {color}")
|
|
89
88
|
if tools:
|
|
@@ -5,13 +5,13 @@ User-invocable skills become Augment custom slash commands. Knowledge skills
|
|
|
5
5
|
(``user-invocable: false``) are excluded — they load automatically via
|
|
6
6
|
AGENTS.md/rules context instead of ``/`` invocation.
|
|
7
7
|
|
|
8
|
-
Per docs.augmentcode.com, Augment custom commands are plain
|
|
9
|
-
with an optional YAML frontmatter header. The body of the file IS
|
|
10
|
-
(no ``template:`` field, no TOML).
|
|
8
|
+
Per docs.augmentcode.com/cli/custom-commands, Augment custom commands are plain
|
|
9
|
+
markdown files with an optional YAML frontmatter header. The body of the file IS
|
|
10
|
+
the prompt (no ``template:`` field, no TOML). The documented frontmatter fields
|
|
11
|
+
are ``description``, ``argument-hint``, and ``model`` (no ``agent`` field):
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
description: "<short one-liner shown in the palette>"
|
|
14
|
-
agent: <optional agent slug to route into>
|
|
15
15
|
argument-hint: "<optional hint shown after the command name>"
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -44,20 +44,9 @@ def _skill_body(skill_file: Path) -> str:
|
|
|
44
44
|
return parts[2].lstrip("\n") if len(parts) >= 3 else text
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
def _map_agent_name(value: str) -> str:
|
|
48
|
-
"""Map ai-toolkit agent names to our prefixed Augment subagent slugs."""
|
|
49
|
-
value = value.strip()
|
|
50
|
-
if not value:
|
|
51
|
-
return value
|
|
52
|
-
if value.startswith(COMMAND_PREFIX):
|
|
53
|
-
return value
|
|
54
|
-
return f"{COMMAND_PREFIX}{value}"
|
|
55
|
-
|
|
56
|
-
|
|
57
47
|
def _render_augment_command(skill_file: Path) -> str:
|
|
58
48
|
"""Render a single Augment command .md file from a user-invocable skill."""
|
|
59
49
|
description = frontmatter_field(skill_file, "description")
|
|
60
|
-
agent_field = frontmatter_field(skill_file, "agent")
|
|
61
50
|
argument_hint = frontmatter_field(skill_file, "argument-hint")
|
|
62
51
|
body = _skill_body(skill_file).rstrip()
|
|
63
52
|
|
|
@@ -65,8 +54,6 @@ def _render_augment_command(skill_file: Path) -> str:
|
|
|
65
54
|
if description:
|
|
66
55
|
safe_desc = description.replace('"', "'")
|
|
67
56
|
lines.append(f'description: "{safe_desc}"')
|
|
68
|
-
if agent_field:
|
|
69
|
-
lines.append(f"agent: {_map_agent_name(agent_field)}")
|
|
70
57
|
if argument_hint:
|
|
71
58
|
safe_hint = argument_hint.replace('"', "'")
|
|
72
59
|
lines.append(f'argument-hint: "{safe_hint}"')
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Generate Augment settings.json hooks block.
|
|
3
3
|
|
|
4
|
-
Augment
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
Augment reads hooks from several settings.json layers (per
|
|
5
|
+
docs.augmentcode.com/cli/hooks): `<workspace>/.augment/settings.local.json`,
|
|
6
|
+
`<workspace>/.augment/settings.json`, `~/.augment/settings.json` (user scope),
|
|
7
|
+
and `/etc/augment/settings.json` (system policy). This generator writes the
|
|
8
|
+
user-scope file: it accepts an optional target directory and defaults to the
|
|
9
|
+
user's `$HOME`, writing `~/.augment/settings.json`. Project-local hook emission
|
|
10
|
+
for `--local` installs is a possible future extension.
|
|
9
11
|
|
|
10
12
|
Augment hook events (per docs.augmentcode.com/cli/hooks.md):
|
|
11
13
|
PreToolUse, PostToolUse, SessionStart, SessionEnd, Stop
|
|
@@ -13,6 +13,12 @@ from pathlib import Path
|
|
|
13
13
|
|
|
14
14
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
15
15
|
from codex_skill_adapter import codex_skill_description
|
|
16
|
+
from dir_rules_shared import (
|
|
17
|
+
rule_code_style,
|
|
18
|
+
rule_output_mode,
|
|
19
|
+
rule_security,
|
|
20
|
+
rule_testing,
|
|
21
|
+
)
|
|
16
22
|
from emission import (
|
|
17
23
|
agents_dir,
|
|
18
24
|
skills_dir,
|
|
@@ -54,6 +60,23 @@ def _emit_skills() -> str:
|
|
|
54
60
|
return "\n".join(lines)
|
|
55
61
|
|
|
56
62
|
|
|
63
|
+
def _emit_coding_rules() -> str:
|
|
64
|
+
"""Inline the universal coding-rule bodies so Codex receives them.
|
|
65
|
+
|
|
66
|
+
Codex reads project instructions only from AGENTS.md (and AGENTS.override.md);
|
|
67
|
+
it does not read a ``.agents/rules/`` directory. Workflow + quality standards
|
|
68
|
+
are already emitted above, so this adds code-style, testing, security, and
|
|
69
|
+
output-mode under a single ``## Coding Rules`` section (H1 demoted to H3).
|
|
70
|
+
"""
|
|
71
|
+
sections: list[str] = []
|
|
72
|
+
for rule_fn in (rule_code_style, rule_testing, rule_security, rule_output_mode):
|
|
73
|
+
body = rule_fn().rstrip()
|
|
74
|
+
if body.startswith("# "):
|
|
75
|
+
body = "### " + body[2:]
|
|
76
|
+
sections.append(body)
|
|
77
|
+
return "## Coding Rules\n\n" + "\n\n".join(sections)
|
|
78
|
+
|
|
79
|
+
|
|
57
80
|
def main() -> None:
|
|
58
81
|
print_toolkit_start()
|
|
59
82
|
|
|
@@ -86,6 +109,11 @@ def main() -> None:
|
|
|
86
109
|
print()
|
|
87
110
|
print(generate_workflow_guidelines())
|
|
88
111
|
|
|
112
|
+
# Universal coding rules — Codex reads instructions only from AGENTS.md,
|
|
113
|
+
# so inline them here (previously emitted to the unread .agents/rules/).
|
|
114
|
+
print()
|
|
115
|
+
print(_emit_coding_rules())
|
|
116
|
+
|
|
89
117
|
print_toolkit_end()
|
|
90
118
|
|
|
91
119
|
# Registered custom rules from ~/.softspark/ai-toolkit/rules/
|
|
@@ -8,7 +8,8 @@ Codex exposes 10 lifecycle events (PascalCase in config.toml / hooks.json):
|
|
|
8
8
|
``PreToolUse``, ``PostToolUse``, ``PermissionRequest``, ``PreCompact``,
|
|
9
9
|
``PostCompact``, ``SessionStart``, ``UserPromptSubmit``, ``SubagentStart``,
|
|
10
10
|
``SubagentStop``, ``Stop``. PreToolUse/PostToolUse only support the ``Bash``
|
|
11
|
-
matcher. We
|
|
11
|
+
matcher. We wire all 10 events in ``CODEX_HOOKS`` below to the shared toolkit
|
|
12
|
+
hook scripts, mirroring the Claude Code mapping in ``app/hooks.json``.
|
|
12
13
|
|
|
13
14
|
Handler types in Codex: ``command`` (what we emit), ``prompt``, and ``agent``.
|
|
14
15
|
Reference: codex-rs/config/src/hook_config.rs.
|
|
@@ -39,6 +40,12 @@ CODEX_HOOKS: dict[str, list[tuple[str, str]]] = {
|
|
|
39
40
|
("Bash", "commit-quality.sh"),
|
|
40
41
|
("Bash", "revert-guard.sh"),
|
|
41
42
|
],
|
|
43
|
+
"PostToolUse": [
|
|
44
|
+
# Fires after Bash/apply_patch/MCP tool output. Capture governance
|
|
45
|
+
# signals and detect repetition loops (mirrors app/hooks.json).
|
|
46
|
+
("Bash", "governance-capture.sh"),
|
|
47
|
+
("Bash", "loop-guard.sh"),
|
|
48
|
+
],
|
|
42
49
|
"PermissionRequest": [
|
|
43
50
|
# Fires when Codex asks the user to approve a tool call. Our guard
|
|
44
51
|
# reviews the tool input and can veto destructive patterns before the
|
|
@@ -49,6 +56,21 @@ CODEX_HOOKS: dict[str, list[tuple[str, str]]] = {
|
|
|
49
56
|
("", "user-prompt-submit.sh"),
|
|
50
57
|
("", "track-usage.sh"),
|
|
51
58
|
],
|
|
59
|
+
"SubagentStart": [
|
|
60
|
+
("", "subagent-start.sh"),
|
|
61
|
+
],
|
|
62
|
+
"SubagentStop": [
|
|
63
|
+
("", "subagent-stop.sh"),
|
|
64
|
+
],
|
|
65
|
+
"PreCompact": [
|
|
66
|
+
# Capture session memory before Codex compacts the conversation.
|
|
67
|
+
("", "pre-compact.sh"),
|
|
68
|
+
("", "pre-compact-save.sh"),
|
|
69
|
+
],
|
|
70
|
+
"PostCompact": [
|
|
71
|
+
# Re-establish working context after compaction.
|
|
72
|
+
("", "session-context.sh"),
|
|
73
|
+
],
|
|
52
74
|
"Stop": [
|
|
53
75
|
("", "quality-check.sh"),
|
|
54
76
|
("", "save-session.sh"),
|
|
@@ -2,25 +2,24 @@
|
|
|
2
2
|
"""Generate ``.cursor/agents/ai-toolkit-*.md`` files for Cursor IDE.
|
|
3
3
|
|
|
4
4
|
Each ai-toolkit agent is mirrored as a Cursor custom agent. Per Cursor's
|
|
5
|
-
docs (
|
|
5
|
+
subagent docs (cursor.com/docs/subagents) the frontmatter schema documents
|
|
6
|
+
only these fields:
|
|
6
7
|
|
|
7
8
|
---
|
|
8
|
-
name: <slug>
|
|
9
|
-
description: "<one-line summary shown in the picker>"
|
|
10
|
-
model:
|
|
11
|
-
color: <color-name> # optional UI hint
|
|
12
|
-
tools: [Read, Write, ...] # list of allowed tool names
|
|
9
|
+
name: <slug> # lowercase letters and hyphens
|
|
10
|
+
description: "<one-line summary shown in the Task picker>"
|
|
11
|
+
model: inherit # `inherit` (default) or a specific model id
|
|
13
12
|
---
|
|
14
13
|
|
|
15
14
|
<system prompt body>
|
|
16
15
|
|
|
17
16
|
Design choices:
|
|
18
17
|
|
|
19
|
-
* ``model`` is
|
|
20
|
-
``haiku``) that do not map to
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
* ``model: inherit`` is emitted — the documented default value. Our agents
|
|
19
|
+
store short aliases (``opus``/``sonnet``/``haiku``) that do not map to
|
|
20
|
+
Cursor's provider-qualified model ids, so we use the literal ``inherit``.
|
|
21
|
+
* ``tools`` and ``color`` are NOT emitted — the current Cursor schema documents
|
|
22
|
+
only name/description/model/readonly/is_background (tools/color were dropped).
|
|
24
23
|
* Files are prefixed ``ai-toolkit-`` so install/uninstall can identify ours.
|
|
25
24
|
* Regeneration removes stale ``ai-toolkit-*.md`` files whose source agent
|
|
26
25
|
no longer exists, but leaves user-authored agents untouched.
|
|
@@ -53,34 +52,19 @@ def _agent_body(agent_file: Path) -> str:
|
|
|
53
52
|
return parts[2].lstrip("\n")
|
|
54
53
|
|
|
55
54
|
|
|
56
|
-
def _parse_tools(tools_raw: str) -> list[str]:
|
|
57
|
-
"""Parse the comma-separated ``tools:`` frontmatter value into a list."""
|
|
58
|
-
if not tools_raw:
|
|
59
|
-
return []
|
|
60
|
-
return [t.strip() for t in tools_raw.split(",") if t.strip()]
|
|
61
|
-
|
|
62
|
-
|
|
63
55
|
def _render_cursor_agent(agent_file: Path) -> str:
|
|
64
56
|
"""Render a single Cursor custom agent .md file."""
|
|
65
57
|
name = frontmatter_field(agent_file, "name")
|
|
66
58
|
description = frontmatter_field(agent_file, "description")
|
|
67
|
-
color = frontmatter_field(agent_file, "color")
|
|
68
|
-
tools_raw = frontmatter_field(agent_file, "tools")
|
|
69
|
-
tools = _parse_tools(tools_raw)
|
|
70
59
|
|
|
71
60
|
safe_desc = description.replace('"', "'")
|
|
72
61
|
|
|
73
62
|
lines: list[str] = ["---"]
|
|
74
63
|
lines.append(f"name: {name}")
|
|
75
64
|
lines.append(f'description: "{safe_desc}"')
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if tools:
|
|
80
|
-
tools_flow = ", ".join(tools)
|
|
81
|
-
lines.append(f"tools: [{tools_flow}]")
|
|
82
|
-
else:
|
|
83
|
-
lines.append("tools: []")
|
|
65
|
+
# `inherit` is the documented default model value; our short aliases do not
|
|
66
|
+
# map to Cursor's provider-qualified model ids.
|
|
67
|
+
lines.append("model: inherit")
|
|
84
68
|
lines.append("---")
|
|
85
69
|
lines.append("")
|
|
86
70
|
body = _agent_body(agent_file).rstrip()
|