@softspark/ai-toolkit 4.12.0 → 4.14.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +31 -15
  3. package/app/.claude-plugin/plugin.json +11 -19
  4. package/app/ARCHITECTURE.md +6 -6
  5. package/app/agents/explorer-agent.md +1 -1
  6. package/app/agents/fact-checker.md +1 -1
  7. package/app/claude-app/global-instructions.md +10 -0
  8. package/app/claude-app/hooks/hooks.json +284 -0
  9. package/app/claude-app/skills/ai-toolkit-rules/SKILL.md +359 -0
  10. package/app/hooks/config-desync-guard.sh +63 -23
  11. package/app/plugins/README.md +4 -1
  12. package/app/skills/json-mode-patterns/SKILL.md +2 -2
  13. package/app/skills/model-routing-patterns/SKILL.md +24 -7
  14. package/app/skills/prompt-caching-patterns/SKILL.md +2 -2
  15. package/app/skills/skill-creator/SKILL.md +1 -1
  16. package/benchmarks/ecosystem-doctor-snapshot.json +91 -25
  17. package/bin/ai-toolkit.js +21 -3
  18. package/kb/planning/drop-cascade-hooks-after-sunset.md +13 -8
  19. package/kb/procedures/ecosystem-sync-sop.md +5 -5
  20. package/kb/procedures/maintenance-sop.md +42 -4
  21. package/kb/procedures/release-preparation-sop.md +5 -1
  22. package/kb/procedures/release-verification-sop.md +25 -9
  23. package/kb/reference/architecture-overview.md +7 -2
  24. package/kb/reference/claude-ecosystem-expansion-foundations.md +12 -3
  25. package/kb/reference/cli-reference.md +4 -2
  26. package/kb/reference/global-install-model.md +24 -3
  27. package/kb/reference/hooks-catalog.md +2 -3
  28. package/kb/reference/plugin-pack-conventions.md +5 -5
  29. package/kb/reference/skills-catalog.md +2 -0
  30. package/kb/reference/supported-tools-registry.md +30 -13
  31. package/kb/reference/unique-features.md +3 -2
  32. package/llms-full.txt +179 -60
  33. package/manifest.json +8 -8
  34. package/package.json +4 -3
  35. package/scripts/_common.py +2 -2
  36. package/scripts/claude_app.py +347 -0
  37. package/scripts/doctor.py +85 -4
  38. package/scripts/ecosystem_tools.json +33 -5
  39. package/scripts/generate_devin_hooks.py +3 -4
  40. package/scripts/generate_windsurf_skills.py +5 -6
  41. package/scripts/install.py +23 -21
  42. package/scripts/install_steps/ai_tools.py +96 -6
  43. package/scripts/install_steps/install_state.py +2 -0
  44. package/scripts/update_projects.py +12 -1
  45. package/scripts/validate.py +34 -2
  46. package/AGENTS.md +0 -655
  47. package/scripts/generate_windsurf_hooks.py +0 -152
@@ -0,0 +1,359 @@
1
+ ---
2
+ name: ai-toolkit-rules
3
+ description: "Mandatory engineering, security, testing, git, performance, quality, and response rules. Claude MUST load this skill for every technical, coding, debugging, review, architecture, DevOps, data, or file-editing task in Chat or Cowork."
4
+ user-invocable: true
5
+ ---
6
+
7
+ # AI Toolkit Rules
8
+
9
+ Apply every relevant rule below before acting. Treat MUST/NEVER language as mandatory.
10
+
11
+ ## Source: `app/rules/claude-toolkit-rules.md`
12
+
13
+ # Claude Toolkit
14
+
15
+ Shared AI development toolkit — lifecycle hooks, safety constitution, multi-platform support.
16
+
17
+ ## Skill Tiers
18
+
19
+ - **Tier 1** — single-agent: `/debug`, `/review`, `/refactor`, `/analyze`, `/docs`, `/plan`, `/explain`, `/tdd`, `/triage-issue`
20
+ - **Tier 1.5** — planning: `/write-a-prd` → `/prd-to-plan` → `/prd-to-issues`; design: `/design-an-interface`, `/architecture-audit`, `/refactor-plan`
21
+ - **Tier 2** — multi-agent: `/workflow <type>` (feature-development, backend-feature, frontend-feature, api-design, database-evolution, test-coverage, security-audit, debugging, incident-response, spike, codebase-onboarding, performance-optimization, infrastructure-change, application-deploy, proactive-troubleshooting)
22
+ - **Tier 3** — custom: `/orchestrate <desc>` (3–6 agents) | `/swarm <mode> <desc>` (map-reduce | consensus | relay)
23
+
24
+ ## Path Safety
25
+ - NEVER guess or hallucinate user home directory paths
26
+ - Use `~` or `$HOME` instead of hardcoded `/Users/<username>/` or `/home/<username>/`
27
+ - When an absolute path is needed, run `echo $HOME` first to get the correct value
28
+
29
+ ## User Preferences
30
+
31
+ - **Style:** Direct & efficient. No pleasantries. Measurable results.
32
+ - **Methodology:** Provide >=3 alternatives. Use Socratic questioning.
33
+ - **Review:** Apply "Devil's Advocate" critique to decisions.
34
+
35
+ ## Source: `app/rules/git-conventions.md`
36
+
37
+ # Git Conventions
38
+
39
+ - Do NOT add `Co-Authored-By: Claude` or any AI co-authorship to commits
40
+ - Do NOT add Claude signatures or attribution to commit messages
41
+ - Conventional commits format: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`
42
+
43
+ ## Source: `app/rules/output-mode.md`
44
+
45
+ # Output Mode
46
+
47
+ `output-mode: concise`
48
+
49
+ Default response mode for this project is **concise**. The `brand-voice` skill (when present in ai-toolkit) auto-loads its `concise` rules; assistants without that skill should still apply the directives below.
50
+
51
+ ## Concise Mode Directives
52
+
53
+ - **No preamble.** Skip "I'll now...", "Sure, let me...", "Great question!" and similar warm-ups. Start with the answer.
54
+ - **Lead with the result.** Conclusion or output first; explanation only if asked or non-obvious.
55
+ - **Max 3 sentences per closed question.** Yes/no, single-fact, or "where is X" answers stay under three sentences.
56
+ - **Tables and lists over prose** when comparing options, listing steps, or showing values.
57
+ - **No trailing summaries.** If the diff or output already shows what changed, do not restate it.
58
+ - **Drop filler adjectives.** No "nice", "great", "powerful", "robust" unless the user asked for evaluation.
59
+ - **Cite file paths as `path:line`** instead of paragraphs describing where things live.
60
+ - **Reserve longer prose** for: architecture proposals, trade-off analyses, plans with risks. Everything else: terse.
61
+
62
+ ## When to escalate to verbose
63
+
64
+ - User explicitly asks: "explain in detail", "walk me through", "give me the full picture".
65
+ - Reporting a non-obvious failure mode where missing context would mislead.
66
+ - Architecture / RFC / ADR / trade-off documents — those have their own structure.
67
+
68
+ ## How to override
69
+
70
+ - Per-session: `/brand-voice default` (or `/brand-voice strict` for even tighter)
71
+ - Per-project: change this rule's `output-mode:` value in the project's `CLAUDE.md`
72
+ - Permanent removal: re-run `ai-toolkit install --skip rules` or strip the `<!-- TOOLKIT:output-mode -->` block manually
73
+
74
+ ## Source: `app/rules/quality-gates.md`
75
+
76
+ # Quality Gates & Mandatory Practices
77
+
78
+ ## MANDATORY PRACTICES
79
+ 1. **Plan First:** Tasks >1h require Plan, Success Criteria, and Pre-Mortem.
80
+ 2. **Quality Gates:**
81
+ * `ruff check .` (0 errors)
82
+ * `mypy --strict src/` (0 errors)
83
+ * `pytest --cov=src` (>70% coverage)
84
+ * **Type Safety:** 100% public APIs, >60% internal.
85
+ 3. **Security:** No secrets in code, sanitization, auth z/n.
86
+
87
+ ## Source: `app/rules/common/coding-style.md`
88
+
89
+ # Universal Coding Style
90
+
91
+ ## Principles
92
+ - KISS: simplest solution that works. Clever code is a liability. If 200 lines could be 50, rewrite.
93
+ - DRY: extract when you repeat 3+ times, not before.
94
+ - YAGNI: do not build features "just in case." No abstractions for single-use code.
95
+ - Prefer immutability: use `const`, `final`, `val`, `let` by default.
96
+ - Fail fast: validate inputs at boundaries, return early on errors.
97
+ - State assumptions before coding. If uncertain or multiple interpretations exist, ask — don't pick silently.
98
+
99
+ ## Naming
100
+ - Use descriptive names that reveal intent (`remainingRetries`, not `r`).
101
+ - Boolean variables/functions: prefix with `is`, `has`, `can`, `should`.
102
+ - Functions: verb + noun (`fetchUser`, `calculateTotal`, `validateInput`).
103
+ - Avoid abbreviations unless universally understood (`id`, `url`, `http`).
104
+ - Collections use plural nouns (`users`, `orderItems`).
105
+
106
+ ## Functions
107
+ - Max 20-30 lines per function. If longer, extract.
108
+ - Max 3 parameters. Beyond that, use an options/config object.
109
+ - Single responsibility: one function does one thing.
110
+ - Pure functions preferred: same input, same output, no side effects.
111
+ - Avoid boolean parameters: use separate functions or enums.
112
+
113
+ ## File Organization
114
+ - One primary concept per file (class, module, component).
115
+ - Group imports: stdlib, external, internal, relative.
116
+ - Constants at top, public API before private helpers.
117
+ - Keep files under 300 lines. Split when they grow.
118
+
119
+ ## Comments
120
+ - Code should be self-documenting. Comment *why*, not *what*.
121
+ - Delete commented-out code. That is what version control is for.
122
+ - Use TODO/FIXME with ticket references: `// TODO(PROJ-123): migrate to v2`.
123
+ - Document public APIs with doc comments (JSDoc, docstrings, etc.).
124
+
125
+ ## Formatting
126
+ - Use project formatter (Prettier, Black, gofmt, rustfmt). No manual formatting debates.
127
+ - Consistent indentation: follow project convention (spaces vs tabs, width).
128
+ - Max line length: 80-120 characters depending on language convention.
129
+ - Trailing commas in multi-line structures (where language supports).
130
+
131
+ ## Surgical Changes
132
+ - Touch only what the task requires. Every changed line should trace to the request.
133
+ - Match existing style, even if you would do it differently.
134
+ - Do not "improve" adjacent code, comments, or formatting unprompted.
135
+ - Orphan cleanup: remove imports/variables/functions that YOUR changes made unused.
136
+
137
+ ## No Dead Code (Constitution Art. VI.1)
138
+ - When a refactor leaves a file, class, function, import, l10n key, or variable unused, DELETE it in the same change. Verify via grep that zero references remain in the repo.
139
+ - This applies to pre-existing code too, if your work makes its unusedness verifiable. "Legacy", "separate refactor", "out of scope", or "świadome pominięcie" are NOT valid excuses.
140
+ - Before claiming the task done: grep for every symbol you removed or renamed; fix orphaned references.
141
+
142
+ ## Fix Every Found Bug (Constitution Art. VI.2)
143
+ - A bug, missing test for changed behavior, or stale doc discovered while working on a task MUST be fixed in the same change — not deferred to "second step", "separate PR", or "świadome pominięcie".
144
+ - When behavior changes, update integration AND unit tests AND the affected docs alongside. A unit test on a new helper is not sufficient when the behavior is exposed over an API — add the integration test too.
145
+ - Legitimate deferral exists ONLY when: (a) the fix requires a user decision — in that case, surface it explicitly and ask, don't bury in a summary; or (b) the issue is genuinely unrelated to the current change surface.
146
+ - Before marking done: re-read the diff and confirm no orphaned references, no missing test coverage for changed paths, no stale docs. If any are present, keep working.
147
+
148
+ ## Goal-Driven Execution
149
+ - Transform vague tasks into verifiable goals before starting.
150
+ - For multi-step work, state a brief plan with verification per step:
151
+ `1. [Step] → verify: [check]`
152
+ - Strong success criteria enable independent looping. Weak criteria ("make it work") require clarification — ask first.
153
+
154
+ ## JSON Wire Format Conventions
155
+ - Field names (keys): `camelCase`. Aligns with JSON:API spec, Google JSON Style Guide, and framework defaults (Symfony Serializer, Spring Jackson, `json_serializable` for Dart). No public major API uses `snake_case` keys in modern designs except ecosystem-bound cases (Rails/Django APIs defaulting to ecosystem convention).
156
+ - Enum / status / permission / domain values: `UPPER_SNAKE_CASE`. Community consensus: [Protocol Buffers style guide](https://protobuf.dev/programming-guides/style/) (mandatory), [Google AIP-126 / api-linter](https://linter.aip.dev/126/upper-snake-values) (enforced), [Zalando Rule #240](https://opensource.zalando.com/restful-api-guidelines/), Java/Kotlin/C++/Python enum convention. `lowercase snake_case` (Stripe-style) is a legitimate outlier but not consensus.
157
+ - Avoid `camelCase` for enum values — no major public API uses it, loses visual distinction between keys and values.
158
+ - Pick one convention per project and enforce it with a CI grep gate. Mixing conventions inside a single API surface is the worst outcome.
159
+ - External contracts (Stripe, GitHub, webhooks you receive) follow their own convention — map to your project convention at the adapter boundary, do not leak their keys past it.
160
+
161
+ ## Anti-Patterns to Avoid
162
+ - God classes/modules with 500+ lines and multiple responsibilities.
163
+ - Deep nesting (>3 levels): use early returns and extract functions.
164
+ - Magic numbers/strings: use named constants.
165
+ - Mutable global state: use dependency injection instead.
166
+
167
+ ## Source: `app/rules/common/git-workflow.md`
168
+
169
+ # Git Workflow Rules
170
+
171
+ ## Commit Messages
172
+ - Use conventional commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`.
173
+ - First line: imperative mood, max 72 chars (`feat: add user registration endpoint`).
174
+ - Body (optional): explain *why*, not *what*. The diff shows what.
175
+ - Reference tickets: `fix: prevent duplicate orders (PROJ-456)`.
176
+
177
+ ## Commit Practices
178
+ - Commit small, atomic changes. One commit = one logical change.
179
+ - Never commit: secrets, `.env` files, build artifacts, large binaries.
180
+ - Never commit broken code to `main`. Use feature branches.
181
+ - Squash fixup commits before merging to keep history clean.
182
+
183
+ ## Branching
184
+ - `main` is always deployable. Protect it with required reviews and CI.
185
+ - Feature branches: `feat/user-registration`, `fix/order-total-calc`.
186
+ - Delete branches after merge. Stale branches are clutter.
187
+ - Rebase feature branches on main before PR to keep linear history.
188
+
189
+ ## Pull Requests
190
+ - Keep PRs small: <400 lines changed. Split large features into stacked PRs.
191
+ - PR title follows conventional commit format.
192
+ - Include: summary, test plan, and screenshots/recordings for UI changes.
193
+ - Require at least one approval before merge.
194
+
195
+ ## Code Review
196
+ - Review for: correctness, security, performance, readability.
197
+ - Approve with comments if nits only. Block for: bugs, security, missing tests.
198
+ - Respond to reviews within 24 hours. Do not let PRs rot.
199
+
200
+ ## Tags and Releases
201
+ - Use semantic versioning: MAJOR.MINOR.PATCH.
202
+ - Tag releases: `git tag v1.2.3`. Automate changelog from commits.
203
+
204
+ ## Recovery
205
+ - Use `git stash` for WIP, not unfinished commits.
206
+ - Prefer `git revert` over `git reset --hard` on shared branches.
207
+ - Never force-push to `main` or shared branches.
208
+
209
+ ## Source: `app/rules/common/performance.md`
210
+
211
+ # Universal Performance Rules
212
+
213
+ ## Mindset
214
+ - Profile before optimizing. Measure, do not guess.
215
+ - Premature optimization is the root of all evil. Ship correct first, fast second.
216
+ - Set performance budgets and test against them in CI.
217
+
218
+ ## Database
219
+ - Fix N+1 queries: use JOINs, eager loading, or batch fetching.
220
+ - Add indexes for columns used in WHERE, ORDER BY, and JOIN clauses.
221
+ - Use EXPLAIN/ANALYZE to verify query plans. Avoid full table scans.
222
+ - Paginate all list endpoints. Never return unbounded result sets.
223
+ - Use connection pooling. Never open a new connection per request.
224
+
225
+ ## Caching
226
+ - Cache at the right layer: CDN > reverse proxy > application > database.
227
+ - Set explicit TTLs. Stale cache is worse than no cache.
228
+ - Cache immutable or slowly-changing data. Avoid caching user-specific mutable data.
229
+ - Use cache-aside pattern: check cache, fetch on miss, populate cache.
230
+ - Include cache invalidation strategy before adding any cache.
231
+
232
+ ## I/O and Network
233
+ - Async/non-blocking for I/O-bound work. Thread pools for CPU-bound work.
234
+ - Batch operations where possible: bulk inserts, batch API calls.
235
+ - Set timeouts on all external calls: HTTP, database, message queues.
236
+ - Use streaming for large payloads instead of loading everything into memory.
237
+
238
+ ## Memory
239
+ - Preallocate collections when size is known.
240
+ - Use streaming/iterators for large datasets instead of loading all into memory.
241
+ - Watch for memory leaks: unclosed connections, growing caches, event listener accumulation.
242
+ - Avoid unnecessary copies/clones of large data structures.
243
+
244
+ ## API Performance
245
+ - Compress responses (gzip/brotli). Return only requested fields.
246
+ - Use HTTP/2 or HTTP/3 where supported.
247
+ - Implement request deduplication for identical concurrent requests.
248
+ - Return 202 Accepted for long-running operations, process async.
249
+
250
+ ## Monitoring
251
+ - Track p50, p95, p99 latencies, not just averages.
252
+ - Alert on latency regressions, not just errors.
253
+ - Log slow queries (>100ms) and slow endpoints (>500ms).
254
+
255
+ ## Source: `app/rules/common/security.md`
256
+
257
+ # Universal Security Rules
258
+
259
+ ## Input Validation
260
+ - Validate ALL input at API boundaries. Trust nothing from clients.
261
+ - Use allowlists over denylists: define what IS valid, reject everything else.
262
+ - Validate type, length, format, and range for every input field.
263
+ - Sanitize output for the target context (HTML, SQL, shell, URL).
264
+
265
+ ## Authentication
266
+ - Hash passwords with bcrypt, scrypt, or argon2. Never MD5/SHA for passwords.
267
+ - Use constant-time comparison for tokens and secrets.
268
+ - Implement rate limiting on auth endpoints (login, register, password reset).
269
+ - Enforce MFA for admin and sensitive operations.
270
+
271
+ ## Authorization
272
+ - Check permissions on every request, not just at the UI level.
273
+ - Use principle of least privilege: default deny, explicitly grant.
274
+ - Validate resource ownership: user can only access their own data.
275
+ - Never rely on client-side authorization checks.
276
+
277
+ ## Secrets Management
278
+ - Never hardcode secrets in source code. Use environment variables or vaults.
279
+ - Rotate secrets regularly. Automate rotation where possible.
280
+ - Use different secrets per environment (dev/staging/prod).
281
+ - Add `.env` to `.gitignore`. Use `.env.example` as a template.
282
+
283
+ ## SQL Injection Prevention
284
+ - Always use parameterized queries or ORM query builders.
285
+ - Never concatenate user input into SQL strings.
286
+ - Validate and cast types before using in queries.
287
+
288
+ ## XSS Prevention
289
+ - Escape all dynamic content rendered in HTML.
290
+ - Use Content Security Policy (CSP) headers.
291
+ - Set `HttpOnly` and `Secure` flags on authentication cookies.
292
+ - Avoid `innerHTML`, `eval()`, and `dangerouslySetInnerHTML`.
293
+
294
+ ## API Security
295
+ - Use HTTPS everywhere. No exceptions.
296
+ - Implement rate limiting and request throttling.
297
+ - Set CORS headers explicitly. Never use `*` in production.
298
+ - Return generic error messages to clients. Log details server-side.
299
+ - Use security headers: HSTS, X-Content-Type-Options, X-Frame-Options.
300
+
301
+ ## Dependencies
302
+ - Audit dependencies regularly (`npm audit`, `pip-audit`, `cargo audit`).
303
+ - Pin dependency versions. Use lockfiles.
304
+ - Remove unused dependencies. Each dependency is an attack surface.
305
+
306
+ ## Logging
307
+ - Never log passwords, tokens, credit cards, or PII.
308
+ - Log security events: failed logins, permission denials, input validation failures.
309
+ - Use structured logging with correlation IDs for traceability.
310
+
311
+ ## Source: `app/rules/common/testing.md`
312
+
313
+ # Universal Testing Rules
314
+
315
+ ## Test Structure
316
+ - Use Arrange-Act-Assert (AAA) pattern in every test.
317
+ - One logical assertion per test. Multiple `assert` calls are fine if testing one behavior.
318
+ - Test names describe behavior: `test_returns_404_when_user_not_found`.
319
+ - Keep tests independent: no shared mutable state between tests.
320
+
321
+ ## Test Organization
322
+ - Mirror source structure: `src/auth/login.ts` -> `tests/auth/login.test.ts`.
323
+ - Separate unit, integration, and e2e tests into distinct directories or markers.
324
+ - Shared fixtures go in `conftest.py`, `test-utils.ts`, or equivalent.
325
+
326
+ ## What to Test
327
+ - Test behavior, not implementation. Tests should survive refactors.
328
+ - Cover: happy path, error cases, edge cases, boundary values.
329
+ - New code: 100% coverage. Overall project: >70%.
330
+ - Critical paths (auth, payments, data mutations): always tested.
331
+
332
+ ## What NOT to Test
333
+ - Framework internals (ORM save, HTTP library send).
334
+ - Trivial getters/setters with no logic.
335
+ - Third-party library correctness.
336
+ - Private methods directly: test through public API.
337
+
338
+ ## Mocking
339
+ - Mock at boundaries: HTTP clients, databases, file systems, clocks.
340
+ - Prefer fakes over mocks when logic is complex.
341
+ - Never mock the thing you are testing.
342
+ - Reset mocks between tests to prevent leakage.
343
+
344
+ ## Test Quality
345
+ - Tests must be deterministic: no flaky tests allowed.
346
+ - Tests must be fast: unit tests <100ms each, test suite <60s.
347
+ - Avoid `sleep` in tests: use polling, events, or test clocks.
348
+ - Do not test implementation details (private methods, internal state).
349
+
350
+ ## Coverage
351
+ - Measure coverage but do not chase 100%: focus on critical paths.
352
+ - Coverage gaps in error handling and edge cases are worse than gaps in happy paths.
353
+ - New PRs must not decrease overall coverage.
354
+
355
+ ## Test Data
356
+ - Use factories/builders to create test data, not raw constructors.
357
+ - Keep test data minimal: only set fields relevant to the test.
358
+ - Do not share mutable test data across tests.
359
+ - Use realistic but not real data (no production data in tests).
@@ -25,39 +25,79 @@ SOURCE="$TOOLKIT_DIR/app/hooks.json"
25
25
  [ -f "$SETTINGS" ] || exit 0
26
26
  [ -f "$SOURCE" ] || exit 0
27
27
 
28
- # Compare the set of ai-toolkit-tagged commands in each file.
28
+ # Compare canonical behavior, accepting older/current settings where Claude has
29
+ # rewritten the JSON without preserving the private `_source` marker.
30
+ DIFF_STATUS=0
29
31
  DIFF=$(python3 - "$SETTINGS" "$SOURCE" <<'PY'
30
32
  import json
31
33
  import sys
32
34
 
33
35
 
34
- def toolkit_commands(path):
36
+ def without_source(value):
37
+ if isinstance(value, dict):
38
+ return {
39
+ key: without_source(item)
40
+ for key, item in value.items()
41
+ if key != "_source"
42
+ }
43
+ if isinstance(value, list):
44
+ return [without_source(item) for item in value]
45
+ return value
46
+
47
+
48
+ def signature(entry):
49
+ return json.dumps(without_source(entry), sort_keys=True, separators=(",", ":"))
50
+
51
+
52
+ def load_hooks(path):
35
53
  try:
36
54
  data = json.load(open(path))
37
55
  except Exception:
38
- return set()
39
- hooks = data.get("hooks", {}) if isinstance(data, dict) else {}
56
+ return {}
57
+ return data.get("hooks", {}) if isinstance(data, dict) else {}
58
+
59
+
60
+ def entry_commands(event, entry):
40
61
  out = set()
41
- for event, entries in hooks.items():
42
- if not isinstance(entries, list):
43
- continue
44
- for entry in entries:
45
- if not isinstance(entry, dict):
46
- continue
47
- tagged_top = entry.get("_source") == "ai-toolkit"
48
- for hook in entry.get("hooks", []):
49
- if not isinstance(hook, dict):
50
- continue
51
- tagged_inner = hook.get("_source") == "ai-toolkit"
52
- if not (tagged_top or tagged_inner):
53
- continue
54
- cmd = hook.get("command", "")
55
- out.add((event, entry.get("matcher", ""), cmd))
62
+ for hook in entry.get("hooks", []):
63
+ if isinstance(hook, dict):
64
+ out.add((event, entry.get("matcher", ""), hook.get("command", "")))
56
65
  return out
57
66
 
58
67
 
59
- installed = toolkit_commands(sys.argv[1])
60
- source = toolkit_commands(sys.argv[2])
68
+ installed_hooks = load_hooks(sys.argv[1])
69
+ source_hooks = load_hooks(sys.argv[2])
70
+ source_signatures = {
71
+ event: {
72
+ signature(entry)
73
+ for entry in entries
74
+ if isinstance(entry, dict)
75
+ }
76
+ for event, entries in source_hooks.items()
77
+ if isinstance(entries, list)
78
+ }
79
+
80
+ source = set()
81
+ for event, entries in source_hooks.items():
82
+ if not isinstance(entries, list):
83
+ continue
84
+ for entry in entries:
85
+ if isinstance(entry, dict):
86
+ source.update(entry_commands(event, entry))
87
+
88
+ installed = set()
89
+ for event, entries in installed_hooks.items():
90
+ if not isinstance(entries, list):
91
+ continue
92
+ for entry in entries:
93
+ if not isinstance(entry, dict):
94
+ continue
95
+ tagged = entry.get("_source") == "ai-toolkit" or any(
96
+ isinstance(hook, dict) and hook.get("_source") == "ai-toolkit"
97
+ for hook in entry.get("hooks", [])
98
+ )
99
+ if tagged or signature(entry) in source_signatures.get(event, set()):
100
+ installed.update(entry_commands(event, entry))
61
101
 
62
102
  missing = source - installed # in source, not installed (toolkit got new hooks)
63
103
  extra = installed - source # in installed, not source (stale toolkit hook)
@@ -75,9 +115,9 @@ if extra:
75
115
  print(f" - [{event}] {cmd}")
76
116
  sys.exit(1)
77
117
  PY
78
- )
118
+ ) || DIFF_STATUS=$?
79
119
 
80
- if [ $? -ne 0 ] && [ -n "$DIFF" ]; then
120
+ if [ "$DIFF_STATUS" -ne 0 ] && [ -n "$DIFF" ]; then
81
121
  cat >&2 <<EOF
82
122
  config-desync-guard: ai-toolkit hooks drifted from source manifest.
83
123
 
@@ -10,10 +10,13 @@ They serve three purposes:
10
10
  3. give `plugin-creator` a concrete scaffold to follow.
11
11
 
12
12
  Plugin packs can target:
13
- - Claude global runtime via `ai-toolkit plugin install --editor claude <name>`
13
+ - Claude Code global runtime via `ai-toolkit plugin install --editor claude <name>`
14
14
  - Codex global plugin layer via `ai-toolkit plugin install --editor codex <name>`
15
15
  - both runtimes via `ai-toolkit plugin install --editor all <name>`
16
16
 
17
+ These packs are not directly uploadable Claude app plugins. For Claude Chat,
18
+ Desktop, and Cowork use `ai-toolkit claude-app export`.
19
+
17
20
  Current packs:
18
21
  - `security-pack`
19
22
  - `research-pack`
@@ -30,7 +30,7 @@ tools = [{
30
30
  }]
31
31
 
32
32
  response = client.messages.create(
33
- model="claude-opus-4-7",
33
+ model="claude-opus-4-8",
34
34
  max_tokens=1024,
35
35
  tools=tools,
36
36
  tool_choice={"type": "tool", "name": "record_analysis"},
@@ -55,7 +55,7 @@ When tool use is unavailable (some SDKs/proxies strip it):
55
55
 
56
56
  ```python
57
57
  response = client.messages.create(
58
- model="claude-opus-4-7",
58
+ model="claude-opus-4-8",
59
59
  max_tokens=1024,
60
60
  system="You return ONLY valid JSON. No prose, no markdown fences.",
61
61
  messages=[{
@@ -12,13 +12,30 @@ Three Claude tiers. Using Opus for everything is 10-40x more expensive than it n
12
12
 
13
13
  ## Model Characteristics (2026)
14
14
 
15
- | Model | Latency | Cost (rel.) | Strengths | When |
16
- |-------|---------|-------------|-----------|------|
17
- | Haiku 4.5 | Fastest | 1x | Classification, extraction, simple tools, moderation | Bulk processing, triage, labels |
18
- | Sonnet 4.6 | Medium | 3-5x | General coding, reasoning, most agent tasks | Default workhorse |
19
- | Opus 4.7 | Slowest | 15-30x | Complex reasoning, orchestration, architecture, large context | Hard, rare, high-stakes |
15
+ | Model | $/1M in·out | Cost (rel.) | Strengths | When |
16
+ |-------|-------------|-------------|-----------|------|
17
+ | Haiku 4.5 | $1 / $5 | 1x | Classification, extraction, simple tools, moderation | Bulk processing, triage, labels |
18
+ | Sonnet 5 | $3 / $15 | ~3x | General coding, reasoning, most agent tasks | Default workhorse |
19
+ | Opus 4.8 | $5 / $25 | ~5x | Complex reasoning, orchestration, architecture, large context | Hard, rare, high-stakes |
20
+ | Fable 5 | $10 / $50 | ~10x | Most demanding long-horizon agentic work | Only when explicitly chosen |
20
21
 
21
- Ratios are approximate and shift between releases. Re-check pricing before committing a production path.
22
+ Prices are per 1M tokens; ratios are approximate and shift between releases. Re-check pricing before committing a production path.
23
+
24
+ > **Fable 5 is not the default "best model".** Its price sits above Opus-tier, and Opus 4.8 is state-of-the-art on planning/orchestration at half the input and output cost. Reach for Fable 5 only when the user explicitly asks for it or a benchmarked task genuinely needs it — for "use the strongest model", the target is `claude-opus-4-8`.
25
+
26
+ ## Effort — the cheaper lever before swapping models
27
+
28
+ On Fable 5 / Opus 4.8 / Sonnet 5, `output_config.effort` (`low` | `medium` | `high` | `xhigh` | `max`) controls thinking depth and token spend **without changing the model** — so it does not invalidate the prompt cache the way a mid-session model swap does. Tune effort first; drop to a cheaper model only when effort alone can't hit the cost target.
29
+
30
+ | Effort | Use for |
31
+ |--------|---------|
32
+ | `low` | Latency-sensitive, non-intelligence-sensitive: chat, simple lookups, cheap subagents |
33
+ | `medium` | Cost-conscious step-down from the default |
34
+ | `high` | Default for most intelligence-sensitive work (a good quality/cost balance) |
35
+ | `xhigh` | Hardest coding and agentic tasks (Claude Code's default) |
36
+ | `max` | Correctness matters more than cost; test for diminishing returns |
37
+
38
+ In our agents, effort is set per skill/agent frontmatter (`effort:`), not swapped at runtime. Combine effort routing with model routing: e.g. `sonnet` at `high` often beats `opus` at `low` for cost-equal quality — benchmark before committing.
22
39
 
23
40
  ## Pattern 1 — Complexity Router (pre-classify)
24
41
 
@@ -69,7 +86,7 @@ When primary is rate-limited or errors, degrade gracefully:
69
86
 
70
87
  ```python
71
88
  def call_with_fallback(messages):
72
- for model in ["claude-opus-4-7", "claude-sonnet-4-6", "claude-haiku-4-5"]:
89
+ for model in ["claude-opus-4-8", "claude-sonnet-5", "claude-haiku-4-5"]:
73
90
  try:
74
91
  return client.messages.create(model=model, messages=messages, ...)
75
92
  except (RateLimitError, OverloadedError):
@@ -24,7 +24,7 @@ from anthropic import Anthropic
24
24
 
25
25
  client = Anthropic()
26
26
  response = client.messages.create(
27
- model="claude-opus-4-7",
27
+ model="claude-opus-4-8",
28
28
  max_tokens=1024,
29
29
  system=[
30
30
  {
@@ -90,7 +90,7 @@ Target ratio for a well-tuned loop: `cache_read / (cache_read + input) > 0.7`. B
90
90
 
91
91
  ```typescript
92
92
  const response = await anthropic.messages.create({
93
- model: "claude-opus-4-7",
93
+ model: "claude-opus-4-8",
94
94
  max_tokens: 1024,
95
95
  system: [
96
96
  { type: "text", text: LONG_SYSTEM, cache_control: { type: "ephemeral" } }
@@ -33,7 +33,7 @@ Create a new skill following the Agent Skills standard.
33
33
  | `user-invocable` | bool | no | `false` = knowledge skill, Claude auto-loads |
34
34
  | `allowed-tools` | csv or YAML list | no | Restrict tool access for safety; YAML-style lists accepted |
35
35
  | `disallowedTools` | csv or YAML list | no | Block specific tools (plugin-shipped agents) |
36
- | `model` | string | no | Override default model (accepts full IDs like `claude-opus-4-7`) |
36
+ | `model` | string | no | Override default model (accepts full IDs like `claude-opus-4-8`) |
37
37
  | `context` | string | no | `fork` to run in isolated subagent |
38
38
  | `agent` | string | no | Agent type to use when `context: fork` |
39
39
  | `skills` | csv | no | Auto-load skills for the invoked subagent |