@cybedefend/vibedefend 1.7.0 → 1.8.1

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 (42) hide show
  1. package/README.md +22 -13
  2. package/dist/clients/antigravity.js +342 -0
  3. package/dist/clients/antigravity.js.map +1 -0
  4. package/dist/clients/registry.js +2 -0
  5. package/dist/clients/registry.js.map +1 -1
  6. package/dist/clients/windsurf.js +20 -8
  7. package/dist/clients/windsurf.js.map +1 -1
  8. package/dist/hook-runner.js +930 -227
  9. package/dist/hooks/install.js +1 -1
  10. package/dist/hooks/install.js.map +1 -1
  11. package/dist/hooks/runtime/antigravity-session.js +400 -0
  12. package/dist/hooks/runtime/antigravity-session.js.map +1 -0
  13. package/dist/hooks/runtime/emit.js +206 -0
  14. package/dist/hooks/runtime/emit.js.map +1 -1
  15. package/dist/hooks/runtime/exit-deadlock-guard.js +46 -0
  16. package/dist/hooks/runtime/exit-deadlock-guard.js.map +1 -0
  17. package/dist/hooks/runtime/fetch-rules.js +39 -3
  18. package/dist/hooks/runtime/fetch-rules.js.map +1 -1
  19. package/dist/hooks/runtime/pre-invocation.js +45 -0
  20. package/dist/hooks/runtime/pre-invocation.js.map +1 -0
  21. package/dist/hooks/runtime/runner-args.js +12 -0
  22. package/dist/hooks/runtime/runner-args.js.map +1 -0
  23. package/dist/hooks/runtime/session-activation.js +10 -4
  24. package/dist/hooks/runtime/session-activation.js.map +1 -1
  25. package/dist/hooks/runtime/session-review.js +42 -0
  26. package/dist/hooks/runtime/session-review.js.map +1 -1
  27. package/dist/hooks/runtime/session-start.js +21 -1
  28. package/dist/hooks/runtime/session-start.js.map +1 -1
  29. package/dist/hooks/runtime/sniff.js +345 -71
  30. package/dist/hooks/runtime/sniff.js.map +1 -1
  31. package/dist/hooks/runtime/work-dir.js +3 -0
  32. package/dist/hooks/runtime/work-dir.js.map +1 -1
  33. package/dist/hooks/shim.js +102 -5
  34. package/dist/hooks/shim.js.map +1 -1
  35. package/dist/install.js +17 -3
  36. package/dist/install.js.map +1 -1
  37. package/dist/json-file.js +6 -3
  38. package/dist/json-file.js.map +1 -1
  39. package/dist/shim.js +53 -3
  40. package/dist/utils.js +9 -0
  41. package/dist/utils.js.map +1 -1
  42. package/package.json +3 -2
package/README.md CHANGED
@@ -59,29 +59,35 @@ npm install -g @cybedefend/vibedefend && vibedefend install
59
59
 
60
60
  VibeDefend auto-detects and wires whichever of these you have installed.
61
61
 
62
- | Capability | Claude Code | Cursor | OpenAI Codex | Windsurf | VS Code Copilot |
63
- |---|:---:|:---:|:---:|:---:|:---:|
64
- | **MCP server install** | ✅ | ✅ | ✅ | ✅ | ✅ |
65
- | **Business + Security Rules** *(injected pre-write)* | ✅ edit + shell⁴ | ✅ | ✅ edit + shell⁴ | ⚠️ writes only | ✅ |
66
- | **Action Guards** *(hard block on deny)* | ✅ all tools | ✅ all tools | ✅ all tools | ⚠️ writes + MCP fallback¹ | ❌ not yet wired |
67
- | **Session Start** *(loads doctrine + proposals inbox)* | ✅ | ✅ | ✅ | ⚠️ proxied² | ✅ |
68
- | **Session Review** *(end-of-session gap analysis + pre-commit diff scan)* | ✅ | ✅ | ✅ | ✅ | ✅ |
69
- | **PreCompact** *(long-session gap analysis)* | ✅ | ✅ | ❌ no event | ❌ no event | ✅ |
70
- | **Doctrine backstop** *(per-prompt reminder)* | ✅ | ❌ | ✱ via MCP³ | ❌ | ❌ |
71
- | **Min version** | latest | ≥ 1.7 | latest | latest | ≥ 1.110 |
62
+ | Capability | Claude Code | Cursor | OpenAI Codex | Windsurf | VS Code Copilot | Google Antigravity |
63
+ |---|:---:|:---:|:---:|:---:|:---:|:---:|
64
+ | **MCP server install** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
65
+ | **Business + Security Rules** *(injected pre-write)* | ✅ edit + shell⁴ | ✅ | ✅ edit + shell⁴ | ⚠️ writes only | ✅ | ⚠️ edit + shell⁴, after the edit⁵ |
66
+ | **Action Guards** *(hard block on deny)* | ✅ all tools | ✅ all tools | ✅ all tools | ⚠️ writes, reads, shell + MCP fallback¹ | ❌ not yet wired | ✅ all tools⁶ |
67
+ | **Session Start** *(loads doctrine + proposals inbox)* | ✅ | ✅ | ✅ | ⚠️ proxied² | ✅ | ✅ |
68
+ | **Session Review** *(end-of-session gap analysis + pre-commit diff scan)* | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
69
+ | **PreCompact** *(long-session gap analysis)* | ✅ | ✅ | ❌ no event | ❌ no event | ✅ | ❌ no event |
70
+ | **Doctrine backstop** *(per-prompt reminder)* | ✅ | ❌ | ✱ via MCP³ | ❌ | ❌ | ❌ |
71
+ | **Min version** | latest | ≥ 1.7 | latest | latest | ≥ 1.110 | ≥ 2.0 (app / IDE) |
72
72
 
73
73
  **Legend** — ✅ supported · ⚠️ supported with caveats · ❌ not exposed by the agent · ✱ alternate mechanism
74
74
 
75
- ¹ Windsurf's `pre_write_code` hook hard-blocks on file writes only. For non-write tool calls (Read / Bash / WebFetch) the installer drops a snippet into `.windsurfrules` instructing the agent to call `cybe_guards_check` via MCP before sensitive actions — soft enforcement that relies on the model following its rules file.
75
+ ¹ Windsurf hard-blocks file writes (`pre_write_code`), file reads (`pre_read_code`) and shell commands (`pre_run_command`): the hook exits 2 and Cascade shows the agent the reason. A warning lets the action through unseen by the agent, since Cascade only shows it a hook's output on a block. Cascade has no hook for web fetches, and MCP tool calls are not gated: for those the installer drops a snippet into `.windsurfrules` instructing the agent to call `cybe_guards_check` via MCP before sensitive actions — soft enforcement that relies on the model following its rules file.
76
76
 
77
77
  ² Windsurf has no native SessionStart event. We wire `pre_user_prompt`, which fires on every turn. The hook is idempotent and cheap (one GET to the proposals endpoint, returns "0 pending" once the inbox is empty), so the per-turn cost is negligible.
78
78
 
79
79
  ³ Codex follows the doctrine via the MCP server's `Server.instructions` field on each session, removing the need for a per-prompt reminder hook.
80
80
 
81
- ⁴ On Claude Code and Codex the rules hook also fires on shell commands that write files (`>` / `>>` redirections, heredocs, `tee`, `sed -i`, `perl -pi`, `cp` / `mv`, `dd of=`, `bash -c '…'`), so an agent that edits through the shell gets the same rules as one using the edit tool. Read-only commands fetch nothing. Inline interpreters (`python -c`, `node -e`) and `git apply` / `patch` are not inspected. Cursor, Windsurf and VS Code Copilot: edit tools only.
81
+ ⁴ On Claude Code, Codex and Antigravity (its `run_command` tool) the rules hook also fires on shell commands that write files (`>` / `>>` redirections, heredocs, `tee`, `sed -i`, `perl -pi`, `cp` / `mv`, `dd of=`, `bash -c '…'`), so an agent that edits through the shell gets the same rules as one using the edit tool. Read-only commands fetch nothing. Inline interpreters (`python -c`, `node -e`) and `git apply` / `patch` are not inspected. Cursor, Windsurf and VS Code Copilot: edit tools only.
82
+
83
+ ⁵ Antigravity has no channel to inject context into the model from its PreToolUse hook, so rules fetched before a write are held and delivered at the agent's next model call (its PreInvocation event) instead — one step later than on every other client, but before the agent acts on what it just read.
84
+
85
+ ⁶ `agy --dangerously-skip-permissions` runs no hook at all, on any event. On Windows, a home path with a space in it is not supported — Antigravity has no way to quote the hook command it runs, so the installer detects this and refuses to wire a dead command rather than silently blocking every tool call. Antigravity's MCP servers are **not** wrapped by the VibeDefend MCP proxy (like Codex today): the CybeDefend server is registered directly against the region's URL.
82
86
 
83
87
  **Codex setup gotcha:** Codex 0.131+ requires you to approve each hook via the `/hooks` panel inside Codex *before* they fire. After running `vibedefend install`, open Codex, run `/hooks`, and trust the `cybedefend` entries — until you do that the panel will show `Installed N / Active 0`.
84
88
 
89
+ **Antigravity sign-in:** Antigravity does not open the CybeDefend sign-in on its own, and `agy` has no login command the installer could run for you (as it runs `codex mcp login` for Codex). Until you sign in once, the `cybedefend` server answers *Unauthorized*. In the Antigravity app, open **Customizations → Installed → MCP Servers** and click **Authenticate** next to `cybedefend`. In the `agy` CLI, run `/mcp`, pick `cybedefend`, then **Authenticate**. The app, the IDE and the CLI each keep their own sign-in. The installer prints these steps under *Next steps*.
90
+
85
91
  **Pre-commit diff scan (on by default):** when Session Review fires, the agent
86
92
  is also asked to run a quick **diff scan** (SAST / IaC / secrets) on the files
87
93
  it changed this session, via the `cybe_scan_diff` MCP tool — a best-effort
@@ -276,7 +282,10 @@ deletes `~/.cybedefend/`, keeping only your own `~/.cybedefend/regions.json`.
276
282
  Repositories keep their committed `.cybedefend/config.json`. A Windsurf
277
283
  `.windsurfrules` block is removed from the current directory only: in any other
278
284
  repo you wired for Windsurf, delete it by hand. Codex's `[features] hooks = true`
279
- flag stays set, since other hooks may rely on it.
285
+ flag stays set, since other hooks may rely on it. Antigravity's `hooks.json` and
286
+ `mcp_config.json` are user-global (shared by the app, the IDE extension and
287
+ `agy`, never per-project), so uninstall drops our `cybedefend-*` groups and MCP
288
+ server from there once, for every project — there is no per-repo cleanup to do.
280
289
 
281
290
  ## Sibling: `cybedefend-cli`
282
291
 
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Google Antigravity adapter.
3
+ *
4
+ * Antigravity shares one hooks file between the app, the IDE extension and
5
+ * `agy` — global, never per-project: `~/.gemini/config/hooks.json` (Windows:
6
+ * `%USERPROFILE%\.gemini\config\hooks.json`). Its top-level keys are hook
7
+ * GROUP names, not event names (contrast Cursor/Codex/Windsurf, which key by
8
+ * event). Each group nests its handlers under the events it fires on:
9
+ *
10
+ * PreToolUse (and other tool events):
11
+ * { "<group>": { "PreToolUse": [{ "matcher": "<regex>", "hooks": [
12
+ * { "type": "command", "command": "…", "timeout": 30 } ] }] } }
13
+ * Every other event (SessionStart, PreInvocation, Stop, …) lists the
14
+ * handler directly, with no matcher/hooks nesting:
15
+ * { "<group>": { "SessionStart": [
16
+ * { "type": "command", "command": "…", "timeout": 30 } ] } }
17
+ * A group may also carry a sibling `"enabled"` boolean, which the user can
18
+ * flip in the Antigravity UI; `writeSettings` preserves it across a
19
+ * reinstall (see `writeSettings` below).
20
+ *
21
+ * We write 5 groups, one per moment, all prefixed `cybedefend-`:
22
+ * - cybedefend-session-start SessionStart → session-start
23
+ * - cybedefend-rules PreToolUse → fetch-rules (matcher "*", self-filtered)
24
+ * - cybedefend-rules-delivery PreInvocation → pre-invocation (injects stashed rules)
25
+ * - cybedefend-guards PreToolUse → guard-check (matcher "*", every tool)
26
+ * - cybedefend-session-review Stop → session-review (only when enabled)
27
+ *
28
+ * A top-level key is OURS when its name starts with `cybedefend-` AND its
29
+ * JSON references our managed hook dir (`textReferencesHookRunner`). That
30
+ * is a stronger bar than the prefix alone — a user's own `cybedefend-mine`
31
+ * group, wired to a command of their own, is never touched. `writeSettings`
32
+ * drops our groups wholesale and rewrites them fresh (so a re-install can
33
+ * never duplicate a handler inside a group — there's nothing to dedupe,
34
+ * each key is written exactly once, and an old group of ours under a
35
+ * command shape a previous version wrote is replaced, never kept alongside
36
+ * the new one), and `uninstall` only drops them.
37
+ *
38
+ * Hook commands: Antigravity runs a POSIX hook through `sh -c "<command>"`
39
+ * and a Windows one through `cmd /C "<command>"` — never execve directly —
40
+ * so:
41
+ * - POSIX: `node <runner> <sub> --client antigravity || echo '<fallback>'`.
42
+ * A missing `node`/runner (or any runner crash) then answers the same
43
+ * fallback a healthy run would print on its own early-exit path, instead
44
+ * of blocking every tool call fail-closed forever.
45
+ * - Windows: `node <runner> <sub> --client antigravity`, no quoting and no
46
+ * `|| echo '<fallback>'`. `agy` escapes embedded quotes, and the
47
+ * fallback JSON (`{"decision":"allow"}`) is itself quote-bearing, so
48
+ * there is no way to nest it inside the already-quoted `cmd /C "…"`
49
+ * invocation without `agy` mangling it on the way in. The runner path
50
+ * can't be quoted either, so a path containing whitespace can't be
51
+ * spawned at all — `detect()`, AND `writeSettings()` itself (belt and
52
+ * suspenders: a manually-ticked client that `detect()` never got to
53
+ * veto, or `vibedefend doctor` re-wiring from `detect().installed`
54
+ * alone), both check this (`antigravityWindowsBlock`) and refuse to
55
+ * wire a command that would never run.
56
+ *
57
+ * The fallback is `{"decision":"allow"}` for the two PreToolUse subcommands
58
+ * (fetch-rules, guard-check) — a dead runner must fail OPEN there, exactly
59
+ * like every other client's hook does when it can't execute — and `{}` for
60
+ * every other subcommand, which Antigravity expects verbatim on success.
61
+ */
62
+ import { existsSync, readFileSync } from 'node:fs';
63
+ import { readJson, writeJson } from '../json-file.js';
64
+ import { home, log, stripBom } from '../utils.js';
65
+ import { HOOK_RUNNER_PATH, toPosixPath, quoteCommandPath, textReferencesHookRunner } from '../hooks/install.js';
66
+ import { PRE_TOOL_USE_SUBCOMMANDS } from '../hooks/runtime/emit.js';
67
+ import { mcpStatus, readJsonServerEntry } from './mcp-url.js';
68
+ import { deleteKeys, editJsonFile } from './unwire.js';
69
+ import { configDirExists, probeBinaryVersion } from './detect.js';
70
+ const ANTIGRAVITY_HOOKS = home('.gemini', 'config', 'hooks.json');
71
+ const ANTIGRAVITY_MCP = home('.gemini', 'config', 'mcp_config.json');
72
+ /**
73
+ * The `command` field of an Antigravity hook handler, targeting `sub` on
74
+ * `--client antigravity`. `--client` and `antigravity` are two separate
75
+ * argv tokens — the runner's arg parser skips anything before the
76
+ * subcommand and ignores a combined `--client=antigravity`.
77
+ */
78
+ export function antigravityHookCommand(sub, opts = {}) {
79
+ const platform = opts.platform ?? process.platform;
80
+ // Forward-slash first (Windows-shell safe), as `hookCommand` does.
81
+ const runnerPath = toPosixPath(opts.runnerPath ?? HOOK_RUNNER_PATH);
82
+ if (platform === 'win32') {
83
+ // No quoting (a quoted path can't be spawned) and no `|| echo` fallback:
84
+ // the fallback JSON is quote-bearing and `agy` escapes embedded quotes,
85
+ // so nesting it inside the already-quoted `cmd /C "…"` invocation would
86
+ // be mangled rather than run.
87
+ return `node ${runnerPath} ${sub} --client antigravity`;
88
+ }
89
+ const fallback = PRE_TOOL_USE_SUBCOMMANDS.has(sub) ? '{"decision":"allow"}' : '{}';
90
+ return `node ${quoteCommandPath(runnerPath)} ${sub} --client antigravity || echo '${fallback}'`;
91
+ }
92
+ /**
93
+ * `null` unless Antigravity on Windows cannot spawn `runnerPath` at all — a
94
+ * whitespace path with no safe quoting mechanism available. Used by both
95
+ * `detect()` and `writeSettings()` (to report/refuse instead of wiring a
96
+ * dead command) and by tests.
97
+ */
98
+ export function antigravityWindowsBlock(platform, runnerPath) {
99
+ if (platform !== 'win32')
100
+ return null;
101
+ if (!/\s/.test(runnerPath))
102
+ return null;
103
+ return `Antigravity on Windows cannot run a hook whose path contains a space: ${runnerPath}`;
104
+ }
105
+ /**
106
+ * The 5 (or 4, with session review off) `cybedefend-*` hook groups, keyed by
107
+ * group name — ready to be merged as whole top-level keys into `hooks.json`.
108
+ */
109
+ export function buildAntigravityHookGroups(opts) {
110
+ const cmd = (sub) => antigravityHookCommand(sub, { platform: opts.platform, runnerPath: opts.runnerPath });
111
+ const groups = {
112
+ 'cybedefend-session-start': {
113
+ SessionStart: [{ type: 'command', command: cmd('session-start'), timeout: 30 }],
114
+ },
115
+ 'cybedefend-rules': {
116
+ PreToolUse: [
117
+ {
118
+ // Every tool (Ruling R14): Antigravity's tool names change with the
119
+ // model (`write_to_file` or `write_file`, `replace_file_content` or
120
+ // `edit_file`, …), and a matcher that missed one silently dropped
121
+ // the rules for every write. fetch-rules keeps only the write and
122
+ // shell tools itself and answers `allow` at once on any other.
123
+ matcher: '*',
124
+ hooks: [{ type: 'command', command: cmd('fetch-rules'), timeout: 30 }],
125
+ },
126
+ ],
127
+ },
128
+ 'cybedefend-rules-delivery': {
129
+ PreInvocation: [{ type: 'command', command: cmd('pre-invocation'), timeout: 10 }],
130
+ },
131
+ 'cybedefend-guards': {
132
+ PreToolUse: [
133
+ {
134
+ matcher: '*',
135
+ hooks: [{ type: 'command', command: cmd('guard-check'), timeout: 30 }],
136
+ },
137
+ ],
138
+ },
139
+ };
140
+ if (opts.enableSessionReview) {
141
+ groups['cybedefend-session-review'] = {
142
+ Stop: [{ type: 'command', command: cmd('session-review'), timeout: 30 }],
143
+ };
144
+ }
145
+ return groups;
146
+ }
147
+ /** Top-level keys of `file` that are ours: prefix `cybedefend-` AND the JSON references our managed hook dir. */
148
+ function ourGroupKeys(file) {
149
+ return Object.keys(file).filter((key) => key.startsWith('cybedefend-') && textReferencesHookRunner(JSON.stringify(file[key])));
150
+ }
151
+ /**
152
+ * Delete every top-level key of `file` that is ours (prefix `cybedefend-`
153
+ * AND its JSON references our managed hook dir). A user's own
154
+ * `cybedefend-*` group that doesn't mention our runner is left alone — the
155
+ * prefix alone is not a strong enough signal to delete someone else's
156
+ * config. Returns whether anything was removed.
157
+ */
158
+ function dropOurGroups(file) {
159
+ const keys = ourGroupKeys(file);
160
+ for (const key of keys)
161
+ delete file[key];
162
+ return keys.length > 0;
163
+ }
164
+ /**
165
+ * The names of our groups the user has switched off (`"enabled": false`,
166
+ * Antigravity's own per-group toggle) before they get dropped and rewritten
167
+ * — so `writeSettings` can carry that flag over onto the fresh replacement
168
+ * instead of silently re-enabling a group the user turned off.
169
+ */
170
+ function disabledOurGroups(file) {
171
+ const disabled = new Set();
172
+ for (const key of ourGroupKeys(file)) {
173
+ const group = file[key];
174
+ if (group && typeof group === 'object' && group.enabled === false) {
175
+ disabled.add(key);
176
+ }
177
+ }
178
+ return disabled;
179
+ }
180
+ function detect() {
181
+ const version = probeBinaryVersion('agy') ?? undefined;
182
+ const hasConfigDir = configDirExists(home('.gemini', 'antigravity')) ||
183
+ configDirExists(home('.gemini', 'antigravity-ide')) ||
184
+ configDirExists(home('.gemini', 'antigravity-cli'));
185
+ const hasApp = process.platform === 'darwin' && existsSync('/Applications/Antigravity.app');
186
+ const installed = version !== undefined || hasConfigDir || hasApp;
187
+ // Computed regardless of `installed`: a Windows home with a whitespace
188
+ // path is the more actionable reason to surface, and `writeSettings` is
189
+ // reachable even from a "not installed" detection (a client manually
190
+ // ticked in the install picker, or `vibedefend doctor` re-wiring from
191
+ // `detect().installed` alone without re-checking `supportsHooks`).
192
+ const windowsBlock = antigravityWindowsBlock(process.platform, HOOK_RUNNER_PATH);
193
+ if (!installed) {
194
+ return {
195
+ installed: false,
196
+ supportsHooks: false,
197
+ reason: windowsBlock ??
198
+ '`agy` CLI not on PATH, no ~/.gemini/antigravity(-ide|-cli)/ directory, ' +
199
+ 'and no /Applications/Antigravity.app.',
200
+ };
201
+ }
202
+ // No version gate — hooks shipped with Antigravity's first release.
203
+ if (windowsBlock) {
204
+ return { installed: true, version, supportsHooks: false, reason: windowsBlock };
205
+ }
206
+ return { installed: true, version, supportsHooks: true };
207
+ }
208
+ function supports(event) {
209
+ // Antigravity has no PreCompact and no UserPromptSubmit event. Action
210
+ // Guards (guard-check) and rules delivery (pre-invocation) are wired
211
+ // unconditionally below — they aren't part of the LifecycleEvent surface
212
+ // `supports()` is asked about.
213
+ return event === 'fetch-rules' || event === 'session-start' || event === 'stop';
214
+ }
215
+ function writeSettings(opts) {
216
+ // Belt and suspenders: `detect()` is what normally keeps this adapter out
217
+ // of the picker on an unspawnable Windows path, but `writeSettings` can
218
+ // still be reached directly (a client ticked by hand before `detect()`
219
+ // ran, or a re-wire driven only by `detect().installed`). Never wire a
220
+ // command that would block every Antigravity tool call for want of a
221
+ // runnable hook — and clean up anything an earlier, unguarded install
222
+ // left behind.
223
+ const windowsBlock = antigravityWindowsBlock(process.platform, HOOK_RUNNER_PATH);
224
+ if (windowsBlock) {
225
+ log.warn(windowsBlock);
226
+ editJsonFile(ANTIGRAVITY_HOOKS, dropOurGroups);
227
+ return;
228
+ }
229
+ const file = readJson(ANTIGRAVITY_HOOKS, {});
230
+ const disabled = disabledOurGroups(file);
231
+ dropOurGroups(file);
232
+ const groups = buildAntigravityHookGroups({ enableSessionReview: opts.enableSessionReview });
233
+ for (const key of disabled) {
234
+ const group = groups[key];
235
+ if (group && typeof group === 'object') {
236
+ group.enabled = false;
237
+ }
238
+ }
239
+ Object.assign(file, groups);
240
+ writeJson(ANTIGRAVITY_HOOKS, file);
241
+ log.ok(`Antigravity hooks wired into ${ANTIGRAVITY_HOOKS}`);
242
+ log.hint('`agy --dangerously-skip-permissions` runs no hook at all.');
243
+ log.hint('Rules reach the agent at its next model call (PreInvocation), not immediately after the edit that triggered them.');
244
+ }
245
+ /**
246
+ * Register the CybeDefend MCP server in `~/.gemini/config/mcp_config.json`.
247
+ * This is NOT wrapped by the VibeDefend MCP proxy (like Codex today) — the
248
+ * entry points straight at the region's URL.
249
+ */
250
+ function registerMcp(opts) {
251
+ log.step(`Registering MCP "${opts.region.mcpName}" in Antigravity`);
252
+ log.hint(`URL: ${opts.region.mcpUrl}`);
253
+ const file = readJson(ANTIGRAVITY_MCP, {});
254
+ file.mcpServers ??= {};
255
+ file.mcpServers[opts.region.mcpName] = { serverUrl: opts.region.mcpUrl };
256
+ writeJson(ANTIGRAVITY_MCP, file);
257
+ log.ok(`MCP "${opts.region.mcpName}" registered in ${ANTIGRAVITY_MCP}`);
258
+ log.hint(`Sign in to it once: ${signInHowTo(opts.region)}`);
259
+ return true;
260
+ }
261
+ /**
262
+ * Antigravity opens no sign-in on its own: until the user authenticates,
263
+ * the server shows "Unauthorized" next to an Authenticate button (observed
264
+ * on Antigravity 2.28.2). `agy` has no login command the installer could
265
+ * run, unlike `codex mcp login`. The app, the IDE and the CLI each keep
266
+ * their own sign-in.
267
+ */
268
+ function signInHowTo(region) {
269
+ return (`in Antigravity, open Customizations → Installed → MCP Servers and click Authenticate next to "${region.mcpName}"; ` +
270
+ `in the agy CLI, run /mcp, pick "${region.mcpName}", then Authenticate. Each of them keeps its own sign-in.`);
271
+ }
272
+ function mcpSignInStep(region) {
273
+ return `Google Antigravity: ${signInHowTo(region)}`;
274
+ }
275
+ /**
276
+ * Pure introspection — never throws, as Windsurf's does. `hooksWired` from a
277
+ * raw-text marker check on `hooks.json`, `mcpRegistered` from the
278
+ * `serverUrl` of our entry in `mcp_config.json` — it must point at this
279
+ * region, not just exist. Both reads strip a leading BOM first, since
280
+ * either file may carry one.
281
+ */
282
+ function inspect(region) {
283
+ let hooksWired = false;
284
+ try {
285
+ if (existsSync(ANTIGRAVITY_HOOKS)) {
286
+ hooksWired = textReferencesHookRunner(stripBom(readFileSync(ANTIGRAVITY_HOOKS, 'utf8')));
287
+ }
288
+ }
289
+ catch {
290
+ /* missing/unreadable → false */
291
+ }
292
+ const entry = readJsonServerEntry(() => stripBom(readFileSync(ANTIGRAVITY_MCP, 'utf8')), 'mcpServers', region.mcpName);
293
+ return { hooksWired, ...mcpStatus(entry?.serverUrl, region) };
294
+ }
295
+ /**
296
+ * Drop our `cybedefend-*` groups from `hooks.json` (whole top-level keys —
297
+ * see `dropOurGroups`) and our servers from `mcp_config.json`. Every other
298
+ * key / server is left untouched.
299
+ *
300
+ * The two files are independent, so both steps always run even when one
301
+ * throws (a malformed `hooks.json` must not leave our MCP server behind) —
302
+ * only once both have been attempted does this re-throw the FIRST error, if
303
+ * any.
304
+ */
305
+ function uninstall(opts) {
306
+ let hooksRemoved = false;
307
+ let hooksError;
308
+ try {
309
+ hooksRemoved = editJsonFile(ANTIGRAVITY_HOOKS, dropOurGroups);
310
+ }
311
+ catch (err) {
312
+ hooksError = err;
313
+ }
314
+ let mcpRemoved = [];
315
+ let mcpError;
316
+ try {
317
+ editJsonFile(ANTIGRAVITY_MCP, (file) => {
318
+ mcpRemoved = deleteKeys(file.mcpServers, opts.mcpNames);
319
+ return mcpRemoved.length > 0;
320
+ });
321
+ }
322
+ catch (err) {
323
+ mcpError = err;
324
+ }
325
+ if (hooksError)
326
+ throw hooksError;
327
+ if (mcpError)
328
+ throw mcpError;
329
+ return { hookFiles: hooksRemoved ? [ANTIGRAVITY_HOOKS] : [], mcpRemoved };
330
+ }
331
+ export const antigravityAdapter = {
332
+ id: 'antigravity',
333
+ label: 'Google Antigravity',
334
+ detect,
335
+ supports,
336
+ writeSettings,
337
+ registerMcp,
338
+ mcpSignInStep,
339
+ inspect,
340
+ uninstall,
341
+ };
342
+ //# sourceMappingURL=antigravity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"antigravity.js","sourceRoot":"","sources":["../../src/clients/antigravity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAChH,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAYpE,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AAClE,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAcrE;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAA0B,EAC1B,OAA4D,EAAE;IAE9D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACnD,mEAAmE;IACnE,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,UAAU,IAAI,gBAAgB,CAAC,CAAC;IAEpE,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,yEAAyE;QACzE,wEAAwE;QACxE,wEAAwE;QACxE,8BAA8B;QAC9B,OAAO,QAAQ,UAAU,IAAI,GAAG,uBAAuB,CAAC;IAC1D,CAAC;IAED,MAAM,QAAQ,GAAG,wBAAwB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC;IACnF,OAAO,QAAQ,gBAAgB,CAAC,UAAU,CAAC,IAAI,GAAG,kCAAkC,QAAQ,GAAG,CAAC;AAClG,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAAyB,EACzB,UAAkB;IAElB,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,yEAAyE,UAAU,EAAE,CAAC;AAC/F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAI1C;IACC,MAAM,GAAG,GAAG,CAAC,GAA0B,EAAU,EAAE,CACjD,sBAAsB,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAExF,MAAM,MAAM,GAA4B;QACtC,0BAA0B,EAAE;YAC1B,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;SAChF;QACD,kBAAkB,EAAE;YAClB,UAAU,EAAE;gBACV;oBACE,oEAAoE;oBACpE,oEAAoE;oBACpE,kEAAkE;oBAClE,kEAAkE;oBAClE,+DAA+D;oBAC/D,OAAO,EAAE,GAAG;oBACZ,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;iBACvE;aACF;SACF;QACD,2BAA2B,EAAE;YAC3B,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;SAClF;QACD,mBAAmB,EAAE;YACnB,UAAU,EAAE;gBACV;oBACE,OAAO,EAAE,GAAG;oBACZ,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;iBACvE;aACF;SACF;KACF,CAAC;IAEF,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7B,MAAM,CAAC,2BAA2B,CAAC,GAAG;YACpC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;SACzE,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,iHAAiH;AACjH,SAAS,YAAY,CAAC,IAA6B;IACjD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAC7B,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,wBAAwB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAC9F,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,IAA6B;IAClD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,IAA6B;IACtD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,KAAiC,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC/F,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,MAAM;IACb,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC;IACvD,MAAM,YAAY,GAChB,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAC/C,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;QACnD,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,UAAU,CAAC,+BAA+B,CAAC,CAAC;IAC5F,MAAM,SAAS,GAAG,OAAO,KAAK,SAAS,IAAI,YAAY,IAAI,MAAM,CAAC;IAElE,uEAAuE;IACvE,wEAAwE;IACxE,qEAAqE;IACrE,sEAAsE;IACtE,mEAAmE;IACnE,MAAM,YAAY,GAAG,uBAAuB,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAEjF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,KAAK;YACpB,MAAM,EACJ,YAAY;gBACZ,yEAAyE;oBACvE,uCAAuC;SAC5C,CAAC;IACJ,CAAC;IAED,oEAAoE;IACpE,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAClF,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AAC3D,CAAC;AAED,SAAS,QAAQ,CAAC,KAAqB;IACrC,sEAAsE;IACtE,qEAAqE;IACrE,yEAAyE;IACzE,+BAA+B;IAC/B,OAAO,KAAK,KAAK,aAAa,IAAI,KAAK,KAAK,eAAe,IAAI,KAAK,KAAK,MAAM,CAAC;AAClF,CAAC;AAED,SAAS,aAAa,CAAC,IAAiB;IACtC,0EAA0E;IAC1E,wEAAwE;IACxE,uEAAuE;IACvE,uEAAuE;IACvE,qEAAqE;IACrE,sEAAsE;IACtE,eAAe;IACf,MAAM,YAAY,GAAG,uBAAuB,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IACjF,IAAI,YAAY,EAAE,CAAC;QACjB,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACvB,YAAY,CAA0B,iBAAiB,EAAE,aAAa,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAA0B,iBAAiB,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACzC,aAAa,CAAC,IAAI,CAAC,CAAC;IAEpB,MAAM,MAAM,GAAG,0BAA0B,CAAC,EAAE,mBAAmB,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC7F,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACtC,KAAiC,CAAC,OAAO,GAAG,KAAK,CAAC;QACrD,CAAC;IACH,CAAC;IACD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5B,SAAS,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;IAEnC,GAAG,CAAC,EAAE,CAAC,gCAAgC,iBAAiB,EAAE,CAAC,CAAC;IAC5D,GAAG,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IACtE,GAAG,CAAC,IAAI,CACN,mHAAmH,CACpH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,IAA8B;IACjD,GAAG,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;IACpE,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,QAAQ,CAAqB,eAAe,EAAE,EAAE,CAAC,CAAC;IAC/D,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC;IACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IACzE,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IACjC,GAAG,CAAC,EAAE,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,mBAAmB,eAAe,EAAE,CAAC,CAAC;IACxE,GAAG,CAAC,IAAI,CAAC,uBAAuB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,WAAW,CAAC,MAAoB;IACvC,OAAO,CACL,iGAAiG,MAAM,CAAC,OAAO,KAAK;QACpH,mCAAmC,MAAM,CAAC,OAAO,2DAA2D,CAC7G,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,MAAoB;IACzC,OAAO,uBAAuB,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;;;;GAMG;AACH,SAAS,OAAO,CAAC,MAAoB;IACnC,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAClC,UAAU,GAAG,wBAAwB,CAAC,QAAQ,CAAC,YAAY,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,MAAM,KAAK,GAAG,mBAAmB,CAC/B,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,EACrD,YAAY,EACZ,MAAM,CAAC,OAAO,CACf,CAAC;IACF,OAAO,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;AAChE,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,SAAS,CAAC,IAAmB;IACpC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,UAAmB,CAAC;IACxB,IAAI,CAAC;QACH,YAAY,GAAG,YAAY,CAA0B,iBAAiB,EAAE,aAAa,CAAC,CAAC;IACzF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,UAAU,GAAG,GAAG,CAAC;IACnB,CAAC;IAED,IAAI,UAAU,GAAa,EAAE,CAAC;IAC9B,IAAI,QAAiB,CAAC;IACtB,IAAI,CAAC;QACH,YAAY,CAAqB,eAAe,EAAE,CAAC,IAAI,EAAE,EAAE;YACzD,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxD,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,GAAG,GAAG,CAAC;IACjB,CAAC;IAED,IAAI,UAAU;QAAE,MAAM,UAAU,CAAC;IACjC,IAAI,QAAQ;QAAE,MAAM,QAAQ,CAAC;IAE7B,OAAO,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC;AAC5E,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAkB;IAC/C,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,oBAAoB;IAC3B,MAAM;IACN,QAAQ;IACR,aAAa;IACb,WAAW;IACX,aAAa;IACb,OAAO;IACP,SAAS;CACV,CAAC"}
@@ -6,6 +6,7 @@
6
6
  * order. Claude Code first because it has the most mature hook surface
7
7
  * and is the assumed default; the others follow alphabetically.
8
8
  */
9
+ import { antigravityAdapter } from './antigravity.js';
9
10
  import { claudeCodeAdapter } from './claude-code.js';
10
11
  import { codexAdapter } from './codex.js';
11
12
  import { cursorAdapter } from './cursor.js';
@@ -17,6 +18,7 @@ export const ALL_ADAPTERS = [
17
18
  vscodeAdapter,
18
19
  windsurfAdapter,
19
20
  codexAdapter,
21
+ antigravityAdapter,
20
22
  ];
21
23
  /** Look up an adapter by ID. Throws if not found (programming error). */
22
24
  export function adapterFor(id) {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/clients/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIhD,MAAM,CAAC,MAAM,YAAY,GAA6B;IACpD,iBAAiB;IACjB,aAAa;IACb,aAAa;IACb,eAAe;IACf,YAAY;CACJ,CAAC;AAEX,yEAAyE;AACzE,MAAM,UAAU,UAAU,CAAC,EAAY;IACrC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wCAAwC,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS;IAIvB,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO;QACP,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE;KAC5B,CAAC,CAAC,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/clients/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIhD,MAAM,CAAC,MAAM,YAAY,GAA6B;IACpD,iBAAiB;IACjB,aAAa;IACb,aAAa;IACb,eAAe;IACf,YAAY;IACZ,kBAAkB;CACV,CAAC;AAEX,yEAAyE;AACzE,MAAM,UAAU,UAAU,CAAC,EAAY;IACrC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wCAAwC,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS;IAIvB,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO;QACP,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE;KAC5B,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -10,6 +10,8 @@
10
10
  * │ Our event │ Windsurf event │
11
11
  * ├──────────────────┼─────────────────────────────────────────────┤
12
12
  * │ fetch-rules │ pre_write_code │
13
+ * │ guard-check │ pre_write_code, pre_read_code, │
14
+ * │ │ pre_run_command │
13
15
  * │ session-start │ pre_user_prompt (no SessionStart in Cascade)│
14
16
  * │ stop │ post_cascade_response │
15
17
  * │ pre-compact │ (not supported — Cascade has no equivalent) │
@@ -68,18 +70,27 @@ function dropOurs(entries) {
68
70
  function writeSettings(opts) {
69
71
  const file = readJson(WINDSURF_HOOKS, {});
70
72
  file.pre_write_code ??= [];
73
+ file.pre_read_code ??= [];
74
+ file.pre_run_command ??= [];
71
75
  file.pre_user_prompt ??= [];
72
76
  file.post_cascade_response ??= [];
73
77
  file.pre_write_code = dropOurs(file.pre_write_code);
78
+ file.pre_read_code = dropOurs(file.pre_read_code);
79
+ file.pre_run_command = dropOurs(file.pre_run_command);
74
80
  file.pre_user_prompt = dropOurs(file.pre_user_prompt);
75
81
  file.post_cascade_response = dropOurs(file.post_cascade_response);
76
82
  file.pre_write_code.push({ command: hookCommand('fetch-rules') });
77
83
  file.pre_user_prompt.push({ command: hookCommand('session-start') });
78
- // Action Guards: pre_write_code fires before every write — closest
79
- // Cascade equivalent to PreToolUse. Also fires guard-check on
80
- // pre_user_prompt so shell / HTTP commands typed by the user are
81
- // gated as well.
84
+ // Action Guards: Cascade has no single PreToolUse, it has one pre-hook per
85
+ // kind of action. guard-check runs on the three that carry a target to
86
+ // gate — a write (`tool_info.file_path`), a read (`tool_info.file_path`)
87
+ // and a shell command (`tool_info.command_line`) — and blocks with exit 2,
88
+ // the agent reading the reason on stderr. Not wired on pre_user_prompt
89
+ // (a prompt has no target) nor pre_mcp_tool_use (tools with arbitrary
90
+ // arguments; the .windsurfrules snippet below covers them).
82
91
  file.pre_write_code.push({ command: hookCommand('guard-check') });
92
+ file.pre_read_code.push({ command: hookCommand('guard-check') });
93
+ file.pre_run_command.push({ command: hookCommand('guard-check') });
83
94
  if (opts.enableSessionReview) {
84
95
  file.post_cascade_response.push({
85
96
  command: hookCommand('session-review'),
@@ -89,10 +100,11 @@ function writeSettings(opts) {
89
100
  log.ok(`Windsurf hooks wired into ${WINDSURF_HOOKS}`);
90
101
  log.hint('Note: Cascade has no PreCompact event, so long-session gap analysis only fires at end-of-response (post_cascade_response).');
91
102
  // Inject the soft-enforcement snippet into .windsurfrules in the project
92
- // directory (process.cwd() at install time = repo root). Windsurf's
93
- // Cascade pre_write_code hook fires on file writes but not on Read/Bash/
94
- // WebFetch tool calls, so the snippet closes that gap by instructing the
95
- // model to call cybe_guards_check before ANY sensitive action via MCP.
103
+ // directory (process.cwd() at install time = repo root). The hooks above
104
+ // gate writes, reads and shell commands; Cascade has no hook for web
105
+ // fetches, and MCP tool calls are not gated, so the snippet closes that gap
106
+ // by instructing the model to call cybe_guards_check before ANY sensitive
107
+ // action via MCP.
96
108
  const windsurfRulesPath = join(process.cwd(), '.windsurfrules');
97
109
  appendGuardSnippetIdempotent(windsurfRulesPath, WINDSURF_GUARDS_SNIPPET, '<see .cybedefend/config.json>');
98
110
  log.ok(`.windsurfrules updated at ${windsurfRulesPath}`);
@@ -1 +1 @@
1
- {"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../src/clients/windsurf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,WAAW,EACX,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,qBAAqB,CAAC;AAY7B,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EACL,eAAe,EACf,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAClE,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAsBrE,SAAS,MAAM;IACb,4EAA4E;IAC5E,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC;IAC5D,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,OAAO,KAAK,SAAS,IAAI,YAAY,CAAC;IAExD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,aAAa,EAAE,KAAK;YACpB,MAAM,EAAE,mEAAmE;SAC5E,CAAC;IACJ,CAAC;IACD,OAAO;QACL,SAAS,EAAE,IAAI;QACf,OAAO;QACP,aAAa,EAAE,IAAI;QACnB,oEAAoE;QACpE,kEAAkE;QAClE,+DAA+D;KAChE,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAqB;IACrC,mEAAmE;IACnE,4DAA4D;IAC5D,OAAO,KAAK,KAAK,aAAa,CAAC;AACjC,CAAC;AAED,SAAS,QAAQ,CAAC,OAA4B;IAC5C,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,aAAa,CAAC,IAAiB;IACtC,MAAM,IAAI,GAAG,QAAQ,CAAoB,cAAc,EAAE,EAAE,CAAC,CAAC;IAC7D,IAAI,CAAC,cAAc,KAAK,EAAE,CAAC;IAC3B,IAAI,CAAC,eAAe,KAAK,EAAE,CAAC;IAC5B,IAAI,CAAC,qBAAqB,KAAK,EAAE,CAAC;IAElC,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACpD,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACtD,IAAI,CAAC,qBAAqB,GAAG,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAElE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAClE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IAErE,mEAAmE;IACnE,8DAA8D;IAC9D,iEAAiE;IACjE,iBAAiB;IACjB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAElE,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7B,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC;YAC9B,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC;SACvC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAChC,GAAG,CAAC,EAAE,CAAC,6BAA6B,cAAc,EAAE,CAAC,CAAC;IACtD,GAAG,CAAC,IAAI,CACN,4HAA4H,CAC7H,CAAC;IAEF,yEAAyE;IACzE,oEAAoE;IACpE,yEAAyE;IACzE,yEAAyE;IACzE,uEAAuE;IACvE,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAChE,4BAA4B,CAAC,iBAAiB,EAAE,uBAAuB,EAAE,+BAA+B,CAAC,CAAC;IAC1G,GAAG,CAAC,EAAE,CAAC,6BAA6B,iBAAiB,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,IAA8B;IACjD,GAAG,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;IACjE,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,QAAQ,CAAkB,YAAY,EAAE,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC;IACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IACzE,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,mBAAmB,YAAY,EAAE,CAAC,CAAC;IACrE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,OAAO,CAAC,MAAoB;IACnC,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/B,UAAU,GAAG,wBAAwB,CACnC,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CACrC,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,MAAM,KAAK,GAAG,mBAAmB,CAC/B,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,EACxC,YAAY,EACZ,MAAM,CAAC,OAAO,CACf,CAAC;IACF,OAAO,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,IAAmB;IACpC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IACE,YAAY,CAAoB,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CACvD,mBAAmB,CAAoB,IAAI,EAAE,QAAQ,CAAC,CACvD,EACD,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;IACpE,IAAI,kBAAkB,CAAC,SAAS,CAAC;QAAE,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE7D,IAAI,UAAU,GAAa,EAAE,CAAC;IAC9B,YAAY,CAAkB,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE;QACnD,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxD,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAkB;IAC5C,EAAE,EAAE,UAAU;IACd,KAAK,EAAE,oBAAoB;IAC3B,MAAM;IACN,QAAQ;IACR,aAAa;IACb,WAAW;IACX,OAAO;IACP,SAAS;CACV,CAAC"}
1
+ {"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../src/clients/windsurf.ts"],"names":[],"mappings":"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"}