@inixiative/hivemind 0.1.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/LICENSE +21 -0
- package/README.md +115 -0
- package/dist/agents/agents.test.d.ts +1 -0
- package/dist/agents/agents.test.js +167 -0
- package/dist/agents/getActiveAgents.d.ts +6 -0
- package/dist/agents/getActiveAgents.js +11 -0
- package/dist/agents/getAgent.d.ts +6 -0
- package/dist/agents/getAgent.js +7 -0
- package/dist/agents/getAgentBySessionId.d.ts +10 -0
- package/dist/agents/getAgentBySessionId.js +17 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.js +12 -0
- package/dist/agents/markAgentDead.d.ts +6 -0
- package/dist/agents/markAgentDead.js +26 -0
- package/dist/agents/markAgentIdle.d.ts +5 -0
- package/dist/agents/markAgentIdle.js +12 -0
- package/dist/agents/registerAgent.d.ts +6 -0
- package/dist/agents/registerAgent.js +29 -0
- package/dist/agents/types.d.ts +30 -0
- package/dist/agents/types.js +1 -0
- package/dist/agents/unregisterAgent.d.ts +5 -0
- package/dist/agents/unregisterAgent.js +8 -0
- package/dist/agents/updateAgentContext.d.ts +5 -0
- package/dist/agents/updateAgentContext.js +12 -0
- package/dist/agents/updateAgentTask.d.ts +5 -0
- package/dist/agents/updateAgentTask.js +12 -0
- package/dist/agents/updateAgentWorktree.d.ts +5 -0
- package/dist/agents/updateAgentWorktree.js +12 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.js +8 -0
- package/dist/cli/init.d.ts +14 -0
- package/dist/cli/init.js +71 -0
- package/dist/cli/install.d.ts +8 -0
- package/dist/cli/install.js +47 -0
- package/dist/cli/join.d.ts +9 -0
- package/dist/cli/join.js +38 -0
- package/dist/cli/registerMcp.d.ts +28 -0
- package/dist/cli/registerMcp.js +138 -0
- package/dist/cli/status.d.ts +8 -0
- package/dist/cli/status.js +82 -0
- package/dist/cli/watch.d.ts +6 -0
- package/dist/cli/watch.js +68 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +49 -0
- package/dist/coordinator/coordinator.test.d.ts +1 -0
- package/dist/coordinator/coordinator.test.js +171 -0
- package/dist/coordinator/index.d.ts +16 -0
- package/dist/coordinator/index.js +166 -0
- package/dist/coordinator/spawn.d.ts +22 -0
- package/dist/coordinator/spawn.js +66 -0
- package/dist/datetime/datetime.test.d.ts +1 -0
- package/dist/datetime/datetime.test.js +63 -0
- package/dist/datetime/formatDate.d.ts +6 -0
- package/dist/datetime/formatDate.js +11 -0
- package/dist/datetime/formatDatetime.d.ts +6 -0
- package/dist/datetime/formatDatetime.js +12 -0
- package/dist/datetime/formatTime.d.ts +6 -0
- package/dist/datetime/formatTime.js +11 -0
- package/dist/datetime/index.d.ts +4 -0
- package/dist/datetime/index.js +7 -0
- package/dist/datetime/isStale.d.ts +10 -0
- package/dist/datetime/isStale.js +18 -0
- package/dist/datetime/now.d.ts +6 -0
- package/dist/datetime/now.js +9 -0
- package/dist/datetime/parseDatetime.d.ts +7 -0
- package/dist/datetime/parseDatetime.js +28 -0
- package/dist/db/constants.d.ts +4 -0
- package/dist/db/constants.js +6 -0
- package/dist/db/db.test.d.ts +1 -0
- package/dist/db/db.test.js +141 -0
- package/dist/db/ensureProjectDirs.d.ts +4 -0
- package/dist/db/ensureProjectDirs.js +12 -0
- package/dist/db/getConnection.d.ts +19 -0
- package/dist/db/getConnection.js +51 -0
- package/dist/db/getCurrentProject.d.ts +8 -0
- package/dist/db/getCurrentProject.js +14 -0
- package/dist/db/getProjectPaths.d.ts +21 -0
- package/dist/db/getProjectPaths.js +26 -0
- package/dist/db/index.d.ts +10 -0
- package/dist/db/index.js +13 -0
- package/dist/db/initializeDb.d.ts +7 -0
- package/dist/db/initializeDb.js +23 -0
- package/dist/db/nextEventSeq.d.ts +5 -0
- package/dist/db/nextEventSeq.js +13 -0
- package/dist/db/nextSubtaskSeq.d.ts +5 -0
- package/dist/db/nextSubtaskSeq.js +12 -0
- package/dist/db/nextTaskSeq.d.ts +5 -0
- package/dist/db/nextTaskSeq.js +13 -0
- package/dist/db/resetDb.d.ts +10 -0
- package/dist/db/resetDb.js +36 -0
- package/dist/events/emit.d.ts +6 -0
- package/dist/events/emit.js +31 -0
- package/dist/events/events.test.d.ts +1 -0
- package/dist/events/events.test.js +145 -0
- package/dist/events/getEventsByAgent.d.ts +6 -0
- package/dist/events/getEventsByAgent.js +14 -0
- package/dist/events/getEventsByBranch.d.ts +6 -0
- package/dist/events/getEventsByBranch.js +12 -0
- package/dist/events/getEventsByPlan.d.ts +6 -0
- package/dist/events/getEventsByPlan.js +14 -0
- package/dist/events/getEventsByWorktree.d.ts +6 -0
- package/dist/events/getEventsByWorktree.js +12 -0
- package/dist/events/getEventsSince.d.ts +12 -0
- package/dist/events/getEventsSince.js +47 -0
- package/dist/events/getRecentEvents.d.ts +6 -0
- package/dist/events/getRecentEvents.js +12 -0
- package/dist/events/index.d.ts +8 -0
- package/dist/events/index.js +9 -0
- package/dist/events/types.d.ts +34 -0
- package/dist/events/types.js +1 -0
- package/dist/git/getBranch.d.ts +4 -0
- package/dist/git/getBranch.js +14 -0
- package/dist/git/getCurrentWorktree.d.ts +5 -0
- package/dist/git/getCurrentWorktree.js +15 -0
- package/dist/git/getGitInfo.d.ts +10 -0
- package/dist/git/getGitInfo.js +23 -0
- package/dist/git/getRepoName.d.ts +4 -0
- package/dist/git/getRepoName.js +32 -0
- package/dist/git/getRepoRoot.d.ts +4 -0
- package/dist/git/getRepoRoot.js +14 -0
- package/dist/git/getWorktrees.d.ts +10 -0
- package/dist/git/getWorktrees.js +39 -0
- package/dist/git/index.d.ts +9 -0
- package/dist/git/index.js +7 -0
- package/dist/git/isGitRepo.d.ts +4 -0
- package/dist/git/isGitRepo.js +13 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/sessionStart.d.ts +21 -0
- package/dist/hooks/sessionStart.js +93 -0
- package/dist/ids/generateHex.d.ts +4 -0
- package/dist/ids/generateHex.js +7 -0
- package/dist/ids/getParentTaskId.d.ts +7 -0
- package/dist/ids/getParentTaskId.js +15 -0
- package/dist/ids/getPlanHexFromTaskId.d.ts +6 -0
- package/dist/ids/getPlanHexFromTaskId.js +9 -0
- package/dist/ids/ids.test.d.ts +1 -0
- package/dist/ids/ids.test.js +215 -0
- package/dist/ids/index.d.ts +16 -0
- package/dist/ids/index.js +17 -0
- package/dist/ids/isSubtask.d.ts +7 -0
- package/dist/ids/isSubtask.js +11 -0
- package/dist/ids/isValidId.d.ts +9 -0
- package/dist/ids/isValidId.js +22 -0
- package/dist/ids/makeAgentId.d.ts +8 -0
- package/dist/ids/makeAgentId.js +15 -0
- package/dist/ids/makeEventId.d.ts +11 -0
- package/dist/ids/makeEventId.js +12 -0
- package/dist/ids/makePlanId.d.ts +11 -0
- package/dist/ids/makePlanId.js +15 -0
- package/dist/ids/makeSubtaskId.d.ts +8 -0
- package/dist/ids/makeSubtaskId.js +15 -0
- package/dist/ids/makeTaskId.d.ts +8 -0
- package/dist/ids/makeTaskId.js +14 -0
- package/dist/ids/makeWorktreeId.d.ts +5 -0
- package/dist/ids/makeWorktreeId.js +12 -0
- package/dist/ids/parseId.d.ts +11 -0
- package/dist/ids/parseId.js +26 -0
- package/dist/ids/sanitizeLabel.d.ts +7 -0
- package/dist/ids/sanitizeLabel.js +12 -0
- package/dist/ids/typedIds.d.ts +34 -0
- package/dist/ids/typedIds.js +22 -0
- package/dist/ids/types.d.ts +14 -0
- package/dist/ids/types.js +1 -0
- package/dist/init/claudeConfig.d.ts +39 -0
- package/dist/init/claudeConfig.js +161 -0
- package/dist/llm/extractTasks.d.ts +28 -0
- package/dist/llm/extractTasks.js +108 -0
- package/dist/llm/index.d.ts +2 -0
- package/dist/llm/index.js +2 -0
- package/dist/llm/reconcileTasks.d.ts +21 -0
- package/dist/llm/reconcileTasks.js +82 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +100 -0
- package/dist/mcp/tools/emitEvent.d.ts +62 -0
- package/dist/mcp/tools/emitEvent.js +84 -0
- package/dist/mcp/tools/events.d.ts +55 -0
- package/dist/mcp/tools/events.js +56 -0
- package/dist/mcp/tools/index.d.ts +18 -0
- package/dist/mcp/tools/index.js +13 -0
- package/dist/mcp/tools/query.d.ts +54 -0
- package/dist/mcp/tools/query.js +70 -0
- package/dist/mcp/tools/register.d.ts +47 -0
- package/dist/mcp/tools/register.js +79 -0
- package/dist/mcp/tools/reset.d.ts +38 -0
- package/dist/mcp/tools/reset.js +56 -0
- package/dist/mcp/tools/setup.d.ts +42 -0
- package/dist/mcp/tools/setup.js +75 -0
- package/dist/mcp/tools/status.d.ts +44 -0
- package/dist/mcp/tools/status.js +74 -0
- package/dist/mcp/tools/tasks.d.ts +116 -0
- package/dist/mcp/tools/tasks.js +143 -0
- package/dist/mcp/tools/worktreeCleanup.d.ts +38 -0
- package/dist/mcp/tools/worktreeCleanup.js +67 -0
- package/dist/plans/createPlan.d.ts +6 -0
- package/dist/plans/createPlan.js +29 -0
- package/dist/plans/getActivePlans.d.ts +6 -0
- package/dist/plans/getActivePlans.js +11 -0
- package/dist/plans/getPlan.d.ts +6 -0
- package/dist/plans/getPlan.js +7 -0
- package/dist/plans/index.d.ts +5 -0
- package/dist/plans/index.js +5 -0
- package/dist/plans/plans.test.d.ts +1 -0
- package/dist/plans/plans.test.js +107 -0
- package/dist/plans/types.d.ts +32 -0
- package/dist/plans/types.js +1 -0
- package/dist/plans/updatePlanStatus.d.ts +6 -0
- package/dist/plans/updatePlanStatus.js +8 -0
- package/dist/tasks/assignTask.d.ts +7 -0
- package/dist/tasks/assignTask.js +20 -0
- package/dist/tasks/blockTask.d.ts +5 -0
- package/dist/tasks/blockTask.js +12 -0
- package/dist/tasks/claimTask.d.ts +7 -0
- package/dist/tasks/claimTask.js +21 -0
- package/dist/tasks/completeTask.d.ts +6 -0
- package/dist/tasks/completeTask.js +18 -0
- package/dist/tasks/createTask.d.ts +6 -0
- package/dist/tasks/createTask.js +36 -0
- package/dist/tasks/getPendingTasks.d.ts +6 -0
- package/dist/tasks/getPendingTasks.js +19 -0
- package/dist/tasks/getTask.d.ts +6 -0
- package/dist/tasks/getTask.js +7 -0
- package/dist/tasks/getTasksByPlan.d.ts +6 -0
- package/dist/tasks/getTasksByPlan.js +11 -0
- package/dist/tasks/index.d.ts +11 -0
- package/dist/tasks/index.js +12 -0
- package/dist/tasks/startTask.d.ts +5 -0
- package/dist/tasks/startTask.js +12 -0
- package/dist/tasks/tasks.test.d.ts +1 -0
- package/dist/tasks/tasks.test.js +209 -0
- package/dist/tasks/types.d.ts +36 -0
- package/dist/tasks/types.js +1 -0
- package/dist/tasks/unclaimTask.d.ts +5 -0
- package/dist/tasks/unclaimTask.js +12 -0
- package/dist/test/factories/agentFactory.d.ts +13 -0
- package/dist/test/factories/agentFactory.js +5 -0
- package/dist/test/factories/eventFactory.d.ts +20 -0
- package/dist/test/factories/eventFactory.js +16 -0
- package/dist/test/factories/factories.test.d.ts +1 -0
- package/dist/test/factories/factories.test.js +101 -0
- package/dist/test/factories/index.d.ts +4 -0
- package/dist/test/factories/index.js +4 -0
- package/dist/test/factories/planFactory.d.ts +15 -0
- package/dist/test/factories/planFactory.js +14 -0
- package/dist/test/factories/taskFactory.d.ts +22 -0
- package/dist/test/factories/taskFactory.js +44 -0
- package/dist/test/multiAgentDemo.d.ts +16 -0
- package/dist/test/multiAgentDemo.js +20 -0
- package/dist/test/multiAgentDemo.test.d.ts +1 -0
- package/dist/test/multiAgentDemo.test.js +14 -0
- package/dist/test/setup.d.ts +9 -0
- package/dist/test/setup.js +50 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/math.d.ts +6 -0
- package/dist/utils/math.js +10 -0
- package/dist/utils/math.test.d.ts +1 -0
- package/dist/utils/math.test.js +26 -0
- package/dist/utils/string.d.ts +11 -0
- package/dist/utils/string.js +17 -0
- package/dist/utils/string.test.d.ts +1 -0
- package/dist/utils/string.test.js +30 -0
- package/dist/watcher/index.d.ts +1 -0
- package/dist/watcher/index.js +1 -0
- package/dist/watcher/planWatcher.d.ts +31 -0
- package/dist/watcher/planWatcher.js +171 -0
- package/dist/worktrees/getAllWorktrees.d.ts +6 -0
- package/dist/worktrees/getAllWorktrees.js +10 -0
- package/dist/worktrees/getWorktreeById.d.ts +6 -0
- package/dist/worktrees/getWorktreeById.js +7 -0
- package/dist/worktrees/getWorktreeByPath.d.ts +6 -0
- package/dist/worktrees/getWorktreeByPath.js +7 -0
- package/dist/worktrees/index.d.ts +9 -0
- package/dist/worktrees/index.js +13 -0
- package/dist/worktrees/registerWorktree.d.ts +6 -0
- package/dist/worktrees/registerWorktree.js +28 -0
- package/dist/worktrees/removeWorktree.d.ts +6 -0
- package/dist/worktrees/removeWorktree.js +9 -0
- package/dist/worktrees/syncWorktreesFromGit.d.ts +7 -0
- package/dist/worktrees/syncWorktreesFromGit.js +51 -0
- package/dist/worktrees/types.d.ts +29 -0
- package/dist/worktrees/types.js +1 -0
- package/dist/worktrees/updateWorktreeCommit.d.ts +5 -0
- package/dist/worktrees/updateWorktreeCommit.js +13 -0
- package/dist/worktrees/updateWorktreeSeen.d.ts +5 -0
- package/dist/worktrees/updateWorktreeSeen.js +13 -0
- package/package.json +58 -0
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hivemind init - Register a project with hivemind
|
|
3
|
+
*
|
|
4
|
+
* Run from a project directory to:
|
|
5
|
+
* 1. Create database in ~/.hivemind/<project>/
|
|
6
|
+
* 2. Set up .claude/settings.json hooks
|
|
7
|
+
* 3. Add CLAUDE.md instructions
|
|
8
|
+
*/
|
|
9
|
+
import { dirname, join } from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { getGitInfo } from '../git/getGitInfo';
|
|
12
|
+
import { initializeDb } from '../db/initializeDb';
|
|
13
|
+
import { getProjectPaths } from '../db/getProjectPaths';
|
|
14
|
+
import { initClaudeConfig } from '../init/claudeConfig';
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const HIVEMIND_ROOT = join(__dirname, '../..');
|
|
17
|
+
export async function initCommand(options) {
|
|
18
|
+
// Determine project name
|
|
19
|
+
const gitInfo = getGitInfo();
|
|
20
|
+
let projectName = options.project;
|
|
21
|
+
if (!projectName) {
|
|
22
|
+
if (gitInfo.isRepo && gitInfo.repoName) {
|
|
23
|
+
projectName = gitInfo.repoName;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
projectName = process.cwd().split('/').pop() || 'default';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
console.log(`hivemind init: ${projectName}\n`);
|
|
30
|
+
// 1. Initialize database
|
|
31
|
+
console.log('[1/2] Database');
|
|
32
|
+
const paths = getProjectPaths(projectName);
|
|
33
|
+
const db = initializeDb(projectName);
|
|
34
|
+
// Get stats
|
|
35
|
+
const agentCount = db.prepare('SELECT COUNT(*) as c FROM agents').get().c;
|
|
36
|
+
const planCount = db.prepare('SELECT COUNT(*) as c FROM plans').get().c;
|
|
37
|
+
const eventCount = db.prepare('SELECT COUNT(*) as c FROM events').get().c;
|
|
38
|
+
db.close();
|
|
39
|
+
console.log(` path: ${paths.dbPath}`);
|
|
40
|
+
if (agentCount > 0 || planCount > 0) {
|
|
41
|
+
console.log(` stats: ${agentCount} agents, ${planCount} plans, ${eventCount} events`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.log(' status: created');
|
|
45
|
+
}
|
|
46
|
+
// 2. Set up Claude config (hooks + CLAUDE.md)
|
|
47
|
+
if (options.hooks !== false) {
|
|
48
|
+
console.log('\n[2/2] Claude Config');
|
|
49
|
+
const projectRoot = gitInfo.root || process.cwd();
|
|
50
|
+
const configResult = initClaudeConfig(projectRoot, projectName, HIVEMIND_ROOT);
|
|
51
|
+
if (configResult.created.length > 0) {
|
|
52
|
+
console.log(` created: ${configResult.created.join(', ')}`);
|
|
53
|
+
}
|
|
54
|
+
if (configResult.updated.length > 0) {
|
|
55
|
+
console.log(` updated: ${configResult.updated.join(', ')}`);
|
|
56
|
+
}
|
|
57
|
+
if (configResult.created.length === 0 && configResult.updated.length === 0) {
|
|
58
|
+
console.log(' status: already configured');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.log('\n[2/2] Claude Config (skipped)');
|
|
63
|
+
}
|
|
64
|
+
// Success
|
|
65
|
+
console.log('\n---');
|
|
66
|
+
console.log('Project registered! Restart Claude Code to activate.');
|
|
67
|
+
console.log('\nNext session will:');
|
|
68
|
+
console.log(' - Auto-register as a hivemind agent');
|
|
69
|
+
console.log(' - Have hivemind MCP tools available');
|
|
70
|
+
console.log(' - Follow 001-style task numbering');
|
|
71
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hivemind install - One-time global setup
|
|
3
|
+
*
|
|
4
|
+
* Run from hivemind directory to:
|
|
5
|
+
* 1. Install dependencies
|
|
6
|
+
* 2. Register MCP server globally
|
|
7
|
+
*/
|
|
8
|
+
import { dirname, join } from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { $ } from 'bun';
|
|
11
|
+
import { registerMcpServer, configurePermissions } from './registerMcp';
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const HIVEMIND_ROOT = join(__dirname, '../..');
|
|
14
|
+
export async function installCommand() {
|
|
15
|
+
console.log('hivemind install\n');
|
|
16
|
+
// 1. Install dependencies
|
|
17
|
+
console.log('[1/3] Dependencies');
|
|
18
|
+
try {
|
|
19
|
+
await $ `cd ${HIVEMIND_ROOT} && bun install`.quiet();
|
|
20
|
+
console.log(' installed');
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
console.error(' failed to install dependencies');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
// 2. Register MCP server
|
|
27
|
+
console.log('\n[2/3] MCP Server');
|
|
28
|
+
const mcpResult = await registerMcpServer(HIVEMIND_ROOT);
|
|
29
|
+
console.log(` ${mcpResult.message}`);
|
|
30
|
+
if (!mcpResult.success) {
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
// 3. Configure permissions (auto-approve structured tools)
|
|
34
|
+
console.log('\n[3/3] Permissions');
|
|
35
|
+
const permResult = configurePermissions();
|
|
36
|
+
console.log(` ${permResult.message}`);
|
|
37
|
+
if (permResult.added.length > 0) {
|
|
38
|
+
console.log(' auto-approved: status, events, query, claim/start/complete task');
|
|
39
|
+
console.log(' requires approval: emit (ad-hoc messages)');
|
|
40
|
+
}
|
|
41
|
+
// Success
|
|
42
|
+
console.log('\n---');
|
|
43
|
+
console.log('Hivemind installed globally!');
|
|
44
|
+
console.log('\nNext steps:');
|
|
45
|
+
console.log(' cd <your-project>');
|
|
46
|
+
console.log(' bun run /path/to/hivemind init');
|
|
47
|
+
}
|
package/dist/cli/join.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hivemind join - Join the hivemind as an agent
|
|
3
|
+
*/
|
|
4
|
+
import { executeRegister } from '../mcp/tools/register';
|
|
5
|
+
import { executeStatus } from '../mcp/tools/status';
|
|
6
|
+
import { getGitInfo } from '../git/getGitInfo';
|
|
7
|
+
export async function joinCommand(options) {
|
|
8
|
+
const gitInfo = getGitInfo();
|
|
9
|
+
if (!gitInfo.isRepo || !gitInfo.repoName) {
|
|
10
|
+
console.log('Not in a git repository. Run from a git project directory.');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
console.log(`hivemind join: ${gitInfo.repoName}\n`);
|
|
14
|
+
try {
|
|
15
|
+
const result = executeRegister({
|
|
16
|
+
project: gitInfo.repoName,
|
|
17
|
+
label: options.label,
|
|
18
|
+
contextSummary: options.context,
|
|
19
|
+
});
|
|
20
|
+
console.log(`Agent: ${result.agentId}`);
|
|
21
|
+
if (result.branch) {
|
|
22
|
+
console.log(`Branch: ${result.branch}`);
|
|
23
|
+
}
|
|
24
|
+
// Show other active agents
|
|
25
|
+
const status = executeStatus({ project: gitInfo.repoName });
|
|
26
|
+
const otherAgents = status.activeAgents?.filter((a) => a.id !== result.agentId) || [];
|
|
27
|
+
if (otherAgents.length > 0) {
|
|
28
|
+
console.log('\nOther active agents:');
|
|
29
|
+
for (const agent of otherAgents) {
|
|
30
|
+
console.log(` ${agent.id}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
console.log('\nJoined successfully!');
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register hivemind MCP server with Claude Code
|
|
3
|
+
*/
|
|
4
|
+
type RegisterResult = {
|
|
5
|
+
success: boolean;
|
|
6
|
+
message: string;
|
|
7
|
+
alreadyRegistered?: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Register the hivemind MCP server using `claude mcp add`
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerMcpServer(hivemindRoot: string): Promise<RegisterResult>;
|
|
13
|
+
/**
|
|
14
|
+
* Check if hivemind MCP server is registered
|
|
15
|
+
*/
|
|
16
|
+
export declare function isMcpRegistered(): Promise<boolean>;
|
|
17
|
+
type PermissionResult = {
|
|
18
|
+
success: boolean;
|
|
19
|
+
message: string;
|
|
20
|
+
added: string[];
|
|
21
|
+
alreadyPresent: string[];
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Configure auto-approve permissions for hivemind tools
|
|
25
|
+
* Adds structured tools to ~/.claude/settings.json permissions.allow
|
|
26
|
+
*/
|
|
27
|
+
export declare function configurePermissions(): PermissionResult;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register hivemind MCP server with Claude Code
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import { $ } from 'bun';
|
|
8
|
+
/**
|
|
9
|
+
* Hivemind tools that should be auto-approved (structured operations)
|
|
10
|
+
* These have predictable semantics and don't require human oversight
|
|
11
|
+
*/
|
|
12
|
+
const AUTO_APPROVED_TOOLS = [
|
|
13
|
+
// Lifecycle
|
|
14
|
+
'mcp__hivemind__hivemind_setup',
|
|
15
|
+
'mcp__hivemind__hivemind_register',
|
|
16
|
+
// Read-only queries
|
|
17
|
+
'mcp__hivemind__hivemind_status',
|
|
18
|
+
'mcp__hivemind__hivemind_events',
|
|
19
|
+
'mcp__hivemind__hivemind_query',
|
|
20
|
+
// Task management (structured operations)
|
|
21
|
+
'mcp__hivemind__hivemind_claim_task',
|
|
22
|
+
'mcp__hivemind__hivemind_start_task',
|
|
23
|
+
'mcp__hivemind__hivemind_complete_task',
|
|
24
|
+
// Maintenance
|
|
25
|
+
'mcp__hivemind__hivemind_worktree_cleanup',
|
|
26
|
+
];
|
|
27
|
+
// NOT auto-approved (require human oversight):
|
|
28
|
+
// - hivemind_emit: allows arbitrary messages to other agents
|
|
29
|
+
// - hivemind_reset: destructive operation that wipes the database
|
|
30
|
+
/**
|
|
31
|
+
* Register the hivemind MCP server using `claude mcp add`
|
|
32
|
+
*/
|
|
33
|
+
export async function registerMcpServer(hivemindRoot) {
|
|
34
|
+
const serverPath = join(hivemindRoot, 'src/mcp/server.ts');
|
|
35
|
+
const command = `bun run ${serverPath}`;
|
|
36
|
+
try {
|
|
37
|
+
// Check if already registered
|
|
38
|
+
const listResult = await $ `claude mcp list 2>/dev/null`.text();
|
|
39
|
+
if (listResult.includes('hivemind')) {
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
message: 'already registered',
|
|
43
|
+
alreadyRegistered: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Register the MCP server
|
|
47
|
+
await $ `claude mcp add --transport stdio hivemind -- ${command}`.quiet();
|
|
48
|
+
return {
|
|
49
|
+
success: true,
|
|
50
|
+
message: `registered: hivemind -> ${command}`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
// Check if claude CLI is available
|
|
55
|
+
try {
|
|
56
|
+
await $ `which claude`.quiet();
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return {
|
|
60
|
+
success: false,
|
|
61
|
+
message: 'claude CLI not found. Install Claude Code first.',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Some other error
|
|
65
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
message: `failed: ${msg}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check if hivemind MCP server is registered
|
|
74
|
+
*/
|
|
75
|
+
export async function isMcpRegistered() {
|
|
76
|
+
try {
|
|
77
|
+
const result = await $ `claude mcp list 2>/dev/null`.text();
|
|
78
|
+
return result.includes('hivemind');
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Configure auto-approve permissions for hivemind tools
|
|
86
|
+
* Adds structured tools to ~/.claude/settings.json permissions.allow
|
|
87
|
+
*/
|
|
88
|
+
export function configurePermissions() {
|
|
89
|
+
const claudeDir = join(homedir(), '.claude');
|
|
90
|
+
const settingsPath = join(claudeDir, 'settings.json');
|
|
91
|
+
// Ensure ~/.claude exists
|
|
92
|
+
if (!existsSync(claudeDir)) {
|
|
93
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
94
|
+
}
|
|
95
|
+
// Load existing settings
|
|
96
|
+
let settings = {};
|
|
97
|
+
if (existsSync(settingsPath)) {
|
|
98
|
+
try {
|
|
99
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Invalid JSON, start fresh
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Ensure permissions.allow exists
|
|
106
|
+
if (!settings.permissions) {
|
|
107
|
+
settings.permissions = {};
|
|
108
|
+
}
|
|
109
|
+
const permissions = settings.permissions;
|
|
110
|
+
if (!Array.isArray(permissions.allow)) {
|
|
111
|
+
permissions.allow = [];
|
|
112
|
+
}
|
|
113
|
+
const allowList = permissions.allow;
|
|
114
|
+
// Track what we add
|
|
115
|
+
const added = [];
|
|
116
|
+
const alreadyPresent = [];
|
|
117
|
+
for (const tool of AUTO_APPROVED_TOOLS) {
|
|
118
|
+
if (allowList.includes(tool)) {
|
|
119
|
+
alreadyPresent.push(tool);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
allowList.push(tool);
|
|
123
|
+
added.push(tool);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Write back if we added anything
|
|
127
|
+
if (added.length > 0) {
|
|
128
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
success: true,
|
|
132
|
+
message: added.length > 0
|
|
133
|
+
? `added ${added.length} permission rules`
|
|
134
|
+
: 'permissions already configured',
|
|
135
|
+
added,
|
|
136
|
+
alreadyPresent,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hivemind status - Show hivemind status for a project
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
import { getGitInfo } from '../git/getGitInfo';
|
|
6
|
+
import { getProjectPaths } from '../db/getProjectPaths';
|
|
7
|
+
import { getConnection } from '../db/getConnection';
|
|
8
|
+
import { getActiveAgents } from '../agents/getActiveAgents';
|
|
9
|
+
import { getActivePlans } from '../plans/getActivePlans';
|
|
10
|
+
import { getRecentEvents } from '../events/getRecentEvents';
|
|
11
|
+
import { isMcpRegistered } from './registerMcp';
|
|
12
|
+
import { formatDatetime } from '../datetime/formatDatetime';
|
|
13
|
+
export async function statusCommand(options) {
|
|
14
|
+
// Determine project
|
|
15
|
+
const gitInfo = getGitInfo();
|
|
16
|
+
let projectName = options.project;
|
|
17
|
+
if (!projectName) {
|
|
18
|
+
if (gitInfo.isRepo && gitInfo.repoName) {
|
|
19
|
+
projectName = gitInfo.repoName;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
projectName = process.cwd().split('/').pop() || 'default';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
console.log(`hivemind status: ${projectName}\n`);
|
|
26
|
+
// Check if database exists
|
|
27
|
+
const paths = getProjectPaths(projectName);
|
|
28
|
+
if (!existsSync(paths.dbPath)) {
|
|
29
|
+
console.log(' not initialized');
|
|
30
|
+
console.log(' run: hivemind init');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Database stats
|
|
34
|
+
const db = getConnection(projectName);
|
|
35
|
+
const agentCount = db.prepare('SELECT COUNT(*) as c FROM agents').get().c;
|
|
36
|
+
const planCount = db.prepare('SELECT COUNT(*) as c FROM plans').get().c;
|
|
37
|
+
const eventCount = db.prepare('SELECT COUNT(*) as c FROM events').get().c;
|
|
38
|
+
console.log('Database');
|
|
39
|
+
console.log(` path: ${paths.dbPath}`);
|
|
40
|
+
console.log(` agents: ${agentCount}, plans: ${planCount}, events: ${eventCount}`);
|
|
41
|
+
// Active agents
|
|
42
|
+
const activeAgents = getActiveAgents(db);
|
|
43
|
+
console.log('\nActive Agents');
|
|
44
|
+
if (activeAgents.length === 0) {
|
|
45
|
+
console.log(' none');
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
for (const agent of activeAgents) {
|
|
49
|
+
const context = agent.context_summary ? ` - ${agent.context_summary}` : '';
|
|
50
|
+
console.log(` ${agent.id}${context}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Active plans
|
|
54
|
+
const activePlans = getActivePlans(db);
|
|
55
|
+
console.log('\nActive Plans');
|
|
56
|
+
if (activePlans.length === 0) {
|
|
57
|
+
console.log(' none');
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
for (const plan of activePlans) {
|
|
61
|
+
console.log(` ${plan.id}: ${plan.title}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Recent events
|
|
65
|
+
const recentEvents = getRecentEvents(db, 5);
|
|
66
|
+
console.log('\nRecent Events');
|
|
67
|
+
if (recentEvents.length === 0) {
|
|
68
|
+
console.log(' none');
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
for (const event of recentEvents) {
|
|
72
|
+
const time = formatDatetime(new Date(event.timestamp));
|
|
73
|
+
const content = event.content?.slice(0, 50) || '';
|
|
74
|
+
console.log(` [${time}] ${event.event_type}: ${content}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
db.close();
|
|
78
|
+
// MCP status
|
|
79
|
+
console.log('\nMCP Server');
|
|
80
|
+
const mcpRegistered = await isMcpRegistered();
|
|
81
|
+
console.log(` registered: ${mcpRegistered ? 'yes' : 'no'}`);
|
|
82
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hivemind watch - Live tail of events
|
|
3
|
+
*/
|
|
4
|
+
import { getConnection } from '../db/getConnection';
|
|
5
|
+
import { getRecentEvents } from '../events/getRecentEvents';
|
|
6
|
+
import { getGitInfo } from '../git/getGitInfo';
|
|
7
|
+
const EVENT_ICONS = {
|
|
8
|
+
'task:claim': '🎯',
|
|
9
|
+
'task:start': '▶️',
|
|
10
|
+
'task:complete': '✅',
|
|
11
|
+
'task:block': '🚫',
|
|
12
|
+
'decision': '💡',
|
|
13
|
+
'question': '❓',
|
|
14
|
+
'answer': '💬',
|
|
15
|
+
'note': '📝',
|
|
16
|
+
'context': '📋',
|
|
17
|
+
'agent:register': '👋',
|
|
18
|
+
'agent:unregister': '👋',
|
|
19
|
+
'plan:create': '📊',
|
|
20
|
+
'plan:sync': '🔄',
|
|
21
|
+
};
|
|
22
|
+
function formatEvent(event) {
|
|
23
|
+
const icon = EVENT_ICONS[event.event_type] || '•';
|
|
24
|
+
const time = event.timestamp.split(' ')[1]; // Just the time part
|
|
25
|
+
const agent = event.agent_id?.replace('agt_', '') || 'system';
|
|
26
|
+
const content = event.content ? ` ${event.content}` : '';
|
|
27
|
+
return `${icon} [${time}] ${agent} ${event.event_type}${content}`;
|
|
28
|
+
}
|
|
29
|
+
export async function watchCommand(options) {
|
|
30
|
+
let project = options.project;
|
|
31
|
+
if (!project) {
|
|
32
|
+
const gitInfo = getGitInfo();
|
|
33
|
+
if (!gitInfo.isRepo || !gitInfo.repoName) {
|
|
34
|
+
console.error('Not in a git repository. Use --project <name>');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
project = gitInfo.repoName;
|
|
38
|
+
}
|
|
39
|
+
const db = getConnection(project);
|
|
40
|
+
let lastSeq = 0;
|
|
41
|
+
// Get initial last seq
|
|
42
|
+
const initial = getRecentEvents(db, 1);
|
|
43
|
+
if (initial.length > 0) {
|
|
44
|
+
lastSeq = initial[0].seq;
|
|
45
|
+
}
|
|
46
|
+
console.log(`👁️ Watching hivemind events for: ${project}`);
|
|
47
|
+
console.log(` Press Ctrl+C to stop\n`);
|
|
48
|
+
// Poll loop
|
|
49
|
+
const POLL_INTERVAL = 1000; // 1 second
|
|
50
|
+
while (true) {
|
|
51
|
+
try {
|
|
52
|
+
const stmt = db.prepare(`
|
|
53
|
+
SELECT * FROM events
|
|
54
|
+
WHERE seq > ?
|
|
55
|
+
ORDER BY seq ASC
|
|
56
|
+
`);
|
|
57
|
+
const newEvents = stmt.all(lastSeq);
|
|
58
|
+
for (const event of newEvents) {
|
|
59
|
+
console.log(formatEvent(event));
|
|
60
|
+
lastSeq = event.seq;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// DB might be locked, just retry
|
|
65
|
+
}
|
|
66
|
+
await Bun.sleep(POLL_INTERVAL);
|
|
67
|
+
}
|
|
68
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Hivemind CLI
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* bun run src/cli.ts install # One-time global setup
|
|
7
|
+
* bun run src/cli.ts init # Register current project
|
|
8
|
+
* bun run src/cli.ts status # Show project status
|
|
9
|
+
* bun run src/cli.ts join # Join as an agent
|
|
10
|
+
* bun run src/cli.ts watch # Live tail of events
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Hivemind CLI
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* bun run src/cli.ts install # One-time global setup
|
|
7
|
+
* bun run src/cli.ts init # Register current project
|
|
8
|
+
* bun run src/cli.ts status # Show project status
|
|
9
|
+
* bun run src/cli.ts join # Join as an agent
|
|
10
|
+
* bun run src/cli.ts watch # Live tail of events
|
|
11
|
+
*/
|
|
12
|
+
import { Command } from 'commander';
|
|
13
|
+
import { installCommand } from './cli/install';
|
|
14
|
+
import { initCommand } from './cli/init';
|
|
15
|
+
import { statusCommand } from './cli/status';
|
|
16
|
+
import { joinCommand } from './cli/join';
|
|
17
|
+
import { watchCommand } from './cli/watch';
|
|
18
|
+
const program = new Command();
|
|
19
|
+
program
|
|
20
|
+
.name('hivemind')
|
|
21
|
+
.description('Multi-agent coordination system for Claude Code')
|
|
22
|
+
.version('0.1.0');
|
|
23
|
+
program
|
|
24
|
+
.command('install')
|
|
25
|
+
.description('One-time setup: install dependencies and register MCP server')
|
|
26
|
+
.action(installCommand);
|
|
27
|
+
program
|
|
28
|
+
.command('init')
|
|
29
|
+
.description('Register current project with hivemind')
|
|
30
|
+
.option('-p, --project <name>', 'Project name (defaults to git repo name)')
|
|
31
|
+
.option('--no-hooks', 'Skip session hook setup')
|
|
32
|
+
.action(initCommand);
|
|
33
|
+
program
|
|
34
|
+
.command('status')
|
|
35
|
+
.description('Show hivemind status for the current project')
|
|
36
|
+
.option('-p, --project <name>', 'Project name')
|
|
37
|
+
.action(statusCommand);
|
|
38
|
+
program
|
|
39
|
+
.command('join')
|
|
40
|
+
.description('Join the hivemind as an agent')
|
|
41
|
+
.option('-l, --label <label>', 'Agent label')
|
|
42
|
+
.option('-c, --context <summary>', 'Context summary')
|
|
43
|
+
.action(joinCommand);
|
|
44
|
+
program
|
|
45
|
+
.command('watch')
|
|
46
|
+
.description('Live tail of hivemind events')
|
|
47
|
+
.option('-p, --project <name>', 'Project name')
|
|
48
|
+
.action(watchCommand);
|
|
49
|
+
program.parse();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|