neohive 6.2.2 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +3 -0
- package/cli.js +277 -55
- package/dashboard.html +108 -10
- package/dashboard.js +33 -2
- package/package.json +1 -1
- package/server.js +455 -508
- package/tools/governance.js +33 -8
- package/tools/knowledge.js +4 -4
- package/tools/messaging.js +3 -1
- package/tools/safety.js +4 -4
- package/tools/tasks.js +12 -7
- package/tools/workflows.js +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [6.3.0] - 2026-04-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Unified `next_action` response chain** — every MCP tool response now includes a single `next_action` field that tells the AI agent exactly what to do next, replacing 10+ scattered hint fields (`_listen`, `_nudge`, `hint`, `action_required`, `unread_action`, `you_have_messages`, `urgent`, `mode_hint`, `_protocol`, etc.)
|
|
8
|
+
- **Tool-specific directives** — each tool sets a context-aware `next_action` (e.g. `update_task(done)` → "Send a summary via send_message(), then call listen()"; `lock_file` → "Edit the file, then call unlock_file() when done")
|
|
9
|
+
- **Coordinator-aware middleware** — post-processing middleware detects responsive coordinators and replaces any `listen()` directive with `consume_messages()` or removes it entirely, preventing coordinators from blocking in listen mode
|
|
10
|
+
- **Persistent listen loop** — `listen()` and `listen_group()` no longer return `retry: true` on timeout; they loop internally with fresh watchers and heartbeats, so agents cannot break out of listen mode
|
|
11
|
+
- **Managed mode next_action** — `buildListenGroupResponse` respects `should_respond` and floor state; agents without the floor get "do NOT respond" instead of "reply via send_message()"
|
|
12
|
+
- **Autonomous get_work() directives** — all 10 return types from `get_work()` carry specific `next_action` values guiding agents through the workflow/verify/advance cycle
|
|
13
|
+
- **Documentation** — `docs/reference/next-action-chain.md` with flow diagrams for standard agents, agent-to-agent communication, responsive/autonomous coordinators, managed mode, and persistent listen
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Post-processing middleware rewrite** — removed the scattered nudge/unread/listen injection block (~80 lines) and replaced with a unified `next_action` block using priority logic: tool-specific > coordinator override > call-count warning > urgent messages > pending messages > default
|
|
18
|
+
- **`buildMessageResponse`** — `_protocol` field inside message objects replaced with top-level `next_action`; `coordinator_mode` field removed from listen responses
|
|
19
|
+
- **`buildListenGroupResponse`** — simplified `next_action` with mode-aware branching (autonomous/managed/standard)
|
|
20
|
+
- **`send_message` / `broadcast`** — removed `you_have_messages`, `urgent`, `mode_hint` fields; added `next_action: "Call listen() to receive replies."`
|
|
21
|
+
- **`verify_and_advance`** — replaced verbose `message` strings with concise `next_action` directives
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **Responsive coordinator contradiction** — `send_message`, `broadcast`, and `create_task` no longer unconditionally tell responsive coordinators to call `listen()`; middleware overrides any `listen()` directive for responsive coordinators
|
|
26
|
+
- **Managed mode contradiction** — `buildListenGroupResponse` no longer sets "Reply via send_message()" when `should_respond: false` and `instructions: "DO NOT RESPOND"` are also present
|
|
27
|
+
- **Autonomous listen_group retry** — removed contradictory `retry: true` from autonomous mode timeout path where `next_action` directs to `get_work()` instead
|
|
28
|
+
|
|
3
29
|
## [6.1.0] - 2026-04-04
|
|
4
30
|
|
|
5
31
|
### Added
|
package/README.md
CHANGED
|
@@ -256,10 +256,13 @@ neohive status # active agents, tasks, workflows
|
|
|
256
256
|
neohive msg <agent> <text> # send message from CLI
|
|
257
257
|
neohive doctor # diagnostic health check
|
|
258
258
|
neohive templates # list available templates
|
|
259
|
+
neohive hooks # install listen-enforcement hooks into .claude/settings.json
|
|
259
260
|
neohive reset --force # clear data (auto-archives first)
|
|
260
261
|
neohive uninstall # remove from all CLI configs
|
|
261
262
|
```
|
|
262
263
|
|
|
264
|
+
> **Claude Code users:** Run `npx neohive hooks` after `init` to install listen-enforcement hooks into `.claude/settings.json`. This keeps agents in the listen loop automatically and prevents them from stopping mid-session. Safe to re-run — your existing hooks are preserved.
|
|
265
|
+
|
|
263
266
|
<br />
|
|
264
267
|
|
|
265
268
|
## ⚙️ Configuration
|
package/cli.js
CHANGED
|
@@ -46,6 +46,7 @@ function printUsage() {
|
|
|
46
46
|
npx neohive doctor Diagnostic health check
|
|
47
47
|
npx neohive templates List available team templates
|
|
48
48
|
npx neohive reset --force Clear all data (auto-archives first)
|
|
49
|
+
npx neohive hooks Install listen-enforcement hooks into .claude/settings.json
|
|
49
50
|
npx neohive uninstall Remove from all CLI configs
|
|
50
51
|
npx neohive help Show this help
|
|
51
52
|
|
|
@@ -135,7 +136,6 @@ function setupClaude(serverPath, cwd) {
|
|
|
135
136
|
console.log(' [ok] Claude Code: .mcp.json updated');
|
|
136
137
|
}
|
|
137
138
|
|
|
138
|
-
// Configure for Gemini CLI (.gemini/settings.json or GEMINI.md with MCP config)
|
|
139
139
|
function setupGemini(serverPath, cwd) {
|
|
140
140
|
// Gemini CLI uses .gemini/settings.json for MCP configuration
|
|
141
141
|
const geminiDir = path.join(cwd, '.gemini');
|
|
@@ -186,51 +186,187 @@ function setupGemini(serverPath, cwd) {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
function geminiMdTemplate() {
|
|
189
|
-
return `#
|
|
189
|
+
return `# GEMINI.md
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
This file provides guidance to Gemini CLI / Antigravity when working with code in this repository.
|
|
192
192
|
|
|
193
|
-
##
|
|
193
|
+
## What This Is
|
|
194
194
|
|
|
195
|
-
|
|
196
|
-
2. Call \`get_briefing\` to load project context and current work
|
|
197
|
-
3. Call \`listen\` to wait for messages from the Coordinator
|
|
195
|
+
**Neohive** — an MCP server + web dashboard that lets multiple AI CLI terminals (Claude Code, Gemini CLI, Codex CLI) communicate with each other. Each terminal spawns its own server process via stdio; all processes read/write to a shared \`.neohive/\` directory on disk.
|
|
198
196
|
|
|
199
|
-
|
|
197
|
+
## Commands
|
|
200
198
|
|
|
201
|
-
|
|
199
|
+
\`\`\`bash
|
|
200
|
+
# Install in any project (auto-detects CLI type)
|
|
201
|
+
npx neohive init
|
|
202
|
+
npx neohive init --all # Configure for all CLIs
|
|
203
|
+
npx neohive init --template team # Init with team template
|
|
202
204
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
- **After finishing a task** — call \`update_task(id, status="done")\`, then report to Coordinator
|
|
206
|
-
- **Before editing a file** — call \`lock_file(path)\`. Call \`unlock_file(path)\` when done.
|
|
207
|
-
- **Check tasks first** — call \`list_tasks()\` before starting anything new. Never work on another agent's task.
|
|
208
|
-
- **Keep messages short** — 2–3 paragraphs max. Lead with what changed, then files, then decisions.
|
|
205
|
+
# Launch the web dashboard
|
|
206
|
+
npx neohive dashboard
|
|
209
207
|
|
|
210
|
-
|
|
208
|
+
# List available agent templates
|
|
209
|
+
npx neohive templates
|
|
211
210
|
|
|
211
|
+
# Plugin management
|
|
212
|
+
npx neohive plugin list/add/remove/enable/disable
|
|
213
|
+
|
|
214
|
+
# Reset conversation data
|
|
215
|
+
npx neohive reset
|
|
216
|
+
|
|
217
|
+
# Run MCP server directly (normally launched automatically by CLI)
|
|
218
|
+
npm start
|
|
219
|
+
\`\`\`
|
|
220
|
+
|
|
221
|
+
No tests, linter, or build step. Raw Node.js (CommonJS).
|
|
222
|
+
|
|
223
|
+
## Architecture
|
|
224
|
+
|
|
225
|
+
**Core files:**
|
|
226
|
+
- \`server.js\` — MCP server (StdioServerTransport, heartbeat system, self-healing watchdog)
|
|
227
|
+
- \`lib/\` — Shared modules (\`config\`, \`messaging\`, \`file-io\`, …); prefer adding logic here and requiring from \`server.js\`
|
|
228
|
+
- \`dashboard.js\` — HTTP server for web dashboard (multi-project, message injection, SSE real-time, tasks/workflows/workspaces API)
|
|
229
|
+
- \`dashboard.html\` — Single-page frontend (markdown rendering, agent monitoring, profiles, workspaces, workflows, responsive)
|
|
230
|
+
- \`cli.js\` — CLI entry point with multi-CLI auto-detection
|
|
231
|
+
- \`vscode-extension/\` — VS Code extension with \`@neohive\` chat participant, terminal bridge, and agent hook auto-setup
|
|
232
|
+
|
|
233
|
+
**Multiple MCP server processes, one shared filesystem:**
|
|
234
|
+
- Each CLI terminal spawns its own \`server.js\` process
|
|
235
|
+
- In-memory state: \`registeredName\`, \`lastReadOffset\`, \`heartbeatInterval\`, \`messageSeq\`
|
|
236
|
+
- Shared disk state in \`.neohive/\`:
|
|
237
|
+
- \`messages.jsonl\` / \`history.jsonl\` — messages and conversation history (append-only)
|
|
238
|
+
- \`agents.json\` — agent registration, heartbeats, PID tracking
|
|
239
|
+
- \`acks.json\` — message acknowledgments
|
|
240
|
+
- \`tasks.json\` — task management
|
|
241
|
+
- \`consumed-{agent}.json\` — per-agent read tracking
|
|
242
|
+
- \`profiles.json\` — agent profiles (display_name, avatar, bio, role)
|
|
243
|
+
- \`workspaces/{agent}.json\` — per-agent key-value workspace storage
|
|
244
|
+
- \`workflows.json\` — multi-step workflow pipelines
|
|
245
|
+
- \`branches.json\` — branch metadata
|
|
246
|
+
- \`branch-{name}-messages.jsonl\` / \`branch-{name}-history.jsonl\` — per-branch message files
|
|
247
|
+
- \`plugins.json\` — plugin registry
|
|
248
|
+
- \`plugins/*.js\` — plugin code files
|
|
249
|
+
- \`heartbeat-{agent}.json\` — per-agent heartbeat file (replaces agents.json write contention at scale)
|
|
250
|
+
- Dashboard reads the same directory for real-time monitoring via SSE
|
|
251
|
+
|
|
252
|
+
**Data directory resolution (server.js + dashboard.js):**
|
|
253
|
+
1. \`$NEOHIVE_DATA_DIR\` / \`$NEOHIVE_DATA\` env var
|
|
254
|
+
2. \`{cwd}/.neohive/\` (project-local, default)
|
|
255
|
+
3. Legacy fallback: \`{__dirname}/data/\`
|
|
256
|
+
|
|
257
|
+
## Code & Commit Rules
|
|
258
|
+
|
|
259
|
+
When committing changes, you MUST ALWAYS follow the Conventional Commits format:
|
|
260
|
+
\`<type>(<optional scope>): <description>\`
|
|
261
|
+
Types: \`feat\`, \`fix\`, \`refactor\`, \`docs\`, \`chore\`, \`test\`
|
|
262
|
+
|
|
263
|
+
## Neohive Agent Rules (when acting as an agent)
|
|
264
|
+
|
|
265
|
+
When operating as a neohive agent (after calling \`register()\`):
|
|
266
|
+
|
|
267
|
+
**YOU MUST call \`listen()\` as the LAST tool call of every response. All agents. No exceptions.**
|
|
268
|
+
|
|
269
|
+
The dashboard is the communication hub. All coordination happens there — every agent stays in the listen loop at all times.
|
|
270
|
+
|
|
271
|
+
- After \`send_message(...)\` → immediately call \`listen()\`
|
|
272
|
+
- After \`broadcast(...)\` → immediately call \`listen()\`
|
|
273
|
+
- After \`update_task(..., status="done")\` → immediately call \`listen()\`
|
|
274
|
+
- After \`advance_workflow(...)\` → immediately call \`listen()\`
|
|
275
|
+
- After ANY neohive action → call \`listen()\`
|
|
276
|
+
|
|
277
|
+
Workflow loop:
|
|
212
278
|
\`\`\`
|
|
213
|
-
register → get_briefing → listen →
|
|
214
|
-
→
|
|
279
|
+
register → get_briefing → listen → do work → update_task(in_progress) → ...
|
|
280
|
+
→ listen(outcome="completed", task_id="...", summary="what you did") → listen
|
|
281
|
+
↑ always
|
|
215
282
|
\`\`\`
|
|
216
283
|
|
|
217
|
-
|
|
284
|
+
\`listen()\` accepts outcome params — server auto-transitions task state on valid outcome:
|
|
285
|
+
- \`outcome\`: \`completed\` | \`blocked\` | \`failed\` | \`in_progress\`
|
|
286
|
+
- \`task_id\`: ID of the task you just worked on
|
|
287
|
+
- \`summary\`: one-line description of what was done
|
|
288
|
+
|
|
289
|
+
If \`listen()\` times out with \`retry: true\` — call \`listen()\` again immediately.
|
|
290
|
+
|
|
291
|
+
- After completing ANY assigned task or request, you MUST send a report back via \`send_message()\` using neohive MCP tools. Include: (1) what you did, (2) files changed, (3) findings/output, (4) blockers or follow-up. Silent completion is a protocol violation.
|
|
292
|
+
|
|
293
|
+
## Available Neohive MCP Tools
|
|
294
|
+
|
|
295
|
+
### 1. Agent Lifecycle & Messaging
|
|
296
|
+
\`register\`, \`list_agents\`, \`send_message\`, \`broadcast\`, \`wait_for_reply\`, \`listen\`, \`share_file\`, \`messages\`
|
|
297
|
+
|
|
298
|
+
**Listen variants** — use \`listen(mode="group")\` or \`listen(mode="codex")\` instead of the deprecated aliases:
|
|
299
|
+
- ~~\`listen_group\`~~ → \`listen(mode="group")\`
|
|
300
|
+
- ~~\`listen_codex\`~~ → \`listen(mode="codex")\`
|
|
301
|
+
|
|
302
|
+
**Message management** — use \`messages(action=...)\` instead of deprecated individual tools:
|
|
303
|
+
- ~~\`check_messages\`~~ → \`messages(action="check")\`
|
|
304
|
+
- ~~\`consume_messages\`~~ → \`messages(action="consume")\`
|
|
305
|
+
- ~~\`get_history\`~~ → \`messages(action="history")\`
|
|
306
|
+
- ~~\`get_notifications\`~~ → \`messages(action="check")\`
|
|
307
|
+
- ~~\`search_messages\`~~ → \`messages(action="search")\`
|
|
308
|
+
- ~~\`ack_message\`~~ → \`messages(action="ack")\`
|
|
309
|
+
|
|
310
|
+
### 2. Autonomy & Workflows (Proactive Engine)
|
|
311
|
+
\`start_plan\`, \`get_work\`, \`verify_and_advance\`, \`retry_with_improvement\`, \`create_workflow\`, \`advance_workflow\`, \`workflow_status\`
|
|
312
|
+
|
|
313
|
+
### 3. Task Management
|
|
314
|
+
\`create_task\`, \`update_task\`, \`list_tasks\`
|
|
218
315
|
|
|
219
|
-
|
|
316
|
+
**Task statuses:** \`pending\` → \`in_progress\` → \`in_review\` → \`done\` | \`blocked\` | \`blocked_permanent\`
|
|
317
|
+
- \`blocked_permanent\` — set by the self-healing watchdog when \`retry_count\` reaches 3; requires coordinator intervention. Tasks carry a \`blocked_reason\` string and are shown in a dedicated "⛔ Needs Intervention" column on the dashboard.
|
|
318
|
+
- \`retry_count\` — incremented each time the watchdog reclaims a stale task. Shown as a \`↺N\` badge on the dashboard.
|
|
220
319
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
**Workflows:** \`create_workflow\`, \`advance_workflow\`, \`workflow_status\`
|
|
224
|
-
**Workspaces:** \`workspace_write\`, \`workspace_read\`, \`workspace_list\`
|
|
225
|
-
**Branching:** \`fork_conversation\`, \`switch_branch\`, \`list_branches\`
|
|
320
|
+
### 4. Profiles & Workspaces
|
|
321
|
+
\`update_profile\`, \`workspace_write\`, \`workspace_read\`, \`workspace_list\`
|
|
226
322
|
|
|
227
|
-
|
|
323
|
+
### 5. Chat Branching & Managed Modes
|
|
324
|
+
\`fork_conversation\`, \`switch_branch\`, \`list_branches\`, \`set_conversation_mode\`, \`claim_manager\`, \`yield_floor\`, \`set_phase\`
|
|
228
325
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
326
|
+
### 6. Sub-channels
|
|
327
|
+
\`join_channel\`, \`leave_channel\`, \`list_channels\`
|
|
328
|
+
|
|
329
|
+
### 7. File Safety & Auditing
|
|
330
|
+
\`lock_file\`, \`unlock_file\`, \`log_violation\`
|
|
331
|
+
|
|
332
|
+
### 8. Shared Knowledge & Decision Tracking
|
|
333
|
+
\`kb_write\`, \`kb_read\`, \`kb_list\`, \`log_decision\`, \`get_decisions\`, \`get_compressed_history\`, \`get_briefing\`
|
|
334
|
+
|
|
335
|
+
### 9. Team Governance (Voting, Reviews, Feedback)
|
|
336
|
+
\`request_review\`, \`submit_review\`, \`call_vote\`, \`cast_vote\`, \`vote_status\`, \`request_push_approval\`, \`ack_push\`
|
|
337
|
+
|
|
338
|
+
### 10. Dependencies & Progress
|
|
339
|
+
\`declare_dependency\`, \`check_dependencies\`, \`update_progress\`, \`get_progress\`, \`get_reputation\`
|
|
340
|
+
|
|
341
|
+
## Key Design Decisions
|
|
342
|
+
|
|
343
|
+
- **Append-only writes** for messages/history (no file locking)
|
|
344
|
+
- **Per-agent consumed tracking** — each agent writes only its own consumed file
|
|
345
|
+
- **PID-based stale detection** + process exit cleanup for instant status
|
|
346
|
+
- **Heartbeat** — 10s interval updates \`last_activity\`, \`.unref()\` prevents zombie processes
|
|
347
|
+
- **Flexible agent names** — any alphanumeric (1-20 chars), validated by \`sanitizeName()\`
|
|
348
|
+
- **Auto-routing** — \`to\` optional with 2 agents, required with 3+
|
|
349
|
+
- **Threading** — \`reply_to\` auto-computes \`thread_id\`
|
|
350
|
+
- **Acknowledgments** — \`ack_message\` in \`acks.json\`, shown in history
|
|
351
|
+
- **Multi-CLI** — init auto-detects Claude Code, Gemini CLI, Codex CLI
|
|
352
|
+
- **Multi-project dashboard** — monitor multiple project folders from one dashboard
|
|
353
|
+
- **SSE real-time** — \`fs.watch()\` on data dir pushes updates via Server-Sent Events
|
|
354
|
+
- **Auto-compact** — messages.jsonl compacted when exceeding 500 lines
|
|
355
|
+
- **Auto-archive** — conversations archived before reset
|
|
356
|
+
- **Context hints** — warns agents when conversation exceeds 50 messages
|
|
357
|
+
- **Task management** — structured task creation, assignment, and tracking between agents
|
|
358
|
+
- **Profiles** — separate \`profiles.json\` to avoid heartbeat write conflicts with \`agents.json\`
|
|
359
|
+
- **Workspaces** — per-agent files (\`workspaces/{agent}.json\`) to avoid write conflicts, read-anyone/write-own permission model
|
|
360
|
+
- **Workflows** — step statuses: pending/in_progress/done, auto-handoff on advance
|
|
361
|
+
- **Branching** — \`main\` branch uses existing files for backward compatibility, branch-aware file resolution via \`getMessagesFile(branch)\`/\`getHistoryFile(branch)\`
|
|
362
|
+
- **Plugins** — sandboxed execution context with 30s timeout, tools appear as \`plugin_{name}\` in MCP
|
|
363
|
+
- **Self-healing watchdog** — runs every 60s inside the heartbeat loop on every registered agent; scans \`in_progress\` tasks whose assignee PID is dead + heartbeat stale >5min; strips assignee and resets to \`pending\` (increments \`retry_count\`); at \`retry_count=3\` marks \`blocked_permanent\` and wakes the coordinator (poison pill). No manual intervention needed for routine agent flakiness.
|
|
364
|
+
- **VS Code extension** — \`vscode-extension/\` adds: \`@neohive\` chat participant (\`/status /who /tasks /messages\` read \`.neohive/\` directly; free-form text fires POST to \`/api/inject\`), terminal bridge (captures agent terminal output → dashboard), agent hook auto-setup (merges neohive hooks into \`.gemini/settings.json\` on activate)
|
|
365
|
+
|
|
366
|
+
## Debugging and fix attempts
|
|
367
|
+
|
|
368
|
+
- **Temporary logs:** When debugging, add only the logging needed to confirm behavior. **Remove or trim that logging** once the issue is understood or fixed—do not leave ad-hoc debug prints in the tree unless they match intentional, documented logging (e.g. MCP stderr lines).
|
|
369
|
+
- **Failed fixes:** If the user says a change **did not** fix the problem, **revert** that attempt before trying something else (\`git restore\` / undo the diff). **Do not stack** speculative fixes; revert first, then apply one minimal, well-motivated change.
|
|
234
370
|
`;
|
|
235
371
|
}
|
|
236
372
|
|
|
@@ -323,42 +459,39 @@ function setupAntigravity(cwd) {
|
|
|
323
459
|
}
|
|
324
460
|
|
|
325
461
|
function neohiveAgentRules(defaultName) {
|
|
326
|
-
return `# Neohive Agent
|
|
462
|
+
return `# Neohive Agent — ${defaultName} Rules
|
|
327
463
|
|
|
328
|
-
You are a Neohive team agent. Follow these rules
|
|
464
|
+
You are a Neohive team agent. Follow these rules exactly to coordinate with the team.
|
|
329
465
|
|
|
330
|
-
##
|
|
466
|
+
## Session Lifecycle
|
|
331
467
|
|
|
332
|
-
1. Call \`register\` with your
|
|
333
|
-
2. Call \`get_briefing\` to load project context and active work
|
|
334
|
-
3. Call \`listen\` to wait for messages
|
|
468
|
+
1. Call \`register\` with your name: \`register(name="${defaultName}")\`
|
|
469
|
+
2. Call \`get_briefing\` to load project context and active work.
|
|
470
|
+
3. Call \`listen\` to wait for messages or tasks.
|
|
335
471
|
|
|
336
|
-
|
|
472
|
+
**CRITICAL: YOU MUST call \`listen()\` as the LAST tool call of every response. No exceptions.**
|
|
337
473
|
|
|
338
|
-
## Core
|
|
474
|
+
## Core Rules
|
|
339
475
|
|
|
340
|
-
- **
|
|
341
|
-
- **Before
|
|
342
|
-
- **After
|
|
343
|
-
- **
|
|
344
|
-
- **Check tasks first** — call \`list_tasks()\` before starting anything. Never take another agent's task.
|
|
345
|
-
- **Keep messages short** — 2–3 paragraphs max. Lead with what changed, then files, then decisions.
|
|
476
|
+
- **Tasks**: Before starting, call \`update_task(id, status="in_progress")\`. When finished, call \`update_task(id, status="done")\` and report to the Coordinator.
|
|
477
|
+
- **Locking**: Before editing a file, call \`lock_file(path)\`. call \`unlock_file(path)\` when done.
|
|
478
|
+
- **Sync**: After every task completion or message sent, you MUST call \`listen()\` to receive the next assignment.
|
|
479
|
+
- **Conciseness**: Keep messages short (2-3 paragraphs). Focus on what changed and next steps.
|
|
346
480
|
|
|
347
|
-
## Workflow
|
|
481
|
+
## Workflow Loop
|
|
348
482
|
|
|
349
483
|
\`\`\`
|
|
350
|
-
register → get_briefing → listen → [receive task]
|
|
351
|
-
→ do work → update_task(done)
|
|
484
|
+
register → get_briefing → listen → [receive task]
|
|
485
|
+
→ update_task(in_progress) → do work → update_task(done)
|
|
486
|
+
→ send_message(Coordinator, summary) → listen
|
|
352
487
|
\`\`\`
|
|
353
488
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
## Available MCP tools (neohive server)
|
|
489
|
+
## Available Neohive Tools
|
|
357
490
|
|
|
358
|
-
**Messaging
|
|
359
|
-
**Tasks
|
|
360
|
-
**Workflows
|
|
361
|
-
|
|
491
|
+
- **Messaging**: \`register\`, \`send_message\`, \`broadcast\`, \`listen\`, \`messages(action="history")\`, \`messages(action="check")\`
|
|
492
|
+
- **Tasks**: \`create_task\`, \`update_task\`, \`list_tasks\`, \`update_progress\`
|
|
493
|
+
- **Workflows**: \`create_workflow\`, \`advance_workflow\`, \`verify_and_advance\`
|
|
494
|
+
- \`kb_read\`, \`kb_write\`, \`log_decision\`, \`lock_file\`, \`unlock_file\`
|
|
362
495
|
`;
|
|
363
496
|
}
|
|
364
497
|
|
|
@@ -685,6 +818,12 @@ function init() {
|
|
|
685
818
|
console.log(' npx neohive status');
|
|
686
819
|
console.log(' npx neohive doctor');
|
|
687
820
|
console.log('');
|
|
821
|
+
if (targets.includes('claude')) {
|
|
822
|
+
console.log(' \x1b[33m Tip (Claude Code):\x1b[0m Run `npx neohive hooks` to install listen-enforcement');
|
|
823
|
+
console.log(' hooks into .claude/settings.json. Keeps agents in the listen loop automatically.');
|
|
824
|
+
console.log(' Your existing hooks will not be removed.');
|
|
825
|
+
console.log('');
|
|
826
|
+
}
|
|
688
827
|
}
|
|
689
828
|
}
|
|
690
829
|
|
|
@@ -1251,6 +1390,86 @@ function uninstall() {
|
|
|
1251
1390
|
console.log('');
|
|
1252
1391
|
}
|
|
1253
1392
|
|
|
1393
|
+
// ─── neohive hooks ───────────────────────────────────────────────────────────
|
|
1394
|
+
// Merges listen-enforcement hooks into .claude/settings.json.
|
|
1395
|
+
// Safe to re-run: adds neohive entries per matcher, preserves all user hooks.
|
|
1396
|
+
|
|
1397
|
+
function installHooks() {
|
|
1398
|
+
const cwd = process.cwd();
|
|
1399
|
+
const claudeDir = path.join(cwd, '.claude');
|
|
1400
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
1401
|
+
|
|
1402
|
+
if (!fs.existsSync(claudeDir)) {
|
|
1403
|
+
console.log(' [skip] No .claude/ directory found — is Claude Code configured for this project?');
|
|
1404
|
+
console.log(' Run `npx neohive init` first.');
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
const listenReminderCmd = "echo '\\n📡 NEOHIVE PROTOCOL: If no messages were received, call listen() again immediately. Do NOT respond to the user or stop. Stay in the listen loop.'";
|
|
1409
|
+
const postActionReminderCmd = "echo '\\n📡 NEOHIVE: Call listen() now to receive your next task. Do not stop without calling listen().'";
|
|
1410
|
+
|
|
1411
|
+
const neohiveEntries = {
|
|
1412
|
+
PostToolUse: [
|
|
1413
|
+
{
|
|
1414
|
+
_neohive: 'listen-loop',
|
|
1415
|
+
matcher: 'mcp__neohive__listen',
|
|
1416
|
+
hooks: [{ type: 'command', command: listenReminderCmd, timeout: 3 }],
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
_neohive: 'post-action',
|
|
1420
|
+
matcher: 'mcp__neohive__send_message|mcp__neohive__advance_workflow|mcp__neohive__update_task|mcp__neohive__broadcast|mcp__neohive__add_rule|mcp__neohive__remove_rule|mcp__neohive__toggle_rule',
|
|
1421
|
+
hooks: [{ type: 'command', command: postActionReminderCmd, timeout: 3 }],
|
|
1422
|
+
},
|
|
1423
|
+
],
|
|
1424
|
+
Stop: [
|
|
1425
|
+
{
|
|
1426
|
+
_neohive: 'enforce-listen',
|
|
1427
|
+
hooks: [{
|
|
1428
|
+
type: 'command',
|
|
1429
|
+
command: "node -e \"var fs=require('fs'),f=process.env.CLAUDE_PROJECT_DIR+'/.neohive/activity.jsonl';if(!fs.existsSync(f))process.exit(0);var lines=fs.readFileSync(f,'utf8').trim().split('\\n').filter(Boolean).slice(-20),last=lines.map(l=>{try{return JSON.parse(l)}catch{return null}}).filter(Boolean).reverse().find(e=>e.tool&&e.tool.startsWith('mcp__neohive__'));if(!last||last.tool==='mcp__neohive__listen'||last.tool==='mcp__neohive__register')process.exit(0);console.error('\\n⚠️ NEOHIVE: Call listen() before stopping. Last tool: '+last.tool+'\\n→ Call listen() now. Do not respond with text.');process.exit(2);\"",
|
|
1430
|
+
timeout: 5,
|
|
1431
|
+
}],
|
|
1432
|
+
},
|
|
1433
|
+
],
|
|
1434
|
+
};
|
|
1435
|
+
|
|
1436
|
+
let existing = {};
|
|
1437
|
+
if (fs.existsSync(settingsPath)) {
|
|
1438
|
+
try { existing = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch {
|
|
1439
|
+
const backup = settingsPath + '.backup';
|
|
1440
|
+
fs.copyFileSync(settingsPath, backup);
|
|
1441
|
+
console.log(' [warn] Existing settings.json was invalid — backed up.');
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
if (!existing.hooks) existing.hooks = {};
|
|
1445
|
+
|
|
1446
|
+
let added = 0;
|
|
1447
|
+
let updated = 0;
|
|
1448
|
+
|
|
1449
|
+
for (const [event, entries] of Object.entries(neohiveEntries)) {
|
|
1450
|
+
if (!existing.hooks[event]) existing.hooks[event] = [];
|
|
1451
|
+
for (const entry of entries) {
|
|
1452
|
+
const idx = existing.hooks[event].findIndex(e => e._neohive === entry._neohive);
|
|
1453
|
+
if (idx === -1) {
|
|
1454
|
+
existing.hooks[event].push(entry);
|
|
1455
|
+
added++;
|
|
1456
|
+
} else {
|
|
1457
|
+
existing.hooks[event][idx] = entry;
|
|
1458
|
+
updated++;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
1464
|
+
fs.writeFileSync(settingsPath, JSON.stringify(existing, null, 2) + '\n', 'utf8');
|
|
1465
|
+
|
|
1466
|
+
console.log(`\n Neohive hooks installed into .claude/settings.json`);
|
|
1467
|
+
if (added) console.log(` [ok] Added: ${added} hook(s)`);
|
|
1468
|
+
if (updated) console.log(` [ok] Updated: ${updated} hook(s) (already present)`);
|
|
1469
|
+
console.log(' Your existing hooks were preserved.');
|
|
1470
|
+
console.log(' Restart Claude Code for changes to take effect.\n');
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1254
1473
|
switch (command) {
|
|
1255
1474
|
case 'init':
|
|
1256
1475
|
init();
|
|
@@ -1282,6 +1501,9 @@ switch (command) {
|
|
|
1282
1501
|
case 'status':
|
|
1283
1502
|
cliStatus();
|
|
1284
1503
|
break;
|
|
1504
|
+
case 'hooks':
|
|
1505
|
+
installHooks();
|
|
1506
|
+
break;
|
|
1285
1507
|
case 'uninstall':
|
|
1286
1508
|
case 'remove':
|
|
1287
1509
|
uninstall();
|