@softspark/ai-toolkit 4.4.1 → 4.5.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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "last_run": "2026-05-25T11:12:53Z",
2
+ "last_run": "2026-05-30T19:51:17Z",
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": "2546ce56fc2d92e4",
27
+ "docs_hash": "46ef1d20d537234f",
28
28
  "headings": [
29
29
  "Admin",
30
30
  "Auggie CLI",
@@ -65,11 +65,15 @@
65
65
  }
66
66
  },
67
67
  "claude-code": {
68
- "docs_hash": "78dbdbf9b1b09fe8",
68
+ "docs_hash": "b2ee6850b58cee40",
69
69
  "headings": [
70
+ "Core concepts",
70
71
  "Documentation Index",
72
+ "Getting started",
71
73
  "On this page",
72
74
  "Overview",
75
+ "Platforms and integrations",
76
+ "Use Claude Code",
73
77
  "\u200bGet started",
74
78
  "\u200bNext steps",
75
79
  "\u200bUse Claude Code everywhere",
@@ -83,11 +87,14 @@
83
87
  "FileChanged": false,
84
88
  "InstructionsLoaded": false,
85
89
  "MCP server": true,
90
+ "MessageDisplay": false,
86
91
  "Notification": true,
87
92
  "PermissionDenied": false,
88
93
  "PermissionRequest": false,
89
94
  "PostCompact": false,
95
+ "PostToolBatch": false,
90
96
  "PostToolUse": true,
97
+ "PostToolUseFailure": false,
91
98
  "PreCompact": false,
92
99
  "PreToolUse": true,
93
100
  "SKILL.md": true,
@@ -101,6 +108,7 @@
101
108
  "TaskCompleted": false,
102
109
  "TaskCreated": false,
103
110
  "TeammateIdle": false,
111
+ "UserPromptExpansion": false,
104
112
  "UserPromptSubmit": false,
105
113
  "WorktreeCreate": false,
106
114
  "WorktreeRemove": false,
@@ -112,10 +120,10 @@
112
120
  "slash command": true,
113
121
  "sub-agent": true
114
122
  },
115
- "version": "2.1.150 (Claude Code)"
123
+ "version": "2.1.158 (Claude Code)"
116
124
  },
117
125
  "cline": {
118
- "docs_hash": "0d30b8f46cb45976",
126
+ "docs_hash": "9ec25e5132332d2f",
119
127
  "headings": [
120
128
  "API Reference",
121
129
  "Best Practices",
@@ -156,7 +164,7 @@
156
164
  }
157
165
  },
158
166
  "codex-cli": {
159
- "docs_hash": "8cad495445dd03e0",
167
+ "docs_hash": "f7a6a5144e0f61a2",
160
168
  "headings": [
161
169
  "About",
162
170
  "Contributing",
@@ -175,7 +183,7 @@
175
183
  "Packages 0",
176
184
  "Provide feedback",
177
185
  "Quickstart",
178
- "Releases 799",
186
+ "Releases 804",
179
187
  "Repository files navigation",
180
188
  "Resources",
181
189
  "Saved searches",
@@ -193,10 +201,14 @@
193
201
  "AGENTS.md": true,
194
202
  "config.toml": false,
195
203
  "hook event: PermissionRequest": false,
204
+ "hook event: PostCompact": false,
196
205
  "hook event: PostToolUse": false,
206
+ "hook event: PreCompact": false,
197
207
  "hook event: PreToolUse": false,
198
208
  "hook event: SessionStart": false,
199
209
  "hook event: Stop": false,
210
+ "hook event: SubagentStart": false,
211
+ "hook event: SubagentStop": false,
200
212
  "hook event: UserPromptSubmit": false,
201
213
  "hook handler: agent": false,
202
214
  "hook handler: command": false,
@@ -205,10 +217,10 @@
205
217
  "mcp_servers": false,
206
218
  "sandbox": true
207
219
  },
208
- "version": "codex-cli 0.133.0"
220
+ "version": "codex-cli 0.134.0"
209
221
  },
210
222
  "cursor": {
211
- "docs_hash": "56c9209877480e01",
223
+ "docs_hash": "6aa8a8d7cc046f13",
212
224
  "headings": [],
213
225
  "markers": {
214
226
  ".cursor/rules": false,
@@ -224,7 +236,7 @@
224
236
  }
225
237
  },
226
238
  "gemini-cli": {
227
- "docs_hash": "6a47f9b11ff1527d",
239
+ "docs_hash": "5569709cc2e463a8",
228
240
  "headings": [
229
241
  "Breadcrumbs",
230
242
  "Directory actions",
@@ -263,16 +275,16 @@
263
275
  }
264
276
  },
265
277
  "github-copilot": {
266
- "docs_hash": "a5b81592ca646743",
278
+ "docs_hash": "56ac2d5768f930b5",
267
279
  "headings": [
268
280
  "About Copilot auto model selection",
269
281
  "About Copilot integrations",
270
282
  "About agent management",
271
283
  "About agent skills",
272
284
  "About billing for GitHub Copilot in organizations and enterprises",
273
- "About billing for individual GitHub Copilot plans",
274
285
  "About custom agents",
275
286
  "About customizing GitHub Copilot responses",
287
+ "About enterprise accounts for Copilot Business",
276
288
  "Articles",
277
289
  "Did you find what you needed?",
278
290
  "GitHub Copilot",
@@ -295,7 +307,7 @@
295
307
  }
296
308
  },
297
309
  "google-antigravity": {
298
- "docs_hash": "6f089d2c7caabceb",
310
+ "docs_hash": "f933b31ac7414c29",
299
311
  "headings": [],
300
312
  "markers": {
301
313
  "AGENTS.md": false,
@@ -311,7 +323,7 @@
311
323
  }
312
324
  },
313
325
  "opencode": {
314
- "docs_hash": "74eb2d934df9b613",
326
+ "docs_hash": "fe7f7590e4553574",
315
327
  "headings": [
316
328
  "Add features",
317
329
  "Ask questions",
@@ -371,7 +383,7 @@
371
383
  }
372
384
  },
373
385
  "windsurf": {
374
- "docs_hash": "eddf51fabbcaa0a3",
386
+ "docs_hash": "a30041baf564742f",
375
387
  "headings": [
376
388
  "Accounts",
377
389
  "Advanced",
@@ -3,7 +3,7 @@ title: "Hooks Catalog"
3
3
  category: reference
4
4
  service: ai-toolkit
5
5
  tags: [hooks, quality, safety, enforcement, settings.json]
6
- version: "1.5.6"
6
+ version: "1.5.7"
7
7
  created: "2026-03-27"
8
8
  last_updated: "2026-05-25"
9
9
  description: "Complete reference of all ai-toolkit hooks: events, scripts, installation, and runtime behavior."
@@ -13,7 +13,7 @@ description: "Complete reference of all ai-toolkit hooks: events, scripts, insta
13
13
 
14
14
  ## Overview
15
15
 
16
- ai-toolkit provides 28 global hook entries across 14 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/`.
16
+ ai-toolkit provides 29 global hook entries across 14 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
18
  ## Supported Surface
19
19
 
@@ -85,6 +85,10 @@ for debugging; `AI_TOOLKIT_HOOK_QUIET=1` keeps it silent explicitly.
85
85
  - `git push --force`
86
86
  - `chmod -R 777`
87
87
 
88
+ **Exemptions (avoid false positives):**
89
+ - `git push --force-with-lease` / `--force-if-includes` — the safe force-push variants are allowed.
90
+ - A single, non-chained `echo`/`printf`/`git commit`/`git tag` carrying a destructive token as *data* (e.g. a commit message mentioning `DROP TABLE`) is allowed. Chained commands (`&&`, `;`, `|`) are still inspected in full.
91
+
88
92
  ### PreToolUse (file ops) — `guard-path.sh`
89
93
 
90
94
  | Field | Value |
@@ -403,6 +407,19 @@ First-match-wins per file. Built-in runners: `bats`, `pytest`, `vitest`, `jest`.
403
407
 
404
408
  **Overrides:** `CLAUDE_SKIP_COHESION=1` (one-off), `CLAUDE_HOOK_BOOTSTRAP=1` (when editing the hook itself). Skipped when `TOOLKIT_HOOK_PROFILE=minimal`.
405
409
 
410
+ ### PostToolUse (loop guard) — `loop-guard.sh`
411
+
412
+ | Field | Value |
413
+ |-------|-------|
414
+ | Event | `PostToolUse` |
415
+ | Matcher | `Bash\|Edit\|MultiEdit\|Write` |
416
+ | Script | `~/.softspark/ai-toolkit/hooks/loop-guard.sh` |
417
+ | Fires | After every Bash command or file edit |
418
+
419
+ **Action:** Advisory only, never blocks. Hashes a `tool|identity` signature of each action (command for Bash; file path + new content for edits) and keeps the last `AI_TOOLKIT_LOOP_WINDOW` (default 6) hashes per session. When the same signature repeats `AI_TOOLKIT_LOOP_THRESHOLD` times (default 3) it emits a `PostToolUse` `additionalContext` advisory telling Claude to reassess instead of retrying. Catches successful-but-identical loops that the `/repeat` circuit breaker (which only counts failures) does not. Edits track content, so normal iterative editing of one file does not trip it. Only short hashes are stored — never raw payloads.
420
+
421
+ **Tunables:** `AI_TOOLKIT_LOOP_WINDOW`, `AI_TOOLKIT_LOOP_THRESHOLD`. Skipped when `TOOLKIT_HOOK_PROFILE=minimal`; honours `AI_TOOLKIT_DISABLED_HOOKS`.
422
+
406
423
  ### PostToolUse (search-first tracker) — `search-tracker.sh`
407
424
 
408
425
  | Field | Value |
@@ -480,6 +497,8 @@ Set in `.claude/settings.local.json`:
480
497
  | `standard` | All hooks (default) |
481
498
  | `strict` | Standard + mypy --strict on task completion |
482
499
 
500
+ **Disabling individual hooks:** set `AI_TOOLKIT_DISABLED_HOOKS` to a comma-separated list of hook names (with or without `.sh`), e.g. `{ "env": { "AI_TOOLKIT_DISABLED_HOOKS": "loop-guard,quality-check" } }`. Listed hooks become no-ops. This covers profile-gated hooks only; the safety guards (`guard-destructive`/`guard-path`/`guard-config`) intentionally cannot be env-disabled — remove them deliberately with `ai-toolkit remove-hook`.
501
+
483
502
  Non-blocking informational context is silent in plain-text mode by default while
484
503
  side effects and blocking decisions still run. Set `AI_TOOLKIT_HOOK_VERBOSE=1`
485
504
  only when debugging hook context locally. `AI_TOOLKIT_HOOK_QUIET=1` keeps hook
@@ -561,7 +580,7 @@ commands explicitly silent, and Codex-generated hooks plus Claude's bundled
561
580
 
562
581
  **Hook script not found:**
563
582
  ```bash
564
- ls ~/.softspark/ai-toolkit/hooks/ # should list 27 .sh files (plus _profile-check.sh + _locate-toolkit.sh + _hook-io.sh + _search-capability.sh helpers + test-cohesion-map.json)
583
+ ls ~/.softspark/ai-toolkit/hooks/ # should list 28 .sh files (plus _profile-check.sh + _locate-toolkit.sh + _hook-io.sh + _search-capability.sh helpers + test-cohesion-map.json)
565
584
  ai-toolkit update # re-copies scripts
566
585
  ```
567
586
 
@@ -5,7 +5,7 @@ service: ai-toolkit
5
5
  tags: [mcp, editors, compatibility, codex, cursor]
6
6
  version: "1.1.0"
7
7
  created: "2026-04-12"
8
- last_updated: "2026-04-28"
8
+ last_updated: "2026-05-30"
9
9
  description: "Official MCP support matrix and native config targets for editors supported by ai-toolkit."
10
10
  ---
11
11
 
@@ -5,7 +5,7 @@ service: ai-toolkit
5
5
  tags: [editors, platforms, generators, integration, ecosystem]
6
6
  version: "1.3.0"
7
7
  created: "2026-04-23"
8
- last_updated: "2026-05-25"
8
+ last_updated: "2026-05-30"
9
9
  description: "Human-readable view of scripts/ecosystem_tools.json — the canonical list of tools ai-toolkit integrates with (Claude Code + 11 editors), their documentation URLs, config paths, our generators, and tracked capability markers."
10
10
  ---
11
11
 
@@ -30,7 +30,7 @@ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed b
30
30
  | Release notes | https://github.com/anthropics/claude-code/releases |
31
31
  | Config paths | `~/.claude/settings.json`, `.claude/settings.local.json`, `CLAUDE.md`, `.claude/agents/*.md`, `.claude/skills/*/SKILL.md`, `~/.claude/themes/*.json` (v2.1.118+) |
32
32
  | Our generators | — (Claude Code is the primary target; toolkit content ships directly as `.md` files and `settings.json` merges) |
33
- | Tracked hook events | Core: `SessionStart`, `SessionEnd`, `UserPromptSubmit`, `Notification`. Tool: `PreToolUse`, `PostToolUse`. Turn: `Stop`, `StopFailure`. Subagent: `SubagentStart`, `SubagentStop`. Compaction: `PreCompact`, `PostCompact`. Permissions: `PermissionRequest`, `PermissionDenied`. Elicitation: `Elicitation`, `ElicitationResult`. Teams: `TaskCreated`, `TaskCompleted`, `TeammateIdle`. Worktrees/env: `WorktreeCreate`, `WorktreeRemove`, `CwdChanged`, `FileChanged`, `ConfigChange`. Setup: `Setup`, `InstructionsLoaded` |
33
+ | Tracked hook events | Core: `SessionStart`, `SessionEnd`, `UserPromptSubmit`, `Notification`, `MessageDisplay`. Tool: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PostToolBatch`. Turn: `Stop`, `StopFailure`, `UserPromptExpansion`. Subagent: `SubagentStart`, `SubagentStop`. Compaction: `PreCompact`, `PostCompact`. Permissions: `PermissionRequest`, `PermissionDenied`. Elicitation: `Elicitation`, `ElicitationResult`. Teams: `TaskCreated`, `TaskCompleted`, `TeammateIdle`. Worktrees/env: `WorktreeCreate`, `WorktreeRemove`, `CwdChanged`, `FileChanged`, `ConfigChange`. Setup: `Setup`, `InstructionsLoaded` |
34
34
  | Tracked handler types | `command`, `prompt`, `agent`, `mcp_tool` |
35
35
  | Other capabilities | slash commands, MCP server/client, sub-agent, output style, `SKILL.md` (≥500 lines warn) |
36
36
  | Version probe | `claude --version` |
@@ -163,7 +163,7 @@ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed b
163
163
  | Release notes | https://github.com/openai/codex/releases |
164
164
  | Config paths | `AGENTS.md`, `.agents/rules/*.md`, `.agents/skills/*/SKILL.md`, `.codex/hooks.json`, `~/.codex/config.toml` |
165
165
  | Our generators | `scripts/generate_codex.py`, `scripts/generate_codex_rules.py`, `scripts/generate_codex_hooks.py`, `scripts/generate_codex_skills.py` (opt-in via `--codex-skills`) |
166
- | Tracked hook events | `PreToolUse`, `PostToolUse`, `SessionStart`, `UserPromptSubmit`, `Stop`, `PermissionRequest` (6 events supported upstream in `config.toml`) |
166
+ | Tracked hook events | Upstream canonical (codex-rs `HookEventName` enum): `PreToolUse`, `PostToolUse`, `PermissionRequest`, `PreCompact`, `PostCompact`, `SessionStart`, `UserPromptSubmit`, `SubagentStart`, `SubagentStop`, `Stop` (10 events). We currently wire a subset: `SessionStart`, `PreToolUse`, `PermissionRequest`, `UserPromptSubmit`, `Stop`. |
167
167
  | Tracked handler types | `command` (emitted by default); `prompt` and `agent` available upstream but authored by hand |
168
168
  | Other capabilities | `AGENTS.md`, `config.toml`, `mcp_servers`, sandbox policies, `.agents/skills/*/SKILL.md` (native Codex skill discovery path) |
169
169
  | Version probe | `codex --version` |
package/llms-full.txt CHANGED
@@ -6965,9 +6965,9 @@ title: "AI Toolkit - Codex CLI Compatibility"
6965
6965
  category: reference
6966
6966
  service: ai-toolkit
6967
6967
  tags: [codex, compatibility, install, skills, hooks]
6968
- version: "1.0.2"
6968
+ version: "1.0.3"
6969
6969
  created: "2026-04-12"
6970
- last_updated: "2026-05-21"
6970
+ last_updated: "2026-05-25"
6971
6971
  description: "Reference for how ai-toolkit maps Claude-oriented skills, hooks, and plugin packs to Codex CLI."
6972
6972
  ---
6973
6973
 
@@ -7072,12 +7072,27 @@ This means Claude-only events such as `TaskCompleted`, `TeammateIdle`,
7072
7072
  `~/.codex/hooks.json` (global layer). Non-Codex events are silently skipped.
7073
7073
  `remove-hook` cleans both Claude and Codex targets.
7074
7074
 
7075
- Generated Codex hook commands include `AI_TOOLKIT_HOOK_QUIET=1`. The
7076
- `UserPromptSubmit` governance hook additionally sets `AI_TOOLKIT_HOOK_FORMAT=json`
7077
- so it can pass quiet `additionalContext` before the model responds. This keeps
7078
- non-blocking reminders and startup context out of visible hook output while
7079
- preserving hook side effects, proactive search-first context, and blocking
7080
- decisions such as search-first Stop enforcement.
7075
+ Generated Codex hook commands include `AI_TOOLKIT_HOOK_QUIET=1`. The generated
7076
+ `UserPromptSubmit` governance hook does not set `AI_TOOLKIT_HOOK_FORMAT=json`
7077
+ by default because Codex currently renders `additionalContext` as visible hook
7078
+ context in the TUI. This keeps prompt-submit output quiet while preserving hook
7079
+ side effects and blocking decisions such as search-first Stop enforcement.
7080
+
7081
+ Codex `UserPromptSubmit` JSON output is event-specific. When emitting context,
7082
+ the hook must include the event name alongside the context:
7083
+
7084
+ ```json
7085
+ {
7086
+ "hookSpecificOutput": {
7087
+ "hookEventName": "UserPromptSubmit",
7088
+ "additionalContext": "..."
7089
+ },
7090
+ "suppressOutput": true
7091
+ }
7092
+ ```
7093
+
7094
+ Older `{"hookSpecificOutput":{"additionalContext":"..."}}` output can be valid
7095
+ JSON but fail newer Codex event-output validation.
7081
7096
 
7082
7097
  Plain-text informational hook context is also silent by default in the shared
7083
7098
  hook helper. Set `AI_TOOLKIT_HOOK_VERBOSE=1` only when debugging hook output
@@ -8880,7 +8895,7 @@ title: "Hooks Catalog"
8880
8895
  category: reference
8881
8896
  service: ai-toolkit
8882
8897
  tags: [hooks, quality, safety, enforcement, settings.json]
8883
- version: "1.5.5"
8898
+ version: "1.5.6"
8884
8899
  created: "2026-03-27"
8885
8900
  last_updated: "2026-05-25"
8886
8901
  description: "Complete reference of all ai-toolkit hooks: events, scripts, installation, and runtime behavior."
@@ -8890,7 +8905,7 @@ description: "Complete reference of all ai-toolkit hooks: events, scripts, insta
8890
8905
 
8891
8906
  ## Overview
8892
8907
 
8893
- ai-toolkit provides 28 global hook entries across 14 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/`.
8908
+ ai-toolkit provides 29 global hook entries across 14 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/`.
8894
8909
 
8895
8910
  ## Supported Surface
8896
8911
 
@@ -8962,6 +8977,10 @@ for debugging; `AI_TOOLKIT_HOOK_QUIET=1` keeps it silent explicitly.
8962
8977
  - `git push --force`
8963
8978
  - `chmod -R 777`
8964
8979
 
8980
+ **Exemptions (avoid false positives):**
8981
+ - `git push --force-with-lease` / `--force-if-includes` — the safe force-push variants are allowed.
8982
+ - A single, non-chained `echo`/`printf`/`git commit`/`git tag` carrying a destructive token as *data* (e.g. a commit message mentioning `DROP TABLE`) is allowed. Chained commands (`&&`, `;`, `|`) are still inspected in full.
8983
+
8965
8984
  ### PreToolUse (file ops) — `guard-path.sh`
8966
8985
 
8967
8986
  | Field | Value |
@@ -8991,12 +9010,29 @@ work, evidence-first debugging, KB-first research, and validation expectations.
8991
9010
  Skipped when `TOOLKIT_HOOK_PROFILE=minimal`. The bundled `app/hooks.json`
8992
9011
  registers this command with `AI_TOOLKIT_HOOK_QUIET=1 AI_TOOLKIT_HOOK_FORMAT=json`.
8993
9012
  This keeps the hook visually quiet (`suppressOutput: true`) while still
8994
- injecting `hookSpecificOutput.additionalContext` before Claude starts working.
9013
+ injecting event-specific JSON context before Claude starts working in runtimes
9014
+ that consume hidden context:
9015
+
9016
+ ```json
9017
+ {
9018
+ "hookSpecificOutput": {
9019
+ "hookEventName": "UserPromptSubmit",
9020
+ "additionalContext": "..."
9021
+ },
9022
+ "suppressOutput": true
9023
+ }
9024
+ ```
9025
+
8995
9026
  That context is the proactive half of search-first enforcement; the paired
8996
9027
  `stop-search-check.sh` remains the corrective half. In plain-text mode,
8997
9028
  informational reminders are silent by default and require
8998
9029
  `AI_TOOLKIT_HOOK_VERBOSE=1`.
8999
9030
 
9031
+ Codex-generated hooks intentionally run this script without
9032
+ `AI_TOOLKIT_HOOK_FORMAT=json` by default because Codex renders
9033
+ `additionalContext` visibly in the TUI; the search-first flag side effect still
9034
+ arms the corrective Stop hook.
9035
+
9000
9036
  ### UserPromptSubmit (usage tracking) — `track-usage.sh`
9001
9037
 
9002
9038
  | Field | Value |
@@ -9006,7 +9042,7 @@ informational reminders are silent by default and require
9006
9042
  | Script | `~/.softspark/ai-toolkit/hooks/track-usage.sh` |
9007
9043
  | Fires | Before Claude starts working on a submitted prompt |
9008
9044
 
9009
- **Action:** Records skill invocations (slash commands like `/commit`, `/review`) to `~/.softspark/ai-toolkit/stats.json` for local usage analytics. Non-slash prompts are ignored.
9045
+ **Action:** Records skill invocations (slash commands like `/commit`, `/review`) to `~/.softspark/ai-toolkit/stats.json` for local usage analytics. Non-slash prompts are ignored. Stats writes are best-effort and stay silent if the local state path is not writable.
9010
9046
 
9011
9047
  ### PostToolUse (edit feedback) — `post-tool-use.sh`
9012
9048
 
@@ -9263,6 +9299,19 @@ First-match-wins per file. Built-in runners: `bats`, `pytest`, `vitest`, `jest`.
9263
9299
 
9264
9300
  **Overrides:** `CLAUDE_SKIP_COHESION=1` (one-off), `CLAUDE_HOOK_BOOTSTRAP=1` (when editing the hook itself). Skipped when `TOOLKIT_HOOK_PROFILE=minimal`.
9265
9301
 
9302
+ ### PostToolUse (loop guard) — `loop-guard.sh`
9303
+
9304
+ | Field | Value |
9305
+ |-------|-------|
9306
+ | Event | `PostToolUse` |
9307
+ | Matcher | `Bash\|Edit\|MultiEdit\|Write` |
9308
+ | Script | `~/.softspark/ai-toolkit/hooks/loop-guard.sh` |
9309
+ | Fires | After every Bash command or file edit |
9310
+
9311
+ **Action:** Advisory only, never blocks. Hashes a `tool|identity` signature of each action (command for Bash; file path + new content for edits) and keeps the last `AI_TOOLKIT_LOOP_WINDOW` (default 6) hashes per session. When the same signature repeats `AI_TOOLKIT_LOOP_THRESHOLD` times (default 3) it emits a `PostToolUse` `additionalContext` advisory telling Claude to reassess instead of retrying. Catches successful-but-identical loops that the `/repeat` circuit breaker (which only counts failures) does not. Edits track content, so normal iterative editing of one file does not trip it. Only short hashes are stored — never raw payloads.
9312
+
9313
+ **Tunables:** `AI_TOOLKIT_LOOP_WINDOW`, `AI_TOOLKIT_LOOP_THRESHOLD`. Skipped when `TOOLKIT_HOOK_PROFILE=minimal`; honours `AI_TOOLKIT_DISABLED_HOOKS`.
9314
+
9266
9315
  ### PostToolUse (search-first tracker) — `search-tracker.sh`
9267
9316
 
9268
9317
  | Field | Value |
@@ -9340,6 +9389,8 @@ Set in `.claude/settings.local.json`:
9340
9389
  | `standard` | All hooks (default) |
9341
9390
  | `strict` | Standard + mypy --strict on task completion |
9342
9391
 
9392
+ **Disabling individual hooks:** set `AI_TOOLKIT_DISABLED_HOOKS` to a comma-separated list of hook names (with or without `.sh`), e.g. `{ "env": { "AI_TOOLKIT_DISABLED_HOOKS": "loop-guard,quality-check" } }`. Listed hooks become no-ops. This covers profile-gated hooks only; the safety guards (`guard-destructive`/`guard-path`/`guard-config`) intentionally cannot be env-disabled — remove them deliberately with `ai-toolkit remove-hook`.
9393
+
9343
9394
  Non-blocking informational context is silent in plain-text mode by default while
9344
9395
  side effects and blocking decisions still run. Set `AI_TOOLKIT_HOOK_VERBOSE=1`
9345
9396
  only when debugging hook context locally. `AI_TOOLKIT_HOOK_QUIET=1` keeps hook
@@ -9421,7 +9472,7 @@ commands explicitly silent, and Codex-generated hooks plus Claude's bundled
9421
9472
 
9422
9473
  **Hook script not found:**
9423
9474
  ```bash
9424
- ls ~/.softspark/ai-toolkit/hooks/ # should list 27 .sh files (plus _profile-check.sh + _locate-toolkit.sh + _hook-io.sh + _search-capability.sh helpers + test-cohesion-map.json)
9475
+ ls ~/.softspark/ai-toolkit/hooks/ # should list 28 .sh files (plus _profile-check.sh + _locate-toolkit.sh + _hook-io.sh + _search-capability.sh helpers + test-cohesion-map.json)
9425
9476
  ai-toolkit update # re-copies scripts
9426
9477
  ```
9427
9478
 
@@ -9988,7 +10039,7 @@ service: ai-toolkit
9988
10039
  tags: [mcp, editors, compatibility, codex, cursor]
9989
10040
  version: "1.1.0"
9990
10041
  created: "2026-04-12"
9991
- last_updated: "2026-04-28"
10042
+ last_updated: "2026-05-30"
9992
10043
  description: "Official MCP support matrix and native config targets for editors supported by ai-toolkit."
9993
10044
  ---
9994
10045
 
@@ -11716,7 +11767,7 @@ service: ai-toolkit
11716
11767
  tags: [editors, platforms, generators, integration, ecosystem]
11717
11768
  version: "1.3.0"
11718
11769
  created: "2026-04-23"
11719
- last_updated: "2026-05-25"
11770
+ last_updated: "2026-05-30"
11720
11771
  description: "Human-readable view of scripts/ecosystem_tools.json — the canonical list of tools ai-toolkit integrates with (Claude Code + 11 editors), their documentation URLs, config paths, our generators, and tracked capability markers."
11721
11772
  ---
11722
11773
 
@@ -11741,7 +11792,7 @@ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed b
11741
11792
  | Release notes | https://github.com/anthropics/claude-code/releases |
11742
11793
  | Config paths | `~/.claude/settings.json`, `.claude/settings.local.json`, `CLAUDE.md`, `.claude/agents/*.md`, `.claude/skills/*/SKILL.md`, `~/.claude/themes/*.json` (v2.1.118+) |
11743
11794
  | Our generators | — (Claude Code is the primary target; toolkit content ships directly as `.md` files and `settings.json` merges) |
11744
- | Tracked hook events | Core: `SessionStart`, `SessionEnd`, `UserPromptSubmit`, `Notification`. Tool: `PreToolUse`, `PostToolUse`. Turn: `Stop`, `StopFailure`. Subagent: `SubagentStart`, `SubagentStop`. Compaction: `PreCompact`, `PostCompact`. Permissions: `PermissionRequest`, `PermissionDenied`. Elicitation: `Elicitation`, `ElicitationResult`. Teams: `TaskCreated`, `TaskCompleted`, `TeammateIdle`. Worktrees/env: `WorktreeCreate`, `WorktreeRemove`, `CwdChanged`, `FileChanged`, `ConfigChange`. Setup: `Setup`, `InstructionsLoaded` |
11795
+ | Tracked hook events | Core: `SessionStart`, `SessionEnd`, `UserPromptSubmit`, `Notification`, `MessageDisplay`. Tool: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PostToolBatch`. Turn: `Stop`, `StopFailure`, `UserPromptExpansion`. Subagent: `SubagentStart`, `SubagentStop`. Compaction: `PreCompact`, `PostCompact`. Permissions: `PermissionRequest`, `PermissionDenied`. Elicitation: `Elicitation`, `ElicitationResult`. Teams: `TaskCreated`, `TaskCompleted`, `TeammateIdle`. Worktrees/env: `WorktreeCreate`, `WorktreeRemove`, `CwdChanged`, `FileChanged`, `ConfigChange`. Setup: `Setup`, `InstructionsLoaded` |
11745
11796
  | Tracked handler types | `command`, `prompt`, `agent`, `mcp_tool` |
11746
11797
  | Other capabilities | slash commands, MCP server/client, sub-agent, output style, `SKILL.md` (≥500 lines warn) |
11747
11798
  | Version probe | `claude --version` |
@@ -11874,7 +11925,7 @@ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed b
11874
11925
  | Release notes | https://github.com/openai/codex/releases |
11875
11926
  | Config paths | `AGENTS.md`, `.agents/rules/*.md`, `.agents/skills/*/SKILL.md`, `.codex/hooks.json`, `~/.codex/config.toml` |
11876
11927
  | Our generators | `scripts/generate_codex.py`, `scripts/generate_codex_rules.py`, `scripts/generate_codex_hooks.py`, `scripts/generate_codex_skills.py` (opt-in via `--codex-skills`) |
11877
- | Tracked hook events | `PreToolUse`, `PostToolUse`, `SessionStart`, `UserPromptSubmit`, `Stop`, `PermissionRequest` (6 events supported upstream in `config.toml`) |
11928
+ | Tracked hook events | Upstream canonical (codex-rs `HookEventName` enum): `PreToolUse`, `PostToolUse`, `PermissionRequest`, `PreCompact`, `PostCompact`, `SessionStart`, `UserPromptSubmit`, `SubagentStart`, `SubagentStop`, `Stop` (10 events). We currently wire a subset: `SessionStart`, `PreToolUse`, `PermissionRequest`, `UserPromptSubmit`, `Stop`. |
11878
11929
  | Tracked handler types | `command` (emitted by default); `prompt` and `agent` available upstream but authored by hand |
11879
11930
  | Other capabilities | `AGENTS.md`, `config.toml`, `mcp_servers`, sandbox policies, `.agents/skills/*/SKILL.md` (native Codex skill discovery path) |
11880
11931
  | Version probe | `codex --version` |
package/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.4.1",
2
+ "version": "4.5.0",
3
3
  "components": {
4
4
  "agents": {
5
5
  "description": "44 specialized agents (orchestrator, backend, frontend, security, devops, etc.)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softspark/ai-toolkit",
3
- "version": "4.4.1",
3
+ "version": "4.5.0",
4
4
  "description": "AI coding toolkit: 107 skills, 44 agents, 12-editor write-through (Claude, Cursor, Windsurf, Copilot, Gemini, Cline, Roo, Aider, Augment, Antigravity, Codex, opencode), machine-enforced safety constitution, SARIF audit, signed npm provenance.",
5
5
  "keywords": [
6
6
  "claude",
@@ -2,7 +2,8 @@
2
2
  """Skill & Agent Security Auditor.
3
3
 
4
4
  Deterministic scanner for ai-toolkit skills and agents.
5
- Detects dangerous code patterns, hardcoded secrets, and permission issues.
5
+ Detects dangerous code patterns, hardcoded secrets, permission issues, and
6
+ invisible/smuggled Unicode in shipped prompt text.
6
7
 
7
8
  Stdlib-only. JSON output to stdout. Non-zero exit on HIGH findings.
8
9
 
@@ -22,6 +23,7 @@ from __future__ import annotations
22
23
  import json
23
24
  import re
24
25
  import sys
26
+ import unicodedata
25
27
  from pathlib import Path
26
28
 
27
29
  sys.path.insert(0, str(Path(__file__).resolve().parent))
@@ -149,6 +151,73 @@ def scan_secrets(filepath: Path, findings: list[Finding]) -> None:
149
151
  findings.append(Finding(severity, rel, lineno, regex, desc))
150
152
 
151
153
 
154
+ # ---------------------------------------------------------------------------
155
+ # Unicode safety — invisible / smuggled characters in shipped prompt text.
156
+ # Prompt files (skills, agents, rules, personas, mcp-templates) ARE the
157
+ # product. A poisoned PR can carry instructions a human reviewer cannot see:
158
+ # regex-over-decoded-text checks (above) never catch them.
159
+ # ---------------------------------------------------------------------------
160
+
161
+ # ASCII smuggling: U+E0000–U+E007F mirror ASCII inside Unicode "tag" chars.
162
+ _UNICODE_TAG_BLOCK = range(0xE0000, 0xE0080)
163
+
164
+ # Trojan Source bidi controls (CVE-2021-42574) — reorder rendered text vs. its
165
+ # logical/source order, hiding instructions from a reviewer.
166
+ _UNICODE_BIDI_HIGH = frozenset({
167
+ 0x202A, 0x202B, 0x202C, 0x202D, 0x202E, # LRE RLE PDF LRO RLO
168
+ 0x2066, 0x2067, 0x2068, 0x2069, # LRI RLI FSI PDI
169
+ })
170
+
171
+ # Invisible / zero-width formatting that can hide or splice text.
172
+ # U+200D (ZERO WIDTH JOINER) is deliberately EXCLUDED — it is required by
173
+ # legitimate emoji sequences and i18n text, so flagging it floods false
174
+ # positives and trains maintainers to disable the gate.
175
+ _UNICODE_INVISIBLE_WARN = frozenset({
176
+ 0x200B, 0x200C, 0x200E, 0x200F, 0x2060, 0xFEFF, 0x00AD,
177
+ 0x180E, 0x115F, 0x1160, 0x3164, 0xFFA0, 0x17B4, 0x17B5,
178
+ })
179
+
180
+
181
+ def _char_name(cp: int) -> str:
182
+ """Best-effort Unicode name for diagnostics."""
183
+ try:
184
+ return unicodedata.name(chr(cp))
185
+ except ValueError:
186
+ return f"U+{cp:04X}"
187
+
188
+
189
+ def scan_unicode(filepath: Path, findings: list[Finding]) -> None:
190
+ """Flag invisible / smuggled Unicode in shipped prompt text."""
191
+ try:
192
+ text = filepath.read_text(encoding="utf-8", errors="replace")
193
+ except OSError:
194
+ return
195
+ rel = str(filepath)
196
+ for lineno, line in enumerate(text.splitlines(), 1):
197
+ for ch in line:
198
+ cp = ord(ch)
199
+ if cp < 0x80: # plain ASCII — fast path, always safe
200
+ continue
201
+ if cp in _UNICODE_TAG_BLOCK:
202
+ findings.append(Finding(
203
+ "HIGH", rel, lineno, "unicode-tag-block",
204
+ f"Unicode tag char {_char_name(cp)} (U+{cp:04X}) — "
205
+ "ASCII smuggling / invisible prompt injection",
206
+ ))
207
+ elif cp in _UNICODE_BIDI_HIGH:
208
+ findings.append(Finding(
209
+ "HIGH", rel, lineno, "unicode-bidi-control",
210
+ f"Bidi control {_char_name(cp)} (U+{cp:04X}) — "
211
+ "Trojan Source text reordering",
212
+ ))
213
+ elif cp in _UNICODE_INVISIBLE_WARN:
214
+ findings.append(Finding(
215
+ "WARN", rel, lineno, "unicode-invisible",
216
+ f"Invisible/zero-width char {_char_name(cp)} (U+{cp:04X}) — "
217
+ "verify it is intentional",
218
+ ))
219
+
220
+
152
221
  # Description quality — per Anthropic docs (code.claude.com/docs/en/skills.md):
153
222
  # description + when_to_use combined ≤ 1536 chars; first sentence carries
154
223
  # the trigger keywords that let the LLM route to this skill.
@@ -373,15 +442,26 @@ def audit(toolkit_root: Path) -> list[Finding]:
373
442
  scan_file_patterns(sh, BASH_WARN, "WARN", findings)
374
443
  scan_secrets(sh, findings)
375
444
 
376
- # Secrets in any text file
445
+ # Secrets + invisible Unicode in any text file
377
446
  for md in skill_dir.rglob("*.md"):
378
447
  scan_secrets(md, findings)
448
+ scan_unicode(md, findings)
379
449
 
380
450
  # Scan agents
381
451
  if agents.is_dir():
382
452
  for agent_md in sorted(agents.glob("*.md")):
383
453
  check_agent(agent_md, findings)
384
454
  scan_secrets(agent_md, findings)
455
+ scan_unicode(agent_md, findings)
456
+
457
+ # Unicode safety across the rest of the shipped prompt surface.
458
+ for extra in ("rules", "personas", "mcp-templates"):
459
+ extra_dir = app / extra
460
+ if not extra_dir.is_dir():
461
+ continue
462
+ for f in sorted(extra_dir.rglob("*")):
463
+ if f.is_file() and f.suffix in (".md", ".json"):
464
+ scan_unicode(f, findings)
385
465
 
386
466
  # Sort: HIGH first, then WARN, then INFO
387
467
  order = {"HIGH": 0, "WARN": 1, "INFO": 2}