@softspark/ai-toolkit 4.7.0 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ Versioning follows [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## v4.8.0 - Devin CLI hooks (Cascade migration) (2026-06-10)
11
+
12
+ Minor release. Migrates the deprecated Windsurf Cascade hooks onto the Devin CLI surface ahead of the 2026-07-01 Cascade sunset. Class D/F ecosystem change per `kb/procedures/ecosystem-sync-sop.md`. No skill/agent count change; no new broad-access skills.
13
+
14
+ ### Added
15
+ - **Devin CLI hooks** — new `scripts/generate_devin_hooks.py` emits `.devin/hooks.v1.json` in the Claude-compatible hook format Devin CLI uses (docs.devin.ai/cli/extensibility/hooks). Wired into `ai-toolkit install --local --editors windsurf --profile full` alongside the existing (now deprecated) Cascade generator. Events are Claude-style (`PreToolUse`/`PostToolUse`/`UserPromptSubmit`/`Stop`/`SessionStart`) with matchers on Devin tool names (`read`/`edit`/`exec`/`mcp__*`); blocking uses the flat `{"decision":"block","reason":...}` shape + exit 2 (no `AI_TOOLKIT_HOOK_FORMAT=json`). Reuses the existing `~/.softspark/ai-toolkit/hooks/*.sh` scripts; `_hook-io.sh` already parses Devin's flat `hook_event_name`/`tool_name`/`tool_input` payload, so no normalizer change was needed. Test count: 1186 → 1196.
16
+
17
+ ### Changed
18
+ - **Cascade hooks deprecation** — `scripts/generate_windsurf_hooks.py` (`.windsurf/hooks.json`) is marked deprecated: the Cascade agent and its hook surface stop working 2026-07-01, and Devin Local / Devin CLI do not read `.windsurf/hooks.json` as a fallback. Both generators run during the transition; `generate_windsurf_hooks.py` will be dropped in the first release after the sunset.
19
+ - **Global hooks reach Devin for free** — documented that Devin CLI reads `~/.claude/settings.json` + `.claude/settings.json` hooks directly (`read_config_from.claude` default on), so a global `ai-toolkit install` already covers Devin even without the project-local file.
20
+ - Registry: `.devin/hooks.v1.json` + `generate_devin_hooks.py` added to the windsurf entry in `scripts/ecosystem_tools.json` and `kb/reference/supported-tools-registry.md`; new "Per-Editor Native Hooks" section in `kb/reference/hooks-catalog.md`. `validate.py` maps the `devin` hook-generator stem back to the windsurf README platform key.
21
+
22
+ ---
23
+
10
24
  ## v4.7.0 - Devin Desktop .devin tree + Antigravity CLI surfaces (2026-06-10)
11
25
 
12
26
  Minor release. Ecosystem sync per `kb/procedures/ecosystem-sync-sop.md` (window 2026-06-05 → 2026-06-10, doctor run + per-tool docs review with adversarial verification). No skill/agent count change; no new broad-access skills.
package/README.md CHANGED
@@ -6,17 +6,16 @@
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
7
  [![Skills](https://img.shields.io/badge/skills-107-brightgreen)](app/skills/)
8
8
  [![Agents](https://img.shields.io/badge/agents-44-blue)](app/agents/)
9
- [![Tests](https://img.shields.io/badge/tests-1186%20passing-success)](tests/)
9
+ [![Tests](https://img.shields.io/badge/tests-1196%20passing-success)](tests/)
10
10
 
11
- ## What's New in v4.7.0
11
+ ## What's New in v4.8.0
12
12
 
13
- v4.7.0 follows the Windsurf Devin Desktop transition to its config surfaces and brings the editor registry up to date with verified upstream docs.
13
+ v4.8.0 migrates the deprecated Windsurf Cascade hooks onto the Devin CLI surface before Cascade sunsets on 2026-07-01.
14
14
 
15
- - **Devin Desktop `.devin/` tree**: windsurf generators now dual-emit rules, workflows, and the skill pointer to `.devin/` (primary since the 2026-06-02 rebrand) alongside legacy `.windsurf/` (still read as fallback); `.devin/rules` joins editor auto-detection.
16
- - **Antigravity CLI skill pointer**: dual-emitted to `.agent/skills/` (IDE) and `.agents/skills/` (CLI, plural); auto-detection no longer misreads a pointer-only `.agents/skills/` as a Codex install.
17
- - **Cascade deprecation**: the Cascade-scoped `.windsurf/hooks.json` surface dies with Cascade on 2026-07-01 deprecation note added, migration target is Devin CLI lifecycle hooks.
18
- - **Registry accuracy**: phantom `.cursor/rules/*.md` removed (Cursor ignores plain `.md`), Augment guidelines path corrected to `.augment-guidelines`, plus verified config surfaces added for Claude Code, Gemini CLI, Cline CLI/SDK, Codex, opencode, and Antigravity CLI.
19
- - **Troubleshooting**: maintenance SOP gains the `claude --safe-mode` (v2.1.169) isolation step.
15
+ - **Devin CLI hooks**: new `generate_devin_hooks.py` emits `.devin/hooks.v1.json` in the Claude-compatible format Devin CLI uses Claude-style events (`PreToolUse`/`PostToolUse`/`UserPromptSubmit`/`Stop`/`SessionStart`) with matchers on Devin tool names (`read`/`edit`/`exec`/`mcp__*`), reusing the existing toolkit hook scripts.
16
+ - **Cascade deprecation**: `.windsurf/hooks.json` is Cascade-scoped and dies 2026-07-01 with no Devin fallback; both generators run during the transition, the Cascade one drops in the first release after the sunset.
17
+ - **Global hooks reach Devin for free**: Devin CLI reads `~/.claude/settings.json` hooks directly, so a global `ai-toolkit install` already covers Devin even without the project-local file.
18
+ - No normalizer change needed: `_hook-io.sh` already parses Devin's flat `hook_event_name`/`tool_name`/`tool_input` payload.
20
19
 
21
20
  See [CHANGELOG.md](CHANGELOG.md) for full history.
22
21
 
@@ -149,7 +148,7 @@ ai-toolkit/
149
148
  │ └── ARCHITECTURE.md # Full system design
150
149
  ├── kb/ # Reference docs, procedures, plans
151
150
  ├── scripts/ # Validation, install, evaluation scripts
152
- ├── tests/ # Bats test suite (1186 tests)
151
+ ├── tests/ # Bats test suite (1196 tests)
153
152
  └── CHANGELOG.md
154
153
  ```
155
154
 
@@ -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": "4.7.0",
4
+ "version": "4.8.0",
5
5
  "author": {
6
6
  "name": "SoftSpark",
7
7
  "url": "https://github.com/softspark"
@@ -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.5.7"
6
+ version: "1.6.0"
7
7
  created: "2026-03-27"
8
- last_updated: "2026-05-25"
8
+ last_updated: "2026-06-10"
9
9
  description: "Complete reference of all ai-toolkit hooks: events, scripts, installation, and runtime behavior."
10
10
  ---
11
11
 
@@ -571,6 +571,31 @@ commands explicitly silent, and Codex-generated hooks plus Claude's bundled
571
571
  - `_source: "ai-toolkit"` tag on every entry — allows idempotent merge/strip
572
572
  - Hooks are **global only** — `--local` does not install hooks into project settings
573
573
 
574
+ ## Per-Editor Native Hooks (profile=full)
575
+
576
+ Beyond the global Claude Code hooks above, full-profile project installs emit native hook files for editors that support their own hook lifecycle. All reuse the same `~/.softspark/ai-toolkit/hooks/*.sh` scripts and the `_source: ai-toolkit` merge tag.
577
+
578
+ | Editor | File | Generator | Format |
579
+ |--------|------|-----------|--------|
580
+ | Cursor | `.cursor/hooks.json` | `generate_cursor_hooks.py` | Cursor hooks schema |
581
+ | Windsurf (Cascade) | `.windsurf/hooks.json` | `generate_windsurf_hooks.py` | Cascade `agent_action_name`/`tool_info` — **deprecated, dies 2026-07-01** |
582
+ | Devin CLI | `.devin/hooks.v1.json` | `generate_devin_hooks.py` | Claude-compatible (the replacement for Cascade) |
583
+ | Gemini CLI | `.gemini/settings.json` (hooks block) | `generate_gemini_hooks.py` | Gemini `BeforeTool`/`AfterTool` events |
584
+ | Augment | `.augment/settings.json` (hooks block) | `generate_augment_hooks.py` | Claude-style events |
585
+
586
+ ### Devin CLI hooks (`.devin/hooks.v1.json`)
587
+
588
+ Windsurf rebranded to Devin Desktop (2026-06-02); the Cascade agent — and its `.windsurf/hooks.json` surface — is available only through **2026-07-01**. Devin Local / Devin CLI do **not** read `.windsurf/hooks.json` as a fallback, so hooks must be regenerated onto the Devin CLI format.
589
+
590
+ Devin CLI uses a **Claude-compatible** hook format (docs.devin.ai/cli/extensibility/hooks). Key facts driving the generator:
591
+
592
+ - **Standalone file shape:** in `.devin/hooks.v1.json` the entire file IS the hooks object — no top-level `"hooks"` wrapper key (unlike `.claude/settings.json`).
593
+ - **Events:** Claude-style PascalCase — `PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `Stop`, `SessionStart`. `post_setup_worktree` has no Devin equivalent (`session-context.sh` moves to `SessionStart`); `post_cascade_response` maps to `Stop` (which carries no response text on stdin).
594
+ - **Matchers:** regex against the Devin **tool name** (`read`, `edit`, `exec`, `grep`, `glob`, `mcp__<server>__<tool>`) — NOT Claude's `Bash`/`Edit`, so the shared guards reliably fire.
595
+ - **Block contract:** the guard scripts emit `{"decision":"block","reason":...}` on stdout (plain mode) AND exit 2 — Devin honors both. Hooks run **without** `AI_TOOLKIT_HOOK_FORMAT=json` because Devin expects the flat `{"decision","reason"}` shape, not Claude's `hookSpecificOutput` envelope.
596
+ - **Stdin payload:** flat `{ "hook_event_name", "tool_name", "tool_input" }` — already handled by `_hook-io.sh` via its `.tool_name` / `.tool_input.*` branches, so no normalizer change was needed.
597
+ - **Global bonus:** Devin CLI reads `~/.claude/settings.json` + `.claude/settings.json` hooks directly (`read_config_from.claude` default on, since CLI `2026.3.20-2`), so a global `ai-toolkit install` already covers Devin even without the project-local file.
598
+
574
599
  ## Troubleshooting
575
600
 
576
601
  **Hooks not loading:**
@@ -3,9 +3,9 @@ title: "Supported Tools Registry"
3
3
  category: reference
4
4
  service: ai-toolkit
5
5
  tags: [editors, platforms, generators, integration, ecosystem]
6
- version: "1.5.0"
6
+ version: "1.6.0"
7
7
  created: "2026-04-23"
8
- last_updated: "2026-06-09"
8
+ last_updated: "2026-06-10"
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
 
@@ -62,12 +62,13 @@ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed b
62
62
  | Docs | https://docs.devin.ai/desktop (Windsurf rebranded to Devin Desktop ~2026-06-02; docs.windsurf.com resolves here) |
63
63
  | Changelog | https://docs.devin.ai/desktop/changelog (windsurf.com/changelog 308-permanent-redirects here) |
64
64
  | Stable docs mirror | https://docs.devin.ai/desktop/... per-page .md twins; legacy `.windsurf/`, `.windsurfrules`, `~/.codeium/windsurf/` paths still read as fallback (new canonical: `.devin/`) |
65
- | Config paths | **Primary (Devin Desktop):** `.devin/rules/*.md`, `.devin/workflows/*.md`, `.devin/skills/*/SKILL.md`, `.devin/config.json`, `.devin/config.local.json`, `~/.config/devin/config.json` (Devin Local MCP/permissions). **Legacy fallback:** `.windsurfrules`, `.windsurf/rules/*.md`, `.windsurf/workflows/*.md`, `.windsurf/skills/*/SKILL.md`, `~/.codeium/windsurf/memories/global_rules.md`, `~/.codeium/windsurf/skills/*/SKILL.md`, `~/.codeium/windsurf/mcp_config.json`. Plus `AGENTS.md`. |
66
- | Compat read paths | `.agents/skills/`, `~/.agents/skills/`, (with Claude Code config-reading) `.claude/skills/`, `~/.claude/skills/` |
67
- | Our generators | `scripts/generate_windsurf.py`, `scripts/generate_windsurf_rules.py` (dual-emits `.devin/` + `.windsurf/`), `scripts/generate_windsurf_hooks.py` (profile=full; **Cascade-scoped, deprecated**), `scripts/generate_windsurf_skills.py` (global + profile=full pointer, dual-emits) |
65
+ | Config paths | **Primary (Devin Desktop):** `.devin/rules/*.md`, `.devin/workflows/*.md`, `.devin/skills/*/SKILL.md`, `.devin/hooks.v1.json` (Devin CLI hooks, Claude format), `.devin/config.json`, `.devin/config.local.json`, `~/.config/devin/config.json` (Devin Local MCP/permissions). **Legacy fallback:** `.windsurfrules`, `.windsurf/rules/*.md`, `.windsurf/workflows/*.md`, `.windsurf/skills/*/SKILL.md`, `~/.codeium/windsurf/memories/global_rules.md`, `~/.codeium/windsurf/skills/*/SKILL.md`, `~/.codeium/windsurf/mcp_config.json`. Plus `AGENTS.md`. |
66
+ | Compat read paths | skills: `.agents/skills/`, `~/.agents/skills/`, (with Claude Code config-reading) `.claude/skills/`, `~/.claude/skills/`. **Hooks: Devin CLI reads `.claude/settings.json` + `~/.claude/settings.json` hooks directly (`read_config_from.claude` default on), so globally-installed toolkit hooks work under Devin with no project-local file.** |
67
+ | Our generators | `scripts/generate_windsurf.py`, `scripts/generate_windsurf_rules.py` (dual-emits `.devin/` + `.windsurf/`), `scripts/generate_windsurf_hooks.py` (profile=full; **Cascade-scoped, deprecated, drop after 2026-07-01**), `scripts/generate_devin_hooks.py` (profile=full; `.devin/hooks.v1.json`, Claude-format Devin CLI hooks), `scripts/generate_windsurf_skills.py` (global + profile=full pointer, dual-emits) |
68
68
  | Tracked capabilities | Cascade, `windsurfrules`, `AGENTS.md`, activation triggers (`always_on`/`glob`/`model_decision`), workflows, skills, MCP, memories, hooks |
69
69
  | Activation modes emitted | always_on (agents/security/quality), glob (testing + language rules), model_decision (code-style/workflow) |
70
- | Sunset notes | Cascade agent is available only through **2026-07-01**; Devin Local is the default agent since 2026-06-02. The `.windsurf/hooks.json` surface dies with Cascade — migrate to Devin CLI lifecycle hooks (docs.devin.ai/cli/extensibility/hooks/\*) before that date. Devin CLI ("Devin for Terminal") shares the Devin Local harness, reads `AGENTS.md` and the standard `SKILL.md` format; not yet a separate registry entry. |
70
+ | Hooks migration | **Done.** Cascade `.windsurf/hooks.json` (`agent_action_name`/`tool_info` format) dies 2026-07-01 with no Devin fallback. `generate_devin_hooks.py` emits `.devin/hooks.v1.json` in the Claude-compatible format Devin CLI uses: Claude-style events (PreToolUse/PostToolUse/UserPromptSubmit/Stop/SessionStart), matchers on Devin tool names (`read`/`edit`/`exec`/`mcp__*`), blocking via flat `{"decision":"block","reason":...}` + exit 2 (no `AI_TOOLKIT_HOOK_FORMAT=json` — Devin does not use Claude's `hookSpecificOutput` envelope). `post_setup_worktree`→`SessionStart`; `post_cascade_response`→`Stop` (no response text on stdin). Both hook generators run at profile=full during the transition; drop `generate_windsurf_hooks.py` in the first release after 2026-07-01. |
71
+ | Sunset notes | Cascade agent is available only through **2026-07-01**; Devin Local is the default agent since 2026-06-02. Devin CLI ("Devin for Terminal") shares the Devin Local harness, reads `AGENTS.md`, the standard `SKILL.md` format, and Claude-format hooks; not yet a separate registry entry. |
71
72
 
72
73
  ### GitHub Copilot
73
74
 
package/llms-full.txt CHANGED
@@ -8900,9 +8900,9 @@ title: "Hooks Catalog"
8900
8900
  category: reference
8901
8901
  service: ai-toolkit
8902
8902
  tags: [hooks, quality, safety, enforcement, settings.json]
8903
- version: "1.5.7"
8903
+ version: "1.6.0"
8904
8904
  created: "2026-03-27"
8905
- last_updated: "2026-05-25"
8905
+ last_updated: "2026-06-10"
8906
8906
  description: "Complete reference of all ai-toolkit hooks: events, scripts, installation, and runtime behavior."
8907
8907
  ---
8908
8908
 
@@ -9468,6 +9468,31 @@ commands explicitly silent, and Codex-generated hooks plus Claude's bundled
9468
9468
  - `_source: "ai-toolkit"` tag on every entry — allows idempotent merge/strip
9469
9469
  - Hooks are **global only** — `--local` does not install hooks into project settings
9470
9470
 
9471
+ ## Per-Editor Native Hooks (profile=full)
9472
+
9473
+ Beyond the global Claude Code hooks above, full-profile project installs emit native hook files for editors that support their own hook lifecycle. All reuse the same `~/.softspark/ai-toolkit/hooks/*.sh` scripts and the `_source: ai-toolkit` merge tag.
9474
+
9475
+ | Editor | File | Generator | Format |
9476
+ |--------|------|-----------|--------|
9477
+ | Cursor | `.cursor/hooks.json` | `generate_cursor_hooks.py` | Cursor hooks schema |
9478
+ | Windsurf (Cascade) | `.windsurf/hooks.json` | `generate_windsurf_hooks.py` | Cascade `agent_action_name`/`tool_info` — **deprecated, dies 2026-07-01** |
9479
+ | Devin CLI | `.devin/hooks.v1.json` | `generate_devin_hooks.py` | Claude-compatible (the replacement for Cascade) |
9480
+ | Gemini CLI | `.gemini/settings.json` (hooks block) | `generate_gemini_hooks.py` | Gemini `BeforeTool`/`AfterTool` events |
9481
+ | Augment | `.augment/settings.json` (hooks block) | `generate_augment_hooks.py` | Claude-style events |
9482
+
9483
+ ### Devin CLI hooks (`.devin/hooks.v1.json`)
9484
+
9485
+ Windsurf rebranded to Devin Desktop (2026-06-02); the Cascade agent — and its `.windsurf/hooks.json` surface — is available only through **2026-07-01**. Devin Local / Devin CLI do **not** read `.windsurf/hooks.json` as a fallback, so hooks must be regenerated onto the Devin CLI format.
9486
+
9487
+ Devin CLI uses a **Claude-compatible** hook format (docs.devin.ai/cli/extensibility/hooks). Key facts driving the generator:
9488
+
9489
+ - **Standalone file shape:** in `.devin/hooks.v1.json` the entire file IS the hooks object — no top-level `"hooks"` wrapper key (unlike `.claude/settings.json`).
9490
+ - **Events:** Claude-style PascalCase — `PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `Stop`, `SessionStart`. `post_setup_worktree` has no Devin equivalent (`session-context.sh` moves to `SessionStart`); `post_cascade_response` maps to `Stop` (which carries no response text on stdin).
9491
+ - **Matchers:** regex against the Devin **tool name** (`read`, `edit`, `exec`, `grep`, `glob`, `mcp__<server>__<tool>`) — NOT Claude's `Bash`/`Edit`, so the shared guards reliably fire.
9492
+ - **Block contract:** the guard scripts emit `{"decision":"block","reason":...}` on stdout (plain mode) AND exit 2 — Devin honors both. Hooks run **without** `AI_TOOLKIT_HOOK_FORMAT=json` because Devin expects the flat `{"decision","reason"}` shape, not Claude's `hookSpecificOutput` envelope.
9493
+ - **Stdin payload:** flat `{ "hook_event_name", "tool_name", "tool_input" }` — already handled by `_hook-io.sh` via its `.tool_name` / `.tool_input.*` branches, so no normalizer change was needed.
9494
+ - **Global bonus:** Devin CLI reads `~/.claude/settings.json` + `.claude/settings.json` hooks directly (`read_config_from.claude` default on, since CLI `2026.3.20-2`), so a global `ai-toolkit install` already covers Devin even without the project-local file.
9495
+
9471
9496
  ## Troubleshooting
9472
9497
 
9473
9498
  **Hooks not loading:**
@@ -11770,9 +11795,9 @@ title: "Supported Tools Registry"
11770
11795
  category: reference
11771
11796
  service: ai-toolkit
11772
11797
  tags: [editors, platforms, generators, integration, ecosystem]
11773
- version: "1.5.0"
11798
+ version: "1.6.0"
11774
11799
  created: "2026-04-23"
11775
- last_updated: "2026-06-09"
11800
+ last_updated: "2026-06-10"
11776
11801
  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."
11777
11802
  ---
11778
11803
 
@@ -11829,12 +11854,13 @@ The canonical data lives in **`scripts/ecosystem_tools.json`** and is consumed b
11829
11854
  | Docs | https://docs.devin.ai/desktop (Windsurf rebranded to Devin Desktop ~2026-06-02; docs.windsurf.com resolves here) |
11830
11855
  | Changelog | https://docs.devin.ai/desktop/changelog (windsurf.com/changelog 308-permanent-redirects here) |
11831
11856
  | Stable docs mirror | https://docs.devin.ai/desktop/... per-page .md twins; legacy `.windsurf/`, `.windsurfrules`, `~/.codeium/windsurf/` paths still read as fallback (new canonical: `.devin/`) |
11832
- | Config paths | **Primary (Devin Desktop):** `.devin/rules/*.md`, `.devin/workflows/*.md`, `.devin/skills/*/SKILL.md`, `.devin/config.json`, `.devin/config.local.json`, `~/.config/devin/config.json` (Devin Local MCP/permissions). **Legacy fallback:** `.windsurfrules`, `.windsurf/rules/*.md`, `.windsurf/workflows/*.md`, `.windsurf/skills/*/SKILL.md`, `~/.codeium/windsurf/memories/global_rules.md`, `~/.codeium/windsurf/skills/*/SKILL.md`, `~/.codeium/windsurf/mcp_config.json`. Plus `AGENTS.md`. |
11833
- | Compat read paths | `.agents/skills/`, `~/.agents/skills/`, (with Claude Code config-reading) `.claude/skills/`, `~/.claude/skills/` |
11834
- | Our generators | `scripts/generate_windsurf.py`, `scripts/generate_windsurf_rules.py` (dual-emits `.devin/` + `.windsurf/`), `scripts/generate_windsurf_hooks.py` (profile=full; **Cascade-scoped, deprecated**), `scripts/generate_windsurf_skills.py` (global + profile=full pointer, dual-emits) |
11857
+ | Config paths | **Primary (Devin Desktop):** `.devin/rules/*.md`, `.devin/workflows/*.md`, `.devin/skills/*/SKILL.md`, `.devin/hooks.v1.json` (Devin CLI hooks, Claude format), `.devin/config.json`, `.devin/config.local.json`, `~/.config/devin/config.json` (Devin Local MCP/permissions). **Legacy fallback:** `.windsurfrules`, `.windsurf/rules/*.md`, `.windsurf/workflows/*.md`, `.windsurf/skills/*/SKILL.md`, `~/.codeium/windsurf/memories/global_rules.md`, `~/.codeium/windsurf/skills/*/SKILL.md`, `~/.codeium/windsurf/mcp_config.json`. Plus `AGENTS.md`. |
11858
+ | Compat read paths | skills: `.agents/skills/`, `~/.agents/skills/`, (with Claude Code config-reading) `.claude/skills/`, `~/.claude/skills/`. **Hooks: Devin CLI reads `.claude/settings.json` + `~/.claude/settings.json` hooks directly (`read_config_from.claude` default on), so globally-installed toolkit hooks work under Devin with no project-local file.** |
11859
+ | Our generators | `scripts/generate_windsurf.py`, `scripts/generate_windsurf_rules.py` (dual-emits `.devin/` + `.windsurf/`), `scripts/generate_windsurf_hooks.py` (profile=full; **Cascade-scoped, deprecated, drop after 2026-07-01**), `scripts/generate_devin_hooks.py` (profile=full; `.devin/hooks.v1.json`, Claude-format Devin CLI hooks), `scripts/generate_windsurf_skills.py` (global + profile=full pointer, dual-emits) |
11835
11860
  | Tracked capabilities | Cascade, `windsurfrules`, `AGENTS.md`, activation triggers (`always_on`/`glob`/`model_decision`), workflows, skills, MCP, memories, hooks |
11836
11861
  | Activation modes emitted | always_on (agents/security/quality), glob (testing + language rules), model_decision (code-style/workflow) |
11837
- | Sunset notes | Cascade agent is available only through **2026-07-01**; Devin Local is the default agent since 2026-06-02. The `.windsurf/hooks.json` surface dies with Cascade — migrate to Devin CLI lifecycle hooks (docs.devin.ai/cli/extensibility/hooks/\*) before that date. Devin CLI ("Devin for Terminal") shares the Devin Local harness, reads `AGENTS.md` and the standard `SKILL.md` format; not yet a separate registry entry. |
11862
+ | Hooks migration | **Done.** Cascade `.windsurf/hooks.json` (`agent_action_name`/`tool_info` format) dies 2026-07-01 with no Devin fallback. `generate_devin_hooks.py` emits `.devin/hooks.v1.json` in the Claude-compatible format Devin CLI uses: Claude-style events (PreToolUse/PostToolUse/UserPromptSubmit/Stop/SessionStart), matchers on Devin tool names (`read`/`edit`/`exec`/`mcp__*`), blocking via flat `{"decision":"block","reason":...}` + exit 2 (no `AI_TOOLKIT_HOOK_FORMAT=json` — Devin does not use Claude's `hookSpecificOutput` envelope). `post_setup_worktree`→`SessionStart`; `post_cascade_response`→`Stop` (no response text on stdin). Both hook generators run at profile=full during the transition; drop `generate_windsurf_hooks.py` in the first release after 2026-07-01. |
11863
+ | Sunset notes | Cascade agent is available only through **2026-07-01**; Devin Local is the default agent since 2026-06-02. Devin CLI ("Devin for Terminal") shares the Devin Local harness, reads `AGENTS.md`, the standard `SKILL.md` format, and Claude-format hooks; not yet a separate registry entry. |
11838
11864
 
11839
11865
  ### GitHub Copilot
11840
11866
 
package/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.7.0",
2
+ "version": "4.8.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.7.0",
3
+ "version": "4.8.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",
@@ -135,6 +135,7 @@
135
135
  ".devin/rules/*.md",
136
136
  ".devin/workflows/*.md",
137
137
  ".devin/skills/*/SKILL.md",
138
+ ".devin/hooks.v1.json",
138
139
  ".devin/config.json",
139
140
  ".devin/config.local.json",
140
141
  "~/.config/devin/config.json",
@@ -152,9 +153,10 @@
152
153
  "scripts/generate_windsurf.py",
153
154
  "scripts/generate_windsurf_rules.py",
154
155
  "scripts/generate_windsurf_skills.py",
155
- "scripts/generate_windsurf_hooks.py"
156
+ "scripts/generate_windsurf_hooks.py",
157
+ "scripts/generate_devin_hooks.py"
156
158
  ],
157
- "status_note": "Windsurf rebranded to Devin Desktop on 2026-06-02. .devin/ is the primary read+write workspace tree; .windsurfrules, .windsurf/* and ~/.codeium/windsurf/* are legacy read-only fallbacks. Our generators dual-emit .devin/* + .windsurf/*. Cascade agent is available only through 2026-07-01 (Devin Local is the default agent since 2026-06-02); the .windsurf/hooks.json surface emitted by generate_windsurf_hooks.py is Cascade-scoped and dies with Cascademigrate to the Devin CLI lifecycle-hooks surface (docs.devin.ai/cli/extensibility/hooks/*) before that date. Devin CLI ('Devin for Terminal', launched 2026-04-29) shares the Devin Local harness, reads AGENTS.md and the same SKILL.md standard; not yet tracked as a separate registry entry.",
159
+ "status_note": "Windsurf rebranded to Devin Desktop on 2026-06-02. .devin/ is the primary read+write workspace tree; .windsurfrules, .windsurf/* and ~/.codeium/windsurf/* are legacy read-only fallbacks. Our generators dual-emit .devin/* + .windsurf/*. HOOKS MIGRATION (done): Cascade agent is available only through 2026-07-01 (Devin Local default since 2026-06-02), and the Cascade-scoped .windsurf/hooks.json (generate_windsurf_hooks.py, agent_action_name/tool_info format) dies with itDevin CLI/Local do NOT read it as a fallback. generate_devin_hooks.py now emits .devin/hooks.v1.json in the Claude-compatible hook format Devin CLI uses (docs.devin.ai/cli/extensibility/hooks): Claude-style events (PreToolUse/PostToolUse/UserPromptSubmit/Stop/SessionStart) with matchers on Devin tool names (read/edit/exec/mcp__*), flat {decision,reason} block contract + exit 2. Globally-installed users ALSO inherit ~/.claude/settings.json hooks automatically (Devin read_config_from.claude defaults on). Both hook generators run at profile=full; drop generate_windsurf_hooks.py in the first release after 2026-07-01. Devin CLI ('Devin for Terminal', launched 2026-04-29) shares the Devin Local harness, reads AGENTS.md and the same SKILL.md standard; not yet tracked as a separate registry entry.",
158
160
  "capability_markers": [
159
161
  "Cascade",
160
162
  "windsurfrules",
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env python3
2
+ """Generate ``.devin/hooks.v1.json`` for the Devin CLI (formerly Windsurf).
3
+
4
+ Devin CLI uses a hook format **compatible with Claude Code hooks**
5
+ (docs.devin.ai/cli/extensibility/hooks/overview). This generator is the
6
+ replacement for the deprecated Cascade ``.windsurf/hooks.json`` surface,
7
+ which stops working when Cascade sunsets on 2026-07-01. Devin Local / Devin
8
+ CLI do NOT read ``.windsurf/hooks.json`` as a fallback, so the hooks must be
9
+ regenerated onto this new file.
10
+
11
+ Output file: ``<target>/.devin/hooks.v1.json``. Per the Devin docs the
12
+ standalone ``hooks.v1.json`` file's entire contents ARE the hooks object —
13
+ there is **no** top-level ``"hooks"`` wrapper key (unlike
14
+ ``.claude/settings.json`` or ``.devin/config.json``).
15
+
16
+ Events use Claude-style PascalCase names. Matchers are regexes against the
17
+ Devin **tool name** (``read``, ``edit``, ``exec``, ``grep``, ``glob``,
18
+ ``mcp__<server>__<tool>``) — NOT Claude's ``Bash``/``Edit`` names — so the
19
+ shared guard scripts reliably fire under Devin.
20
+
21
+ Blocking contract: the shared guard scripts emit ``{"decision":"block",
22
+ "reason":...}`` on stdout (plain mode) AND exit 2 — Devin honors both (docs:
23
+ exit 2 = deny; JSON ``{"decision":"block"}`` = deny). Hooks therefore run
24
+ WITHOUT ``AI_TOOLKIT_HOOK_FORMAT=json`` because Devin expects the flat
25
+ ``{"decision","reason"}`` shape, not Claude's ``hookSpecificOutput`` envelope.
26
+
27
+ Existing user hook entries are preserved; only entries tagged
28
+ ``_source: ai-toolkit`` are replaced on regeneration.
29
+
30
+ Usage:
31
+ python3 scripts/generate_devin_hooks.py [target-dir]
32
+ """
33
+ from __future__ import annotations
34
+
35
+ import json
36
+ import sys
37
+ from pathlib import Path
38
+
39
+ HOOKS_PREFIX = '"$HOME/.softspark/ai-toolkit/hooks/'
40
+ SOURCE_TAG = "ai-toolkit"
41
+
42
+ # event -> list of (matcher_regex, [script names]).
43
+ # Matchers target Devin tool names: read, edit, exec, mcp__<server>__<tool>.
44
+ # An empty matcher fires for every tool name (Devin: omitted/empty = match all).
45
+ DEVIN_HOOKS: dict[str, list[tuple[str, list[str]]]] = {
46
+ "PreToolUse": [
47
+ ("^(read|edit)$", ["guard-path.sh"]),
48
+ ("^edit$", ["guard-config.sh"]),
49
+ ("^exec$", ["guard-destructive.sh", "commit-quality.sh", "revert-guard.sh"]),
50
+ ("^mcp__", ["guard-config.sh"]),
51
+ ],
52
+ "PostToolUse": [
53
+ ("^edit$", ["post-tool-use.sh", "governance-capture.sh", "test-cohesion.sh"]),
54
+ ("^exec$", ["governance-capture.sh"]),
55
+ ("^mcp__.*__(smart_query|hybrid_search_kb|crag_search|multi_hop_search|verify_answer)$",
56
+ ["search-tracker.sh"]),
57
+ ],
58
+ "UserPromptSubmit": [
59
+ ("", ["user-prompt-submit.sh", "track-usage.sh"]),
60
+ ],
61
+ "Stop": [
62
+ ("", ["quality-check.sh", "save-session.sh", "stop-search-check.sh"]),
63
+ ],
64
+ # Cascade's post_setup_worktree has no Devin equivalent; session-context
65
+ # moves to SessionStart (Devin fires SessionStart when a session begins).
66
+ "SessionStart": [
67
+ ("", ["session-context.sh"]),
68
+ ],
69
+ }
70
+
71
+
72
+ def build_hook_entry(matcher: str, scripts: list[str]) -> dict:
73
+ """Build one Devin matcher-group: ``{matcher, hooks:[{type,command}]}``."""
74
+ return {
75
+ "_source": SOURCE_TAG,
76
+ "matcher": matcher,
77
+ "hooks": [
78
+ {"type": "command", "command": f'{HOOKS_PREFIX}{s}"'}
79
+ for s in scripts
80
+ ],
81
+ }
82
+
83
+
84
+ def build_toolkit_hooks() -> dict[str, list[dict]]:
85
+ return {
86
+ event: [build_hook_entry(matcher, scripts) for matcher, scripts in groups]
87
+ for event, groups in DEVIN_HOOKS.items()
88
+ }
89
+
90
+
91
+ def _is_toolkit_entry(entry: dict) -> bool:
92
+ return isinstance(entry, dict) and entry.get("_source") == SOURCE_TAG
93
+
94
+
95
+ def strip_toolkit_hooks(hooks: dict) -> dict:
96
+ """Drop ai-toolkit matcher-groups; keep user-authored entries."""
97
+ kept: dict = {}
98
+ for event, entries in hooks.items():
99
+ if not isinstance(entries, list):
100
+ kept[event] = entries
101
+ continue
102
+ survivors = [e for e in entries if not _is_toolkit_entry(e)]
103
+ if survivors:
104
+ kept[event] = survivors
105
+ return kept
106
+
107
+
108
+ def merge_hooks(existing: dict, toolkit: dict) -> dict:
109
+ merged = strip_toolkit_hooks(existing)
110
+ for event, entries in toolkit.items():
111
+ merged.setdefault(event, []).extend(entries)
112
+ return merged
113
+
114
+
115
+ def generate(target_dir: Path) -> Path:
116
+ devin_dir = target_dir / ".devin"
117
+ devin_dir.mkdir(parents=True, exist_ok=True)
118
+ path = devin_dir / "hooks.v1.json"
119
+
120
+ # The standalone hooks.v1.json file IS the hooks object (no wrapper key).
121
+ existing: dict = {}
122
+ if path.is_file():
123
+ try:
124
+ with open(path, encoding="utf-8") as f:
125
+ existing = json.load(f)
126
+ if not isinstance(existing, dict):
127
+ existing = {}
128
+ except (json.JSONDecodeError, OSError):
129
+ existing = {}
130
+
131
+ merged = merge_hooks(existing, build_toolkit_hooks())
132
+
133
+ with open(path, "w", encoding="utf-8") as f:
134
+ json.dump(merged, f, indent=4, ensure_ascii=False, sort_keys=True)
135
+ f.write("\n")
136
+ return path
137
+
138
+
139
+ def main() -> None:
140
+ target = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.cwd()
141
+ path = generate(target)
142
+ total = sum(len(scripts) for groups in DEVIN_HOOKS.values()
143
+ for _, scripts in groups)
144
+ rel = path.relative_to(target) if path.is_relative_to(target) else path
145
+ print(f"Generated: {rel} ({total} hooks across {len(DEVIN_HOOKS)} events)")
146
+
147
+
148
+ if __name__ == "__main__":
149
+ main()
@@ -748,7 +748,7 @@ def _install_local_dry_run(reset: bool, editors: list[str] | None = None,
748
748
  if "cursor" in eds:
749
749
  print(" Would generate: .cursor/hooks.json + .cursor/agents/ + .cursor/skills/ (profile=full)")
750
750
  if "windsurf" in eds:
751
- print(" Would generate: .windsurf/hooks.json + .devin/skills/ + .windsurf/skills/ (profile=full)")
751
+ print(" Would generate: .devin/hooks.v1.json + .windsurf/hooks.json (Cascade, deprecated) + .devin/skills/ + .windsurf/skills/ (profile=full)")
752
752
  if "cline" in eds:
753
753
  print(" Would generate: .cline/skills/ (profile=full)")
754
754
  if "augment" in eds:
@@ -980,7 +980,10 @@ def _create_local_ai_tool_configs(cwd: Path, rules_dir: Path,
980
980
  gen_windsurf_rules(cwd, language_modules=language_modules,
981
981
  rules_dir=rules_dir)
982
982
  if add_native_surfaces:
983
+ # .windsurf/hooks.json is Cascade-scoped and dies 2026-07-01;
984
+ # .devin/hooks.v1.json is the Devin CLI replacement (Claude format).
983
985
  _try_generator("generate_windsurf_hooks", cwd)
986
+ _try_generator("generate_devin_hooks", cwd)
984
987
  # Windsurf pointer stays unconditional (its .claude scan is gated).
985
988
  _try_generator("generate_windsurf_skills", cwd)
986
989
 
@@ -846,6 +846,9 @@ def _validate_version_sync(tk_dir: Path, vr: ValidationResult) -> None:
846
846
  # generators come and go.
847
847
  _NATIVE_HOOK_EDITORS = {"claude", "opencode"}
848
848
 
849
+ # generate_<stem>_hooks.py stems that belong to an existing README platform key.
850
+ _HOOK_STEM_ALIAS = {"devin": "windsurf"}
851
+
849
852
  # README platform label (lowercased) -> canonical editor key.
850
853
  _README_PLATFORM_KEY = {
851
854
  "claude code": "claude",
@@ -877,10 +880,12 @@ def _validate_editor_hooks_honesty(tk_dir: Path, vr: ValidationResult) -> None:
877
880
  return # installed copy without source — nothing to cross-check
878
881
 
879
882
  # Actual hook-enabled editors: native set + generate_<editor>_hooks.py stems.
883
+ # Some stems map back to a README platform key (e.g. the Devin CLI hooks
884
+ # generator is part of the windsurf/Devin-Desktop integration).
880
885
  actual = set(_NATIVE_HOOK_EDITORS)
881
886
  for gen in scripts_dir.glob("generate_*_hooks.py"):
882
887
  stem = gen.name[len("generate_"):-len("_hooks.py")]
883
- actual.add(stem)
888
+ actual.add(_HOOK_STEM_ALIAS.get(stem, stem))
884
889
 
885
890
  content = readme.read_text(encoding="utf-8")
886
891
  if "| Hooks |" not in content: