hivecode-mcp 0.12.1 → 0.12.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +188 -8
- package/core.js +91 -91
- package/docs/HIVE_RULES.md +41 -41
- package/docs/MCP.md +5 -5
- package/docs/SELF_HOSTING.md +256 -256
- package/hive-activity.js +336 -310
- package/hive-await.js +187 -0
- package/hive-branch.js +656 -0
- package/hive-busy.js +88 -88
- package/hive-coord.js +110 -110
- package/hive-gate.js +135 -135
- package/hive-hook-install.js +179 -103
- package/hive-instructions.js +74 -66
- package/hive-listen.js +81 -0
- package/hive-mailbox.js +517 -386
- package/hive-mcp.js +483 -126
- package/hive-mux-proto.js +58 -58
- package/hive-mux.js +350 -350
- package/hive-obligations.js +247 -247
- package/hive-pr-staleness.js +189 -189
- package/hive-pr.js +337 -0
- package/hive-privacy.js +327 -288
- package/hive-receipts.js +233 -233
- package/hive-relay-health.js +7 -2
- package/hive-secrets.js +89 -0
- package/hive-setup.js +548 -445
- package/hive-stdio.js +172 -168
- package/hive-stop-hook.js +290 -241
- package/hive-throttle.js +118 -118
- package/hive-update.js +58 -58
- package/hive-version.js +110 -59
- package/icr-merge.js +58 -58
- package/icr.js +121 -15
- package/lang-json.js +211 -211
- package/lang-ruby.js +230 -230
- package/lang-toml.js +136 -136
- package/lang-yaml.js +183 -183
- package/limits.js +413 -394
- package/package.json +20 -11
- package/reconcile.cjs +614 -477
- package/substrate.js +252 -252
- package/sync.js +4691 -3005
- package/grm-link.cjs +0 -141
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Hivecode
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hivecode
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
<h1>Hivecode</h1>
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**An operating system for AI agents that share a workspace.**
|
|
4
4
|
|
|
5
|
-
A few people, each with their own AI agent — Claude Code,
|
|
6
|
-
your own bot — work on one project at the same time. Every edit reaches everyone in about
|
|
7
|
-
second. Agents lock a file before they change it, so they never overwrite each other. They
|
|
5
|
+
A few people, each with their own AI agent — Claude Code, Antigravity, another app that speaks
|
|
6
|
+
MCP, or your own bot — work on one project at the same time. Every edit reaches everyone in about
|
|
7
|
+
a second. Agents lock a file before they change it, so they never overwrite each other. They
|
|
8
8
|
talk to each other by name, and they wait for work instead of wandering off. You watch all of
|
|
9
|
-
it live in your browser, approve what matters, pause any agent, and
|
|
9
|
+
it live in your browser, approve what matters, pause any agent, and put any file back to an
|
|
10
|
+
earlier point.
|
|
10
11
|
|
|
11
12
|
---
|
|
12
13
|
|
|
@@ -19,12 +20,44 @@ it live in your browser, approve what matters, pause any agent, and undo anythin
|
|
|
19
20
|
4. An agent **claims** a file before editing it and **releases** it after. While someone
|
|
20
21
|
holds a file, anyone else's write to it is refused — never silently overwritten.
|
|
21
22
|
5. You watch and steer from the **Control Room** in your browser.
|
|
23
|
+
6. A file someone deletes is deleted for everyone, but every other folder keeps a copy in
|
|
24
|
+
`.hive-deleted/` for 7 days. A folder that disappears, or empties all at once, deletes nothing.
|
|
22
25
|
|
|
23
26
|
Nothing to host. Rooms run on the Hivecode relay, and anyone who has a link can join that
|
|
24
27
|
room — **treat the link like a password** and share it only with your team.
|
|
25
28
|
|
|
26
29
|
---
|
|
27
30
|
|
|
31
|
+
## Your code: where it goes, and who can see it
|
|
32
|
+
|
|
33
|
+
Read this before you join from a real project.
|
|
34
|
+
|
|
35
|
+
- **Your shared files go to the relay and to everyone in the room.** The default relay is run by
|
|
36
|
+
the Hivecode author, not by you. Files travel over an encrypted connection (`wss://`), and the
|
|
37
|
+
relay keeps a copy so the room survives everyone going offline. Your agent's `hive_join` says
|
|
38
|
+
which relay it is using every time, and whose it is.
|
|
39
|
+
- **The link is the key.** Anyone who has it can read and change every file in the room. Share
|
|
40
|
+
it like a password. If it leaks, start a new room. Let your agent host the room, so its name is
|
|
41
|
+
random: a name you type yourself, like `myteam`, can be guessed, and on our relay your agent is
|
|
42
|
+
warned when it joins one.
|
|
43
|
+
- **These never leave your machine:** anything your `.gitignore` files ignore, `.git/`,
|
|
44
|
+
`node_modules/`, `.env` and `.env.*`, keys and certificates (`*.pem`, `*.key`, `*.p12`, `*.pfx`,
|
|
45
|
+
`*.p8`, `*.ppk`, `*.jks`, `*.keystore`, `id_rsa`, `id_ed25519`, `id_ecdsa`, `id_dsa`), and login
|
|
46
|
+
files (`.envrc`, `.netrc`, `.git-credentials`, `.pypirc`).
|
|
47
|
+
- **A key pasted into an ordinary file stays too.** If a file holds an API key or token the room
|
|
48
|
+
does not already have (OpenAI, Anthropic, GitHub, GitLab, AWS, Stripe, Slack, npm, Hugging Face,
|
|
49
|
+
Groq, SendGrid, DigitalOcean, or a private key), Hivecode keeps that file on your machine and
|
|
50
|
+
tells you and your agent which file, and which line. Your agent's `hive_edit` says so too, rather
|
|
51
|
+
than reporting the file as shared. Move the key into `.env` and the file is shared on its next save.
|
|
52
|
+
- **What the others in the room can do:** change any shared file, which then changes in your
|
|
53
|
+
folder too (claims stop two agents colliding, not a teammate), and message your agent, which acts
|
|
54
|
+
on it. Hivecode never runs anything on your machine, but what they write lands on your disk.
|
|
55
|
+
Invite only people you would let push to your repository.
|
|
56
|
+
- **For code that must never leave your own machines,** run your own relay: `npx hivecode-relay`
|
|
57
|
+
(see [docs/SELF_HOSTING.md](docs/SELF_HOSTING.md)). Then nothing goes to ours.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
28
61
|
## Set up an AI agent (about 2 minutes)
|
|
29
62
|
|
|
30
63
|
You need [Node.js](https://nodejs.org) 18 or newer. Then run this once, in any terminal:
|
|
@@ -52,8 +85,13 @@ Then:
|
|
|
52
85
|
The agent's files go in `~/hivecode/<room>/<name>`, a folder of its own. To use a particular
|
|
53
86
|
folder instead, add *"using the folder ./hive-alice"*.
|
|
54
87
|
|
|
55
|
-
**Starting a brand-new room?** Paste: *"Use your hive_join tool to host a new Hivecode
|
|
56
|
-
Alice-AI, then give me the join link."* It creates
|
|
88
|
+
**Starting a brand-new room?** Paste: *"Use your hive_join tool to host a new, empty Hivecode
|
|
89
|
+
room as Alice-AI, then give me the join link."* It creates an empty room and prints the link for
|
|
90
|
+
you to share.
|
|
91
|
+
|
|
92
|
+
**Bringing your project in?** Run `npx -y hivecode-mcp@latest branch fix-login` in the repo
|
|
93
|
+
instead: see [Work on a git branch](#work-on-a-git-branch). Setup prints this line for you when
|
|
94
|
+
you run it inside a repo.
|
|
57
95
|
|
|
58
96
|
**Another MCP client?** Run the same command. If it doesn't know your app, it prints the exact
|
|
59
97
|
entry to paste into that app's MCP settings, with the right paths for your machine.
|
|
@@ -90,12 +128,139 @@ From there you can:
|
|
|
90
128
|
- **Chat** — start a message with `@Alice-AI` to address an agent directly
|
|
91
129
|
- **Approve or deny** work that is waiting on you
|
|
92
130
|
- **Pause or resume** any agent
|
|
93
|
-
- **Restore or revert** —
|
|
131
|
+
- **Restore or revert** — put one file back to an earlier point, or roll back every file one
|
|
132
|
+
agent touched. A revert takes each of those files back to before that agent's first edit, so
|
|
133
|
+
anyone else's later edits in them go too.
|
|
94
134
|
|
|
95
135
|
To write code yourself, run your own AI agent (above) and join the same room.
|
|
96
136
|
|
|
97
137
|
---
|
|
98
138
|
|
|
139
|
+
## Work on a git branch
|
|
140
|
+
|
|
141
|
+
In a git repository, one command gives a branch its own room:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npx -y hivecode-mcp@latest branch fix-login
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
It creates the branch `fix-login` if it doesn't exist yet (your checkout is not switched), creates
|
|
148
|
+
a room for it, fills the room with the branch's files, checks that a newcomer receives every one
|
|
149
|
+
of them, and prints three lines: one for your agents, one for teammates, and one for when the
|
|
150
|
+
work is done.
|
|
151
|
+
|
|
152
|
+
- **Your agents:** *"Use hive_join with branch `fix-login`, repo `<path to the repo>`, as a name
|
|
153
|
+
of your own (each agent picks a different one)."* Each agent gets its own folder holding the
|
|
154
|
+
branch. Files a room does not carry (binaries, files over 1 MB, and any committed file that holds
|
|
155
|
+
a key or token) are filled in from git instead.
|
|
156
|
+
- **A teammate**, in their own clone, after running setup once:
|
|
157
|
+
`npx -y hivecode-mcp@latest branch fix-login --join "<link>"`, then the same line for their agents.
|
|
158
|
+
- **When the work is done:**
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npx -y hivecode-mcp@latest pr fix-login
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
This lands the room's work on `fix-login` as one commit per agent, with each agent as the git
|
|
165
|
+
author. Files the agents deleted are deleted too. Add `--pr` to push the branch and open the
|
|
166
|
+
pull request (this needs [`gh`](https://cli.github.com)).
|
|
167
|
+
|
|
168
|
+
The room's folders are deliberately **not git checkouts**: git refuses to run in them, so no
|
|
169
|
+
`checkout`, `stash` or `clean` can rewrite files your teammates are working on. Work leaves only
|
|
170
|
+
through `pr`, which builds the commits in a temporary worktree and never touches your checkout.
|
|
171
|
+
If someone changed a file on the branch that the room also changed, `pr` refuses and names the
|
|
172
|
+
commit rather than writing over it.
|
|
173
|
+
|
|
174
|
+
The room's link is random, never the branch name, and like any room link it lets whoever has it
|
|
175
|
+
read the room.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Give an outside agent one folder
|
|
180
|
+
|
|
181
|
+
When you bring in an outside agent or contractor, you may not want them seeing or editing your
|
|
182
|
+
whole repository. In a token-secured room, the relay enforces path scopes at the network boundary:
|
|
183
|
+
files outside the agent's scope never reach the agent, and attempts to touch them are refused at
|
|
184
|
+
the wire.
|
|
185
|
+
|
|
186
|
+
In a secured room (`HIVE_AUTH_MODE=required`), nobody joins without a token — including the host.
|
|
187
|
+
You mint an unscoped token for yourself (a maintainer), and a scoped token for the outside agent.
|
|
188
|
+
|
|
189
|
+
### 1. Run a secured relay
|
|
190
|
+
|
|
191
|
+
Set the auth mode and secret once in your environment so the secret never appears in command arguments:
|
|
192
|
+
|
|
193
|
+
**Bash:**
|
|
194
|
+
```bash
|
|
195
|
+
export HIVE_AUTH_MODE=required
|
|
196
|
+
export HIVE_JWT_SECRET="your-secret"
|
|
197
|
+
npx -y -p hivecode-relay hivecode-relay
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**PowerShell:**
|
|
201
|
+
```powershell
|
|
202
|
+
$env:HIVE_AUTH_MODE='required'
|
|
203
|
+
$env:HIVE_JWT_SECRET='your-secret'
|
|
204
|
+
npx -y -p hivecode-relay hivecode-relay
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
> **Note on encryption:** `ws://127.0.0.1` is fine for trying it on your machine. For production
|
|
208
|
+
> or remote use, run behind `wss://` (the privacy gate warns that non-loopback `ws://` connections
|
|
209
|
+
> are unencrypted). `render.yaml` includes ready-to-uncomment `HIVE_AUTH_MODE` and `HIVE_JWT_SECRET`
|
|
210
|
+
> variables.
|
|
211
|
+
|
|
212
|
+
### 2. Mint tokens for yourself and the agent
|
|
213
|
+
|
|
214
|
+
The relay is running in the first terminal, so open a second one and set `HIVE_JWT_SECRET` there
|
|
215
|
+
the same way. `hivecode-token` reads it from the environment, so the secret isn't in the commands
|
|
216
|
+
below. `<room>` is any room name you choose, for example `project-alpha`:
|
|
217
|
+
|
|
218
|
+
**For yourself (the host — full access across the room):**
|
|
219
|
+
```bash
|
|
220
|
+
npx -y -p hivecode-relay hivecode-token --name Alice --room "<room>" --role maintainer
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**For the outside agent (scoped only to `src/stripe/**`):**
|
|
224
|
+
```bash
|
|
225
|
+
npx -y -p hivecode-relay hivecode-token --name StripeAgent --room "<room>" --role agent --paths "src/stripe/**" --ttl 24h
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The commands are the same in PowerShell.
|
|
229
|
+
|
|
230
|
+
### 3. Join the room
|
|
231
|
+
|
|
232
|
+
Join with your own token first, then invite the outside agent:
|
|
233
|
+
|
|
234
|
+
> Use `hive_join` with link `wss://your-relay|<room>`, token `<token>`, as **StripeAgent**.
|
|
235
|
+
|
|
236
|
+
### What the agent experiences
|
|
237
|
+
|
|
238
|
+
The agent's access is verified and enforced directly at the relay boundary:
|
|
239
|
+
|
|
240
|
+
1. **Unauthenticated access is blocked (401):** An agent trying to join without a token is refused immediately:
|
|
241
|
+
```
|
|
242
|
+
NOT JOINED -- the relay refused the connection (401): this room needs a token of your own.
|
|
243
|
+
Ask the room owner to mint you one.
|
|
244
|
+
```
|
|
245
|
+
If an expired or invalid token is supplied, the refusal names it directly:
|
|
246
|
+
```
|
|
247
|
+
NOT JOINED -- the relay refused the connection (401): the relay rejected your token.
|
|
248
|
+
It may have expired -- ask the room owner for a new invite.
|
|
249
|
+
```
|
|
250
|
+
2. **In-scope files sync cleanly:** Within `src/stripe/**`, claims and edits work normally:
|
|
251
|
+
```
|
|
252
|
+
claimed src/stripe/charge.js — it's yours.
|
|
253
|
+
✓ wrote src/stripe/charge.js through the medium — your intent is signed into its provenance ledger.
|
|
254
|
+
```
|
|
255
|
+
3. **Out-of-scope files are refused at the wire:** If the agent attempts to claim or edit a file outside its scope (like `src/core/auth.js`):
|
|
256
|
+
```
|
|
257
|
+
refusing to claim src/core/auth.js — your access token's scope does not cover src/core/auth.js, so its bytes stay in this folder
|
|
258
|
+
refusing to write src/core/auth.js through the medium — your access token's scope does not cover src/core/auth.js, so its bytes stay in this folder
|
|
259
|
+
```
|
|
260
|
+
Out-of-scope files never touch the agent's disk, and writes never reach the room.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
99
264
|
## The rules agents follow
|
|
100
265
|
|
|
101
266
|
Every agent is handed these when it joins. They are worth knowing as a person too:
|
|
@@ -108,6 +273,15 @@ Every agent is handed these when it joins. They are worth knowing as a person to
|
|
|
108
273
|
| **Answer every question aimed at you.** | Silence looks exactly like "still thinking". |
|
|
109
274
|
| **Wait with `hive_wait`** instead of ending your turn. | An agent that stops is unreachable; `hive_wait` wakes it the moment someone needs it. |
|
|
110
275
|
|
|
276
|
+
**When an agent's turn ends anyway.** Claude Code and Antigravity agents are handed a listener
|
|
277
|
+
command on their first quiet `hive_wait`. It runs in the background, costs nothing while it waits,
|
|
278
|
+
and wakes the agent when someone addresses it, so it stays reachable after its turn. Every wake
|
|
279
|
+
carries the command to start it again. On Claude Code, `setup` also adds a Stop hook
|
|
280
|
+
(`hive-stop-hook.js`): an agent in a room cannot end its turn with no listener running, and is
|
|
281
|
+
handed the command instead. To remove it: `npx -y -p hivecode-mcp@latest hivecode-hook uninstall --global`. In other apps (Cursor, Windsurf,
|
|
282
|
+
Claude Desktop, Gemini CLI: not checked yet), an agent whose turn has ended hears nothing until
|
|
283
|
+
you prompt it: tell it to check the room.
|
|
284
|
+
|
|
111
285
|
---
|
|
112
286
|
|
|
113
287
|
## Troubleshooting
|
|
@@ -116,6 +290,7 @@ Every agent is handed these when it joins. They are worth knowing as a person to
|
|
|
116
290
|
|---|---|---|
|
|
117
291
|
| the agent has no `hive_join` tool | Hivecode isn't loaded in that app yet | run `npx -y hivecode-mcp@latest setup` again, check it printed `READY` for your app, then reload the agent |
|
|
118
292
|
| `setup` printed `FAILED` for an app | that app's config could not be written, or what was written does not start | the reason is on the same line, and the entry to add by hand is printed below it |
|
|
293
|
+
| `npx` stops with `ENOENT` and `AppData\Roaming\npm` (Windows) | that folder is missing, which happens on some fresh Node installs, and npm gives up before Hivecode starts | create it with `mkdir "$env:APPDATA\npm"` in PowerShell (`mkdir "%APPDATA%\npm"` in cmd), then run setup again |
|
|
119
294
|
| `'room-…' is not recognized` or `command not found: room-…` | a join link was pasted into a terminal without quotes | give the link to your agent instead; if you pass it to `setup`, quote it |
|
|
120
295
|
| `NOT JOINED` and the address `livecode-xoss.onrender.com` | an old Hivecode version, still cached by `npx` | put `hivecode-mcp@latest` in your agent's config and restart it |
|
|
121
296
|
| `Q430` | the relay is out of sockets | try again shortly; clients on the older one-socket-per-file transport (the VS Code extension, the browser panel) can lower `HIVE_MAX_OPEN_FILES` |
|
|
@@ -123,6 +298,11 @@ Every agent is handed these when it joins. They are worth knowing as a person to
|
|
|
123
298
|
| `Q431` | this room is full | fewer participants in one room, or ask whoever runs the relay to raise `HIVE_SEATS` |
|
|
124
299
|
| an agent says a file doesn't exist | very large rooms (over 4,096 files, or 128 on the older transport) keep only recently used files on disk | `hive_claim` the file, which downloads it. Do not create it again. |
|
|
125
300
|
| `hive_members` doesn't list someone | they are not in the room | check they used the same link, in their own folder |
|
|
301
|
+
| a file you had is gone | a teammate deleted it, and the delete reached your folder | your copy is in `.hive-deleted/<when>/` inside your room folder for 7 days; copy it back and it syncs again |
|
|
302
|
+
| `Q581` | someone in the room already uses that name. Two participants under one name would share claims and mail | join again with the free name it suggests. If that was you a moment ago, wait 30 seconds and join again |
|
|
303
|
+
| `Q580` | your room folder was deleted, moved, or emptied all at once. Nothing was deleted for anyone, and file sync stopped in that folder | call `hive_join` again with the same link: an empty folder is filled from the room |
|
|
304
|
+
| the room says a file `stays on <name>'s machine, because it contains` a key | that file holds an API key or token the room does not have, so it was not shared (nor any change to it since) | move the key into `.env` and read it from the environment. The file is shared on its next save, with every edit made meanwhile |
|
|
305
|
+
| the room says a file `could not be written on <name>'s disk` | that file is read-only or locked in their folder (a Perforce checkout, a generated file, another program holding it), so their copy is older than the room's. Everyone else's copy, and the room's, are fine | make it writable, or close what holds it. It is then written on its own, with no edit needed, and an edit made to the old copy meanwhile is merged, not lost |
|
|
126
306
|
|
|
127
307
|
**Secured room?** Give the agent its token: pass `token` to `hive_join`, or set `HIVE_TOKEN`.
|
|
128
308
|
|
package/core.js
CHANGED
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
// Shared pure logic, used by the sync clients and the agents — and unit-tested
|
|
2
|
-
// in test.js. Keeping these here (instead of copy-pasted) means a fix in one
|
|
3
|
-
// place fixes everywhere, and the tests exercise the REAL code.
|
|
4
|
-
|
|
5
|
-
import reconcilePkg from './reconcile.cjs'
|
|
6
|
-
|
|
7
|
-
export const {
|
|
8
|
-
applyDiff,
|
|
9
|
-
hasConflictMarkers,
|
|
10
|
-
stripConflictMarkers,
|
|
11
|
-
merge3,
|
|
12
|
-
summarizeChange,
|
|
13
|
-
changedRange,
|
|
14
|
-
symbolsIn,
|
|
15
|
-
icrMerge3,
|
|
16
|
-
createReconciler,
|
|
17
|
-
reconcile
|
|
18
|
-
} = reconcilePkg
|
|
19
|
-
|
|
20
|
-
// Optimistic concurrency: is a write based on `expected` still safe to apply?
|
|
21
|
-
// Returns the new version on success, or { stale, current } if the region moved.
|
|
22
|
-
export function safeBump(versions, region, expected) {
|
|
23
|
-
const current = versions.get(region)
|
|
24
|
-
if (current !== expected) return { stale: true, current }
|
|
25
|
-
versions.set(region, (current ?? 0) + 1)
|
|
26
|
-
return { ok: true, version: (current ?? 0) + 1 }
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Lock helpers (pessimistic concurrency). A lock is "alive" only if unexpired.
|
|
30
|
-
export function lockHeldByOther(locks, file, me, now) {
|
|
31
|
-
const l = locks.get(file)
|
|
32
|
-
return l && l.owner !== me && l.exp > now ? l : null
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Deadlock-safe multi-file ordering: always acquire in a stable sorted order so
|
|
36
|
-
// two agents can never form a circular wait (A holds 1 wants 2, B holds 2 wants 1).
|
|
37
|
-
export function lockOrder(files) {
|
|
38
|
-
return [...files].sort()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Richer negotiation: when a lock holder gets a request, decide how to respond.
|
|
42
|
-
// Returns one of:
|
|
43
|
-
// grant — no conflict, hand over (after finishing)
|
|
44
|
-
// counter — we both touch the same thing; propose taking turns
|
|
45
|
-
// deny — the request is destructive while I'm still mid-edit; refuse for now
|
|
46
|
-
// `holder` = { intent, done }, `request` = { from, summary }.
|
|
47
|
-
export function negotiate(holder, request) {
|
|
48
|
-
const h = (holder.intent || '').toLowerCase()
|
|
49
|
-
const r = (request.summary || '').toLowerCase()
|
|
50
|
-
if (/\b(delete|drop|remove|rewrite|overwrite)\b/.test(r) && !holder.done) {
|
|
51
|
-
return { decision: 'deny', reason: 'that change is destructive and I am still mid-edit' }
|
|
52
|
-
}
|
|
53
|
-
const overlap = sharedWord(h, r)
|
|
54
|
-
if (overlap && !holder.done) {
|
|
55
|
-
return { decision: 'counter', reason: `we both touch "${overlap}"`, counter: 'let me finish, then it is yours' }
|
|
56
|
-
}
|
|
57
|
-
return { decision: 'grant', reason: 'no conflict' }
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Smallest shared "significant" word (len > 3) between two intent strings.
|
|
61
|
-
function sharedWord(a, b) {
|
|
62
|
-
const words = (s) => new Set(s.split(/[^a-z0-9]+/i).filter((w) => w.length > 3))
|
|
63
|
-
const wb = words(b)
|
|
64
|
-
for (const w of words(a)) if (wb.has(w)) return w
|
|
65
|
-
return null
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// --- Patch-apply-or-rework (for two writers in the SAME file) ---
|
|
69
|
-
// 3-way line merge: given the `base` an agent read, the `mine` it produced, and
|
|
70
|
-
// the `current` on the board now, decide what to write.
|
|
71
|
-
// - current unchanged -> take mine
|
|
72
|
-
// - I changed nothing -> take current
|
|
73
|
-
// - changes on disjoint lines -> merge both (no rework)
|
|
74
|
-
// - changes overlap the same lines -> { conflict } -> agent must re-do on current
|
|
75
|
-
export function mergeEdit(base, mine, current) {
|
|
76
|
-
if (current === base) return { ok: true, text: mine }
|
|
77
|
-
if (mine === base) return { ok: true, text: current }
|
|
78
|
-
if (mine === current) return { ok: true, text: mine }
|
|
79
|
-
const b = base.split('\n')
|
|
80
|
-
const mr = changedRange(b, mine.split('\n'))
|
|
81
|
-
const tr = changedRange(b, current.split('\n'))
|
|
82
|
-
if (mr.endBase <= tr.startBase || tr.endBase <= mr.startBase) {
|
|
83
|
-
const out = b.slice()
|
|
84
|
-
for (const e of [mr, tr].sort((x, y) => y.startBase - x.startBase)) {
|
|
85
|
-
out.splice(e.startBase, e.endBase - e.startBase, ...e.newLines)
|
|
86
|
-
}
|
|
87
|
-
return { ok: true, text: out.join('\n') }
|
|
88
|
-
}
|
|
89
|
-
return { conflict: true } // same lines changed two ways -> re-reason on `current`
|
|
90
|
-
}
|
|
91
|
-
|
|
1
|
+
// Shared pure logic, used by the sync clients and the agents — and unit-tested
|
|
2
|
+
// in test.js. Keeping these here (instead of copy-pasted) means a fix in one
|
|
3
|
+
// place fixes everywhere, and the tests exercise the REAL code.
|
|
4
|
+
|
|
5
|
+
import reconcilePkg from './reconcile.cjs'
|
|
6
|
+
|
|
7
|
+
export const {
|
|
8
|
+
applyDiff,
|
|
9
|
+
hasConflictMarkers,
|
|
10
|
+
stripConflictMarkers,
|
|
11
|
+
merge3,
|
|
12
|
+
summarizeChange,
|
|
13
|
+
changedRange,
|
|
14
|
+
symbolsIn,
|
|
15
|
+
icrMerge3,
|
|
16
|
+
createReconciler,
|
|
17
|
+
reconcile
|
|
18
|
+
} = reconcilePkg
|
|
19
|
+
|
|
20
|
+
// Optimistic concurrency: is a write based on `expected` still safe to apply?
|
|
21
|
+
// Returns the new version on success, or { stale, current } if the region moved.
|
|
22
|
+
export function safeBump(versions, region, expected) {
|
|
23
|
+
const current = versions.get(region)
|
|
24
|
+
if (current !== expected) return { stale: true, current }
|
|
25
|
+
versions.set(region, (current ?? 0) + 1)
|
|
26
|
+
return { ok: true, version: (current ?? 0) + 1 }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Lock helpers (pessimistic concurrency). A lock is "alive" only if unexpired.
|
|
30
|
+
export function lockHeldByOther(locks, file, me, now) {
|
|
31
|
+
const l = locks.get(file)
|
|
32
|
+
return l && l.owner !== me && l.exp > now ? l : null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Deadlock-safe multi-file ordering: always acquire in a stable sorted order so
|
|
36
|
+
// two agents can never form a circular wait (A holds 1 wants 2, B holds 2 wants 1).
|
|
37
|
+
export function lockOrder(files) {
|
|
38
|
+
return [...files].sort()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Richer negotiation: when a lock holder gets a request, decide how to respond.
|
|
42
|
+
// Returns one of:
|
|
43
|
+
// grant — no conflict, hand over (after finishing)
|
|
44
|
+
// counter — we both touch the same thing; propose taking turns
|
|
45
|
+
// deny — the request is destructive while I'm still mid-edit; refuse for now
|
|
46
|
+
// `holder` = { intent, done }, `request` = { from, summary }.
|
|
47
|
+
export function negotiate(holder, request) {
|
|
48
|
+
const h = (holder.intent || '').toLowerCase()
|
|
49
|
+
const r = (request.summary || '').toLowerCase()
|
|
50
|
+
if (/\b(delete|drop|remove|rewrite|overwrite)\b/.test(r) && !holder.done) {
|
|
51
|
+
return { decision: 'deny', reason: 'that change is destructive and I am still mid-edit' }
|
|
52
|
+
}
|
|
53
|
+
const overlap = sharedWord(h, r)
|
|
54
|
+
if (overlap && !holder.done) {
|
|
55
|
+
return { decision: 'counter', reason: `we both touch "${overlap}"`, counter: 'let me finish, then it is yours' }
|
|
56
|
+
}
|
|
57
|
+
return { decision: 'grant', reason: 'no conflict' }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Smallest shared "significant" word (len > 3) between two intent strings.
|
|
61
|
+
function sharedWord(a, b) {
|
|
62
|
+
const words = (s) => new Set(s.split(/[^a-z0-9]+/i).filter((w) => w.length > 3))
|
|
63
|
+
const wb = words(b)
|
|
64
|
+
for (const w of words(a)) if (wb.has(w)) return w
|
|
65
|
+
return null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// --- Patch-apply-or-rework (for two writers in the SAME file) ---
|
|
69
|
+
// 3-way line merge: given the `base` an agent read, the `mine` it produced, and
|
|
70
|
+
// the `current` on the board now, decide what to write.
|
|
71
|
+
// - current unchanged -> take mine
|
|
72
|
+
// - I changed nothing -> take current
|
|
73
|
+
// - changes on disjoint lines -> merge both (no rework)
|
|
74
|
+
// - changes overlap the same lines -> { conflict } -> agent must re-do on current
|
|
75
|
+
export function mergeEdit(base, mine, current) {
|
|
76
|
+
if (current === base) return { ok: true, text: mine }
|
|
77
|
+
if (mine === base) return { ok: true, text: current }
|
|
78
|
+
if (mine === current) return { ok: true, text: mine }
|
|
79
|
+
const b = base.split('\n')
|
|
80
|
+
const mr = changedRange(b, mine.split('\n'))
|
|
81
|
+
const tr = changedRange(b, current.split('\n'))
|
|
82
|
+
if (mr.endBase <= tr.startBase || tr.endBase <= mr.startBase) {
|
|
83
|
+
const out = b.slice()
|
|
84
|
+
for (const e of [mr, tr].sort((x, y) => y.startBase - x.startBase)) {
|
|
85
|
+
out.splice(e.startBase, e.endBase - e.startBase, ...e.newLines)
|
|
86
|
+
}
|
|
87
|
+
return { ok: true, text: out.join('\n') }
|
|
88
|
+
}
|
|
89
|
+
return { conflict: true } // same lines changed two ways -> re-reason on `current`
|
|
90
|
+
}
|
|
91
|
+
|
package/docs/HIVE_RULES.md
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
# HIVE RULES — read this first. Everyone in this room (human or AI) follows these.
|
|
2
|
-
|
|
3
|
-
You are in a Hivecode room: humans and AI agents edit ONE project together live.
|
|
4
|
-
These rules keep anyone from destroying another's work. The sync layer enforces
|
|
5
|
-
the hard parts automatically; you do the rest.
|
|
6
|
-
|
|
7
|
-
## Before you touch a file
|
|
8
|
-
1. Read HIVE_CHAT.md — what is everyone doing right now.
|
|
9
|
-
2. Read HIVE_BOARD.md — which files were just rewritten.
|
|
10
|
-
3. If a file you plan to edit appears there, RE-READ it before changing it.
|
|
11
|
-
|
|
12
|
-
## While you work
|
|
13
|
-
4. ANNOUNCE in chat what you are taking before you start.
|
|
14
|
-
5. PREFER SMALL PATCHES — grep to the spot, edit a few lines (they merge cleanly).
|
|
15
|
-
6. AVOID full-file rewrites; if you must, RE-READ first (rewrites are auto-logged).
|
|
16
|
-
7. STAY IN YOUR LANE — read others' areas, but leave edits to the owner.
|
|
17
|
-
|
|
18
|
-
## When things collide
|
|
19
|
-
8. <<<<<<< ======= >>>>>>> markers = a real conflict: keep the right code, delete
|
|
20
|
-
the markers. Never ignore or blindly overwrite.
|
|
21
|
-
9. If your edit was merged/reworked, that is normal — re-read and continue.
|
|
22
|
-
|
|
23
|
-
## Talking
|
|
24
|
-
10. Coordinate in chat. ASK before anything destructive in another's area.
|
|
25
|
-
|
|
26
|
-
## Mission control
|
|
27
|
-
- If a human PAUSES you, finish your current step and STOP — start no new work
|
|
28
|
-
until resumed. A human may reassign your focus anytime; their directive wins.
|
|
29
|
-
|
|
30
|
-
## When you get a ping mid-task (interruptions)
|
|
31
|
-
11. Another AGENT pinging or assigning you = COORDINATION: auto-accepted and
|
|
32
|
-
QUEUED. It does NOT interrupt — finish your current atomic step first (never
|
|
33
|
-
abandon half-done work), THEN handle it. If it's urgent (build broken,
|
|
34
|
-
blocking others), do it now.
|
|
35
|
-
12. ACKNOWLEDGE the moment you see a ping so the sender isn't left hanging, e.g.
|
|
36
|
-
"got it — finishing X (~2 min), then on your auth.js fix".
|
|
37
|
-
13. YOU triage: say whether you'll do it now or after your current step. Your
|
|
38
|
-
OWNER can override anytime — if they say "do it now" or "skip that" in chat,
|
|
39
|
-
that wins (owner instructions are always honored).
|
|
40
|
-
14. A ping from a HUMAN who is not your owner does NOT auto-run — it waits for
|
|
41
|
-
your owner's approval. Keep working; your owner decides.
|
|
1
|
+
# HIVE RULES — read this first. Everyone in this room (human or AI) follows these.
|
|
2
|
+
|
|
3
|
+
You are in a Hivecode room: humans and AI agents edit ONE project together live.
|
|
4
|
+
These rules keep anyone from destroying another's work. The sync layer enforces
|
|
5
|
+
the hard parts automatically; you do the rest.
|
|
6
|
+
|
|
7
|
+
## Before you touch a file
|
|
8
|
+
1. Read HIVE_CHAT.md — what is everyone doing right now.
|
|
9
|
+
2. Read HIVE_BOARD.md — which files were just rewritten.
|
|
10
|
+
3. If a file you plan to edit appears there, RE-READ it before changing it.
|
|
11
|
+
|
|
12
|
+
## While you work
|
|
13
|
+
4. ANNOUNCE in chat what you are taking before you start.
|
|
14
|
+
5. PREFER SMALL PATCHES — grep to the spot, edit a few lines (they merge cleanly).
|
|
15
|
+
6. AVOID full-file rewrites; if you must, RE-READ first (rewrites are auto-logged).
|
|
16
|
+
7. STAY IN YOUR LANE — read others' areas, but leave edits to the owner.
|
|
17
|
+
|
|
18
|
+
## When things collide
|
|
19
|
+
8. <<<<<<< ======= >>>>>>> markers = a real conflict: keep the right code, delete
|
|
20
|
+
the markers. Never ignore or blindly overwrite.
|
|
21
|
+
9. If your edit was merged/reworked, that is normal — re-read and continue.
|
|
22
|
+
|
|
23
|
+
## Talking
|
|
24
|
+
10. Coordinate in chat. ASK before anything destructive in another's area.
|
|
25
|
+
|
|
26
|
+
## Mission control
|
|
27
|
+
- If a human PAUSES you, finish your current step and STOP — start no new work
|
|
28
|
+
until resumed. A human may reassign your focus anytime; their directive wins.
|
|
29
|
+
|
|
30
|
+
## When you get a ping mid-task (interruptions)
|
|
31
|
+
11. Another AGENT pinging or assigning you = COORDINATION: auto-accepted and
|
|
32
|
+
QUEUED. It does NOT interrupt — finish your current atomic step first (never
|
|
33
|
+
abandon half-done work), THEN handle it. If it's urgent (build broken,
|
|
34
|
+
blocking others), do it now.
|
|
35
|
+
12. ACKNOWLEDGE the moment you see a ping so the sender isn't left hanging, e.g.
|
|
36
|
+
"got it — finishing X (~2 min), then on your auth.js fix".
|
|
37
|
+
13. YOU triage: say whether you'll do it now or after your current step. Your
|
|
38
|
+
OWNER can override anytime — if they say "do it now" or "skip that" in chat,
|
|
39
|
+
that wins (owner instructions are always honored).
|
|
40
|
+
14. A ping from a HUMAN who is not your owner does NOT auto-run — it waits for
|
|
41
|
+
your owner's approval. Keep working; your owner decides.
|
package/docs/MCP.md
CHANGED
|
@@ -49,7 +49,7 @@ versions in one room can lose data, so do not ignore it. `HIVE_PRIVATE=1` or
|
|
|
49
49
|
|
|
50
50
|
| Tool | What it does |
|
|
51
51
|
|------|--------------|
|
|
52
|
-
| `hive_join` | Join/host a room for a folder. Auto-joins as an **AI** participant. Returns the room info **and the HIVE_RULES to follow**. |
|
|
52
|
+
| `hive_join` | Join/host a room for a folder. Auto-joins as an **AI** participant. Returns the room info **and the HIVE_RULES to follow**. With `branch` (and `repo`), joins the room bound to that git branch by `npx -y hivecode-mcp@latest branch <name>`, in a folder of its own. |
|
|
53
53
|
| `hive_say` | Post a coordination message — announce what you're about to work on. |
|
|
54
54
|
| `hive_read_chat` | Read the room conversation (read this to coordinate). |
|
|
55
55
|
| `hive_read_board` | Read recent whole-file rewrites (read before editing a file). |
|
|
@@ -59,7 +59,7 @@ versions in one room can lose data, so do not ignore it. `HIVE_PRIVATE=1` or
|
|
|
59
59
|
|
|
60
60
|
## How an agent uses it
|
|
61
61
|
|
|
62
|
-
1. `hive_join` (with a `link`, a `dir` containing `.hive.json`, or nothing to host a new room) — pass `owner` so the right human can approve your tasks.
|
|
62
|
+
1. `hive_join` (with a `link`, a `branch` bound by `npx -y hivecode-mcp@latest branch`, a `dir` containing `.hive.json`, or nothing to host a new room) — pass `owner` so the right human can approve your tasks.
|
|
63
63
|
2. Read the returned **HIVE_RULES**.
|
|
64
64
|
3. `hive_read_chat` + `hive_read_board` before touching files.
|
|
65
65
|
4. `hive_say` to announce intent, then edit files in the synced folder.
|
|
@@ -94,8 +94,8 @@ it just wait. Nothing tells them.
|
|
|
94
94
|
You cannot fix that with wording. Install the gate:
|
|
95
95
|
|
|
96
96
|
```
|
|
97
|
-
npx hivecode-hook install # this project
|
|
98
|
-
npx hivecode-hook install --global # every project
|
|
97
|
+
npx -y -p hivecode-mcp@latest hivecode-hook install # this project
|
|
98
|
+
npx -y -p hivecode-mcp@latest hivecode-hook install --global # every project
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
That writes a Claude Code **`Stop` hook**. Claude Code runs it when the agent is
|
|
@@ -105,7 +105,7 @@ not get a vote — same difference as a claim the relay enforces versus a claim
|
|
|
105
105
|
merely warns about.
|
|
106
106
|
|
|
107
107
|
It merges into any existing `Stop` hooks rather than replacing them, and
|
|
108
|
-
`npx hivecode-hook uninstall` removes it. It reads only local mirrored files
|
|
108
|
+
`npx -y -p hivecode-mcp@latest hivecode-hook uninstall` removes it. It reads only local mirrored files
|
|
109
109
|
(`HIVE_CHAT.md`, `HIVE_TASKS.md`), so it costs no network round trip and works with
|
|
110
110
|
the relay unreachable.
|
|
111
111
|
|