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 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
- **A live shared workspace for people and their AI agents.**
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, Cursor, Windsurf, Antigravity, or
6
- your own bot — work on one project at the same time. Every edit reaches everyone in about a
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 undo anything.
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 room as
56
- Alice-AI, then give me the join link."* It creates the room and prints the link for you to share.
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** — undo one file, or everything one agent did
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
+
@@ -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