@softspark/ai-toolkit 3.0.0 → 3.0.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.
- package/CHANGELOG.md +35 -0
- package/README.md +19 -5
- package/app/.claude-plugin/plugin.json +1 -1
- package/app/skills/hook-creator/SKILL.md +7 -3
- package/app/skills/introspect/SKILL.md +1 -1
- package/benchmarks/ecosystem-doctor-snapshot.json +13 -13
- package/bin/ai-toolkit.js +5 -1
- package/kb/procedures/release-preparation-sop.md +14 -5
- package/kb/procedures/release-verification-sop.md +112 -8
- package/kb/reference/cli-reference.md +14 -3
- package/kb/reference/competitive-features-implementation.md +9 -9
- package/kb/reference/hooks-catalog.md +8 -2
- package/kb/reference/supported-tools-registry.md +7 -7
- package/kb/reference/windows-support.md +50 -0
- package/llms-full.txt +220 -34
- package/llms.txt +1 -0
- package/manifest.json +1 -1
- package/package.json +6 -2
- package/scripts/_common.py +21 -0
- package/scripts/check_deps.py +14 -0
- package/scripts/stats.py +126 -39
- package/scripts/validate.py +160 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,41 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## v3.0.2 — Validation, Windows, Telemetry, and generate:all parity (2026-04-24)
|
|
11
|
+
|
|
12
|
+
Patch release that closes known validation gaps, expands the hook-surface contracts, adds Windows dependency hints, exposes local product telemetry, and restores `npm run generate:all` parity with the CLI so registered custom rules reach every editor.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Hook surface validation** — `scripts/validate.py` now accepts the current Claude Code hook event surface, including `PostToolUseFailure`, `PostToolBatch`, and `UserPromptExpansion`.
|
|
17
|
+
- **Hook handler contracts** — validation now checks supported handler types (`command`, `http`, `prompt`, `agent`, `mcp_tool`), required handler fields, and prompt/agent event compatibility.
|
|
18
|
+
- **Language rule validation** — `scripts/validate.py` now checks `app/rules/<language>/*.md` frontmatter, category names, filename/category alignment, directory/language alignment, and required category coverage.
|
|
19
|
+
- **Windows dependency hints** — `_common.detect_os()` recognizes Windows package managers (`winget`, Chocolatey, Scoop), and `check_deps.py` emits package install commands for Python, Git, Node, SQLite, and supported optional tooling.
|
|
20
|
+
- **Product telemetry summary** — `ai-toolkit stats --summary` reports local usage telemetry; `--summary --json` emits machine-readable totals, coverage, unused catalog count, recent activity, and top skills.
|
|
21
|
+
- **Dedicated gap tests** — added contracts for structured rules, Windows dependency support, council/brand-voice/introspect skill coverage, and `npm run generate:all` directory-rule generator coverage. Total test count: 945 -> 960.
|
|
22
|
+
- **Windows Support KB** — new `kb/reference/windows-support.md` documents WSL, Git Bash, package managers, and hook runtime constraints.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- **`package.json` `generate:all`** — now invokes all directory-based rule generators (`generate_cursor_mdc.py`, `generate_windsurf_rules.py`, `generate_roo_rules.py`, `generate_augment_rules.py`) so registered custom rules in `~/.softspark/ai-toolkit/rules/` propagate to every editor that supports per-rule module files. Restores parity with `ai-toolkit generate-all` (CLI).
|
|
27
|
+
- **`app/skills/hook-creator/SKILL.md`** — documents the expanded hook event and handler type surface.
|
|
28
|
+
- **`README.md` and `kb/reference/cli-reference.md`** — document `stats --summary` and Windows support.
|
|
29
|
+
- **`kb/reference/hooks-catalog.md`** — documents the validated hook surface and non-command handler support.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## v3.0.1 — Release SOP Deep-Coverage Checks (2026-04-24)
|
|
34
|
+
|
|
35
|
+
Doc-only patch. No code, generators, or runtime behavior changed.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- **`kb/procedures/release-verification-sop.md` 1.3.0 -> 1.4.0** — added Phase 9 (six new checks for v3.0.0 native surfaces: `--profile full` emission, `--codex-skills` orthogonality, breaking-change surfaces at `standard`, install idempotence, live JSON parse, registry/generator drift). Refreshed stale thresholds (`Tests >= 350` -> `Tests >= 900`, `e.g., 669` -> `e.g., 945`). Editor list updated from 8 to 11 (+codex, +gemini, +opencode). Added HOME-scoped write safety warning.
|
|
40
|
+
- **`kb/procedures/release-preparation-sop.md` 1.9.0 -> 1.10.0** — added the registry-vs-generators drift check to Phase 5 so a bad registry can never escape into a release.
|
|
41
|
+
- **`kb/reference/supported-tools-registry.md` 1.1.0 -> 1.2.0** — enumerated the 11 new v3.0.0 generators (cursor_hooks/agents, windsurf_hooks, gemini_hooks/commands/skills, augment_hooks/agents/commands/skills, codex_skills) with profile and opt-in annotations.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
10
45
|
## v3.0.0 — Deep Coverage: Full Native Surface Utilization (2026-04-23)
|
|
11
46
|
|
|
12
47
|
Skips `2.13.0`. Upgrade path is `2.12.x` -> `3.0.0`.
|
package/README.md
CHANGED
|
@@ -6,19 +6,29 @@
|
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](app/skills/)
|
|
8
8
|
[](app/agents/)
|
|
9
|
-
[](tests/)
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
## What's New in v3.0.
|
|
13
|
+
## What's New in v3.0.2
|
|
14
|
+
|
|
15
|
+
**3.0.2 is a patch release** that closes known validation gaps, expands the validated hook surface, adds Windows dependency hints, exposes local product telemetry, and restores `npm run generate:all` parity with the CLI.
|
|
16
|
+
|
|
17
|
+
- `validate.py` now checks hook handler types, required handler fields, prompt/agent event compatibility, and structured language-rule frontmatter/category coverage.
|
|
18
|
+
- Hook docs and validation now cover `PostToolUseFailure`, `PostToolBatch`, `UserPromptExpansion`, plus `command`, `http`, `prompt`, `agent`, and `mcp_tool` handler types.
|
|
19
|
+
- `ai-toolkit stats --summary` reports local product telemetry: total invocations, unique skills used, catalog coverage, unused skills, recent activity, and top skills.
|
|
20
|
+
- Windows dependency detection now emits package hints for `winget`, Chocolatey, and Scoop; WSL remains the recommended runtime for Bash hooks.
|
|
21
|
+
- `npm run generate:all` now invokes every directory-based rule generator, so registered custom rules in `~/.softspark/ai-toolkit/rules/` propagate to every editor that supports per-rule module files.
|
|
22
|
+
|
|
23
|
+
### Carried from v3.0.0 (feature release)
|
|
14
24
|
|
|
15
25
|
- **Deep coverage: every editor at 100% of its native surface.** New generators emit hooks, sub-agents, custom commands, and skill pointers per editor: `generate_cursor_agents.py`, `generate_cursor_hooks.py`, `generate_windsurf_hooks.py`, `generate_gemini_commands.py`, `generate_gemini_hooks.py`, `generate_gemini_skills.py`, `generate_augment_agents.py`, `generate_augment_commands.py`, `generate_augment_hooks.py`, `generate_augment_skills.py`, `generate_codex_skills.py`.
|
|
16
26
|
- **`--profile full`** turns on every native surface across all supported editors in one flag. `minimal` / `standard` / `strict` retain prior semantics but `standard` now also wires Gemini hooks and the Copilot directory layout (see Breaking Changes).
|
|
17
27
|
- **Opt-in Codex skill mirroring** via `--codex-skills`. Codex gets the full skill catalog materialized under `.agents/skills/`; other editors stay on pointer-skill or compat-read.
|
|
18
|
-
- **58 new bats tests** covering native surface generators
|
|
28
|
+
- **58 new bats tests** covering native surface generators plus per-editor suites for aider, antigravity, augment, claude-code, cline, codex, copilot, cursor, gemini, opencode, roo, windsurf.
|
|
19
29
|
- **Skill quality pass** (folded in from the 2.12 work that is now skipped): 62 skills upgraded to 4-5 / 5 on the meta-architect audit; `add_gotcha` added as a fifth mutation strategy.
|
|
20
30
|
|
|
21
|
-
### Breaking changes
|
|
31
|
+
### Breaking changes (from 3.0.0)
|
|
22
32
|
|
|
23
33
|
- `--profile standard` now installs **Gemini hooks** automatically. To opt out, use `--profile minimal` or pass `--skip gemini-hooks`.
|
|
24
34
|
- Copilot now uses the **directory layout** (`.github/copilot/`) instead of a single monolithic file. Existing single-file installs are preserved but new installs emit the directory form.
|
|
@@ -59,6 +69,8 @@ npx @softspark/ai-toolkit install
|
|
|
59
69
|
|
|
60
70
|
**That's it.** Claude Code picks up 99 skills, 44 agents, quality hooks, and the safety constitution automatically.
|
|
61
71
|
|
|
72
|
+
**Windows:** WSL is the recommended runtime. Native Windows works when Git Bash is available for hook scripts; dependency hints cover `winget`, Chocolatey, and Scoop. See [Windows Support](kb/reference/windows-support.md).
|
|
73
|
+
|
|
62
74
|
### Update
|
|
63
75
|
|
|
64
76
|
```bash
|
|
@@ -154,7 +166,7 @@ ai-toolkit/
|
|
|
154
166
|
│ └── ARCHITECTURE.md # Full system design
|
|
155
167
|
├── kb/ # Reference docs, procedures, plans
|
|
156
168
|
├── scripts/ # Validation, install, evaluation scripts
|
|
157
|
-
├── tests/ # Bats test suite (
|
|
169
|
+
├── tests/ # Bats test suite (960 tests)
|
|
158
170
|
└── CHANGELOG.md
|
|
159
171
|
```
|
|
160
172
|
|
|
@@ -180,6 +192,8 @@ ai-toolkit/
|
|
|
180
192
|
|
|
181
193
|
**Persistent memory** — `memory-pack` plugin: SQLite + FTS5 search across past sessions.
|
|
182
194
|
|
|
195
|
+
**Local product telemetry** — `ai-toolkit stats --summary` reports total invocations, skill coverage, unused catalog skills, recent activity, and top skills from local usage data.
|
|
196
|
+
|
|
183
197
|
**Persona presets** — 4 roles (backend-lead, frontend-lead, devops-eng, junior-dev) adjust style and priorities.
|
|
184
198
|
|
|
185
199
|
**Config inheritance** — Enterprise `extends` system with constitution immutability and enforcement constraints. See [Enterprise Config Guide](kb/reference/enterprise-config-guide.md).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-toolkit",
|
|
3
3
|
"description": "Professional-grade Claude Code toolkit with persona presets, skill security auditor, expanded lifecycle hooks, experimental opt-in plugin packs, benchmark harvesting, and multi-tool support.",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "SoftSpark",
|
|
7
7
|
"url": "https://github.com/softspark"
|
|
@@ -30,6 +30,8 @@ Create a new Claude Code hook following ai-toolkit conventions.
|
|
|
30
30
|
|-------|-----------|---------|-------------|
|
|
31
31
|
| `PreToolUse` | Before a tool executes | tool name (e.g. `Bash`) or `if:` rule | Safety guards, validation, `"defer"` for headless |
|
|
32
32
|
| `PostToolUse` | After a tool executes | tool name | Feedback loops, logging, format-on-save |
|
|
33
|
+
| `PostToolUseFailure` | After a tool fails | tool name | Failure telemetry, recovery hints |
|
|
34
|
+
| `PostToolBatch` | After a batch of tool calls completes | any | Batch summaries, aggregate validation |
|
|
33
35
|
|
|
34
36
|
### Turn lifecycle
|
|
35
37
|
|
|
@@ -37,6 +39,7 @@ Create a new Claude Code hook following ai-toolkit conventions.
|
|
|
37
39
|
|-------|-----------|---------|-------------|
|
|
38
40
|
| `Stop` | Claude finishes responding | any | Quality checks, session save |
|
|
39
41
|
| `StopFailure` | Turn ends due to an API error (rate limit, auth) | any | Alerting, fallback behavior |
|
|
42
|
+
| `UserPromptExpansion` | Claude expands or rewrites a submitted prompt | any | Prompt policy and context shaping |
|
|
40
43
|
|
|
41
44
|
### Subagent lifecycle
|
|
42
45
|
|
|
@@ -88,12 +91,13 @@ Create a new Claude Code hook following ai-toolkit conventions.
|
|
|
88
91
|
|
|
89
92
|
## Hook Handler Types
|
|
90
93
|
|
|
91
|
-
Claude Code supports
|
|
94
|
+
Claude Code supports five handler `type` values in `hooks.json`:
|
|
92
95
|
|
|
93
96
|
| Type | Purpose | Required fields |
|
|
94
97
|
|------|---------|-----------------|
|
|
95
98
|
| `command` | Run a shell script / binary | `command` (path + args) |
|
|
96
|
-
| `
|
|
99
|
+
| `http` | Call a local or remote HTTP endpoint | `url` |
|
|
100
|
+
| `prompt` | Inject a prompt to the fast inline model and use its verdict | `prompt` |
|
|
97
101
|
| `agent` | Spawn a full subagent to evaluate the event (must target `Stop` / `SubagentStop`) | `agent` (agent name) |
|
|
98
102
|
| `mcp_tool` | Invoke an MCP tool directly (no subprocess) | `server`, `tool`, `arguments` |
|
|
99
103
|
|
|
@@ -137,7 +141,7 @@ Claude Code supports four handler `type` values in `hooks.json`:
|
|
|
137
141
|
Required fields:
|
|
138
142
|
- `_source`: always `"ai-toolkit"` (used by merge/strip logic)
|
|
139
143
|
- `matcher`: tool name or regex for Pre/PostToolUse, empty string for global events
|
|
140
|
-
- `hooks[].type`: `"command"`, `"prompt"`, `"agent"`, or `"mcp_tool"` (ai-toolkit uses `"command"`)
|
|
144
|
+
- `hooks[].type`: `"command"`, `"http"`, `"prompt"`, `"agent"`, or `"mcp_tool"` (ai-toolkit uses `"command"`)
|
|
141
145
|
- `hooks[].command`: path to script using `$HOME/.softspark/ai-toolkit/hooks/` prefix (for `type: command`)
|
|
142
146
|
|
|
143
147
|
Optional fields (read from Claude Code docs, not emitted by ai-toolkit by default):
|
|
@@ -61,7 +61,7 @@ Answer these three questions:
|
|
|
61
61
|
|
|
62
62
|
## Step 4: Select Recovery Action
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
Choose the **smallest recovery action** and apply the smallest possible fix — do not restart from scratch unless absolutely necessary:
|
|
65
65
|
|
|
66
66
|
| Pattern | Recovery Action |
|
|
67
67
|
|---------|----------------|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"last_run": "2026-04-
|
|
2
|
+
"last_run": "2026-04-24T08:04:02Z",
|
|
3
3
|
"schema_version": 1,
|
|
4
4
|
"tools": {
|
|
5
5
|
"aider": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"augment": {
|
|
27
|
-
"docs_hash": "
|
|
27
|
+
"docs_hash": "5754553b0e436fd7",
|
|
28
28
|
"headings": [
|
|
29
29
|
"Agent",
|
|
30
30
|
"Code Completions",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"claude-code": {
|
|
60
|
-
"docs_hash": "
|
|
60
|
+
"docs_hash": "0c111b1b1f28960d",
|
|
61
61
|
"headings": [
|
|
62
62
|
"Claude Code overview",
|
|
63
63
|
"\u200bGet started",
|
|
@@ -102,10 +102,10 @@
|
|
|
102
102
|
"slash command": true,
|
|
103
103
|
"sub-agent": true
|
|
104
104
|
},
|
|
105
|
-
"version": "2.1.
|
|
105
|
+
"version": "2.1.119 (Claude Code)"
|
|
106
106
|
},
|
|
107
107
|
"cline": {
|
|
108
|
-
"docs_hash": "
|
|
108
|
+
"docs_hash": "17c24d27216f70cf",
|
|
109
109
|
"headings": [
|
|
110
110
|
"Cline CLI",
|
|
111
111
|
"Cline Documentation",
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
}
|
|
136
136
|
},
|
|
137
137
|
"codex-cli": {
|
|
138
|
-
"docs_hash": "
|
|
138
|
+
"docs_hash": "7a7f5cdf9411c5e2",
|
|
139
139
|
"headings": [
|
|
140
140
|
"About",
|
|
141
141
|
"Contributing",
|
|
@@ -154,7 +154,7 @@
|
|
|
154
154
|
"Packages 0",
|
|
155
155
|
"Provide feedback",
|
|
156
156
|
"Quickstart",
|
|
157
|
-
"Releases
|
|
157
|
+
"Releases 735",
|
|
158
158
|
"Repository files navigation",
|
|
159
159
|
"Resources",
|
|
160
160
|
"Saved searches",
|
|
@@ -184,10 +184,10 @@
|
|
|
184
184
|
"mcp_servers": false,
|
|
185
185
|
"sandbox": true
|
|
186
186
|
},
|
|
187
|
-
"version": "codex-cli 0.
|
|
187
|
+
"version": "codex-cli 0.124.0"
|
|
188
188
|
},
|
|
189
189
|
"cursor": {
|
|
190
|
-
"docs_hash": "
|
|
190
|
+
"docs_hash": "a94b8e8f685b0831",
|
|
191
191
|
"headings": [],
|
|
192
192
|
"markers": {
|
|
193
193
|
".cursor/rules": false,
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
}
|
|
204
204
|
},
|
|
205
205
|
"gemini-cli": {
|
|
206
|
-
"docs_hash": "
|
|
206
|
+
"docs_hash": "9415ea08e344013d",
|
|
207
207
|
"headings": [
|
|
208
208
|
"Breadcrumbs",
|
|
209
209
|
"Directory actions",
|
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
}
|
|
243
243
|
},
|
|
244
244
|
"github-copilot": {
|
|
245
|
-
"docs_hash": "
|
|
245
|
+
"docs_hash": "8bcd2db0db925807",
|
|
246
246
|
"headings": [
|
|
247
247
|
"About Copilot auto model selection",
|
|
248
248
|
"About Copilot integrations",
|
|
@@ -290,7 +290,7 @@
|
|
|
290
290
|
}
|
|
291
291
|
},
|
|
292
292
|
"opencode": {
|
|
293
|
-
"docs_hash": "
|
|
293
|
+
"docs_hash": "760fbf466036892f",
|
|
294
294
|
"headings": [
|
|
295
295
|
"Add features",
|
|
296
296
|
"Ask questions",
|
|
@@ -351,7 +351,7 @@
|
|
|
351
351
|
}
|
|
352
352
|
},
|
|
353
353
|
"windsurf": {
|
|
354
|
-
"docs_hash": "
|
|
354
|
+
"docs_hash": "81d0aafbf97b18c8",
|
|
355
355
|
"headings": [
|
|
356
356
|
"Advanced",
|
|
357
357
|
"App Deploys",
|
package/bin/ai-toolkit.js
CHANGED
|
@@ -74,7 +74,7 @@ const COMMANDS = {
|
|
|
74
74
|
benchmark: 'Benchmark toolkit (--my-config to compare your setup vs defaults vs ecosystem)',
|
|
75
75
|
'benchmark-ecosystem': 'Generate ecosystem benchmark snapshot (GitHub metadata + offline fallback)',
|
|
76
76
|
evaluate: 'Run skill evaluation suite',
|
|
77
|
-
stats: 'Show skill usage statistics (--
|
|
77
|
+
stats: 'Show skill usage statistics (--summary for product telemetry, --reset to clear)',
|
|
78
78
|
create: 'Scaffold new skill from template (e.g. create skill my-lint --template=linter)',
|
|
79
79
|
mcp: 'Manage MCP templates and install native editor MCP configs',
|
|
80
80
|
config: 'Manage config inheritance (validate, diff, init, create-base, check)',
|
|
@@ -280,6 +280,10 @@ function showHelp() {
|
|
|
280
280
|
console.log(' Remove from .mcp.json or native editor configs');
|
|
281
281
|
console.log('\nOptions for doctor:');
|
|
282
282
|
console.log(' --fix Auto-repair detected issues');
|
|
283
|
+
console.log('\nOptions for stats:');
|
|
284
|
+
console.log(' --summary Show aggregated product telemetry (usage coverage, top skills, unused catalog)');
|
|
285
|
+
console.log(' --json Emit raw stats, or machine-readable telemetry when combined with --summary');
|
|
286
|
+
console.log(' --reset Clear local usage stats');
|
|
283
287
|
console.log('\nOptions for eject:');
|
|
284
288
|
console.log(' [target-dir] Target directory (default: current directory)');
|
|
285
289
|
console.log('');
|
|
@@ -3,10 +3,10 @@ title: "SOP: Release Preparation"
|
|
|
3
3
|
category: procedures
|
|
4
4
|
service: ai-toolkit
|
|
5
5
|
tags: [sop, release, version, publish, changelog, semver, provenance, sarif, ecosystem]
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.10.0"
|
|
7
7
|
created: "2026-04-10"
|
|
8
|
-
last_updated: "2026-04-
|
|
9
|
-
description: "Step-by-step checklist for preparing a new ai-toolkit release — ecosystem-sync drift check, version sync, changelog, artifact regeneration, validation, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF, and checksum-pin checks added in v2.8.0, the single-run npm test discipline added in v1.8.0,
|
|
8
|
+
last_updated: "2026-04-24"
|
|
9
|
+
description: "Step-by-step checklist for preparing a new ai-toolkit release — ecosystem-sync drift check, version sync, changelog, artifact regeneration, validation, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF, and checksum-pin checks added in v2.8.0, the single-run npm test discipline added in v1.8.0, the ecosystem-sync gate added in v1.9.0, and the registry-vs-generators drift gate added in v1.10.0."
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# SOP: Release Preparation
|
|
@@ -278,7 +278,15 @@ python3 scripts/audit_skills.py --ci
|
|
|
278
278
|
python3 scripts/audit_skills.py --sarif > audit.sarif # MANDATORY — GHAS ingest
|
|
279
279
|
python3 scripts/audit_skills.py --permissions # review Bash/Write/Edit footprint
|
|
280
280
|
|
|
281
|
-
#
|
|
281
|
+
# Registry / generator drift (added in 1.10.0). Meta-generators excluded.
|
|
282
|
+
META="generate_agents_md.py|generate_llms_txt.py"
|
|
283
|
+
diff \
|
|
284
|
+
<(grep -oE 'scripts/generate_[a-z_]+\.py' kb/reference/supported-tools-registry.md | sort -u) \
|
|
285
|
+
<(ls scripts/generate_*.py | grep -vE "$META" | sort -u) \
|
|
286
|
+
&& echo "OK: registry matches filesystem" \
|
|
287
|
+
|| { echo "DRIFT: update supported-tools-registry.md before tagging"; exit 1; }
|
|
288
|
+
|
|
289
|
+
# Run npm test ONCE, cache output, parse from file. The suite is 900+ bats
|
|
282
290
|
# cases — rerunning it per check wastes minutes. Do not pipe npm test into
|
|
283
291
|
# tail/grep multiple times in the same session.
|
|
284
292
|
npm test > /tmp/npm-test.log 2>&1
|
|
@@ -291,11 +299,12 @@ echo "ok: $(grep -c '^ok ' /tmp/npm-test.log) | not ok: $(grep -c '^not ok' /tmp
|
|
|
291
299
|
- `audit_skills.py --ci`: `HIGH: 0 | WARN: 0` (INFO is acceptable)
|
|
292
300
|
- `audit_skills.py --sarif`: valid JSON, non-empty `runs[0].tool.driver.rules`
|
|
293
301
|
- `audit_skills.py --permissions`: review `Skills with Bash + Write + Edit` list — any newly-added skill with broad access MUST be justified in the CHANGELOG entry
|
|
302
|
+
- Registry drift: `OK: registry matches filesystem`. If `DRIFT:` appears, add the missing `scripts/generate_*.py` rows to `kb/reference/supported-tools-registry.md` before tagging.
|
|
294
303
|
- `npm test`: `1..N` with zero `not ok` (read from the cached `/tmp/npm-test.log`, do not rerun)
|
|
295
304
|
|
|
296
305
|
**One-liner:**
|
|
297
306
|
```bash
|
|
298
|
-
python3 scripts/validate.py --strict && python3 scripts/audit_skills.py --ci && python3 scripts/audit_skills.py --sarif > audit.sarif && npm test
|
|
307
|
+
python3 scripts/validate.py --strict && python3 scripts/audit_skills.py --ci && python3 scripts/audit_skills.py --sarif > audit.sarif && diff <(grep -oE 'scripts/generate_[a-z_]+\.py' kb/reference/supported-tools-registry.md | sort -u) <(ls scripts/generate_*.py | grep -vE 'generate_agents_md\.py|generate_llms_txt\.py' | sort -u) && npm test
|
|
299
308
|
```
|
|
300
309
|
|
|
301
310
|
**If tests fail:** Fix the issue, do NOT skip. Common failures:
|
|
@@ -3,10 +3,10 @@ title: "SOP: Release Verification"
|
|
|
3
3
|
category: procedures
|
|
4
4
|
service: ai-toolkit
|
|
5
5
|
tags: [sop, verification, release, smoke-test, install, update, qa, provenance, sarif]
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.4.0"
|
|
7
7
|
created: "2026-04-08"
|
|
8
|
-
last_updated: "2026-04-
|
|
9
|
-
description: "End-to-end smoke test after installing or updating @softspark/ai-toolkit — verifies CLI, install, doctor, validation, tests, eject, npm provenance attestation, SARIF audit, and per-skill permissions. Reflects the v2.8.0 supply-chain standard. v1.3.0
|
|
8
|
+
last_updated: "2026-04-24"
|
|
9
|
+
description: "End-to-end smoke test after installing or updating @softspark/ai-toolkit — verifies CLI, install, doctor, validation, tests, eject, npm provenance attestation, SARIF audit, and per-skill permissions. Reflects the v2.8.0 supply-chain standard. v1.3.0 added the single-run npm test discipline; v1.4.0 adds v3.0.0 deep-coverage checks (--profile full, --codex-skills, breaking-change surfaces, idempotence, registry drift, live-JSON parse) and refreshes stale thresholds."
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# SOP: Release Verification
|
|
@@ -52,6 +52,10 @@ python3 scripts/audit_skills.py --ci # 10. Security audit
|
|
|
52
52
|
python3 scripts/audit_skills.py --sarif | python3 -c "import json,sys; assert json.load(sys.stdin)['version']=='2.1.0'; print('SARIF OK')" # 11. SARIF 2.1.0 well-formed?
|
|
53
53
|
python3 scripts/audit_skills.py --permissions | head -30 # 12. Broad-access skills reviewed?
|
|
54
54
|
npm view @softspark/ai-toolkit@X.Y.Z --json | python3 -c "import json,sys; d=json.load(sys.stdin); assert d['dist']['attestations']['provenance']['predicateType']=='https://slsa.dev/provenance/v1'; print('PROVENANCE OK')" # 13. Provenance attested on npm?
|
|
55
|
+
|
|
56
|
+
# Deep-coverage verification (Phase 9, v3.0.0+)
|
|
57
|
+
META="generate_agents_md.py|generate_llms_txt.py"
|
|
58
|
+
diff <(grep -oE 'scripts/generate_[a-z_]+\.py' kb/reference/supported-tools-registry.md | sort -u) <(ls scripts/generate_*.py | grep -vE "$META" | sort -u) && echo "OK: registry matches" # 14. Registry <-> generators drift?
|
|
55
59
|
```
|
|
56
60
|
|
|
57
61
|
---
|
|
@@ -117,8 +121,8 @@ ai-toolkit status
|
|
|
117
121
|
```
|
|
118
122
|
|
|
119
123
|
**Verify `--dry-run`:**
|
|
120
|
-
- [ ] Agents >=
|
|
121
|
-
- [ ] Skills >=
|
|
124
|
+
- [ ] Agents >= 44
|
|
125
|
+
- [ ] Skills >= 99
|
|
122
126
|
- [ ] Hooks merged into settings.json
|
|
123
127
|
- [ ] "Other AI Tools" section lists cursor, windsurf, gemini, augment (antigravity via --local)
|
|
124
128
|
|
|
@@ -168,7 +172,7 @@ cd - && rm -rf /tmp/ai-toolkit-verify
|
|
|
168
172
|
- [ ] Would create: CLAUDE.md
|
|
169
173
|
- [ ] Would create: .claude/settings.local.json
|
|
170
174
|
- [ ] Would inject: .claude/constitution.md
|
|
171
|
-
- [ ] Editors: all
|
|
175
|
+
- [ ] Editors: all 11 listed (copilot, cursor, windsurf, cline, roo, aider, augment, antigravity, codex, gemini, opencode)
|
|
172
176
|
- [ ] Would generate configs for each editor (legacy + directory-based)
|
|
173
177
|
- [ ] Would install: .git/hooks/pre-commit
|
|
174
178
|
- [ ] Would inject language rules (auto-detected)
|
|
@@ -189,7 +193,7 @@ python3 scripts/audit_skills.py --ci
|
|
|
189
193
|
```
|
|
190
194
|
|
|
191
195
|
**Verify validate.py:**
|
|
192
|
-
- [ ] Agents >=
|
|
196
|
+
- [ ] Agents >= 44, Skills >= 99, Tests >= 900
|
|
193
197
|
- [ ] Hook events: 12, Hook scripts: >= 20
|
|
194
198
|
- [ ] Plugin packs >= 10, KB documents >= 20
|
|
195
199
|
- [ ] `Errors: 0 | Warnings: 0` → `VALIDATION PASSED`
|
|
@@ -217,7 +221,7 @@ echo "exit: $exit"
|
|
|
217
221
|
|
|
218
222
|
**Verify:**
|
|
219
223
|
- [ ] `exit == 0`
|
|
220
|
-
- [ ] `ok == expected test count` (e.g.,
|
|
224
|
+
- [ ] `ok == expected test count` (e.g., 945 on v3.0.0)
|
|
221
225
|
- [ ] `not ok == 0`
|
|
222
226
|
- [ ] Bats runs tests in parallel (4 jobs)
|
|
223
227
|
- [ ] Groups: agents, autodetect, cli, generators, guards, hooks, inject,
|
|
@@ -322,6 +326,101 @@ AI_TOOLKIT_STRICT_PIN=1 ai-toolkit update --dry-run
|
|
|
322
326
|
|
|
323
327
|
---
|
|
324
328
|
|
|
329
|
+
## Phase 9: Deep-Coverage Checks (v3.0.0+)
|
|
330
|
+
|
|
331
|
+
These verify the native-surface generators shipped in v3.0.0 actually emit the right files for the right profiles, and that the tool registry stays in sync with shipped generators.
|
|
332
|
+
|
|
333
|
+
> **Safety warning — HOME-scoped writes:** Running `--profile full` with `augment` in the editor list writes to `$HOME/.augment/settings.json` (Augment stores hooks under HOME, not per-project). Use `--dry-run` for verification unless you intend to carry ai-toolkit hook entries on this machine. The generator is marker-safe (only rewrites its own `_source: ai-toolkit` entries) but is still a side-effect.
|
|
334
|
+
|
|
335
|
+
### 9.1 `--profile full` emits every native surface
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
D=/tmp/aitk-profile-full-${RANDOM} && mkdir -p "$D" && cd "$D" && git init -q
|
|
339
|
+
ai-toolkit install --local --editors cursor,windsurf,gemini,augment,codex \
|
|
340
|
+
--profile full --codex-skills --dry-run 2>&1 \
|
|
341
|
+
| grep -E "\\.cursor/(hooks\\.json|agents)|\\.windsurf/hooks\\.json|\\.gemini/(settings\\.json|commands)|\\.augment/(agents|commands)|\\.codex/skills"
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Verify** — at least the following lines appear:
|
|
345
|
+
- [ ] `.cursor/hooks.json` and `.cursor/agents/`
|
|
346
|
+
- [ ] `.windsurf/hooks.json`
|
|
347
|
+
- [ ] `.gemini/settings.json` hooks AND `.gemini/commands/`
|
|
348
|
+
- [ ] `.augment/agents/` + `.augment/commands/` + `$HOME/.augment/settings.json`
|
|
349
|
+
- [ ] `.codex/skills/` (opt-in via `--codex-skills`)
|
|
350
|
+
|
|
351
|
+
### 9.2 `--codex-skills` is orthogonal to `--profile`
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
D=/tmp/aitk-codex-skills-${RANDOM} && mkdir -p "$D" && cd "$D" && git init -q
|
|
355
|
+
ai-toolkit install --local --editors codex --profile standard --codex-skills --dry-run 2>&1 \
|
|
356
|
+
| grep -q "Would generate: .codex/skills" && echo "OK: --codex-skills works without --profile full"
|
|
357
|
+
ai-toolkit install --local --editors codex --profile full --dry-run 2>&1 \
|
|
358
|
+
| grep -q "Would generate: .codex/skills" && echo "FAIL: --profile full should NOT auto-emit .codex/skills" \
|
|
359
|
+
|| echo "OK: --profile full alone does not auto-emit .codex/skills (correct — opt-in only)"
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**Verify:**
|
|
363
|
+
- [ ] `--codex-skills` emits `.codex/skills/` at any profile
|
|
364
|
+
- [ ] `--profile full` alone does NOT emit `.codex/skills/` (must be opt-in)
|
|
365
|
+
|
|
366
|
+
### 9.3 Breaking-change surfaces land on `--profile standard`
|
|
367
|
+
|
|
368
|
+
v3.0.0 moved two surfaces from opt-in to default:
|
|
369
|
+
- Copilot directory layout (`.github/instructions/`, `.github/prompts/`)
|
|
370
|
+
- Gemini hooks (`.gemini/settings.json`)
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
D=/tmp/aitk-breaking-${RANDOM} && mkdir -p "$D" && cd "$D" && git init -q
|
|
374
|
+
ai-toolkit install --local --editors copilot,gemini --profile standard --dry-run 2>&1 \
|
|
375
|
+
| tee /tmp/aitk-breaking.log
|
|
376
|
+
grep -q "\\.github/instructions/" /tmp/aitk-breaking.log && echo "OK: Copilot dir layout at standard"
|
|
377
|
+
grep -q "\\.gemini/settings\\.json hooks" /tmp/aitk-breaking.log && echo "OK: Gemini hooks at standard"
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Verify both lines print `OK:`**. If either is missing, a regression has unwound the v3.0.0 breaking change.
|
|
381
|
+
|
|
382
|
+
### 9.4 Install is idempotent
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
D=/tmp/aitk-idem-${RANDOM} && mkdir -p "$D" && cd "$D" && git init -q
|
|
386
|
+
ai-toolkit install --local --editors cursor,gemini --profile full >/dev/null 2>&1
|
|
387
|
+
SHA1=$(find .cursor .gemini -type f -exec shasum {} + | shasum | awk '{print $1}')
|
|
388
|
+
ai-toolkit install --local --editors cursor,gemini --profile full >/dev/null 2>&1
|
|
389
|
+
SHA2=$(find .cursor .gemini -type f -exec shasum {} + | shasum | awk '{print $1}')
|
|
390
|
+
[ "$SHA1" = "$SHA2" ] && echo "OK: idempotent" || echo "FAIL: install is not idempotent"
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Verify:** prints `OK: idempotent`. A second run must produce byte-identical files in every managed path.
|
|
394
|
+
|
|
395
|
+
### 9.5 Live-install JSON outputs parse
|
|
396
|
+
|
|
397
|
+
The bats suite validates JSON shape at generation time. This re-checks that what actually landed on disk after a live install parses without errors.
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
D=/tmp/aitk-json-${RANDOM} && mkdir -p "$D" && cd "$D" && git init -q
|
|
401
|
+
ai-toolkit install --local --editors cursor,windsurf,gemini,augment --profile full >/dev/null 2>&1
|
|
402
|
+
for f in .cursor/hooks.json .windsurf/hooks.json .gemini/settings.json $HOME/.augment/settings.json; do
|
|
403
|
+
[ -f "$f" ] && python3 -c "import json; json.load(open('$f'))" && echo "OK: $f"
|
|
404
|
+
done
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**Verify:** each emitted file prints `OK: <path>`. Any `json.decoder.JSONDecodeError` means the merge logic corrupted the output.
|
|
408
|
+
|
|
409
|
+
### 9.6 Registry / generator drift check
|
|
410
|
+
|
|
411
|
+
`kb/reference/supported-tools-registry.md` should enumerate every per-editor `scripts/generate_*.py` we ship. Meta-generators (`generate_agents_md.py`, `generate_llms_txt.py`) are excluded — they produce docs/artifacts, not editor configs.
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
META="generate_agents_md.py|generate_llms_txt.py"
|
|
415
|
+
REG=$(grep -oE 'scripts/generate_[a-z_]+\.py' kb/reference/supported-tools-registry.md | sort -u)
|
|
416
|
+
FS=$(ls scripts/generate_*.py | grep -vE "$META" | sort -u)
|
|
417
|
+
diff <(echo "$REG") <(echo "$FS") && echo "OK: registry matches filesystem" || echo "DRIFT: update supported-tools-registry.md"
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Verify:** prints `OK: registry matches filesystem`. If not, add the missing rows to the registry before tagging the next release.
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
325
424
|
## Troubleshooting
|
|
326
425
|
|
|
327
426
|
### `ai-toolkit: command not found`
|
|
@@ -376,3 +475,8 @@ ai-toolkit eject /tmp/test # retry
|
|
|
376
475
|
| Tests | `npm test`: N/N passed, 0 failures |
|
|
377
476
|
| Eject | Standalone `.claude/` with real files AND `output-styles/` directory |
|
|
378
477
|
| Guards | Destructive commands blocked |
|
|
478
|
+
| Deep coverage | `--profile full` emits all 9 v3.0.0 native surfaces; `--codex-skills` works orthogonally |
|
|
479
|
+
| Breaking changes | Copilot directory layout + Gemini hooks emit at `--profile standard` (v3.0.0 contract) |
|
|
480
|
+
| Idempotence | Second `install` run produces byte-identical output in every managed path |
|
|
481
|
+
| Live JSON | Every generated `.json` file on disk parses as valid JSON |
|
|
482
|
+
| Registry | `supported-tools-registry.md` enumerates every `scripts/generate_*.py` we ship |
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
title: "CLI Reference"
|
|
3
3
|
category: reference
|
|
4
4
|
service: ai-toolkit
|
|
5
|
-
tags: [cli, commands, reference, install, update, plugin, mcp]
|
|
5
|
+
tags: [cli, commands, reference, install, update, plugin, mcp, telemetry]
|
|
6
6
|
created: "2026-04-13"
|
|
7
|
-
last_updated: "2026-04-
|
|
7
|
+
last_updated: "2026-04-24"
|
|
8
8
|
description: "Complete CLI reference for all ai-toolkit commands, options, and flags."
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -111,7 +111,7 @@ Usage: ai-toolkit <command> [options]
|
|
|
111
111
|
|
|
112
112
|
| Command | Description |
|
|
113
113
|
|---------|-------------|
|
|
114
|
-
| `stats` | Show skill usage statistics (`--reset` to clear, `--json` for raw output) |
|
|
114
|
+
| `stats` | Show skill usage statistics (`--summary` for product telemetry, `--reset` to clear, `--json` for raw output) |
|
|
115
115
|
| `benchmark --my-config` | Compare your config vs defaults vs ecosystem |
|
|
116
116
|
| `benchmark-ecosystem` | Generate ecosystem benchmark snapshot |
|
|
117
117
|
| `create skill <name>` | Scaffold new skill from template (`--template=linter\|reviewer\|generator\|workflow\|knowledge`) |
|
|
@@ -119,6 +119,17 @@ Usage: ai-toolkit <command> [options]
|
|
|
119
119
|
| `compile-slm` | Compile toolkit into minimal SLM system prompt (`--budget`, `--model-size`, `--dry-run`) |
|
|
120
120
|
| `evaluate` | Run skill evaluation suite |
|
|
121
121
|
|
|
122
|
+
### `stats`
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
ai-toolkit stats # table of local skill usage
|
|
126
|
+
ai-toolkit stats --summary # product telemetry summary
|
|
127
|
+
ai-toolkit stats --summary --json # machine-readable telemetry
|
|
128
|
+
ai-toolkit stats --reset # clear local stats
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`--summary` reports total invocations, unique skills used, catalog coverage, unused catalog skills, active skills in the last 7 days, and top skills. Data stays local in `~/.softspark/ai-toolkit/stats.json`.
|
|
132
|
+
|
|
122
133
|
## Install / Update Options
|
|
123
134
|
|
|
124
135
|
```bash
|
|
@@ -13,7 +13,7 @@ tags:
|
|
|
13
13
|
doc_type: plan
|
|
14
14
|
status: completed
|
|
15
15
|
created: "2026-04-07"
|
|
16
|
-
last_updated: "2026-04-
|
|
16
|
+
last_updated: "2026-04-24"
|
|
17
17
|
completion: "100%"
|
|
18
18
|
description: "Implementation plan for features identified from competitive analysis of everything-claude-code and claude-mem. Focus on learning system, language rules, advanced hooks, MCP templates, and rag-mcp integration. COMPLETED: 8/9 features shipped (1 skipped). See kb/reference/ for permanent documentation."
|
|
19
19
|
---
|
|
@@ -142,8 +142,8 @@ app/rules/
|
|
|
142
142
|
- [x] 13 languages × 5 rule files created (70 files: 13 dirs × 5 + 5 common)
|
|
143
143
|
- [x] `ai-toolkit install --local` auto-detects language and injects rules (two-phase: marker files + extension scan)
|
|
144
144
|
- [x] Manual override: `ai-toolkit install --local --lang typescript` (with aliases: go→golang, c++→cpp, cs→csharp)
|
|
145
|
-
- [
|
|
146
|
-
- [
|
|
145
|
+
- [x] validate.py checks rules format
|
|
146
|
+
- [x] Tests: dedicated `tests/test_rules.bats`
|
|
147
147
|
|
|
148
148
|
---
|
|
149
149
|
|
|
@@ -497,7 +497,7 @@ context: fork
|
|
|
497
497
|
- [x] `/council` invocable
|
|
498
498
|
- [x] 4 perspectives generated
|
|
499
499
|
- [x] Structured output with recommendation
|
|
500
|
-
- [
|
|
500
|
+
- [x] Tests: dedicated council skill contract
|
|
501
501
|
|
|
502
502
|
---
|
|
503
503
|
|
|
@@ -516,7 +516,7 @@ context: fork
|
|
|
516
516
|
**Success Criteria:**
|
|
517
517
|
- [x] Skill auto-loads when writing docs/content
|
|
518
518
|
- [x] Anti-trope list prevents generic LLM rhetoric
|
|
519
|
-
- [
|
|
519
|
+
- [x] Tests: dedicated brand-voice skill contract
|
|
520
520
|
|
|
521
521
|
---
|
|
522
522
|
|
|
@@ -538,7 +538,7 @@ context: fork
|
|
|
538
538
|
- [x] `/introspect` invocable when agent is stuck
|
|
539
539
|
- [x] Classifies failure pattern
|
|
540
540
|
- [x] Suggests recovery action
|
|
541
|
-
- [
|
|
541
|
+
- [x] Tests: dedicated introspect skill contract
|
|
542
542
|
|
|
543
543
|
---
|
|
544
544
|
|
|
@@ -660,9 +660,9 @@ npx @softspark/ai-toolkit inject-hook ./rag-mcp-hooks.json # NEW
|
|
|
660
660
|
|
|
661
661
|
All major features shipped. Outstanding items:
|
|
662
662
|
|
|
663
|
-
1. [
|
|
664
|
-
2. [
|
|
665
|
-
3. [
|
|
663
|
+
1. [x] `validate.py` checks rules format (1.1)
|
|
664
|
+
2. [x] Dedicated `test_rules` test file exists (1.1)
|
|
665
|
+
3. [x] Dedicated tests exist for council, brand-voice, introspect skills (3.1-3.3)
|
|
666
666
|
4. [x] `observe-session.sh` lives in rag-mcp (consumer), not ai-toolkit — by design
|
|
667
667
|
|
|
668
668
|
---
|
|
@@ -3,9 +3,9 @@ title: "Hooks Catalog"
|
|
|
3
3
|
category: reference
|
|
4
4
|
service: ai-toolkit
|
|
5
5
|
tags: [hooks, quality, safety, enforcement, settings.json]
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.5.0"
|
|
7
7
|
created: "2026-03-27"
|
|
8
|
-
last_updated: "2026-04-
|
|
8
|
+
last_updated: "2026-04-24"
|
|
9
9
|
description: "Complete reference of all ai-toolkit hooks: events, scripts, installation, and runtime behavior."
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -15,6 +15,12 @@ description: "Complete reference of all ai-toolkit hooks: events, scripts, insta
|
|
|
15
15
|
|
|
16
16
|
ai-toolkit provides 21 global hook entries across 12 lifecycle events that enforce quality, safety, and workflow rules across all Claude Code sessions. Hooks are merged into `~/.claude/settings.json` on install, with logic in standalone scripts at `~/.softspark/ai-toolkit/hooks/`.
|
|
17
17
|
|
|
18
|
+
## Supported Surface
|
|
19
|
+
|
|
20
|
+
`scripts/validate.py` validates both event names and handler shapes before release. The accepted lifecycle surface includes `PostToolUseFailure`, `PostToolBatch`, and `UserPromptExpansion` in addition to the installed ai-toolkit events below.
|
|
21
|
+
|
|
22
|
+
Supported handler types are `command`, `http`, `prompt`, `agent`, and `mcp_tool`. ai-toolkit ships command hooks by default; non-command handlers are validated so external consumers can safely inject richer hook definitions through `inject-hook`.
|
|
23
|
+
|
|
18
24
|
## Installation
|
|
19
25
|
|
|
20
26
|
```bash
|