agents-can-communicate 0.1.18 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +87 -69
  2. package/SECURITY.md +31 -0
  3. package/bin/acc-bootstrap.mjs +56 -0
  4. package/bin/acc-claude-channel.mjs +177 -0
  5. package/bin/acc-hook.mjs +94 -12
  6. package/bin/acc-mcp.mjs +6 -2
  7. package/bin/acc.mjs +13 -3
  8. package/docs/ADAPTER_AUTHORING.md +204 -0
  9. package/docs/ARCHITECTURE.md +131 -0
  10. package/docs/CAPABILITIES.md +117 -214
  11. package/docs/CLI.md +164 -0
  12. package/docs/CONCEPTS.md +134 -0
  13. package/docs/CONFIGURATION.md +147 -0
  14. package/docs/DESIGN_DECISIONS.md +89 -0
  15. package/docs/GETTING_STARTED.md +145 -0
  16. package/docs/GLOSSARY.md +26 -0
  17. package/docs/HOW_IT_WORKS.md +277 -0
  18. package/docs/MCP.md +94 -0
  19. package/docs/PROTOCOL.md +200 -0
  20. package/docs/RELEASING.md +115 -0
  21. package/docs/SECURITY_MODEL.md +131 -0
  22. package/docs/TROUBLESHOOTING.md +108 -0
  23. package/docs/WHY_ACC.md +61 -0
  24. package/docs/index.md +44 -0
  25. package/node_modules/@agents-can-communicate/adapter-claude-code/certification.json +228 -0
  26. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/PreToolUse-Edit.json +19 -0
  27. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/PreToolUse.json +17 -0
  28. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/SessionEnd.json +8 -0
  29. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/SessionStart.json +7 -0
  30. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/UserPromptSubmit.json +9 -0
  31. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/certification-provenance.json +269 -0
  32. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.252.json +21 -0
  33. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.258.json +23 -0
  34. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.260.json +23 -0
  35. package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +13 -2
  36. package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/.mcp.json +8 -0
  37. package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/skills/acc/SKILL.md +22 -22
  38. package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +45 -5
  39. package/node_modules/@agents-can-communicate/adapter-claude-code/src/channel.mjs +377 -0
  40. package/node_modules/@agents-can-communicate/adapter-claude-code/src/install.mjs +27 -7
  41. package/node_modules/@agents-can-communicate/adapter-claude-code/src/native-delivery.mjs +229 -0
  42. package/node_modules/@agents-can-communicate/adapter-codex/certification.json +150 -0
  43. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/PreToolUse.json +14 -0
  44. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/SessionEnd.json +7 -0
  45. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/SessionStart.json +9 -0
  46. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/UserPromptSubmit.json +10 -0
  47. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/certification-provenance.json +199 -0
  48. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/delivery/codex-cli-0.152.0.json +21 -0
  49. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/delivery/codex-cli-0.152.1-remote-workspace.json +25 -0
  50. package/node_modules/@agents-can-communicate/adapter-codex/package.json +11 -2
  51. package/node_modules/@agents-can-communicate/adapter-codex/plugin/.codex-plugin/plugin.json +1 -1
  52. package/node_modules/@agents-can-communicate/adapter-codex/plugin/skills/acc/SKILL.md +22 -22
  53. package/node_modules/@agents-can-communicate/adapter-codex/src/adapter.mjs +54 -12
  54. package/node_modules/@agents-can-communicate/adapter-codex/src/app-server-client.mjs +121 -0
  55. package/node_modules/@agents-can-communicate/adapter-codex/src/native-delivery.mjs +151 -0
  56. package/node_modules/@agents-can-communicate/adapter-codex/src/ws-json-rpc.mjs +192 -0
  57. package/node_modules/@agents-can-communicate/adapter-gemini-cli/certification.json +68 -0
  58. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/gemini-extension.json +1 -1
  59. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/skills/acc/SKILL.md +22 -22
  60. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeAgent-0.57.0.json +8 -0
  61. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeTool-0.57.0.json +12 -0
  62. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeTool-shell-0.57.0.json +12 -0
  63. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/SessionEnd-0.57.0.json +8 -0
  64. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/SessionStart-0.57.0.json +8 -0
  65. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/certification-provenance.json +293 -0
  66. package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +8 -1
  67. package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/adapter.mjs +31 -13
  68. package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/install.mjs +4 -2
  69. package/node_modules/@agents-can-communicate/adapter-grok/certification.json +3 -0
  70. package/node_modules/@agents-can-communicate/adapter-grok/package.json +2 -1
  71. package/node_modules/@agents-can-communicate/adapter-grok/plugin/skills/acc/SKILL.md +22 -22
  72. package/node_modules/@agents-can-communicate/adapter-grok/src/adapter.mjs +11 -9
  73. package/node_modules/@agents-can-communicate/adapter-kimi/certification.json +52 -0
  74. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/PreToolUse-Bash.json +12 -0
  75. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/PreToolUse-Write.json +12 -0
  76. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/SessionHeartbeat.json +7 -0
  77. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/SessionStart.json +9 -0
  78. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/UserPromptSubmit.json +8 -0
  79. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/certification-provenance.json +66 -0
  80. package/node_modules/@agents-can-communicate/adapter-kimi/package.json +8 -1
  81. package/node_modules/@agents-can-communicate/adapter-kimi/plugin/skills/acc/SKILL.md +22 -22
  82. package/node_modules/@agents-can-communicate/adapter-kimi/src/adapter.mjs +7 -3
  83. package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
  84. package/node_modules/@agents-can-communicate/adapter-sdk/src/capabilities.mjs +52 -18
  85. package/node_modules/@agents-can-communicate/adapter-sdk/src/certification.mjs +158 -0
  86. package/node_modules/@agents-can-communicate/adapter-sdk/src/context-projector.mjs +36 -17
  87. package/node_modules/@agents-can-communicate/adapter-sdk/src/hook-shim.mjs +9 -1
  88. package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +7 -2
  89. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-activation.mjs +76 -0
  90. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-delivery.mjs +202 -0
  91. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-vocabulary.mjs +101 -0
  92. package/node_modules/@agents-can-communicate/adapter-sdk/src/session-binding.mjs +28 -4
  93. package/node_modules/@agents-can-communicate/cli/package.json +1 -1
  94. package/node_modules/@agents-can-communicate/cli/src/args.mjs +12 -31
  95. package/node_modules/@agents-can-communicate/cli/src/doctor-command.mjs +70 -5
  96. package/node_modules/@agents-can-communicate/cli/src/help.mjs +2 -5
  97. package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +111 -12
  98. package/node_modules/@agents-can-communicate/cli/src/main.mjs +100 -121
  99. package/node_modules/@agents-can-communicate/core/package.json +1 -1
  100. package/node_modules/@agents-can-communicate/core/src/attention.mjs +106 -0
  101. package/node_modules/@agents-can-communicate/core/src/conversations.mjs +276 -0
  102. package/node_modules/@agents-can-communicate/core/src/delivery-bindings.mjs +131 -0
  103. package/node_modules/@agents-can-communicate/core/src/finish-retries.mjs +97 -0
  104. package/node_modules/@agents-can-communicate/core/src/inbox.mjs +91 -107
  105. package/node_modules/@agents-can-communicate/core/src/index.mjs +3 -3
  106. package/node_modules/@agents-can-communicate/core/src/intents.mjs +0 -1
  107. package/node_modules/@agents-can-communicate/core/src/ports.mjs +2 -1
  108. package/node_modules/@agents-can-communicate/core/src/receipts.mjs +109 -0
  109. package/node_modules/@agents-can-communicate/core/src/service.mjs +21 -10
  110. package/node_modules/@agents-can-communicate/core/src/sessions.mjs +22 -20
  111. package/node_modules/@agents-can-communicate/core/src/status.mjs +11 -9
  112. package/node_modules/@agents-can-communicate/core/src/sync.mjs +3 -294
  113. package/node_modules/@agents-can-communicate/delivery-router/package.json +12 -0
  114. package/node_modules/@agents-can-communicate/delivery-router/src/index.mjs +1 -0
  115. package/node_modules/@agents-can-communicate/delivery-router/src/router.mjs +131 -0
  116. package/node_modules/@agents-can-communicate/hook-runner/package.json +4 -2
  117. package/node_modules/@agents-can-communicate/hook-runner/src/client-version.mjs +20 -0
  118. package/node_modules/@agents-can-communicate/hook-runner/src/native-binding.mjs +90 -0
  119. package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +190 -105
  120. package/node_modules/@agents-can-communicate/installer/package.json +1 -1
  121. package/node_modules/@agents-can-communicate/installer/src/apply.mjs +70 -10
  122. package/node_modules/@agents-can-communicate/installer/src/bootstrap-runtime.mjs +144 -0
  123. package/node_modules/@agents-can-communicate/installer/src/detect.mjs +89 -5
  124. package/node_modules/@agents-can-communicate/installer/src/index.mjs +10 -2
  125. package/node_modules/@agents-can-communicate/installer/src/native-activation.mjs +161 -0
  126. package/node_modules/@agents-can-communicate/installer/src/ownership.mjs +112 -12
  127. package/node_modules/@agents-can-communicate/installer/src/plan.mjs +54 -2
  128. package/node_modules/@agents-can-communicate/installer/src/shell-bootstrap.mjs +210 -0
  129. package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
  130. package/node_modules/@agents-can-communicate/mcp-server/src/input-validator.mjs +79 -0
  131. package/node_modules/@agents-can-communicate/mcp-server/src/resources.mjs +23 -28
  132. package/node_modules/@agents-can-communicate/mcp-server/src/server.mjs +102 -72
  133. package/node_modules/@agents-can-communicate/mcp-server/src/tools.mjs +54 -97
  134. package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
  135. package/node_modules/@agents-can-communicate/protocol/src/config.mjs +1 -1
  136. package/node_modules/@agents-can-communicate/protocol/src/conversations.mjs +64 -0
  137. package/node_modules/@agents-can-communicate/protocol/src/fields.mjs +17 -0
  138. package/node_modules/@agents-can-communicate/protocol/src/index.mjs +4 -1
  139. package/node_modules/@agents-can-communicate/protocol/src/schema.mjs +64 -90
  140. package/node_modules/@agents-can-communicate/protocol/src/states.mjs +13 -40
  141. package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
  142. package/node_modules/@agents-can-communicate/storage-filesystem/src/active-journal.mjs +230 -0
  143. package/node_modules/@agents-can-communicate/storage-filesystem/src/atomic-json.mjs +77 -28
  144. package/node_modules/@agents-can-communicate/storage-filesystem/src/identity.mjs +1 -1
  145. package/node_modules/@agents-can-communicate/storage-filesystem/src/journal.mjs +83 -35
  146. package/node_modules/@agents-can-communicate/storage-filesystem/src/retention.mjs +112 -0
  147. package/node_modules/@agents-can-communicate/storage-filesystem/src/safe-file.mjs +18 -8
  148. package/node_modules/@agents-can-communicate/storage-filesystem/src/store.mjs +68 -26
  149. package/node_modules/@agents-can-communicate/storage-filesystem/src/writer-mutex.mjs +113 -35
  150. package/package.json +20 -1
  151. package/node_modules/@agents-can-communicate/core/src/communication.mjs +0 -334
  152. package/node_modules/@agents-can-communicate/core/src/message-signals.mjs +0 -41
  153. package/node_modules/@agents-can-communicate/core/src/notify.mjs +0 -95
  154. package/node_modules/@agents-can-communicate/core/src/tasks.mjs +0 -244
  155. package/node_modules/@agents-can-communicate/core/src/workstreams.mjs +0 -109
@@ -1,219 +1,122 @@
1
1
  # Capabilities
2
2
 
3
- Capability honesty is part of the product: ACC coordinates sessions it does not own, so a
4
- workspace can promise only what every session in it actually exposes — one weaker
5
- participant lowers the reported protection level instead of inheriting a stronger label
6
- from its peers.
7
-
8
- Every row below is **measured**, not asserted: a `yes` has a fixture captured from a real
9
- session of that client version; a `no` means the behavior was not observed, not that it is
10
- impossible. Certified 2026-08-16 on macOS 15 (darwin 25.5.0, arm64) only — at least one
11
- finding here is filesystem- and path-shaped, so re-run the table before trusting it on
12
- another platform.
13
-
14
- ## Clients
15
-
16
- | Adapter | Client | Version |
17
- |---|---|---|
18
- | `codex` | `codex-cli` | 0.147.0 |
19
- | `claude_code` | Claude Code | 2.1.233 |
20
- | `gemini_cli` | Gemini CLI | 0.37.0 and 0.55.1 |
21
- | `grok` | Grok | 1.0.13 |
22
- | `kimi` | Kimi Code | 0.36.1 |
23
-
24
- ## Matrix
25
-
26
- | Capability | codex | claude_code | gemini_cli | grok | kimi |
27
- |---|---|---|---|---|---|
28
- | `lifecycle.sessionStart` | yes | yes | yes | yes | yes |
29
- | `lifecycle.sessionResume` | no | no | no | no | no |
30
- | `lifecycle.sessionEnd` | yes | yes | yes | yes | no |
3
+ Capability honesty separates four questions that are easy to collapse:
4
+
5
+ 1. **Certified support** — did this exact client version and platform pass a shipped
6
+ real-client fixture?
7
+ 2. **Current reachability** — does one current session generation expose a live binding
8
+ whose lease is valid now?
9
+ 3. **Recipient policy** — did that recipient opt into spending a turn for this message
10
+ kind?
11
+ 4. **Fallback** — what durable path remains when any earlier answer is no?
12
+
13
+ A source method or vendor documentation is not certification. Unknown versions and
14
+ platforms degrade to false. No weaker session inherits a stronger peer's capability.
15
+
16
+ ## Certified support
17
+
18
+ Passing evidence currently ships for these exact versions on `darwin-arm64`:
19
+
20
+ | Capability | Codex 0.147.0 | Claude Code 2.1.233 | Gemini CLI 0.57.0 | Grok 1.0.13 | Kimi 0.36.1 |
21
+ |---|---:|---:|---:|---:|---:|
22
+ | `lifecycle.sessionStart` | yes | yes | yes | no | yes |
23
+ | `lifecycle.sessionEnd` | yes | yes | yes | no | no |
31
24
  | `lifecycle.heartbeat` | no | no | no | no | yes |
32
- | `lifecycle.childSessions` | no | no | no | no | no |
33
- | `context.startupInjection` | no | no | no | no | no |
34
25
  | `context.beforeTurnInjection` | yes | yes | yes | no | yes |
35
- | `context.safePointInjection` | no | no | no | no | no |
36
- | `guards.beforeRead` | no | no | no | no | no |
37
26
  | `guards.beforeWrite` | yes | yes | yes | no | yes |
38
- | `guards.beforeShell` | yes | yes | yes | no | yes |
39
- | `delivery.polling` | yes | yes | yes | yes | yes |
40
- | `delivery.activeNotification` | no | no | no | no | no |
41
- | `delivery.wakeDormantSession` | no | no | no | no | no |
42
- | `execution.launch` | no | no | no | no | no |
43
- | `execution.resume` | no | no | no | no | no |
44
- | `execution.terminate` | no | no | no | no | no |
45
-
46
- ## Resolving a client's pid is not universal either
47
-
48
- Not a capability above — no adapter method backs it, so it has no row in the matrix — but
49
- it is presence's other signal for telling a dead process from an idle one, and it does not
50
- reach every client.
51
-
52
- A session's recorded pid comes from walking its process ancestry until the adapter's own
53
- declared binary (`client.command`) turns up in `ps -o comm=`. That only works when the
54
- operating system's own name for the process actually is that binary: true for a native
55
- executable, false for a script run through an interpreter, where `comm` reports the
56
- interpreter's name rather than the script's.
57
-
58
- | Client | `client.command` | `ps -o comm=` reports | Pid resolves |
59
- |---|---|---|---|
60
- | `codex` | `codex` | `codex`, a native binary | yes |
61
- | `claude_code` | `claude` | `claude`, a native binary | yes |
62
- | `gemini_cli` | `gemini` | `node` — `gemini.js` starts `#!/usr/bin/env node` | **no** |
63
- | `grok` | `grok` | `grok`, a native Mach-O at `~/.grok/bin/grok` | yes |
64
- | `kimi` | `kimi` | not installed on the machine this table was measured on; Kimi Code ships via npm as a Node.js CLI (`@moonshot-ai/kimi-code`), the same shape as Gemini CLI | **almost certainly no — not measured** |
65
-
66
- A Gemini session records `pid: null` for its whole life, and Kimi's is very likely the
67
- same, unconfirmed. `null` is the correct "nobody knows" answer and is handled identically
68
- wherever it is read — not a correctness bug. It does change what presence delivers, though:
69
- a confirmed-dead pid retires a session immediately and exactly, and today that is `codex`,
70
- `claude_code`, and `grok`. `gemini_cli` and `kimi` fall back to the same age-based floor every
71
- session has for whenever a pid is unavailable — thirty minutes of silence — so their
72
- sessions still leave, just later and on a timer instead of on the fact. See
73
- [ARCHITECTURE.md](ARCHITECTURE.md#presence) for the full floor.
74
-
75
- ## What the yes values do not promise
76
-
77
- A capability says the client can do the thing. Several of them are conditional on how the
78
- client is being run, and the conditions differ per harness. These are the ones that bite.
79
-
80
- **`guards.beforeWrite` on `codex` depends on the model.** Whether the client offers
81
- `apply_patch` at all is a property of the model's metadata (`apply_patch_tool_type`), not
82
- a user setting. With a model that does not have it, edits run through `exec_command`,
83
- which reaches hooks as `tool_name: "Bash"` carrying a command string. A command names no
84
- resource, so there is nothing to compare against a claim. Observed on 0.147.0: the default
85
- toolset contained no `apply_patch`.
86
-
87
- **`guards.beforeWrite` on `gemini_cli` depends on the approval mode.** In the default and
88
- `plan` modes the client declares no write tool to the model at all. `write_file` and
89
- `replace` appear under `auto_edit`; `run_shell_command` under `yolo`.
90
-
91
- **`guards.beforeShell` is resource-aware where the write is unambiguous.** ACC reads the
92
- command for its write positions only — a redirection, an operand of a command whose whole
93
- job is to put bytes somewhere — and declares those paths as targets. Reading positions are
94
- left alone: `cat file` and `grep file` name a path and write nothing, and treating them as
95
- writes would have sessions blocking each other for looking.
96
-
97
- What it does not see is a language runtime opening the file itself (`python3 -c
98
- "open(...)"`), a command assembled at runtime, or an `eval`. A shell can still evade the
99
- guard. Until 0.1.7 every shell write did, which is why partial sight is the improvement it
100
- is: a session told to prefer the shell for file changes walked through every claim in the
101
- workspace.
102
-
103
- Where the guard cannot help, the turn context does: it names the claims other sessions
104
- hold and says which way this session stands with them. Two facts decide the wording — what
105
- the claim's owner asked for (`guarded` or `advisory`; see [Glossary](GLOSSARY.md)), and
106
- whether ACC can stop this session at all:
107
-
108
- | Claim | This session | Note |
109
- |---|---|---|
110
- | guarded | can be guarded | `file edits and recognised shell writes are blocked; a runtime can still get past` |
111
- | guarded | cannot be guarded | `not enforced for this session; do not edit it` |
112
- | advisory | either | `advisory; nothing will stop you, the owner is asking` |
113
-
114
- Unenforceable is not the same as unknown — and neither is it the same as unclaimed.
115
-
116
- **`lifecycle.sessionEnd` on `kimi` is false and it matters.** Each `kimi -p` run leaves an
117
- attached session that never closes itself — it just stops taking turns. Presence retires it
118
- instead, most likely without ever resolving a pid (see above), which means the session
119
- reads `offline` — and disappears from the default `acc status` view — only after thirty
120
- minutes of silence, not on its declared 60s heartbeat cadence. Interactive sessions
121
- heartbeat and do not have this problem.
122
-
123
- **`lifecycle.heartbeat` is Kimi's alone.** It fires on a timer — observed at 60002, 120004
124
- and 180006 ms of uptime — so an idle Kimi session keeps its presence honest. The other
125
- clients reach a hook only when the user takes a turn, so their idle sessions go stale while
126
- alive. This is why it is a capability of its own rather than a flavour of
127
- `delivery.polling`.
128
-
129
- **`context.beforeTurnInjection` on `grok` is false.** Grok 1.0.13 discards
130
- UserPromptSubmit stdout and `additionalContext`. The hook still runs (presence
131
- and polling), but the model is not shown that text. Agents on this client read
132
- `acc status` / `acc inbox` from the skill.
133
-
134
- **`guards.beforeWrite` / `beforeShell` on `grok` are false.** PreToolUse fires, and
135
- the matcher names `write`, `search_replace`, and `run_terminal_command`. A deny
136
- has not yet been captured blocking a real call, so the capability stays false.
137
-
138
- ## Response contracts, which do not port
139
-
140
- The single most portable-looking mistake an adapter can make. Measured by running each
141
- candidate against a real session of each client and checking whether the tool actually
142
- ran. A dash means the candidate was never run against that client, not that it fails —
143
- only the shape each shipped adapter actually uses was measured on every client.
144
-
145
- | Reply to a guard hook | codex | claude_code | gemini_cli | grok | kimi |
146
- |---|---|---|---|---|---|
147
- | exit code 2 | denies | - | denies | - | denies |
148
- | `{"hookSpecificOutput":{…,"permissionDecision":"deny"}}` | - | denies | **ignored** | documented | denies |
149
- | `{"decision":"deny","reason":…}` | - | - | - | documented | - |
150
- | `{"decision":"block","reason":…}` | - | - | denies | - | **ignored** |
151
- | `{"permission":"deny"}` | - | - | ignored | - | ignored |
152
- | exit code 1 | - | - | ignored | - | ignored |
153
-
154
- Codex has no structured reply at all: it denies by exiting 2 with the reason on stderr.
155
- Gemini ignores the shape that Claude Code and Kimi Code both honour, and Kimi ignores the
156
- shape Gemini needs. Each ignored case fails silently — the write goes through and the
157
- client reports nothing.
158
-
159
- Context injection does not follow the deny contract even within one client:
160
-
161
- | Injection | codex | claude_code | gemini_cli | grok | kimi |
162
- |---|---|---|---|---|---|
163
- | `hookSpecificOutput.additionalContext` | - | works | works | **discarded** on UserPromptSubmit | works, but **not unwrapped** |
164
- | plain text on stdout | works | - | dropped | **discarded** on UserPromptSubmit | works |
165
-
166
- Codex delivers a hook's stdout as a `developer` role message, verbatim — the most direct
167
- of the four channels, and a reason for care rather than comfort: at that role a model
168
- reads text as instruction, so peer-authored text has to stay framed as data.
169
-
170
- Kimi Code shows the model whatever a hook printed, wrapped in
171
- `<hook_result hook_event="…">`, so the JSON envelope itself would end up in the
172
- conversation. Gemini unwraps the envelope and appends `<hook_context>…</hook_context>` to
173
- the user turn, and drops a bare string entirely.
174
-
175
- These two tables are the measurement; they say nothing about how an adapter produces the
176
- right shape without knowing which client it is talking to. That contract —
177
- `denyOutcome()` / `injectOutcome()` — is documented in
178
- [ADAPTER_AUTHORING.md](ADAPTER_AUTHORING.md#response-contracts-do-not-port).
179
-
180
- ## Installation is not uniform either
181
-
182
- | | codex | claude_code | gemini_cli | grok | kimi |
183
- |---|---|---|---|---|---|
184
- | Where hooks live | marketplace plugin | plugin | `settings.json` | `~/.grok/hooks/acc.json` | `config.toml` |
185
- | Project-level config | no | no | yes | yes (`<project>/.grok/hooks`, unused) | **no** |
186
- | Hook `timeout` unit | - | - | milliseconds | **seconds** | **seconds** (max 600) |
187
- | Command path | absolute required | `${CLAUDE_PLUGIN_ROOT}` | absolute required | absolute required | absolute required |
188
- | Extra step by the user | hook trust | - | - | - | - |
189
-
190
- Kimi Code is the only one with no project-level config, so ACC edits the user's global
191
- `config.toml` — as a delimited block it owns, because ACC ships without dependencies and a
192
- hand-written TOML round-tripper would take the user's comments and formatting with it.
193
-
194
- Codex needs four things before a hook runs, not one: the plugin directory, a parseable
195
- marketplace, both `[marketplaces.…]` and `[plugins."…"]` registered in its config, and the
196
- plugin copied into `plugins/cache/<marketplace>/<plugin>/<version>/`. ACC does all four —
197
- that last copy is exactly and only what `codex plugin add` does, measured by diffing the
198
- home around it. Hook trust remains a manual step, which is the client's security model.
199
-
200
- ## What a participant declares about itself
201
-
202
- Every session records `enforcement` (`guarded` | `advisory`) and `lifecycle`
203
- (`managed` | `manual`), taken from the adapter's proven capabilities in this matrix rather
204
- than from the harness's name — both default to the weaker reading, so a generic MCP client
205
- or a human at the CLI reads as advisory and manual. What that downgrade means for a
206
- workspace, and why one MCP participant in the room is enough to drop everyone else's
207
- protection, is explained canonically in
208
- [MCP.md](MCP.md#native-adapter-vs-mcp-client).
209
-
210
- **"Stoppable" is not "unevadable".** Even in a guarded workspace, a session that writes
211
- through a language runtime rather than a recognised shell form gets past — see
212
- `guards.beforeShell` above. The claim still says who is working where; enforcement is the
213
- floor, not the ceiling.
214
-
215
- ---
216
-
217
- See also: [README](index.md) for navigation, [Glossary](GLOSSARY.md) for terms,
218
- [Adapter authoring](ADAPTER_AUTHORING.md) for the deny/inject implementation contract, and
219
- [MCP](MCP.md) for the participation tier and the native-vs-MCP explanation.
27
+ | `guards.beforeShell` | no | yes | yes | no | yes |
28
+ | `delivery.nextTurn` | yes | yes | yes | no | yes |
29
+ | `delivery.livePush` | no | no | no | no | no |
30
+ | `delivery.replyRoute` | no | no | no | no | no |
31
+
32
+ Every other capability in the closed shape defaults to false, including session resume,
33
+ child sessions, startup or safe-point injection, and before-read guards.
34
+
35
+ The `delivery.livePush` and `delivery.replyRoute` row is `no` for the exact hook versions
36
+ this matrix is keyed to. Native live delivery was captured on newer clients - Claude Code
37
+ 2.1.258 (livePush and replyRoute) and Codex 0.152.1 (livePush) - and is admitted through the
38
+ native delivery contract rather than exact-version certification: it is off until a per-client
39
+ opt-in, experimental, and never turns on for a client below the captured minimum.
40
+
41
+ The limitations belong next to the adapters they affect:
42
+
43
+ | Adapter | Exact limitation and evidence |
44
+ |---|---|
45
+ | Codex | 0.147.0 next-turn stdout arrives as unwrapped developer-role context and requires plugin trust. A 0.152.1 capture proved the App Server queue transport, but the release capture then measured that native delivery there requires `codex --remote unix://`, and in that mode the session runs inside the daemon: both the hook payload and the App Server's own thread record report the daemon's directory instead of the session's, so ACC cannot tell which workspace the session is in. Nothing ACC can reach carries the real one, and placing a session in the wrong workspace is worse than not placing it, so `delivery.livePush` is **not** claimed - the probe and the handshake both refuse with `workspace_identity_unavailable`. `replyRoute` stays false. |
46
+ | Claude Code | 2.1.233 next-turn delivery waits for the next user prompt. A 2.1.258 Channel capture proved idle offer, busy queue-after-turn, explicit reply, duplicate suppression, and durable fallback, so `delivery.livePush` and `delivery.replyRoute` are live capabilities behind the native contract (experimental, off until opted in; Claude's development-channel warning is vendor-owned and visible). |
47
+ | Gemini CLI | Only 0.57.0 has package-shipped next-turn certification. 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. |
48
+ | Grok | 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. |
49
+ | Kimi Code | 0.36.1 has next-turn and guard evidence, 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. |
50
+ | Generic MCP | Tool polling is not next-turn injection, live push, or a native reply route. It has no write guard or client-lifecycle evidence. |
51
+
52
+ `certification.json` beside each adapter is machine-readable. `COMPATIBILITY.md` records the
53
+ captured client behavior, including what could not be observed.
54
+
55
+ ## Current reachability
56
+
57
+ Certification is static evidence; reachability is runtime state. A live-capable adapter
58
+ would publish a generation-bound binding with `availableModes`, `clientVersion`,
59
+ `livePolicy`, and `leaseUntil`. `acc status --json` reports these as `deliveryBindings`
60
+ with a computed `reachable` boolean while keeping the opaque endpoint private.
61
+
62
+ The router requires exactly one current eligible generation. No binding, an expired lease,
63
+ several live sessions for one participant, a busy target, or a version that does not match
64
+ passing evidence all stay on durable fallback.
65
+
66
+ The lease is extended by whoever serves the endpoint, because only that process knows it is
67
+ still alive. A client that publishes no heartbeat - Claude Code among them - would otherwise
68
+ let the lease run out under an idle session, which is exactly when live delivery is worth
69
+ having. Giving a binding up is a separate, final fact rather than an expired lease, so a
70
+ channel that has not yet noticed cannot extend something the session already retired.
71
+
72
+ Current shipped reality: Claude Code on darwin-arm64 has a passing experimental `livePush`
73
+ capture behind the native delivery contract, off until a per-client opt-in. Codex is
74
+ next-turn and inbox only: its queue transport works, but the mode that makes a session
75
+ reachable is the mode that hides which workspace it is in. Every other client is next-turn or
76
+ inbox only;
77
+ Gemini CLI and Kimi Code are next-turn only at their exact captured versions; Grok and MCP
78
+ poll inbox.
79
+
80
+ ## Recipient policy
81
+
82
+ Native live delivery may start a model turn and spend tokens, so the recipient owns the
83
+ policy:
84
+
85
+ | Policy | Meaning |
86
+ |---|---|
87
+ | `off` | normal next-turn and inbox only |
88
+ | `actionable` | questions, requests, answers, decisions, and addressed handoffs may use live push; notes wait for the next turn |
89
+ | `all` | every addressed message kind may use live push |
90
+
91
+ The default is `off`. `acc install --delivery actionable|all` is an explicit request, not
92
+ a force switch. The installer applies it only when the detected exact client has certified
93
+ live push; otherwise effective policy remains off and the fallback diagnostic is printed.
94
+ Room messages are never live-push candidates.
95
+
96
+ ## Fallback
97
+
98
+ | Participant | Durable behavior when acceleration is unavailable |
99
+ |---|---|
100
+ | exact-certified Codex 0.147.0 | complete peer body at the next normal turn; `acc inbox` remains recoverable |
101
+ | exact-certified Claude Code 2.1.233 | complete peer body at the next normal prompt; `acc inbox` remains recoverable |
102
+ | exact-certified Gemini CLI 0.57.0 | complete peer body at the next normal turn; `acc inbox` remains recoverable |
103
+ | exact-certified Kimi Code 0.36.1 | complete peer body at the next normal turn; `acc inbox` remains recoverable |
104
+ | Grok, generic MCP, unknown version, other platform | explicit `acc inbox` polling |
105
+
106
+ A send that committed durably succeeds even if a transport later fails. The delivery array
107
+ names the queued fallback and safe error code. There is no terminal failed receipt.
108
+
109
+ ## Guard limitations
110
+
111
+ A guarded claim stops only paths the client exposes to a captured pre-tool hook. Codex's
112
+ write guard depends on the model offering `apply_patch`; recognised shell writes can be
113
+ matched, but a language runtime opening a file cannot. Gemini's edit tools depend on
114
+ approval mode. Grok has no certified guard. One live advisory session lowers workspace
115
+ protection to advisory because that is the strongest honest room-wide statement.
116
+
117
+ Hook response shapes are vendor-specific and not portable. An ignored deny response often
118
+ fails silently, which is why each true cell above needs its own fixture rather than a
119
+ shared documentation example.
120
+
121
+ Next: [Protocol](PROTOCOL.md) · [MCP](MCP.md) ·
122
+ [Adapter authoring](ADAPTER_AUTHORING.md)
package/docs/CLI.md ADDED
@@ -0,0 +1,164 @@
1
+ # CLI
2
+
3
+ The `acc` command is the universal local boundary. Setup commands are for a person;
4
+ communication commands are the small surface installed skills teach to agents. Every
5
+ command accepts `--json` and `--cwd <path>`. `--workspace <config>` selects an explicit
6
+ workspace config where supported by the common boundary.
7
+
8
+ <!-- test:command -->
9
+ ```bash
10
+ acc help
11
+ acc version
12
+ ```
13
+
14
+ ## Communication commands
15
+
16
+ | Command | Required | Optional |
17
+ |---|---|---|
18
+ | `acc status` | — | `--participant`, `--all` |
19
+ | `acc sync` | — | `--session`, `--cursor`, `--limit`, `--scope delta|full` |
20
+ | `acc work` | `--summary` unless `--clear` | `--session`, `--generation`, `--mode`, `--state`, repeated `--hint`, `--clear` |
21
+ | `acc claim` | `--resource` | `--session`, `--generation`, `--mode`, `--enforcement`, `--reason`, `--lease` |
22
+ | `acc release` | `--claim` or `--resource` | `--session`, `--generation`, `--authority`, `--reason` |
23
+ | `acc message` | `--subject`, `--body` | repeated `--to`, `--type`, `--obligation`, `--client-message-id`, owner flags |
24
+ | `acc request` | `--to`, `--title` | `--detail`, `--client-message-id`, owner flags |
25
+ | `acc inbox` | — | `--message`, owner flags |
26
+ | `acc reply` | `--message`, `--body` | `--subject`, `--client-message-id`, owner flags |
27
+ | `acc ack` | `--message` | owner flags |
28
+ | `acc finish` | `--goal` | `--status`, `--to`, repeated `--completed`, `--remaining`, `--blocker`, `--client-message-id`, owner flags |
29
+
30
+ Owner flags are `--session` and `--generation`. A normal hooked session omits them because
31
+ the CLI resolves its current binding. Scripts and adapters may pass them explicitly.
32
+
33
+ ### Presence and intent
34
+
35
+ ```bash
36
+ acc status
37
+ acc work --summary "checking receipt transitions" --mode review \
38
+ --hint 'file:packages/core/src/receipts.mjs'
39
+ acc work --clear
40
+ ```
41
+
42
+ `status` returns participants, current intent, claims, protection, attention, and current
43
+ delivery bindings. `sync` is a bounded event read; use `--scope full` only for an explicit
44
+ whole-workspace forensic question. Neither is the recovery path for one message.
45
+
46
+ ### Claims
47
+
48
+ ```bash
49
+ acc claim --resource 'file:packages/core/**' --reason "editing receipt logic"
50
+ acc release --resource 'file:packages/core/**'
51
+ ```
52
+
53
+ File resources use repository-relative paths. A directory claim ends in `/**`. Exit code
54
+ `5` means a conflict. `--authority` is the explicit force-release path and should carry a
55
+ reason; ordinary sessions release only their own claims.
56
+
57
+ ### Messages and requests
58
+
59
+ ```bash
60
+ acc message --to models --type question --subject "receipt wording" \
61
+ --body "Should transport acceptance be called offered?" \
62
+ --client-message-id client_stable_1
63
+
64
+ acc request --to models --title "review receipt wording" \
65
+ --detail "Check CLI and MCP results; reply with defects only."
66
+ ```
67
+
68
+ `message` accepts generic kinds `note`, `question`, `request`, and `decision`. Defaults are
69
+ `note` plus obligation `none`; questions and requests require `reply`; an addressed
70
+ decision may explicitly use `--obligation acknowledge`. `answer` is created only by
71
+ `reply`, and `handoff` only by `finish`.
72
+
73
+ No `--to` creates a room message where the kind allows it. Addressed messages create a
74
+ separate receipt for each recipient. `request` is convenience for one addressed `request`
75
+ message with a reply obligation; it creates no execution record.
76
+
77
+ The JSON result for `message`, `request`, `reply`, and `finish` is:
78
+
79
+ ```json
80
+ {
81
+ "message": { "messageId": "message_x", "clientMessageId": "client_x" },
82
+ "delivery": [
83
+ { "recipientParticipantId": "models", "outcome": "queued",
84
+ "transport": "durable", "errorCode": "delivery_disabled" }
85
+ ]
86
+ }
87
+ ```
88
+
89
+ Human output starts with `recorded message_x`. A transport failure after that commit does
90
+ not change the command exit code. Reuse an explicit `--client-message-id` after an
91
+ uncertain result to recover the same logical message.
92
+
93
+ ### Inbox, reply, and acknowledgement
94
+
95
+ ```bash
96
+ acc inbox
97
+ acc inbox --message message_x
98
+ acc reply --message message_x --body "Yes. Use offered."
99
+ acc ack --message message_y
100
+ ```
101
+
102
+ Inbox returns only unresolved messages addressed to this participant. Reading advances
103
+ that participant's receipt to `retrieved`. Reply creates an `answer` in the same thread and
104
+ acknowledges the original atomically. `ack` acknowledges without writing an answer and has
105
+ no state override.
106
+
107
+ ### Handoff
108
+
109
+ ```bash
110
+ acc finish --goal "document receipt semantics" --status partial \
111
+ --completed "protocol updated" --remaining "acceptance proof" \
112
+ --blocker "packed test not run" --to models
113
+ ```
114
+
115
+ Status is `complete`, `partial`, or `blocked`. `finish` records a structured handoff,
116
+ releases the caller's claims, and ends ACC presence for that session. It never closes the
117
+ external AI client. An addressed handoff requires acknowledgement; a room handoff does not.
118
+
119
+ ## Setup and maintenance
120
+
121
+ | Command | Flags |
122
+ |---|---|
123
+ | `acc install` | `--adapter`, `--home`, `--delivery off|actionable|all`, `--dry-run`, `--downgrade` |
124
+ | `acc uninstall` | `--adapter`, `--home`, `--dry-run` |
125
+ | `acc doctor` | `--home`, `--repair` |
126
+ | `acc config init` | `--yes`, `--force` |
127
+ | `acc config validate` | — |
128
+ | `acc update` | `--apply` |
129
+ | `acc help` | — |
130
+ | `acc version` | — |
131
+
132
+ `--delivery off|actionable|all` is a per-client recipient policy request, not a capability
133
+ switch, and the default is `off`. `--adapter` is repeatable to name several clients. An
134
+ explicit `--delivery` applies uniformly and never prompts; omitting it on an interactive
135
+ terminal asks one default-No question per eligible client, and on a non-interactive run or a
136
+ `--dry-run` it keeps fresh clients off. A recorded opt-in is kept on upgrade. If the detected
137
+ client cannot receive native delivery - unsupported, below the captured minimum, a
138
+ prerelease, known-bad, a wrong platform, or an unsupported shell - installation keeps the
139
+ effective policy off and prints the reason. A live install writes an owned zsh PATH block and
140
+ a per-command shim that keeps your command name and `exec`s the real client; `ACC_BYPASS=1`
141
+ runs the unmodified client, and ACC is never the parent of the session after that `exec`.
142
+
143
+ Only `update` touches the network. `ACC_NO_UPDATE_CHECK=1` disables update checks. Hooks
144
+ never perform them.
145
+
146
+ ## Adapter lifecycle commands
147
+
148
+ `acc attach --participant <id>`, `acc heartbeat --session <id> --generation <token>`, and
149
+ `acc detach --session <id> --generation <token>` are public executable boundaries used by
150
+ adapters. Installed skills do not teach models to call them. They maintain ACC presence;
151
+ they do not start, keep alive, or close the external client process.
152
+
153
+ ## Exit codes
154
+
155
+ | Code | Meaning |
156
+ |---|---|
157
+ | `0` | success |
158
+ | `2` | usage |
159
+ | `3` | timeout |
160
+ | `4` | data or incompatible state |
161
+ | `5` | claim or generation conflict |
162
+ | `6` | attention |
163
+
164
+ Next: [Protocol](PROTOCOL.md) · [MCP](MCP.md) · [Configuration](CONFIGURATION.md)