claudelink 1.0.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/dist/cli.js ADDED
@@ -0,0 +1,277 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const NEXUS_DIR = path_1.default.join(os_1.default.homedir(), ".claudelink");
11
+ const MCP_SERVER_CONFIG = {
12
+ type: "stdio",
13
+ command: "claudelink-server",
14
+ };
15
+ const CLAUDE_MD_CONTENT = `
16
+ ## ClaudeLink - Autonomous Agent Communication
17
+
18
+ You are part of a multi-agent team. Other agents may be running in separate terminals and can send you messages at any time via ClaudeLink.
19
+
20
+ ### Automatic Inbox Checking
21
+
22
+ - **BEFORE starting any task**: Check your inbox using \`read_inbox\` first
23
+ - **AFTER completing any task**: Check your inbox again using \`read_inbox\`
24
+ - If you receive a message, acknowledge it and act on it before moving on
25
+ - If a message requires you to change your current work, do so immediately
26
+ - If a message is from another agent asking for information, respond using \`send\` before continuing your own work
27
+ - High-priority messages take precedence over your current task
28
+
29
+ ### Autonomous Collaboration
30
+
31
+ - When you finish work that another agent might care about, proactively send them an update
32
+ - If you encounter a problem that another agent's role could help with, send them a message
33
+ - When you make a decision that affects the project, post it to the bulletin board
34
+ - If you're blocked waiting for another agent, say so and check inbox again
35
+
36
+ ### Communication Shortcuts
37
+
38
+ - **"check response"** or **"check messages"** — Use \`read_inbox\` to check for new messages
39
+ - **"ask the [role]"** — Send a message to that role and check inbox for their reply
40
+ - **"tell the [role]"** — Send a one-way message to that role
41
+ - **"who's online"** — Use \`get_agents\` to list all connected agents
42
+ - **"update the board"** — Use \`post_bulletin\` to post a status update
43
+ - **"check the board"** — Use \`get_bulletin\` to read the bulletin board
44
+ `.trim();
45
+ const CLAUDE_MD_MARKER = "## ClaudeLink - Autonomous Agent Communication";
46
+ function installClaudeMd(scope) {
47
+ let claudeMdPath;
48
+ if (scope === "global") {
49
+ const claudeDir = path_1.default.join(os_1.default.homedir(), ".claude");
50
+ if (!fs_1.default.existsSync(claudeDir)) {
51
+ fs_1.default.mkdirSync(claudeDir, { recursive: true });
52
+ }
53
+ claudeMdPath = path_1.default.join(claudeDir, "CLAUDE.md");
54
+ }
55
+ else {
56
+ claudeMdPath = path_1.default.join(process.cwd(), "CLAUDE.md");
57
+ }
58
+ // Check if CLAUDE.md exists and already has ClaudeLink content
59
+ if (fs_1.default.existsSync(claudeMdPath)) {
60
+ const existing = fs_1.default.readFileSync(claudeMdPath, "utf-8");
61
+ if (existing.includes(CLAUDE_MD_MARKER)) {
62
+ console.log(` CLAUDE.md already has ClaudeLink instructions (${claudeMdPath})`);
63
+ return;
64
+ }
65
+ // Append to existing file
66
+ const separator = existing.endsWith("\n") ? "\n" : "\n\n";
67
+ fs_1.default.writeFileSync(claudeMdPath, existing + separator + CLAUDE_MD_CONTENT + "\n");
68
+ console.log(` Added ClaudeLink instructions to existing ${claudeMdPath}`);
69
+ }
70
+ else {
71
+ // Create new file
72
+ fs_1.default.writeFileSync(claudeMdPath, "# Global Instructions\n\n" + CLAUDE_MD_CONTENT + "\n");
73
+ console.log(` Created ${claudeMdPath} with ClaudeLink instructions`);
74
+ }
75
+ }
76
+ function printBanner() {
77
+ console.log(`
78
+ ╔═══════════════════════════════════════════╗
79
+ ║ C L A U D E L I N K ║
80
+ ║ The hub where your AI agents connect. ║
81
+ ╚═══════════════════════════════════════════╝
82
+ `);
83
+ }
84
+ function initProject() {
85
+ const cwd = process.cwd();
86
+ const mcpJsonPath = path_1.default.join(cwd, ".mcp.json");
87
+ // Create ~/.claudelink directory
88
+ if (!fs_1.default.existsSync(NEXUS_DIR)) {
89
+ fs_1.default.mkdirSync(NEXUS_DIR, { recursive: true });
90
+ console.log(` Created ${NEXUS_DIR}/`);
91
+ }
92
+ // Read or create .mcp.json
93
+ let mcpConfig = { mcpServers: {} };
94
+ if (fs_1.default.existsSync(mcpJsonPath)) {
95
+ try {
96
+ const content = fs_1.default.readFileSync(mcpJsonPath, "utf-8");
97
+ mcpConfig = JSON.parse(content);
98
+ if (!mcpConfig.mcpServers) {
99
+ mcpConfig.mcpServers = {};
100
+ }
101
+ console.log(` Found existing .mcp.json`);
102
+ }
103
+ catch {
104
+ console.log(` Warning: Could not parse existing .mcp.json, creating fresh one`);
105
+ mcpConfig = { mcpServers: {} };
106
+ }
107
+ }
108
+ // Add claudelink server config
109
+ mcpConfig.mcpServers["claudelink"] = MCP_SERVER_CONFIG;
110
+ fs_1.default.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2) + "\n");
111
+ console.log(` Updated ${mcpJsonPath}`);
112
+ // Install CLAUDE.md with autonomous mode instructions
113
+ installClaudeMd("project");
114
+ console.log(`
115
+ ClaudeLink is ready!
116
+
117
+ What was set up:
118
+ - .mcp.json: MCP server config (tells Claude Code to connect to ClaudeLink)
119
+ - CLAUDE.md: Autonomous mode instructions (agents check inbox automatically)
120
+
121
+ Next steps:
122
+ 1. Restart Claude Code in your terminals
123
+ 2. In each terminal, tell Claude to register:
124
+ "Register as a developer agent"
125
+ "Register as a code reviewer"
126
+ 3. Agents can now communicate:
127
+ "Send a message to the reviewer: please check auth.ts"
128
+ "Check my inbox for messages"
129
+ "Post to the bulletin board: deployment at 3pm"
130
+
131
+ Data stored in: ${NEXUS_DIR}/nexus.db
132
+ Config written to: ${mcpJsonPath}
133
+ `);
134
+ }
135
+ function initGlobal() {
136
+ // Create ~/.claudelink directory
137
+ if (!fs_1.default.existsSync(NEXUS_DIR)) {
138
+ fs_1.default.mkdirSync(NEXUS_DIR, { recursive: true });
139
+ console.log(` Created ${NEXUS_DIR}/`);
140
+ }
141
+ // Use claude mcp add command for proper global registration
142
+ const { execSync } = require("child_process");
143
+ let mcpSuccess = false;
144
+ try {
145
+ execSync("claude mcp add --scope user claudelink -- claudelink-server", {
146
+ stdio: "inherit",
147
+ });
148
+ mcpSuccess = true;
149
+ }
150
+ catch {
151
+ console.log(`
152
+ Could not run "claude mcp add" automatically.
153
+
154
+ Run this command manually to add ClaudeLink globally:
155
+
156
+ claude mcp add --scope user claudelink -- claudelink-server
157
+ `);
158
+ }
159
+ // Install global CLAUDE.md with autonomous mode instructions
160
+ installClaudeMd("global");
161
+ if (mcpSuccess) {
162
+ console.log(`
163
+ ClaudeLink is ready (global install)!
164
+
165
+ What was set up:
166
+ - ~/.claude.json: MCP server config (available in ALL projects)
167
+ - ~/.claude/CLAUDE.md: Autonomous mode instructions (agents check inbox automatically)
168
+
169
+ Next steps:
170
+ 1. Restart Claude Code in your terminals
171
+ 2. In each terminal, tell Claude to register:
172
+ "Register as a developer agent"
173
+ "Register as a code reviewer"
174
+ 3. Agents can now communicate!
175
+
176
+ Data stored in: ${NEXUS_DIR}/nexus.db
177
+ `);
178
+ }
179
+ }
180
+ function showHelp() {
181
+ console.log(`
182
+ Usage: claudelink <command>
183
+
184
+ Commands:
185
+ init Add ClaudeLink to .mcp.json in current project + CLAUDE.md
186
+ init --global Add ClaudeLink globally + ~/.claude/CLAUDE.md
187
+ status Show registered agents and their status
188
+ reset Clear all messages and agent registrations
189
+ help Show this help message
190
+ `);
191
+ }
192
+ function showStatus() {
193
+ const dbPath = path_1.default.join(NEXUS_DIR, "nexus.db");
194
+ if (!fs_1.default.existsSync(dbPath)) {
195
+ console.log(" No ClaudeLink database found. Run 'claudelink init' first.");
196
+ return;
197
+ }
198
+ // Dynamic import to avoid requiring better-sqlite3 for CLI-only usage
199
+ try {
200
+ const Database = require("better-sqlite3");
201
+ const db = new Database(dbPath, { readonly: true });
202
+ const agents = db.prepare("SELECT * FROM agents ORDER BY registered_at DESC").all();
203
+ const msgCount = db.prepare("SELECT COUNT(*) as count FROM messages WHERE read = 0").get();
204
+ const bulletinCount = db.prepare("SELECT COUNT(*) as count FROM bulletin").get();
205
+ console.log(`\n ClaudeLink Status`);
206
+ console.log(` ─────────────────`);
207
+ console.log(` Database: ${dbPath}`);
208
+ console.log(` Unread messages: ${msgCount.count}`);
209
+ console.log(` Bulletin entries: ${bulletinCount.count}`);
210
+ console.log(` Registered agents: ${agents.length}\n`);
211
+ for (const agent of agents) {
212
+ let alive = false;
213
+ try {
214
+ process.kill(agent.pid, 0);
215
+ alive = true;
216
+ }
217
+ catch { }
218
+ const status = alive ? "ONLINE" : "OFFLINE";
219
+ console.log(` [${status}] ${agent.role} (pid: ${agent.pid}) - registered: ${agent.registered_at}`);
220
+ if (agent.description) {
221
+ console.log(` ${agent.description}`);
222
+ }
223
+ }
224
+ console.log();
225
+ db.close();
226
+ }
227
+ catch (err) {
228
+ console.log(` Error reading database: ${err.message}`);
229
+ }
230
+ }
231
+ function resetDB() {
232
+ const dbPath = path_1.default.join(NEXUS_DIR, "nexus.db");
233
+ if (fs_1.default.existsSync(dbPath)) {
234
+ fs_1.default.unlinkSync(dbPath);
235
+ // Clean up WAL files if present
236
+ if (fs_1.default.existsSync(dbPath + "-wal"))
237
+ fs_1.default.unlinkSync(dbPath + "-wal");
238
+ if (fs_1.default.existsSync(dbPath + "-shm"))
239
+ fs_1.default.unlinkSync(dbPath + "-shm");
240
+ console.log(" ClaudeLink database cleared. All messages and registrations removed.");
241
+ }
242
+ else {
243
+ console.log(" No database found. Nothing to reset.");
244
+ }
245
+ }
246
+ // --- Main ---
247
+ const args = process.argv.slice(2);
248
+ const command = args[0];
249
+ printBanner();
250
+ switch (command) {
251
+ case "init":
252
+ if (args.includes("--global")) {
253
+ initGlobal();
254
+ }
255
+ else {
256
+ initProject();
257
+ }
258
+ break;
259
+ case "status":
260
+ showStatus();
261
+ break;
262
+ case "reset":
263
+ resetDB();
264
+ break;
265
+ case "help":
266
+ case "--help":
267
+ case "-h":
268
+ showHelp();
269
+ break;
270
+ default:
271
+ if (command) {
272
+ console.log(` Unknown command: ${command}\n`);
273
+ }
274
+ showHelp();
275
+ break;
276
+ }
277
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/db.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ export interface Agent {
2
+ id: string;
3
+ role: string;
4
+ description: string | null;
5
+ registered_at: string;
6
+ last_seen: string;
7
+ pid: number;
8
+ alive: boolean;
9
+ }
10
+ export interface Message {
11
+ id: number;
12
+ from_role: string;
13
+ from_agent: string;
14
+ to_agent: string | null;
15
+ content: string;
16
+ priority: string;
17
+ created_at: string;
18
+ }
19
+ export interface BulletinEntry {
20
+ id: number;
21
+ from_role: string;
22
+ from_agent: string;
23
+ content: string;
24
+ created_at: string;
25
+ }
26
+ export declare class NexusDB {
27
+ private db;
28
+ constructor();
29
+ private migrate;
30
+ registerAgent(role: string, description: string | null, pid: number): string;
31
+ heartbeat(agentId: string): void;
32
+ getAgents(): Agent[];
33
+ sendMessage(fromId: string, toRole: string, content: string, priority?: string): number;
34
+ broadcastMessage(fromId: string, content: string): void;
35
+ readInbox(agentId: string): Message[];
36
+ postBulletin(fromId: string, content: string): void;
37
+ getBulletin(limit?: number): BulletinEntry[];
38
+ pruneDeadAgents(): void;
39
+ close(): void;
40
+ }
package/dist/db.js ADDED
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.NexusDB = void 0;
7
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const os_1 = __importDefault(require("os"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const crypto_1 = __importDefault(require("crypto"));
12
+ const NEXUS_DIR = path_1.default.join(os_1.default.homedir(), ".claudelink");
13
+ const DB_PATH = path_1.default.join(NEXUS_DIR, "nexus.db");
14
+ function isProcessAlive(pid) {
15
+ try {
16
+ process.kill(pid, 0);
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ class NexusDB {
24
+ constructor() {
25
+ if (!fs_1.default.existsSync(NEXUS_DIR)) {
26
+ fs_1.default.mkdirSync(NEXUS_DIR, { recursive: true });
27
+ }
28
+ this.db = new better_sqlite3_1.default(DB_PATH);
29
+ this.db.pragma("journal_mode = WAL");
30
+ this.db.pragma("busy_timeout = 5000");
31
+ this.migrate();
32
+ }
33
+ migrate() {
34
+ this.db.exec(`
35
+ CREATE TABLE IF NOT EXISTS agents (
36
+ id TEXT PRIMARY KEY,
37
+ role TEXT NOT NULL,
38
+ description TEXT,
39
+ registered_at TEXT DEFAULT (datetime('now')),
40
+ last_seen TEXT DEFAULT (datetime('now')),
41
+ pid INTEGER NOT NULL
42
+ );
43
+
44
+ CREATE TABLE IF NOT EXISTS messages (
45
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
46
+ from_agent TEXT NOT NULL,
47
+ to_agent TEXT,
48
+ content TEXT NOT NULL,
49
+ priority TEXT DEFAULT 'normal',
50
+ read INTEGER DEFAULT 0,
51
+ created_at TEXT DEFAULT (datetime('now')),
52
+ FOREIGN KEY (from_agent) REFERENCES agents(id)
53
+ );
54
+
55
+ CREATE TABLE IF NOT EXISTS bulletin (
56
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
57
+ from_agent TEXT NOT NULL,
58
+ content TEXT NOT NULL,
59
+ created_at TEXT DEFAULT (datetime('now')),
60
+ FOREIGN KEY (from_agent) REFERENCES agents(id)
61
+ );
62
+
63
+ CREATE INDEX IF NOT EXISTS idx_messages_to_agent ON messages(to_agent);
64
+ CREATE INDEX IF NOT EXISTS idx_messages_read ON messages(read);
65
+ CREATE INDEX IF NOT EXISTS idx_agents_role ON agents(role);
66
+ `);
67
+ }
68
+ registerAgent(role, description, pid) {
69
+ this.pruneDeadAgents();
70
+ const id = crypto_1.default.randomUUID();
71
+ this.db
72
+ .prepare(`INSERT INTO agents (id, role, description, pid) VALUES (?, ?, ?, ?)`)
73
+ .run(id, role, description, pid);
74
+ return id;
75
+ }
76
+ heartbeat(agentId) {
77
+ this.db
78
+ .prepare(`UPDATE agents SET last_seen = datetime('now') WHERE id = ?`)
79
+ .run(agentId);
80
+ }
81
+ getAgents() {
82
+ this.pruneDeadAgents();
83
+ const rows = this.db
84
+ .prepare(`SELECT * FROM agents ORDER BY registered_at DESC`)
85
+ .all();
86
+ return rows.map((row) => ({
87
+ ...row,
88
+ alive: isProcessAlive(row.pid),
89
+ }));
90
+ }
91
+ sendMessage(fromId, toRole, content, priority = "normal") {
92
+ const targets = this.db
93
+ .prepare(`SELECT id FROM agents WHERE role = ?`)
94
+ .all(toRole);
95
+ if (targets.length === 0) {
96
+ throw new Error(`No agent found with role "${toRole}". Use get_agents to see available agents.`);
97
+ }
98
+ const insert = this.db.prepare(`INSERT INTO messages (from_agent, to_agent, content, priority) VALUES (?, ?, ?, ?)`);
99
+ const sendAll = this.db.transaction(() => {
100
+ for (const target of targets) {
101
+ insert.run(fromId, target.id, content, priority);
102
+ }
103
+ });
104
+ sendAll();
105
+ return targets.length;
106
+ }
107
+ broadcastMessage(fromId, content) {
108
+ this.db
109
+ .prepare(`INSERT INTO messages (from_agent, to_agent, content, priority) VALUES (?, NULL, ?, 'normal')`)
110
+ .run(fromId, content);
111
+ }
112
+ readInbox(agentId) {
113
+ const readMessages = this.db.transaction(() => {
114
+ const rows = this.db
115
+ .prepare(`SELECT m.id, m.from_agent, m.to_agent, m.content, m.priority, m.created_at,
116
+ a.role as from_role
117
+ FROM messages m
118
+ LEFT JOIN agents a ON m.from_agent = a.id
119
+ WHERE (m.to_agent = ? OR m.to_agent IS NULL)
120
+ AND m.from_agent != ?
121
+ AND m.read = 0
122
+ ORDER BY m.created_at ASC`)
123
+ .all(agentId, agentId);
124
+ if (rows.length > 0) {
125
+ const ids = rows.map((r) => r.id);
126
+ const placeholders = ids.map(() => "?").join(",");
127
+ this.db
128
+ .prepare(`UPDATE messages SET read = 1 WHERE id IN (${placeholders})`)
129
+ .run(...ids);
130
+ }
131
+ return rows;
132
+ });
133
+ return readMessages();
134
+ }
135
+ postBulletin(fromId, content) {
136
+ this.db
137
+ .prepare(`INSERT INTO bulletin (from_agent, content) VALUES (?, ?)`)
138
+ .run(fromId, content);
139
+ }
140
+ getBulletin(limit = 10) {
141
+ return this.db
142
+ .prepare(`SELECT b.id, b.from_agent, b.content, b.created_at,
143
+ a.role as from_role
144
+ FROM bulletin b
145
+ LEFT JOIN agents a ON b.from_agent = a.id
146
+ ORDER BY b.created_at DESC
147
+ LIMIT ?`)
148
+ .all(limit);
149
+ }
150
+ pruneDeadAgents() {
151
+ const agents = this.db
152
+ .prepare(`SELECT id, pid FROM agents`)
153
+ .all();
154
+ const deadIds = agents
155
+ .filter((a) => !isProcessAlive(a.pid))
156
+ .map((a) => a.id);
157
+ if (deadIds.length > 0) {
158
+ const placeholders = deadIds.map(() => "?").join(",");
159
+ this.db
160
+ .prepare(`DELETE FROM agents WHERE id IN (${placeholders})`)
161
+ .run(...deadIds);
162
+ }
163
+ }
164
+ close() {
165
+ this.db.close();
166
+ }
167
+ }
168
+ exports.NexusDB = NexusDB;
169
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};