agents-can-communicate 0.1.16 → 0.1.18

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 (49) hide show
  1. package/README.md +63 -133
  2. package/bin/acc-hook.mjs +2 -0
  3. package/docs/CAPABILITIES.md +105 -85
  4. package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +1 -1
  5. package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/skills/acc/SKILL.md +80 -154
  6. package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +3 -1
  7. package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
  8. package/node_modules/@agents-can-communicate/adapter-codex/plugin/skills/acc/SKILL.md +80 -154
  9. package/node_modules/@agents-can-communicate/adapter-codex/src/adapter.mjs +3 -1
  10. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/skills/acc/SKILL.md +80 -154
  11. package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +1 -1
  12. package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/adapter.mjs +3 -1
  13. package/node_modules/@agents-can-communicate/adapter-grok/package.json +13 -0
  14. package/node_modules/@agents-can-communicate/adapter-grok/plugin/hooks/hooks.json +61 -0
  15. package/node_modules/@agents-can-communicate/adapter-grok/plugin/skills/acc/SKILL.md +154 -0
  16. package/node_modules/@agents-can-communicate/adapter-grok/src/adapter.mjs +61 -0
  17. package/node_modules/@agents-can-communicate/adapter-grok/src/hooks.mjs +127 -0
  18. package/node_modules/@agents-can-communicate/adapter-grok/src/install.mjs +101 -0
  19. package/node_modules/@agents-can-communicate/adapter-kimi/package.json +1 -1
  20. package/node_modules/@agents-can-communicate/adapter-kimi/plugin/skills/acc/SKILL.md +80 -154
  21. package/node_modules/@agents-can-communicate/adapter-kimi/src/adapter.mjs +3 -1
  22. package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
  23. package/node_modules/@agents-can-communicate/adapter-sdk/src/context-projector.mjs +125 -189
  24. package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +1 -1
  25. package/node_modules/@agents-can-communicate/cli/package.json +1 -1
  26. package/node_modules/@agents-can-communicate/cli/src/args.mjs +3 -0
  27. package/node_modules/@agents-can-communicate/cli/src/help.mjs +4 -2
  28. package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +3 -1
  29. package/node_modules/@agents-can-communicate/cli/src/main.mjs +23 -2
  30. package/node_modules/@agents-can-communicate/cli/src/session-owner.mjs +1 -1
  31. package/node_modules/@agents-can-communicate/core/package.json +1 -1
  32. package/node_modules/@agents-can-communicate/core/src/inbox.mjs +134 -0
  33. package/node_modules/@agents-can-communicate/core/src/index.mjs +1 -0
  34. package/node_modules/@agents-can-communicate/core/src/message-signals.mjs +41 -0
  35. package/node_modules/@agents-can-communicate/core/src/ports.mjs +1 -1
  36. package/node_modules/@agents-can-communicate/core/src/service.mjs +3 -0
  37. package/node_modules/@agents-can-communicate/core/src/sessions.mjs +48 -0
  38. package/node_modules/@agents-can-communicate/core/src/sync.mjs +36 -0
  39. package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
  40. package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +77 -33
  41. package/node_modules/@agents-can-communicate/installer/package.json +1 -1
  42. package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
  43. package/node_modules/@agents-can-communicate/mcp-server/src/server.mjs +29 -21
  44. package/node_modules/@agents-can-communicate/mcp-server/src/tools.mjs +25 -1
  45. package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
  46. package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
  47. package/node_modules/@agents-can-communicate/storage-filesystem/src/store.mjs +23 -7
  48. package/node_modules/@agents-can-communicate/storage-filesystem/src/writer-mutex.mjs +18 -2
  49. package/package.json +4 -1
package/README.md CHANGED
@@ -4,171 +4,101 @@
4
4
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
5
  [![Node](https://img.shields.io/badge/node-%E2%89%A524-brightgreen.svg)](https://nodejs.org)
6
6
 
7
- **Give every agent session a shared room for coordination. Keep your attention on the
8
- work.**
7
+ **Give the agent sessions you already opened a shared room and stop being the wire
8
+ between them.**
9
9
 
10
- ACC is a local-first coordination layer for the AI agent sessions you already opened. It
11
- gives them shared presence, intent, claims, messages, and work requests while every
12
- session keeps its own authority.
10
+ ACC is a local-first coordination layer for independent AI coding sessions on one repo.
11
+ They see who else is here, claim the files they touch, message each other directly, and
12
+ hand work across — while each keeps its own client, checkout, permissions, and human. It
13
+ runs entirely on your machine, on Node's standard library with **zero runtime
14
+ dependencies**, and your transcripts never leave the client.
13
15
 
14
- Coordination runs locally on your machine. Raw transcripts stay private. The runtime is
15
- built entirely on Node's standard library.
16
+ ## The wall is you
17
+
18
+ One session refactors and is about to remove a field called `item.drive`. Another, in a
19
+ file you're not looking at, still reads it. Neither terminal knows the other exists — so
20
+ either you carry the warning across by hand, or it ships broken.
21
+
22
+ **Without ACC**, every warning, question, and handoff between sessions stops at you and
23
+ starts again from you. **With ACC**, the sessions carry them to each other: the second
24
+ agent sees the claim, gets the measured impact as a message, and the change lands in one
25
+ piece. You go back to directing.
16
26
 
17
27
  ```mermaid
18
28
  flowchart TB
19
- Y["You<br/>set direction"]
20
- A["Agent session A"]
21
- B["Agent session B"]
22
- C["Agent session C"]
23
- R["ACC shared room<br/>presence · intent · claims<br/>messages · work requests"]
24
- O["Coordinated work<br/>with shared context"]
25
-
29
+ Y["Youset direction"]
30
+ A["session A"]
31
+ B["session B"]
32
+ C["session C"]
33
+ R["ACC shared room<br/>presence · claims · messages · handoffs"]
26
34
  Y --> A
27
35
  Y --> B
28
36
  Y --> C
29
37
  A <--> R
30
38
  B <--> R
31
39
  C <--> R
32
- R --> O
33
40
  ```
34
41
 
35
- ## You opened more agents. You became the coordinator.
36
-
37
- One session implements. Another writes tests. A third reviews. At first, more agents means
38
- more work gets done.
39
-
40
- Then you start copying context between windows. You warn two agents away from the same
41
- file. You relay a question, return with the answer, and try to remember which terminal was
42
- waiting for what. The agents are capable; they need a room they can share.
43
-
44
- ACC gives them that room. Each session stays in its original client, checkout, and trust
45
- boundary. You still decide when it starts and stops. ACC only supplies the coordination
46
- that was previously passing through you.
47
-
48
- ## A handoff the agents carry themselves
49
-
50
- One agent finishes building a feature and sees that its final tests still need work. It
51
- asks the testing agent to take over, including a short summary of what is ready and what
52
- remains.
53
-
54
- ```mermaid
55
- flowchart LR
56
- A["Feature agent<br/>finishes its part"] --> B["Requests tests<br/>from the testing agent"]
57
- B --> C["ACC keeps the handoff<br/>ready for that agent"]
58
- C --> D["Testing agent<br/>completes the work"]
59
- D --> E["Result returns<br/>to the feature agent"]
60
- ```
61
-
62
- The request stays with the testing agent across terminal restarts. When that agent returns,
63
- it receives the handoff, completes the tests, and sends the result back. You choose the
64
- direction and review the outcome; the agents carry the context between them.
65
-
66
42
  ## Install
67
43
 
68
- Run these commands in a terminal on each macOS or Linux machine where your agent clients
69
- run:
44
+ Two commands, once per macOS or Linux machine where your clients run:
70
45
 
71
46
  ```bash
72
47
  npm install -g agents-can-communicate
73
48
  acc install
74
49
  ```
75
50
 
76
- The first command makes `acc` available across the machine. The second finds Codex,
77
- Claude Code, Gemini CLI, and Kimi Code installations and activates the integrations that
78
- are available. Codex completes activation after you trust the plugin; `acc doctor` shows
79
- the current state.
80
-
81
- `acc install` names every client setting it activated and how to undo it.
82
-
83
- Open or restart your agent client inside a project. Each new session joins that project's
84
- room automatically. Open another session in the same project and the two can coordinate;
85
- run `acc status` from the project directory whenever you want to see the room yourself.
51
+ `acc install` wires ACC into the clients you have Codex, Claude Code, Gemini CLI, Grok,
52
+ Kimi Code and names everything it changed. **Restart the client afterwards** (hooks load
53
+ at startup); Codex also needs you to trust the plugin. Then just open a session in a
54
+ project and it joins that project's room by itself; open a second and they coordinate.
55
+ `acc doctor` shows what's active, `acc update --apply` keeps it current, `acc uninstall`
56
+ removes only what ACC wrote.
86
57
 
87
- ACC stores coordination data in the standard application-data location for your system.
88
- The defaults are `~/Library/Application Support/acc` on macOS and `~/.local/share/acc` on
89
- Linux. `XDG_DATA_HOME` relocates the Linux default; `ACC_DATA_HOME` overrides either
90
- platform, as described in [configuration](docs/CONFIGURATION.md). Project files stay
91
- unchanged. Git worktrees from one repository share a room, and plain folders receive the
92
- same coordination experience.
58
+ Coordination data lives in the platform app-data directory (`~/Library/Application
59
+ Support/acc`, `~/.local/share/acc`; override with `ACC_DATA_HOME`), never in your repo.
60
+ Every worktree of a repo shares one room; a plain folder works the same.
93
61
 
94
- Keep ACC current with `acc update --apply`. It installs the latest release and refreshes
95
- the client integrations together. `acc doctor` points to that action when their versions
96
- drift.
62
+ ## What the room holds
97
63
 
98
- Run `acc uninstall` to remove ACC's client integrations. Settings you changed remain
99
- yours.
100
-
101
- ## What changes after installation
102
-
103
- **Agents know who is around.** Each session can see the other participants, their current
104
- focus, and the files they have claimed.
105
-
106
- **Parallel work becomes deliberate.** Agents claim shared files before editing. Supported
107
- client edits respect those claims and identify the participant already working there.
108
-
109
- **Questions and work find their way back.** Requests, decisions, and handoffs stay with
110
- the intended agent across session restarts, and results return to the agent that asked.
111
-
112
- **Human authority stays clear.** Peer messages arrive with attribution and remain peer
113
- context. Your instructions and approved policy continue to set the boundaries.
114
-
115
- **Solo work stays quiet.** A single session receives the familiar client experience.
116
- Shared context appears when another participant or pending handoff makes it useful.
117
-
118
- ## Fits the workflow you already have
119
-
120
- Your agent client remains the place where sessions start, permissions are granted, and
121
- work happens. ACC joins at natural moments, shares the relevant context, and returns
122
- control to the client. Forward progress stays the priority during any coordination delay.
123
-
124
- ACC currently connects directly to Codex, Claude Code, Gemini CLI, and Kimi Code. Other
125
- clients that support MCP can join the same room, see its activity, and exchange work when
126
- they sync.
127
-
128
- When a client exposes supported file edits, ACC can protect a claimed file before another
129
- agent changes it. Shell commands and separate local applications rely on visible claims
130
- instead. `acc status` explains the protection available in the current room.
131
-
132
- Current support focuses on multiple sessions working in one project on one machine, on
133
- macOS or Linux. Each client retains its session lifecycle and full conversation history.
134
- The [capability evidence](docs/CAPABILITIES.md) records exactly what each integration has
135
- demonstrated in a real client.
64
+ | | |
65
+ |---|---|
66
+ | **presence** | who's live, their client and branch, and what each intends — one `acc status`. |
67
+ | **claims** | the files each session is touching; on guardable clients a clashing edit is refused and the owner named. |
68
+ | **messages** | questions, decisions, notes — attributed, delivered on the recipient's next turn, and data they weigh rather than orders. |
69
+ | **requests & handoffs** | work addressed to a participant, so it waits across restarts and carries the answer back. |
136
70
 
137
- ACC currently retains every coordination record. It is sized for an active project's
138
- history; thousands of messages make each turn slower to assemble, so use your project
139
- documentation for long-term archives.
71
+ A targeted `acc inbox` survives context compaction, and `acc reply` answers and
72
+ acknowledges in one operation. A session alone in a repo pays nothing no banner, no
73
+ protocol, nothing left behind.
140
74
 
141
75
  ## Everyday controls
142
76
 
143
- The installed guidance teaches agents how to claim files, ask questions, request work,
144
- and complete handoffs. These commands give you a direct view and control when you want it:
77
+ The installed guidance teaches your agents to claim, ask, request, and hand off on their
78
+ own. These give you a direct view when you want one:
145
79
 
146
- | Command | What it is for |
80
+ | Command | For |
147
81
  |---|---|
148
- | `acc status` | See active sessions, claimed work, and the room's protection level |
149
- | `acc doctor` | Confirm which client integrations are active |
150
- | `acc update --apply` | Install the latest release and refresh integrations |
151
- | `acc uninstall` | Remove ACC's client integrations safely |
152
-
153
- Every operation is documented in the [CLI reference](docs/CLI.md).
154
-
155
- ## Keep exploring
156
-
157
- - **Start using ACC:** [getting started](docs/GETTING_STARTED.md) ·
158
- [configuration](docs/CONFIGURATION.md) · [troubleshooting](docs/TROUBLESHOOTING.md)
159
- - **Understand the promise:** [why ACC](docs/WHY_ACC.md) · [concepts](docs/CONCEPTS.md) ·
160
- [capabilities](docs/CAPABILITIES.md) · [security](docs/SECURITY_MODEL.md)
161
- - **Build on ACC:** [MCP](docs/MCP.md) · [writing an adapter](docs/ADAPTER_AUTHORING.md) ·
162
- [protocol](docs/PROTOCOL.md)
82
+ | `acc status` | who's here, what they claim, and the room's protection level |
83
+ | `acc inbox` | recover an addressed message without a workspace dump |
84
+ | `acc reply` | answer and acknowledge in one operation |
85
+ | `acc doctor` | confirm which client integrations are active and current |
86
+ | `acc update --apply` | install the latest release and refresh integrations |
87
+ | `acc uninstall` | remove ACC's integrations — settings you changed stay yours |
163
88
 
164
- See it in action: [three workstreams](examples/three-workstreams.md) ·
165
- [research in a plain directory](examples/non-git-research.md). Contributions start with
166
- [Repository Guidelines](AGENTS.md).
89
+ ## Documentation
167
90
 
168
- ## Requirements
91
+ Start at the **[documentation map](docs/index.md)** — it lays out a path for whatever
92
+ brought you here: [why ACC](docs/WHY_ACC.md) and [concepts](docs/CONCEPTS.md) to evaluate
93
+ it, [getting started](docs/GETTING_STARTED.md) to run it, the [CLI](docs/CLI.md) /
94
+ [protocol](docs/PROTOCOL.md) / [capabilities](docs/CAPABILITIES.md) reference, and
95
+ [adapter authoring](docs/ADAPTER_AUTHORING.md) to extend it. New to the vocabulary? The
96
+ [glossary](docs/GLOSSARY.md) defines every term in one line.
169
97
 
170
- Node 24+, macOS or Linux. Git optional.
98
+ See it run: [three workstreams](examples/three-workstreams.md) · [research in a plain
99
+ folder](examples/non-git-research.md). Contributing starts with [AGENTS.md](AGENTS.md).
171
100
 
172
- ## License
101
+ ## Requirements & license
173
102
 
174
- Free and MIT-licensed. Use it, fork it, keep it — see [LICENSE](LICENSE).
103
+ Node 24+, macOS or Linux, Git optional. MIT — use it, fork it, keep it
104
+ ([LICENSE](LICENSE)).
package/bin/acc-hook.mjs CHANGED
@@ -13,12 +13,14 @@ import { runHook } from "@agents-can-communicate/hook-runner";
13
13
  import { createClaudeCodeAdapter } from "@agents-can-communicate/adapter-claude-code";
14
14
  import { createCodexAdapter } from "@agents-can-communicate/adapter-codex";
15
15
  import { createGeminiCliAdapter } from "@agents-can-communicate/adapter-gemini-cli";
16
+ import { createGrokAdapter } from "@agents-can-communicate/adapter-grok";
16
17
  import { createKimiAdapter } from "@agents-can-communicate/adapter-kimi";
17
18
 
18
19
  const adapters = {
19
20
  claude_code: createClaudeCodeAdapter(),
20
21
  codex: createCodexAdapter(),
21
22
  gemini_cli: createGeminiCliAdapter(),
23
+ grok: createGrokAdapter(),
22
24
  kimi: createKimiAdapter(),
23
25
  };
24
26
 
@@ -1,17 +1,15 @@
1
1
  # Capabilities
2
2
 
3
- Capability honesty is part of the product, not an implementation footnote. ACC coordinates
4
- sessions it does not own, so the workspace can promise only what every session actually
5
- exposes. One weaker participant lowers the reported protection level instead of inheriting
6
- a stronger label from its peers.
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
7
 
8
- What each harness was **observed** doing, on the versions named here. Nothing in this
9
- table is inferred from documentation: every `yes` has a fixture captured from a real
10
- session, and every `no` means it was not seen, not that it is impossible.
11
-
12
- Certified 2026-08-16 on macOS 15 (darwin 25.5.0, arm64). No other operating system has
13
- been tested, and at least one finding here is filesystem- and path-shaped, so the table
14
- should be re-run before claiming another platform.
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.
15
13
 
16
14
  ## Clients
17
15
 
@@ -20,33 +18,34 @@ should be re-run before claiming another platform.
20
18
  | `codex` | `codex-cli` | 0.147.0 |
21
19
  | `claude_code` | Claude Code | 2.1.233 |
22
20
  | `gemini_cli` | Gemini CLI | 0.37.0 and 0.55.1 |
21
+ | `grok` | Grok | 1.0.13 |
23
22
  | `kimi` | Kimi Code | 0.36.1 |
24
23
 
25
24
  ## Matrix
26
25
 
27
- | Capability | codex | claude_code | gemini_cli | kimi |
28
- |---|---|---|---|---|
29
- | `lifecycle.sessionStart` | yes | yes | yes | yes |
30
- | `lifecycle.sessionResume` | no | no | no | no |
31
- | `lifecycle.sessionEnd` | yes | yes | yes | no |
32
- | `lifecycle.heartbeat` | no | no | no | yes |
33
- | `lifecycle.childSessions` | no | no | no | no |
34
- | `context.startupInjection` | no | no | no | no |
35
- | `context.beforeTurnInjection` | yes | yes | yes | yes |
36
- | `context.safePointInjection` | no | no | no | no |
37
- | `guards.beforeRead` | no | no | no | no |
38
- | `guards.beforeWrite` | yes | yes | yes | yes |
39
- | `guards.beforeShell` | yes | yes | yes | yes |
40
- | `delivery.polling` | yes | yes | yes | yes |
41
- | `delivery.activeNotification` | no | no | no | no |
42
- | `delivery.wakeDormantSession` | no | no | no | no |
43
- | `execution.launch` | no | no | no | no |
44
- | `execution.resume` | no | no | no | no |
45
- | `execution.terminate` | no | no | no | no |
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 |
31
+ | `lifecycle.heartbeat` | no | no | no | no | yes |
32
+ | `lifecycle.childSessions` | no | no | no | no | no |
33
+ | `context.startupInjection` | no | no | no | no | no |
34
+ | `context.beforeTurnInjection` | yes | yes | yes | no | yes |
35
+ | `context.safePointInjection` | no | no | no | no | no |
36
+ | `guards.beforeRead` | no | no | no | no | no |
37
+ | `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 |
46
45
 
47
46
  ## Resolving a client's pid is not universal either
48
47
 
49
- Not a capability above - no adapter method backs it, so it has no row in the matrix - but
48
+ Not a capability above no adapter method backs it, so it has no row in the matrix but
50
49
  it is presence's other signal for telling a dead process from an idle one, and it does not
51
50
  reach every client.
52
51
 
@@ -60,15 +59,16 @@ interpreter's name rather than the script's.
60
59
  |---|---|---|---|
61
60
  | `codex` | `codex` | `codex`, a native binary | yes |
62
61
  | `claude_code` | `claude` | `claude`, a native binary | yes |
63
- | `gemini_cli` | `gemini` | `node` - `gemini.js` starts `#!/usr/bin/env node` | **no** |
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** |
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
65
 
66
66
  A Gemini session records `pid: null` for its whole life, and Kimi's is very likely the
67
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
- and `claude_code` only. `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
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
72
  sessions still leave, just later and on a timer instead of on the fact. See
73
73
  [ARCHITECTURE.md](ARCHITECTURE.md#presence) for the full floor.
74
74
 
@@ -89,8 +89,8 @@ toolset contained no `apply_patch`.
89
89
  `replace` appear under `auto_edit`; `run_shell_command` under `yolo`.
90
90
 
91
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
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
94
  left alone: `cat file` and `grep file` name a path and write nothing, and treating them as
95
95
  writes would have sessions blocking each other for looking.
96
96
 
@@ -101,8 +101,9 @@ is: a session told to prefer the shell for file changes walked through every cla
101
101
  workspace.
102
102
 
103
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 -
105
- what the claim's owner asked for, and whether ACC can stop this session at all:
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:
106
107
 
107
108
  | Claim | This session | Note |
108
109
  |---|---|---|
@@ -110,51 +111,59 @@ what the claim's owner asked for, and whether ACC can stop this session at all:
110
111
  | guarded | cannot be guarded | `not enforced for this session; do not edit it` |
111
112
  | advisory | either | `advisory; nothing will stop you, the owner is asking` |
112
113
 
113
- Unenforceable is not the same as unknown - and neither is it the same as unclaimed.
114
+ Unenforceable is not the same as unknown and neither is it the same as unclaimed.
114
115
 
115
116
  **`lifecycle.sessionEnd` on `kimi` is false and it matters.** Each `kimi -p` run leaves an
116
- attached session that never closes itself - it just stops taking turns. Presence retires it
117
+ attached session that never closes itself it just stops taking turns. Presence retires it
117
118
  instead, most likely without ever resolving a pid (see above), which means the session
118
- reads `offline` - and disappears from the default `acc status` view - only after thirty
119
+ reads `offline` and disappears from the default `acc status` view only after thirty
119
120
  minutes of silence, not on its declared 60s heartbeat cadence. Interactive sessions
120
121
  heartbeat and do not have this problem.
121
122
 
122
- **`lifecycle.heartbeat` is Kimi's alone.** It fires on a timer - observed at 60002, 120004
123
- and 180006 ms of uptime - so an idle Kimi session keeps its presence honest. The other
124
- three reach a hook only when the user takes a turn, so their idle sessions go stale while
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
125
126
  alive. This is why it is a capability of its own rather than a flavour of
126
127
  `delivery.polling`.
127
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
+
128
138
  ## Response contracts, which do not port
129
139
 
130
140
  The single most portable-looking mistake an adapter can make. Measured by running each
131
141
  candidate against a real session of each client and checking whether the tool actually
132
- ran.
133
-
134
- A dash means the candidate was never run against that client, not that it fails. Only the
135
- shape each adapter actually uses was measured on every client.
136
-
137
- | Reply to a guard hook | codex | claude_code | gemini_cli | kimi |
138
- |---|---|---|---|---|
139
- | exit code 2 | denies | - | denies | denies |
140
- | `{"hookSpecificOutput":{…,"permissionDecision":"deny"}}` | - | denies | **ignored** | denies |
141
- | `{"decision":"block","reason":…}` | - | - | denies | **ignored** |
142
- | `{"permission":"deny"}` | - | - | ignored | ignored |
143
- | exit code 1 | - | - | ignored | ignored |
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 |
144
153
 
145
154
  Codex has no structured reply at all: it denies by exiting 2 with the reason on stderr.
146
155
  Gemini ignores the shape that Claude Code and Kimi Code both honour, and Kimi ignores the
147
- shape Gemini needs. Each ignored case fails silently - the write goes through and the
156
+ shape Gemini needs. Each ignored case fails silently the write goes through and the
148
157
  client reports nothing.
149
158
 
150
159
  Context injection does not follow the deny contract even within one client:
151
160
 
152
- | Injection | codex | claude_code | gemini_cli | kimi |
153
- |---|---|---|---|---|
154
- | `hookSpecificOutput.additionalContext` | - | works | works | works, but **not unwrapped** |
155
- | plain text on stdout | works | - | dropped | works |
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 |
156
165
 
157
- Codex delivers a hook's stdout as a `developer` role message, verbatim - the most direct
166
+ Codex delivers a hook's stdout as a `developer` role message, verbatim the most direct
158
167
  of the four channels, and a reason for care rather than comfort: at that role a model
159
168
  reads text as instruction, so peer-authored text has to stay framed as data.
160
169
 
@@ -163,37 +172,48 @@ Kimi Code shows the model whatever a hook printed, wrapped in
163
172
  conversation. Gemini unwraps the envelope and appends `<hook_context>…</hook_context>` to
164
173
  the user turn, and drops a bare string entirely.
165
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
+
166
180
  ## Installation is not uniform either
167
181
 
168
- | | codex | claude_code | gemini_cli | kimi |
169
- |---|---|---|---|---|
170
- | Where hooks live | marketplace plugin | plugin | `settings.json` | `config.toml` |
171
- | Project-level config | no | no | yes | **no** |
172
- | Hook `timeout` unit | - | - | milliseconds | **seconds** (max 600) |
173
- | Command path | absolute required | `${CLAUDE_PLUGIN_ROOT}` | absolute required | absolute required |
174
- | Extra step by the user | hook trust | - | - | - |
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 | - | - | - | - |
175
189
 
176
190
  Kimi Code is the only one with no project-level config, so ACC edits the user's global
177
- `config.toml` - as a delimited block it owns, because ACC ships without dependencies and a
191
+ `config.toml` as a delimited block it owns, because ACC ships without dependencies and a
178
192
  hand-written TOML round-tripper would take the user's comments and formatting with it.
179
193
 
180
194
  Codex needs four things before a hook runs, not one: the plugin directory, a parseable
181
195
  marketplace, both `[marketplaces.…]` and `[plugins."…"]` registered in its config, and the
182
- plugin copied into `plugins/cache/<marketplace>/<plugin>/<version>/`. ACC does all four -
196
+ plugin copied into `plugins/cache/<marketplace>/<plugin>/<version>/`. ACC does all four
183
197
  that last copy is exactly and only what `codex plugin add` does, measured by diffing the
184
198
  home around it. Hook trust remains a manual step, which is the client's security model.
185
199
 
186
200
  ## What a participant declares about itself
187
201
 
188
202
  Every session records `enforcement` (`guarded` | `advisory`) and `lifecycle`
189
- (`managed` | `manual`), taken from the adapter's proven capabilities rather than from the
190
- harness name. Both default to the weaker reading, so a generic MCP client or a human at
191
- the CLI reads as advisory and manual.
192
-
193
- A workspace reports `protection: guarded` only when every live session can be stopped. One
194
- MCP client and a guarded claim is advice - so the workspace says `advisory`, whatever its
195
- claims were declared as.
196
-
197
- "Stoppable" is not "unevadable". Even in a guarded workspace, a session that writes through
198
- a language runtime rather than a recognised shell form gets past. The claim still says who
199
- is working where; enforcement is the floor, not the ceiling.
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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-claude-code",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {