agents-can-communicate 0.8.5 → 0.9.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 (142) hide show
  1. package/README.md +11 -7
  2. package/bin/entrypoints/acc-antigravity-relay.mjs +2 -4
  3. package/bin/entrypoints/acc-hook.mjs +33 -19
  4. package/bin/entrypoints/hook-output.mjs +14 -5
  5. package/docs/ADAPTER_AUTHORING.md +29 -0
  6. package/docs/CAPABILITIES.md +7 -6
  7. package/docs/CLI.md +5 -0
  8. package/docs/CONFIGURATION.md +41 -10
  9. package/docs/DESIGN_DECISIONS.md +0 -2
  10. package/docs/GETTING_STARTED.md +39 -6
  11. package/docs/HOW_IT_WORKS.md +13 -8
  12. package/docs/SECURITY_MODEL.md +32 -5
  13. package/docs/TROUBLESHOOTING.md +76 -8
  14. package/docs/UPGRADING.md +47 -5
  15. package/node_modules/@agents-can-communicate/adapter-antigravity/certification.json +78 -0
  16. package/node_modules/@agents-can-communicate/adapter-antigravity/fixtures/certification-provenance.json +111 -0
  17. package/node_modules/@agents-can-communicate/adapter-antigravity/fixtures/delivery/antigravity-desktop-2.19.1-product-evidence.json +156 -0
  18. package/node_modules/@agents-can-communicate/adapter-antigravity/fixtures/delivery/antigravity-desktop-2.19.1-product.json +25 -0
  19. package/node_modules/@agents-can-communicate/adapter-antigravity/fixtures/desktop-2.19.1.json +141 -0
  20. package/node_modules/@agents-can-communicate/adapter-antigravity/package.json +4 -1
  21. package/node_modules/@agents-can-communicate/adapter-antigravity/plugin/plugin.json +1 -1
  22. package/node_modules/@agents-can-communicate/adapter-antigravity/plugin/skills/acc/SKILL.md +3 -0
  23. package/node_modules/@agents-can-communicate/adapter-antigravity/src/adapter.mjs +13 -2
  24. package/node_modules/@agents-can-communicate/adapter-antigravity/src/agentapi.mjs +7 -5
  25. package/node_modules/@agents-can-communicate/adapter-antigravity/src/allow-rule.mjs +98 -17
  26. package/node_modules/@agents-can-communicate/adapter-antigravity/src/client-process.mjs +64 -0
  27. package/node_modules/@agents-can-communicate/adapter-antigravity/src/desktop-allow-rule.mjs +140 -0
  28. package/node_modules/@agents-can-communicate/adapter-antigravity/src/desktop-delivery.mjs +110 -0
  29. package/node_modules/@agents-can-communicate/adapter-antigravity/src/desktop-endpoint.mjs +203 -0
  30. package/node_modules/@agents-can-communicate/adapter-antigravity/src/install.mjs +61 -30
  31. package/node_modules/@agents-can-communicate/adapter-antigravity/src/native-delivery.mjs +61 -24
  32. package/node_modules/@agents-can-communicate/adapter-antigravity/src/relay-endpoint.mjs +30 -20
  33. package/node_modules/@agents-can-communicate/adapter-antigravity/src/relay-start.mjs +2 -1
  34. package/node_modules/@agents-can-communicate/adapter-antigravity/src/relay.mjs +20 -12
  35. package/node_modules/@agents-can-communicate/adapter-antigravity/src/relays.mjs +18 -4
  36. package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +1 -1
  37. package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/skills/acc/SKILL.md +3 -0
  38. package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +6 -0
  39. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-delivery.mjs +50 -37
  40. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-endpoint.mjs +44 -31
  41. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-registry.mjs +99 -14
  42. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-settings.mjs +3 -7
  43. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-socket-directories.mjs +6 -4
  44. package/node_modules/@agents-can-communicate/adapter-claude-code/src/install.mjs +32 -7
  45. package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
  46. package/node_modules/@agents-can-communicate/adapter-codex/plugin/skills/acc/SKILL.md +3 -0
  47. package/node_modules/@agents-can-communicate/adapter-codex/src/allow-rule.mjs +129 -0
  48. package/node_modules/@agents-can-communicate/adapter-codex/src/app-server-client.mjs +68 -3
  49. package/node_modules/@agents-can-communicate/adapter-codex/src/daemon-layouts.mjs +13 -0
  50. package/node_modules/@agents-can-communicate/adapter-codex/src/embedded-host.mjs +42 -11
  51. package/node_modules/@agents-can-communicate/adapter-codex/src/install.mjs +36 -13
  52. package/node_modules/@agents-can-communicate/adapter-codex/src/maintenance-host.mjs +68 -27
  53. package/node_modules/@agents-can-communicate/adapter-codex/src/native-delivery.mjs +36 -18
  54. package/node_modules/@agents-can-communicate/adapter-codex/src/native-endpoint.mjs +39 -16
  55. package/node_modules/@agents-can-communicate/adapter-codex/src/ws-json-rpc.mjs +4 -2
  56. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/gemini-extension.json +1 -1
  57. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/skills/acc/SKILL.md +3 -0
  58. package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +1 -1
  59. package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/adapter.mjs +2 -1
  60. package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/install.mjs +15 -9
  61. package/node_modules/@agents-can-communicate/adapter-grok/package.json +1 -1
  62. package/node_modules/@agents-can-communicate/adapter-grok/plugin/skills/acc/SKILL.md +3 -0
  63. package/node_modules/@agents-can-communicate/adapter-grok/src/install.mjs +25 -14
  64. package/node_modules/@agents-can-communicate/adapter-kimi/package.json +1 -1
  65. package/node_modules/@agents-can-communicate/adapter-kimi/plugin/skills/acc/SKILL.md +3 -0
  66. package/node_modules/@agents-can-communicate/adapter-kimi/src/adapter.mjs +2 -1
  67. package/node_modules/@agents-can-communicate/adapter-kimi/src/install.mjs +15 -10
  68. package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
  69. package/node_modules/@agents-can-communicate/adapter-sdk/src/capabilities.mjs +50 -5
  70. package/node_modules/@agents-can-communicate/adapter-sdk/src/certification.mjs +11 -2
  71. package/node_modules/@agents-can-communicate/adapter-sdk/src/executables.mjs +149 -0
  72. package/node_modules/@agents-can-communicate/adapter-sdk/src/hook-shim.mjs +79 -12
  73. package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +9 -1
  74. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-delivery.mjs +65 -10
  75. package/node_modules/@agents-can-communicate/adapter-sdk/src/own-version.mjs +27 -1
  76. package/node_modules/@agents-can-communicate/adapter-sdk/src/private-files.mjs +35 -0
  77. package/node_modules/@agents-can-communicate/adapter-sdk/src/process-table.mjs +232 -0
  78. package/node_modules/@agents-can-communicate/adapter-sdk/src/session-binding.mjs +8 -1
  79. package/node_modules/@agents-can-communicate/adapter-sdk/src/windows-command.mjs +69 -0
  80. package/node_modules/@agents-can-communicate/adapter-sdk/src/windows-process-chain.wsf +45 -0
  81. package/node_modules/@agents-can-communicate/cli/package.json +2 -1
  82. package/node_modules/@agents-can-communicate/cli/src/config-command.mjs +2 -1
  83. package/node_modules/@agents-can-communicate/cli/src/doctor-command.mjs +60 -4
  84. package/node_modules/@agents-can-communicate/cli/src/hook-support.mjs +9 -0
  85. package/node_modules/@agents-can-communicate/cli/src/hook-workspace.mjs +12 -3
  86. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/activation.mjs +3 -2
  87. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/download.mjs +12 -3
  88. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/entry.mjs +7 -5
  89. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/generation.mjs +7 -7
  90. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/launchers.mjs +8 -5
  91. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/maintenance.mjs +1 -1
  92. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/mutex.mjs +7 -6
  93. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/portable-fs.mjs +165 -0
  94. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/schedule.mjs +1 -1
  95. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/state.mjs +18 -8
  96. package/node_modules/@agents-can-communicate/cli/src/native-session-diagnostics.mjs +11 -3
  97. package/node_modules/@agents-can-communicate/cli/src/platform-paths.mjs +15 -10
  98. package/node_modules/@agents-can-communicate/cli/src/runtime-paths.mjs +3 -2
  99. package/node_modules/@agents-can-communicate/cli/src/update-command.mjs +11 -1
  100. package/node_modules/@agents-can-communicate/cli/src/workspace-discovery.mjs +4 -2
  101. package/node_modules/@agents-can-communicate/core/package.json +1 -1
  102. package/node_modules/@agents-can-communicate/core/src/delivery-bindings.mjs +7 -0
  103. package/node_modules/@agents-can-communicate/core/src/materialisation.mjs +39 -1
  104. package/node_modules/@agents-can-communicate/core/src/session-opening.mjs +11 -0
  105. package/node_modules/@agents-can-communicate/core/src/sessions.mjs +8 -2
  106. package/node_modules/@agents-can-communicate/delivery-router/package.json +1 -1
  107. package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
  108. package/node_modules/@agents-can-communicate/hook-runner/src/client-pid.mjs +65 -6
  109. package/node_modules/@agents-can-communicate/hook-runner/src/client-version.mjs +80 -0
  110. package/node_modules/@agents-can-communicate/hook-runner/src/native-attempt.mjs +1 -1
  111. package/node_modules/@agents-can-communicate/hook-runner/src/owner-context.mjs +34 -6
  112. package/node_modules/@agents-can-communicate/hook-runner/src/process-table.mjs +3 -50
  113. package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +154 -28
  114. package/node_modules/@agents-can-communicate/installer/package.json +3 -2
  115. package/node_modules/@agents-can-communicate/installer/src/delivery-diagnostics.mjs +2 -1
  116. package/node_modules/@agents-can-communicate/installer/src/detect.mjs +13 -3
  117. package/node_modules/@agents-can-communicate/installer/src/hook-support.mjs +5 -0
  118. package/node_modules/@agents-can-communicate/installer/src/native-activation.mjs +6 -14
  119. package/node_modules/@agents-can-communicate/installer/src/ownership.mjs +6 -2
  120. package/node_modules/@agents-can-communicate/installer/src/plan.mjs +14 -0
  121. package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
  122. package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
  123. package/node_modules/@agents-can-communicate/protocol/src/config.mjs +6 -2
  124. package/node_modules/@agents-can-communicate/protocol/src/resources.mjs +6 -2
  125. package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
  126. package/node_modules/@agents-can-communicate/storage-filesystem/src/active-journal.mjs +5 -2
  127. package/node_modules/@agents-can-communicate/storage-filesystem/src/atomic-json.mjs +41 -23
  128. package/node_modules/@agents-can-communicate/storage-filesystem/src/doomed-directory.mjs +4 -12
  129. package/node_modules/@agents-can-communicate/storage-filesystem/src/identity.mjs +7 -3
  130. package/node_modules/@agents-can-communicate/storage-filesystem/src/index.mjs +1 -0
  131. package/node_modules/@agents-can-communicate/storage-filesystem/src/journal.mjs +24 -7
  132. package/node_modules/@agents-can-communicate/storage-filesystem/src/portable-fs.mjs +165 -0
  133. package/node_modules/@agents-can-communicate/storage-filesystem/src/publication-path.mjs +8 -0
  134. package/node_modules/@agents-can-communicate/storage-filesystem/src/reclaim.mjs +26 -17
  135. package/node_modules/@agents-can-communicate/storage-filesystem/src/recovery.mjs +7 -5
  136. package/node_modules/@agents-can-communicate/storage-filesystem/src/retention.mjs +7 -16
  137. package/node_modules/@agents-can-communicate/storage-filesystem/src/safe-directory.mjs +138 -24
  138. package/node_modules/@agents-can-communicate/storage-filesystem/src/safe-file.mjs +3 -2
  139. package/node_modules/@agents-can-communicate/storage-filesystem/src/stage-sweep.mjs +9 -6
  140. package/node_modules/@agents-can-communicate/storage-filesystem/src/store.mjs +30 -8
  141. package/node_modules/@agents-can-communicate/storage-filesystem/src/writer-mutex.mjs +102 -32
  142. package/package.json +1 -5
package/README.md CHANGED
@@ -52,8 +52,10 @@ flowchart TB
52
52
 
53
53
  ## Try one handoff
54
54
 
55
- You’ll need **macOS or Linux, Node.js 24 or newer**, and supported coding clients on the same
56
- machine and operating-system user.
55
+ You’ll need **macOS, Linux or Windows 10/11, Node.js 24 or newer**, and supported coding
56
+ clients on the same machine and operating-system user. On Windows, ACC runs natively, with no
57
+ WSL, and live delivery reaches Claude Code, Codex and Antigravity CLI there too. See
58
+ [Windows](docs/GETTING_STARTED.md#windows).
57
59
 
58
60
  ```bash
59
61
  npm install -g agents-can-communicate
@@ -96,11 +98,13 @@ instructions.
96
98
  Automatic delivery depends on the client version and platform. Verified integrations can
97
99
  provide messages at the next normal turn; other sessions read their ACC inbox explicitly.
98
100
 
99
- Experimental live delivery can wake eligible Claude Code and Codex sessions on Apple Silicon
100
- macOS. It requires opt-in and an active verified connection, is off by default, and can spend
101
- model tokens. Claude Code sessions wake through the inbox that Claude Code itself opens, so
102
- you start Claude Code with your ordinary command. A busy Claude Code session gets the message
103
- between two tool calls. A busy Codex session gets it when the current turn ends.
101
+ Experimental live delivery can wake eligible Claude Code, Codex and Antigravity CLI
102
+ sessions, conversations in the Antigravity desktop app, and local Code sessions in Claude.app. It requires opt-in and an active verified
103
+ connection, is off by default, and can spend model tokens. Claude Code sessions wake through
104
+ the inbox that Claude Code itself opens, so you start Claude Code with your ordinary command.
105
+ A busy Claude Code session gets the message between two tool calls. A busy Codex session gets
106
+ it when the current turn ends. Chats in the Codex app run on the app's own server and get
107
+ messages at their next turn.
104
108
 
105
109
  See [client capabilities](docs/CAPABILITIES.md) for exact support. Run `acc doctor` from your
106
110
  project if a peer is missing or delivery differs from what you expect; see
@@ -2,7 +2,6 @@
2
2
  // The relay the agent starts: `start` in its tool shell, `run` detached from it.
3
3
  // Fails open everywhere - `start` prints one line and exits 0; `run` answers its
4
4
  // ready line and exits quietly when anything it needs is missing.
5
- import { execFile } from "node:child_process";
6
5
  import { randomBytes } from "node:crypto";
7
6
  import { appendFile } from "node:fs/promises";
8
7
  import path from "node:path";
@@ -11,7 +10,7 @@ import { agentApiCommand, createAgentApi } from "@agents-can-communicate/adapter
11
10
  import { createRelay } from "@agents-can-communicate/adapter-antigravity/relay";
12
11
  import { listRegistrations, newRelayId, relayDir } from "@agents-can-communicate/adapter-antigravity/relay-endpoint";
13
12
  import { findConversation, spawnRelay, startRelay } from "@agents-can-communicate/adapter-antigravity/relay-start";
14
- import { loadSessionBinding } from "@agents-can-communicate/adapter-sdk";
13
+ import { loadSessionBinding, readProcessArgs } from "@agents-can-communicate/adapter-sdk";
15
14
  import { platformDataHome } from "@agents-can-communicate/cli";
16
15
  import { createCoordinationService } from "@agents-can-communicate/core";
17
16
  import { resolveClientPid } from "@agents-can-communicate/hook-runner/client-pid";
@@ -27,8 +26,7 @@ const ids = { next: kind => createId(kind, randomBytes) };
27
26
  const alive = pid => { try { process.kill(pid, 0); return true; } catch { return false; } };
28
27
  const READY_MS = 10_000;
29
28
 
30
- const argvOf = pid => new Promise(resolve => execFile("ps", ["-o", "args=", "-p", String(pid)],
31
- { timeout: 1_000 }, (_error, out) => resolve(String(out ?? "").trim().split(/\s+/).filter(Boolean))));
29
+ const argvOf = async pid => await readProcessArgs(pid, { timeoutMs: 1_000 }) ?? [];
32
30
 
33
31
  // Through the launcher that ran `start`, never this module directly: an entry
34
32
  // module does not run itself, and under the managed runtime the launcher takes
@@ -10,26 +10,36 @@ import { pathToFileURL } from "node:url";
10
10
 
11
11
  import { createId } from "@agents-can-communicate/protocol";
12
12
  import { runHook } from "@agents-can-communicate/hook-runner";
13
- import { hookEntrypointFor, resolvePinnedGeneration } from "@agents-can-communicate/cli";
13
+ import { hookEntrypointFor, resolvePinnedGeneration }
14
+ from "@agents-can-communicate/cli/hook-support";
14
15
 
15
- import { createAntigravityAdapter } from "@agents-can-communicate/adapter-antigravity";
16
- import { createClaudeCodeAdapter } from "@agents-can-communicate/adapter-claude-code";
17
- import { createCodexAdapter } from "@agents-can-communicate/adapter-codex";
18
- import { createGeminiCliAdapter } from "@agents-can-communicate/adapter-gemini-cli";
19
- import { createGrokAdapter } from "@agents-can-communicate/adapter-grok";
20
- import { createKimiAdapter } from "@agents-can-communicate/adapter-kimi";
21
-
22
- const adapters = {
16
+ // A hook runs one client's adapter, and loads only that one: every other
17
+ // adapter was a set of modules loaded on each turn and never run, about a
18
+ // millisecond each on windows-latest.
19
+ const ADAPTERS = {
23
20
  // Registered like any other client. Its hook commands carry an extra
24
21
  // argument - the event name - because this client's payload has none.
25
- antigravity: createAntigravityAdapter(),
26
- claude_code: createClaudeCodeAdapter(),
27
- codex: createCodexAdapter(),
28
- gemini_cli: createGeminiCliAdapter(),
29
- grok: createGrokAdapter(),
30
- kimi: createKimiAdapter(),
22
+ antigravity: () => import("@agents-can-communicate/adapter-antigravity")
23
+ .then(module => module.createAntigravityAdapter()),
24
+ claude_code: () => import("@agents-can-communicate/adapter-claude-code")
25
+ .then(module => module.createClaudeCodeAdapter()),
26
+ codex: () => import("@agents-can-communicate/adapter-codex")
27
+ .then(module => module.createCodexAdapter()),
28
+ gemini_cli: () => import("@agents-can-communicate/adapter-gemini-cli")
29
+ .then(module => module.createGeminiCliAdapter()),
30
+ grok: () => import("@agents-can-communicate/adapter-grok")
31
+ .then(module => module.createGrokAdapter()),
32
+ kimi: () => import("@agents-can-communicate/adapter-kimi")
33
+ .then(module => module.createKimiAdapter()),
31
34
  };
32
35
 
36
+ // The adapters this hook can use: its own, or none for an id nobody registered,
37
+ // which runHook answers the way it always has.
38
+ async function adaptersFor(adapterId) {
39
+ if (!Object.hasOwn(ADAPTERS, adapterId)) return {};
40
+ return { [adapterId]: await ADAPTERS[adapterId]() };
41
+ }
42
+
33
43
  const readStdin = () => new Promise(resolve => {
34
44
  // A hook is always given its payload on stdin, but a client that closes it
35
45
  // without writing must not leave this process hanging in front of a turn.
@@ -50,7 +60,7 @@ import { completeHookOutput } from "./hook-output.mjs";
50
60
  // a hook that has no pin to look up pays nothing beyond it. Any adapter or
51
61
  // payload that will not yield a session id simply has no pin to find, same as
52
62
  // today's no-pin behaviour.
53
- async function harnessSessionIdFor(adapterId, payload, args) {
63
+ async function harnessSessionIdFor(adapters, adapterId, payload, args) {
54
64
  try {
55
65
  const event = await adapters[adapterId]?.normalizeHook(payload, { args });
56
66
  return typeof event?.sessionId === "string" ? event.sessionId : null;
@@ -75,9 +85,10 @@ async function harnessSessionIdFor(adapterId, payload, args) {
75
85
  // mid-resolution by another hook for the same session, or simply wrong)
76
86
  // could say. Unbounded delegation would be a hang, worse than any of the
77
87
  // failures this file already falls open from.
78
- async function delegateToPin({ managerRoot, packageRoot, adapterId, payload, args, delegated }) {
88
+ async function delegateToPin({ managerRoot, packageRoot, adapters, adapterId, payload, args,
89
+ delegated }) {
79
90
  if (delegated || managerRoot === null || packageRoot === null) return false;
80
- const harnessSessionId = await harnessSessionIdFor(adapterId, payload, args);
91
+ const harnessSessionId = await harnessSessionIdFor(adapters, adapterId, payload, args);
81
92
  if (harnessSessionId === null) return false;
82
93
  const pinned = await resolvePinnedGeneration({ root: managerRoot, harnessSessionId, active: packageRoot });
83
94
  if (pinned === null) return false;
@@ -103,7 +114,10 @@ export async function main({ managerRoot = null, packageRoot = null, payload, de
103
114
  }
104
115
  }
105
116
 
106
- if (await delegateToPin({ managerRoot, packageRoot, adapterId, payload, args, delegated })) return;
117
+ // A broken adapter module fails the hook open like any other error here.
118
+ const adapters = await adaptersFor(adapterId).catch(() => ({}));
119
+ if (await delegateToPin({ managerRoot, packageRoot, adapters, adapterId, payload, args,
120
+ delegated })) return;
107
121
 
108
122
  const result = await runHook({ adapterId, payload, args, adapters,
109
123
  runtime: { clock: { now: () => new Date().toISOString() },
@@ -56,16 +56,25 @@ function tryWrite(stream, output) {
56
56
  }
57
57
  }
58
58
 
59
+ const RECOVERY = new Map([
60
+ ["workspace_contains_runtime", ": workspace contains ACC runtime state; open a project"
61
+ + " directory and restart the client (or set ACC_DATA_HOME outside the workspace)"],
62
+ ["workspace_path_unquotable", ": this directory's path has a double quote, $, ` or %, which"
63
+ + " no Windows shell quotes alike; rename it and restart the client"],
64
+ ]);
65
+
66
+ // The step a hook was in when its budget ran out, as the runner names it: a few
67
+ // plain words, never text from the hook's input.
68
+ const PHASE = /^[a-z][a-z ]{0,59}$/;
69
+
59
70
  export async function completeHookOutput(result,
60
71
  { stdout = process.stdout, stderr = process.stderr } = {}) {
61
72
  if (result.failed || result.timedOut) {
62
73
  // Only a known code selects static recovery advice. Arbitrary payload or
63
74
  // filesystem error text must never become client-visible instructions.
64
- const recovery = result.failureCode === "workspace_contains_runtime"
65
- ? ": workspace contains ACC runtime state; open a project directory and restart the client"
66
- + " (or set ACC_DATA_HOME outside the workspace)"
67
- : "";
68
- tryWrite(stderr, `acc: coordination unavailable${recovery}; hook continued without context\n`);
75
+ const recovery = RECOVERY.get(result.failureCode) ?? "";
76
+ const held = result.timedOut && PHASE.test(result.phase ?? "") ? ` (timed out while ${result.phase})` : "";
77
+ tryWrite(stderr, `acc: coordination unavailable${recovery}${held}; hook continued without context\n`);
69
78
  }
70
79
  try {
71
80
  await writeOutput(stdout, result.stdout ?? "", { deadlineAt: result.deadlineAt });
@@ -92,6 +92,30 @@ command that matches neither resolves nothing, and the failure is silent: the se
92
92
  `pid: null`, falls back to reading presence by age alone, and is not pinned to its
93
93
  generation, with nothing telling you why.
94
94
 
95
+ Some vendors ship a second product that runs the same hooks: Antigravity 2.0, the desktop
96
+ app, runs `~/.gemini/config/hooks.json` under its own language server, with no `agy`, on a
97
+ version line of its own. Declare such a product as a variant and recognise its process:
98
+
99
+ ```js
100
+ client: { command: "agy", certificationName: "antigravity-cli", versionArgs: ["--version"],
101
+ variants: [{ certificationName: "antigravity-desktop", displayName: "Antigravity" }] },
102
+ identifyClientProcess: entry => /* null, or { certificationName, version } */,
103
+ clientVersionOf: async ({ pid, entry, env }) => /* the running client's version, or null */,
104
+ ```
105
+
106
+ - `identifyClientProcess(entry)` is called with each ancestor `{ comm, args }` before the
107
+ `client.command` match. It is synchronous and reads only the entry it is given; a throw is a
108
+ "no". A `certificationName` that names no declared variant is ignored, with its version.
109
+ - Evidence may name a declared variant. A variant is judged only by its own evidence: its
110
+ versions count on its own line, so the primary client's captures never stand in for it.
111
+ Declaring a capability `true` still needs passing evidence of the primary client.
112
+ - The session's version is, in order: the version `identifyClientProcess` returned, then
113
+ `clientVersionOf()`, then the client's own executable when `ps` names it by absolute path,
114
+ then `client.command` on `PATH`. The `PATH` probe alone named the wrong build for a
115
+ Claude.app session (its own claude, 2.1.286, against 2.1.289 on `PATH`) and for every
116
+ Claude Code session that outlived an in-place update; Claude Code's adapter therefore reads
117
+ the version from the session record Claude Code keeps for that pid.
118
+
95
119
  ## Declare only proven capabilities
96
120
 
97
121
  Fourteen booleans in four groups, declared in the manifest's `capabilities` object:
@@ -168,6 +192,11 @@ The rules `defineAdapter` enforces, and the ones the runtime applies:
168
192
  anchor must have passing `delivery.livePush` evidence for the same client and version, and
169
193
  the minimum must itself be an anchor. The platform an evidence row names is where the
170
194
  capture was taken; it is provenance, and the anchor names no platform.
195
+ - An anchor may name a declared variant, `{ version, protocolContract, client }`, for a
196
+ delivery protocol only that product speaks. Each protocol's floor is its own first passing
197
+ capture: a handshake or probe is judged against the floor of the protocol it reports, and
198
+ one protocol cannot be anchored for two products. `minimum` stays the primary client's
199
+ first capture, and `knownBad` names the primary client's versions.
171
200
  - There is intentionally **no maximum version** and **no platform**. A newer release is
172
201
  admitted, on every platform, only when a current read-only feature probe
173
202
  (`probeNativeDelivery()`) and a per-session handshake (`bindNativeSession()`) both report
@@ -4,8 +4,8 @@ Use this page to set expectations after installation. Integration means ACC can
4
4
  peer awareness and coordination instructions; it does not guarantee what a model will do
5
5
  with them. Delivery also varies independently from awareness. The durable inbox works for
6
6
  every participant, a client at or after a captured version may add next-turn delivery, and the
7
- experimental Codex LocalDaemon, Claude Code inbox wake and Antigravity CLI relay paths can
8
- deliver while a session is idle.
7
+ experimental Codex LocalDaemon, Claude Code inbox wake and Antigravity relay and desktop paths
8
+ can deliver while a session is idle.
9
9
 
10
10
  Capability honesty separates four questions that are easy to collapse:
11
11
 
@@ -64,16 +64,17 @@ What may refuse live delivery is exactly three things:
64
64
 
65
65
  Nothing else: not the platform, not a prerelease suffix, not where the evidence was taken.
66
66
  A platform whose transport is technically different is refused by the probe as a fact about
67
- that transport, which is what Claude Code's named pipe on native Windows is. Codex, Claude Code and Antigravity CLI reply through `acc reply`. Their native
67
+ that transport. Codex, Claude Code and Antigravity CLI reply through `acc reply`. Their native
68
68
  `replyRoute` remains false.
69
69
 
70
70
  The limitations belong next to the adapters they affect:
71
71
 
72
72
  | Adapter | Exact limitation and evidence |
73
73
  |---|---|
74
- | Antigravity CLI | 1.2.7 on darwin-arm64, captured in print mode, and every later release by the forward rule. Only `SessionStart`, `PreInvocation`, `PostInvocation` and `Stop` load; `SessionEnd`, `PreToolUse` and `PostToolUse` are accepted into the config file and silently dropped, so there is no tool guard and no session-end deregistration - a session goes offline by presence age or an explicit `acc finish`. Payloads carry no `hook_event_name`, so each registered command passes its own event name. The end-of-turn `Stop` continuation reaches the model and is a bounded nudge, not a gate: ACC continues a turn at most once and fails open, and the client caps consecutive continuations itself (vendor 1.1.9). `agy agentapi send-message` can wake an idle session - captured - but only with that session's language-server address and CSRF token, which exist in the agent's own shell and in no hook. ACC does not take that token, so live push and reply routing are false. A peer message that arrives while the model writes its last answer is carried by the `Stop` continuation instead. A write that parses can register nothing, so install and doctor read `agy -p "/hooks"` back instead of trusting the file. Live push (1.2.7, darwin-arm64, TUI only, experimental, recorded opt-in) runs through a relay the agent starts once per conversation from its own shell - the only process holding the session endpoint - after ACC's context asks it to, up to three times while none is serving; the operator approves that command at the client's permission prompt. An idle session wakes; a busy one sees the message after its running answer, or at the next model invocation when the turn waits on a tool. Print mode and the first session in a folder trusted at that launch get no relay. The client asks before every shell command (1.2.12), so install always adds the prefix rule `command(<wrapper>)` to the client's settings to let the woken agent's ACC commands run without that prompt. A woken session answered with no prompt under that rule on 1.2.12 (2026-09-28); print mode with it has not been captured. |
75
- | Codex | Next-turn context, captured on 0.147.0, requires plugin trust. The observed stock 0.153.4 upgrade from ACC 0.3.1 to 0.4 required fresh review of five modified hook definitions; a subsequent restart retained all five active (activation evidence, not new event certification). LocalDaemon native delivery was captured through the installed package on 0.152.1 and 0.153.4, darwin-arm64; minimum 0.152.1, recorded opt-in, current feature probe and exact thread/cwd/process/version/protocol checks are required. Ordinary launch preserves the receiver workspace without ACC arguments or daemon ownership. Embedded or unreachable sessions keep their inbox. Native `replyRoute` remains false. |
76
- | Claude Code | 2.1.233 next-turn delivery waits for the next user prompt. From 2.1.282, captured on darwin-arm64 and applied on every platform whose inbox is a Unix socket, `delivery.livePush` is a live capability behind the native contract (experimental, off until opted in). ACC wakes the session through the inbox socket that Claude Code opens for every session, with one line of fixed ACC text and the message id. An idle session starts a turn. A busy session takes the wake between two tool calls. Each delivered wake fires `UserPromptSubmit`, so the next-turn hook shows the body and records the receipt `offered` via `next-turn`. The model answers with `acc reply`, so `delivery.replyRoute` stays false. A session in `bypassPermissions` mode holds each wake for approval unless `crossSessionInbound` is `accept`, and `refuse` drops wakes. Native Windows keeps next-turn delivery: its inbox is a named pipe that requires an auth line, and it is uncaptured. Linux is uncaptured. |
74
+ | Antigravity CLI | 1.2.7 on darwin-arm64, captured in print mode, and every later release by the forward rule. Only `SessionStart`, `PreInvocation`, `PostInvocation` and `Stop` load; `SessionEnd`, `PreToolUse` and `PostToolUse` are accepted into the config file and silently dropped, so there is no tool guard and no session-end deregistration - a session goes offline by presence age or an explicit `acc finish`. Payloads carry no `hook_event_name`, so each registered command passes its own event name. The end-of-turn `Stop` continuation reaches the model and is a bounded nudge, not a gate: ACC continues a turn at most once and fails open, and the client caps consecutive continuations itself (vendor 1.1.9). `agy agentapi send-message` can wake an idle session - captured - but only with that session's language-server address and CSRF token, which exist in the agent's own shell and in no hook; reply routing is false. A peer message that arrives while the model writes its last answer is carried by the `Stop` continuation instead. A write that parses can register nothing, so install and doctor read `agy -p "/hooks"` back instead of trusting the file. Live push (1.2.7, darwin-arm64, TUI only, experimental, recorded opt-in) runs through a relay the agent starts once per conversation from its own shell - the only process holding the session endpoint - after ACC's context asks it to, up to three times while none is serving; install allows that command too, so the agent starts the relay without a prompt (1.2.16, 2026-10-04); on Windows, where install adds no rule, the operator approves it at the client's permission prompt. An idle session wakes; a busy one sees the message after its running answer, or at the next model invocation when the turn waits on a tool. Print mode and the first session in a folder trusted at that launch get no relay. The client asks before every shell command (1.2.12), so install adds the prefix rule `command(<wrapper>)` to the client's settings, except on Windows, to let the woken agent's ACC commands run without that prompt. A woken session answered with no prompt under that rule on 1.2.12 (2026-09-28); print mode with it has not been captured. On Windows the relay listens on a named pipe, `\\.\pipe\acc-relay-<32 hex>`, starts with `node`, and runs `agy.exe` itself, never a `.cmd`, since the message reaches agy as an argument. |
75
+ | Antigravity 2.0 (desktop app) | 2.19.1 on darwin-arm64, captured 2026-10-04. The app runs the same `~/.gemini/config/hooks.json` under its own language server, with no `agy`, so ACC identifies the session by that server and the version on its command line (`--override_ide_version`), and judges it by the desktop's own evidence, never by Antigravity CLI's version line. `SessionStart` and `PreInvocation` fire; a peer message reaches the model at the next model invocation. Live push (2.19.1, darwin-arm64, experimental, recorded opt-in) needs no relay and no command from the agent: ACC reads the endpoint from the language server's command line when it binds and when it delivers, keeps the token only in one `agentapi` child's environment, and pushes into the conversation through the server's own `agentapi`. A product capture passed all six cases: an idle conversation woke with no user input; a push during a long answer was shown after it, uninterrupted; the woken agent answered with `acc reply` without an approval prompt; a resent message reached the model once; with the app quit the message stayed queued; after a restart the conversation's next turn bound it again. The app runs no `SessionStart` for a conversation it reopens, so after a restart live delivery returns at that next turn. One language server serves every window and conversation, so a desktop participant goes offline when the app quits. The app runs the agent's commands in a sandbox where ACC's wrapper cannot run; the model then retries outside it, which the app allows by the grants in `~/.gemini/config/config.json`, and install adds ACC's rule there once the app has run. Installing the integration still needs Antigravity CLI, whose `agy -p "/hooks"` reads the registration back. |
76
+ | Codex | Next-turn context, captured on 0.147.0, requires plugin trust. The observed stock 0.153.4 upgrade from ACC 0.3.1 to 0.4 required fresh review of five modified hook definitions; a subsequent restart retained all five active (activation evidence, not new event certification). LocalDaemon native delivery was captured through the installed package on 0.152.1 and 0.153.4, darwin-arm64; minimum 0.152.1, recorded opt-in, current feature probe and exact thread/cwd/process/version/protocol checks are required. Ordinary launch preserves the receiver workspace without ACC arguments or daemon ownership. On macOS and Linux, install adds ACC's own Codex rules file, so the commands a participant runs need no approval and Codex's auto-review never judges a message to a local peer. On Windows, where Node cannot open the daemon's AF_UNIX socket, ACC speaks the same protocol over the stdio of `codex app-server proxy` (measured on 0.159.3); Codex starts its daemon only from a terminal that is not elevated. Embedded or unreachable sessions keep their inbox. The Codex app (inside ChatGPT.app, read on 26.928) runs every chat on a private app server over stdio rather than the shared daemon (openai/codex#41014); its chats run ACC's hooks, receive messages at their next turn, and are reported as `client_session_embedded`. Native `replyRoute` remains false. |
77
+ | Claude Code | 2.1.233 next-turn delivery waits for the next user prompt. From 2.1.282, captured on darwin-arm64 and applied on every platform, `delivery.livePush` is a live capability behind the native contract (experimental, off until opted in). ACC wakes the session through the inbox socket that Claude Code opens for every session, with one line of fixed ACC text and the message id. An idle session starts a turn. A busy session takes the wake between two tool calls. Each delivered wake fires `UserPromptSubmit`, so the next-turn hook shows the body and records the receipt `offered` via `next-turn`. The model answers with `acc reply`, so `delivery.replyRoute` stays false. A session in `bypassPermissions` mode holds each wake for approval unless `crossSessionInbound` is `accept`, and `refuse` drops wakes. Claude.app runs a local Code session on a Claude Code build of its own with the same `~/.claude`: such a session registers the same inbox (`entrypoint: claude-desktop`), and on 2.1.286 (2026-10-04) an idle one woke and answered with `acc reply` with no adapter change. Its Cloud, SSH and Cowork sessions run on another machine. ACC takes a session's version from the record Claude Code keeps for that process, because the `claude` on `PATH` can be another build. On native Windows the inbox is a named pipe, `\\.\pipe\LOCAL\cc-msg-<32 hex>`, that drops a frame without an auth line; ACC authenticates with the peer key Claude Code publishes beside the session record for other sessions of the same user, never the session's own token, so the recipient's inbound settings apply as on POSIX. Measured on 2.1.286; the real-clients CI job wakes an idle interactive Claude Code on Linux and on Windows. |
77
78
  | Gemini CLI | Package-shipped next-turn certification starts at 0.57.0. Its TUI has no captured external wake or queue interface and `--acp` changes launch ownership, so native delivery is fallback-only; live push and reply routing remain false. |
78
79
  | Grok | The Grok 1.0.24 installed-client check observed own CLI arguments after a terminal result, followed by owned work, message, and finish calls. This identity-only path does not certify peer-context injection. Documentation-shaped payloads do not count as real captures. The public leader surface exposed no proven addressed injection into an ordinary TUI session, so native delivery is `awaiting_compatibility_capture`; all capabilities remain false. |
79
80
  | Kimi Code | Next-turn and guard evidence was captured on 0.36.1, plus a 60-second heartbeat. Its server/queue APIs do not prove a transparent binding to an independently opened session, so native delivery is fallback-only. |
package/docs/CLI.md CHANGED
@@ -369,6 +369,11 @@ before leaving, request the concrete continuation and obtain a substantive reply
369
369
  | `acc help` | — |
370
370
  | `acc version` | — |
371
371
 
372
+ `acc uninstall` takes back what the current ACC data home installed. A client on the machine
373
+ that this data home has no install record for - one another data home wired, such as your own
374
+ beside an isolated `ACC_DATA_HOME` - is skipped with the reason; name it with `--adapter` to
375
+ remove its ACC wiring anyway.
376
+
372
377
  `--delivery off|actionable|all` is a per-client recipient policy request, not a capability
373
378
  switch, and the default is `off`. `--adapter` is repeatable to name several clients. An
374
379
  explicit `--delivery` applies uniformly and never prompts; omitting it on an interactive
@@ -218,26 +218,56 @@ generated permission component is unchanged.
218
218
  If any component was edited or another setting depends on it, ACC preserves the entire
219
219
  bundle and reports it for review. Plugin registration can still be removed independently.
220
220
 
221
+ ### Codex command approval
222
+
223
+ Codex asks before a command that wants to leave its sandbox. With
224
+ `approvals_reviewer = "auto_review"`, a model reviews that request instead of you, and it can
225
+ refuse an ACC message that names a branch or a path as disclosure to an outside party. So
226
+ `acc install` adds ACC's own rules file on macOS and Linux:
227
+
228
+ ```text
229
+ ~/.codex/rules/agents-can-communicate.rules
230
+ prefix_rule(pattern = ["<home>/.agents/acc-local/plugins/agents-can-communicate/acc-cli.sh",
231
+ ["work", "claim", "release", "message", "request", "inbox", "reply",
232
+ "ack", "status", "sync", "finish"]],
233
+ decision = "allow")
234
+ ```
235
+
236
+ Codex loads every `*.rules` file in that directory. A command the rule allows needs no
237
+ approval, so no reviewer sees it. Only ACC's wrapper and only the commands a participant runs
238
+ are allowed: `acc install`, `uninstall`, `update` and `config` still ask. Install does not ask
239
+ about the rule; it is part of ACC's Codex integration, as its hooks are. A file of that name
240
+ that ACC did not write stays yours, and ACC adds no rule then. So does ACC's file once you edit
241
+ it, for example to take a command out: reinstall and update leave it as it is, and doctor
242
+ reports it as edited. A wrapper path that a rule cannot
243
+ hold as it is gets none either. `acc uninstall` removes the file while it is unchanged, and
244
+ `acc doctor` asks for `acc install --adapter codex` when it is missing. Windows gets no rule:
245
+ how Codex matches a PowerShell command against one is unmeasured.
246
+
221
247
  ### Antigravity CLI command approval
222
248
 
223
249
  Antigravity CLI asks for approval before each shell command, ACC's included. A session that
224
250
  live delivery wakes while you are away would therefore stop at the agent's first ACC command,
225
- and the peer would get no answer until someone approved it. So when `acc install` installs
226
- the Antigravity adapter, it always adds one rule to the client's own settings:
251
+ and the peer would get no answer until someone approved it. The relay that lets ACC wake an
252
+ idle session is started by the agent too, with a command the client would also ask about. So
253
+ when `acc install` installs the Antigravity adapter, it always adds two rules to the client's
254
+ own settings:
227
255
 
228
256
  ```text
229
257
  ~/.gemini/antigravity-cli/settings.json
230
258
  permissions.allow: command(<home>/.gemini/config/acc/acc-cli.sh)
259
+ command(sh "<home>/.gemini/config/acc/acc-relay.sh" start)
231
260
  ```
232
261
 
233
262
  A one-word rule is a prefix: every command that starts with that path runs without asking.
234
263
  The agent then runs every ACC command without asking you, including one a peer's message
235
- prompts; every other command still asks. Install does not ask about the rule, and the
236
- delivery policy does not change it: it is part of ACC's Antigravity integration, as its hooks
237
- are.
264
+ prompts. The second rule is the exact command that starts live delivery, in the words the
265
+ client itself saves when you choose to always allow it. Every other command still asks.
266
+ Install does not ask about the rules, and the delivery policy does not change them: they are
267
+ part of ACC's Antigravity integration, as its hooks are.
238
268
 
239
269
  ACC keeps every other key and rule in the file, leaves a rule you already had as yours, and
240
- records what it added in its own data home. `acc uninstall` removes every copy of that rule (one
270
+ records what it added in its own data home. `acc uninstall` removes every copy of each rule (one
241
271
  in the same words cannot be told from ACC's), and a
242
272
  container or file ACC created only if nothing else is in it. A rule removed by hand comes back
243
273
  at the next `acc install` or automatic refresh; uninstall is what keeps it out. A file that is
@@ -246,9 +276,10 @@ client reads the file when it starts, so restart `agy` after install.
246
276
 
247
277
  The rule matches only a command whose first word is the path without quotes, so ACC's skill
248
278
  for this client writes the path without quotes. When your home path contains a space or a
249
- shell metacharacter, the path needs quotes, no rule can match it, and ACC adds none.
250
- `acc doctor` reports the rule as present, absent, or unable to apply, and asks for
251
- `acc install --adapter antigravity` when ACC's rule is missing.
279
+ shell metacharacter, the path needs quotes, no rule can match it, and ACC adds neither rule:
280
+ without the wrapper's, the agent would still ask before each ACC command.
281
+ `acc doctor` reports each rule as present, absent, or unable to apply, and asks for
282
+ `acc install --adapter antigravity` when one of ACC's rules is missing.
252
283
 
253
284
  ## Override local paths and identity
254
285
 
@@ -258,7 +289,7 @@ that resolves inside a workspace.
258
289
 
259
290
  | Variable | Purpose |
260
291
  |---|---|
261
- | `ACC_DATA_HOME` | Base directory under which ACC creates `acc/` for runtime and coordination state. Defaults: `~/Library/Application Support` on macOS; `~/.local/share` on Linux, or `XDG_DATA_HOME` |
292
+ | `ACC_DATA_HOME` | Base directory under which ACC creates `acc/` for runtime and coordination state. Defaults: `~/Library/Application Support` on macOS; `~/.local/share` on Linux, or `XDG_DATA_HOME`; `%LOCALAPPDATA%` on Windows |
262
293
  | `ACC_CONFIG_HOME` | Parsed and validated path override; no current configuration-storage consumer |
263
294
  | `ACC_CACHE_HOME` | Parsed and validated path override; no current cache-storage consumer |
264
295
  | `ACC_PARTICIPANT` | Which participant a session belongs to, when the client does not say |
@@ -90,8 +90,6 @@ where a guard stops behaves better than one that believes it absolute.
90
90
  4. **Multi-root discovery rules** beyond the current `roots` list.
91
91
  5. **Default claim lease length** for hook-only adapters. A hook-only session cannot sustain
92
92
  a short renewal cadence, so lease policy must not assume one.
93
- 6. **Windows.** Measured as not working, not merely untested — see the
94
- [repository changelog](https://github.com/automatis-tools/agents-can-communicate/blob/main/CHANGELOG.md).
95
93
 
96
94
  ---
97
95
 
@@ -13,7 +13,8 @@ pair or session-bound ACC MCP tools. See [CLI ownership](CLI.md#coordinate-from-
13
13
 
14
14
  ## 1. Install once on this machine
15
15
 
16
- ACC requires macOS or Linux and Node.js 24 or newer.
16
+ ACC requires Node.js 24 or newer on macOS, Linux, or Windows 10 or 11. On Windows, read
17
+ [Windows](#windows) below first.
17
18
 
18
19
  Already using ACC? Follow the [upgrade guide](UPGRADING.md) for the 0.4.x → 0.5.0
19
20
  update or the data-format boundary when upgrading from 0.3.1.
@@ -72,8 +73,9 @@ Code opens for every session. After you opt in, start Claude Code with your ordi
72
73
  ACC adds no launch flag, shell change or wrapper. A session in `bypassPermissions` mode asks
73
74
  you to approve each ACC wake. See
74
75
  [held or dropped wakes](TROUBLESHOOTING.md#a-claude-code-session-holds-or-drops-acc-wakes).
75
- The feature is off by default, can spend model tokens, and currently requires Apple Silicon
76
- macOS and Claude Code 2.1.282 or newer. You do not need it for durable messages or supported
76
+ The feature is off by default, can spend model tokens, and requires Claude Code 2.1.282 or
77
+ newer. Local sessions in Claude.app's Code tab wake the same way; its Cloud, SSH and Cowork
78
+ sessions run on another machine. You do not need it for durable messages or supported
77
79
  next-turn delivery.
78
80
 
79
81
  ## 2. Open two sessions and give them ordinary tasks
@@ -142,8 +144,8 @@ Antigravity CLI carries one extra condition: its hooks are given a project direc
142
144
  when the session has an open workspace. A session started without one attaches nothing, and
143
145
  the client shows no hook output to say so - `acc doctor` names it.
144
146
 
145
- Codex LocalDaemon and the Claude Code inbox wake offer optional native delivery on
146
- Apple Silicon macOS. They are experimental and can spend tokens. Codex queues a message
147
+ Codex LocalDaemon and the Claude Code inbox wake offer optional native delivery. They are
148
+ experimental and can spend tokens. Codex queues a message
147
149
  until a running turn finishes. A busy Claude Code session takes the wake between two tool
148
150
  calls. Claude Code requires 2.1.282 or newer and recorded opt-in, and it wakes through the
149
151
  inbox that each session opens itself. Codex requires 0.152.1 or newer, LocalDaemon
@@ -157,7 +159,12 @@ three times while none is running, and you approve that command at the client's
157
159
  Antigravity also asks before each shell command, so install adds a rule that lets ACC's own
158
160
  commands run without that prompt, and a woken session can answer while you are away; see
159
161
  [Antigravity CLI command approval](CONFIGURATION.md#antigravity-cli-command-approval).
160
- [Capabilities](CAPABILITIES.md) explains policy, versions and fallback.
162
+ Antigravity 2.0, the desktop app, runs the same hooks under its own language server, and ACC
163
+ delivers into its conversations through that server: nothing for the agent to start. The app
164
+ keeps its own command grants in `~/.gemini/config/config.json`; install adds ACC's rule there
165
+ once the app has run. After the app restarts, a conversation is reachable again from its next
166
+ turn. Chats in the Codex app run on the app's own server and get messages at their
167
+ next turn. [Capabilities](CAPABILITIES.md) explains policy, versions and fallback.
161
168
 
162
169
  Delivery evidence is deliberately narrow: `queued -> offered -> retrieved -> acknowledged`.
163
170
  An offer is not proof that the model read anything, retrieval is not proof of attention, and
@@ -199,5 +206,31 @@ acc uninstall
199
206
  Uninstall removes only bytes ACC wrote that still match its install record. User edits are
200
207
  reported and preserved.
201
208
 
209
+ ## Windows
210
+
211
+ ACC runs natively on Windows 10 and 11, with no WSL. Install it the same way, in PowerShell or
212
+ in a Command Prompt:
213
+
214
+ ```powershell
215
+ npm install -g agents-can-communicate
216
+ acc install
217
+ ```
218
+
219
+ What is different on Windows:
220
+
221
+ - ACC keeps its state in `%LOCALAPPDATA%\acc`, never in the roaming profile.
222
+ - Each client's hooks run a small Node script instead of a shell script, in the form that
223
+ client's hook runner reads. `node` must be on `PATH` for Grok and Antigravity CLI hooks.
224
+ Claude Code needs 2.1.139 or later.
225
+ - Live delivery reaches a running session as on macOS and Linux: Claude Code through its inbox
226
+ pipe, Codex through its app-server daemon, Antigravity CLI through ACC's relay. Codex starts
227
+ its daemon only from a terminal that is not running as administrator.
228
+ - Antigravity CLI cannot run a hook whose path is quoted. When your profile path has a space,
229
+ ACC writes the path's 8.3 short name. ACC adds no allow rule on Windows, so Antigravity CLI
230
+ asks before each ACC command.
231
+ - The first hook after the machine starts can take a few seconds, because ACC reads the
232
+ process tree through WMI, in Windows Script Host or, where Script Host is off, PowerShell.
233
+ If it runs out of time, the session attaches on the first prompt instead.
234
+
202
235
  Next: [Why ACC](WHY_ACC.md) · [Capabilities](CAPABILITIES.md) · [CLI](CLI.md) ·
203
236
  [Troubleshooting](TROUBLESHOOTING.md)
@@ -102,16 +102,16 @@ All recipients have the same durable record, but adapters expose different accel
102
102
  - **Next normal turn:** exact captured versions of Codex, Claude Code, Gemini CLI, Antigravity CLI and Kimi
103
103
  Code can receive complete attributed peer context when the user next prompts that client.
104
104
  This does not wake an idle session.
105
- - **Optional Claude Code inbox wake:** on Apple Silicon macOS with Claude Code 2.1.282 or
106
- later, ACC wakes the session through the inbox socket that the session opens itself. The
107
- wake is one line of fixed ACC text with the message id. It carries no subject, body or
105
+ - **Optional Claude Code inbox wake:** with Claude Code 2.1.282 or later, ACC wakes the
106
+ session through the inbox that the session opens itself: a Unix socket on macOS and Linux,
107
+ a named pipe on Windows. The wake is one line of fixed ACC text with the message id. It carries no subject, body or
108
108
  sender name. An idle session starts a turn. A busy session takes the wake between two tool
109
109
  calls and keeps its turn. Each delivered wake fires `UserPromptSubmit`, ACC's next-turn
110
110
  hook, which shows the message in its untrusted block. The model answers with
111
111
  `acc reply`. This is experimental, off by default and can spend tokens. Claude Code's
112
112
  own inbound controls apply to each wake.
113
113
 
114
- - **Optional Codex LocalDaemon delivery:** on Apple Silicon macOS, a captured
114
+ - **Optional Codex LocalDaemon delivery:** a captured
115
115
  minimum of 0.152.1 plus a current probe and exact session checks allow delivery
116
116
  to an independently opened thread. It is experimental, off by default, and can
117
117
  spend tokens. Messages wait for a running turn to finish; a daemon-retained
@@ -120,13 +120,18 @@ All recipients have the same durable record, but adapters expose different accel
120
120
  and does not manage the vendor daemon during message delivery. Separately,
121
121
  [confirmed update maintenance](UPGRADING.md#confirmed-client-service-maintenance) can restart it.
122
122
 
123
- - **Optional Antigravity CLI relay:** on Apple Silicon macOS with 1.2.7 or later, the session
124
- endpoint exists only in the agent's own shell, so ACC's context asks the agent once per
125
- conversation to start a relay; the user approves that command. The relay keeps the endpoint
123
+ - **Optional Antigravity CLI relay:** with 1.2.7 or later, the session endpoint exists only
124
+ in the agent's own shell, so ACC's context asks the agent once per conversation to start a
125
+ relay, a command install allows. The relay keeps the endpoint
126
126
  in memory, wakes an idle session with a fenced peer message, holds one for a busy session,
127
127
  and ends with the client. It is experimental, off by default, and can spend tokens. The
128
128
  woken agent's ACC commands run without the client's approval prompt because install adds
129
- one allow rule for ACC's wrapper.
129
+ an allow rule for ACC's wrapper. On Windows install adds no rule, so the client asks first.
130
+
131
+ - **Optional Antigravity desktop delivery:** with Antigravity 2.19.1 or later, ACC pushes a
132
+ message into a desktop conversation through the app's own language server, reading its
133
+ endpoint when it binds and when it delivers, and storing no token. The agent starts
134
+ nothing. It is experimental, off by default, and can spend tokens.
130
135
 
131
136
  Grok, generic MCP, unsupported versions and uncaptured platforms use inbox polling.
132
137
  [Capabilities](CAPABILITIES.md) lists evidence and fallback.
@@ -103,12 +103,32 @@ unchanged; edited or newly referenced settings remain intact. See
103
103
  [Codex outgoing permissions](CONFIGURATION.md#codex-outgoing-permissions). Configuration
104
104
  readiness does not prove that an active session's overrides permit a live offer.
105
105
 
106
- Antigravity CLI asks before each shell command. Installing its adapter adds one prefix rule
107
- to that client's `permissions.allow`, for ACC's own wrapper path only. The agent then runs
108
- every ACC command without a prompt, including one that a peer's message prompts. Every other
109
- command still asks. ACC records the one rule it added and uninstall removes only that rule.
106
+ On macOS and Linux, installing the Codex adapter also writes ACC's own Codex rules file. It
107
+ allows ACC's wrapper to run the commands a participant runs, such as `message` and `reply`,
108
+ without an approval, so Codex's auto-review never judges a message to a local peer. Install,
109
+ uninstall, update and config still ask. See
110
+ [Codex command approval](CONFIGURATION.md#codex-command-approval).
111
+
112
+ Antigravity CLI asks before each shell command. Installing its adapter adds two rules to that
113
+ client's `permissions.allow`: a prefix rule for ACC's own wrapper path, and the exact command
114
+ that starts the relay. The agent then runs every ACC command, and starts live delivery,
115
+ without a prompt, including when a peer's message prompts it. Every other command still asks.
116
+ ACC records the rules it added and uninstall removes only those.
110
117
  It never writes a settings file that it cannot parse. See
111
118
  [Antigravity CLI command approval](CONFIGURATION.md#antigravity-cli-command-approval).
119
+ Antigravity 2.0, the desktop app, keeps its grants in `~/.gemini/config/config.json`. Once the
120
+ app has created that file, install adds the same wrapper rule there, under the same ownership
121
+ record, and never creates the file itself.
122
+
123
+ Antigravity 2.0 starts its language server with the server's CSRF token on its command line,
124
+ where every process on the machine can read it. To deliver into a desktop conversation, ACC
125
+ reads that command line from the one server its own hook ran under: the pid and start time
126
+ recorded when the session bound, and the arguments checked again at every use. The token goes
127
+ into the environment of one `agentapi` child for one call and nowhere else: not into the
128
+ endpoint record, the delivery binding, the native-attempt record, logs or diagnostics. The
129
+ record names the server's pid, its start time and the loopback port that answered `/healthz`.
130
+ What the token lets ACC do there is what the relay does for Antigravity CLI: put one fenced,
131
+ ACC-rendered peer message into one conversation.
112
132
 
113
133
  ## Claims
114
134
 
@@ -125,7 +145,14 @@ from operating merely because its own state is unavailable.
125
145
  ## Filesystem and installation
126
146
 
127
147
  - Runtime state, bindings, sockets, and install ownership records stay outside repositories.
128
- - Managed paths are checked for containment and symlink escape.
148
+ - Managed paths are checked for containment and symlink escape. Windows has no `O_NOFOLLOW`:
149
+ ACC refuses a symlink or junction at the last component by name, then checks that the
150
+ opened handle is the file it checked.
151
+ - On Windows, ACC state lives in `%LOCALAPPDATA%`, whose ACL grants only the user, SYSTEM and
152
+ Administrators; files inherit it. Mode bits do not exist there.
153
+ - A workspace config root that starts with a separator or a drive letter is refused on every
154
+ platform. On Windows such a root could name another drive or a network share (`\\host\share`),
155
+ which a hook would then contact.
129
156
  - Store publication uses atomic no-replace behavior, journaling, and writer locks.
130
157
  - Corrupt or incompatible store versions fail closed before mutation.
131
158
  - Client installers preserve unrelated settings and record content hashes.