claudemesh-cli 0.4.0 → 0.5.1

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.
Files changed (2) hide show
  1. package/dist/index.js +1006 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6514,7 +6514,7 @@ function loadConfig() {
6514
6514
  if (!parsed || !Array.isArray(parsed.meshes)) {
6515
6515
  return { version: 1, meshes: [] };
6516
6516
  }
6517
- return { version: 1, meshes: parsed.meshes, displayName: parsed.displayName, groups: parsed.groups };
6517
+ return { version: 1, meshes: parsed.meshes, displayName: parsed.displayName, groups: parsed.groups, messageMode: parsed.messageMode };
6518
6518
  } catch (e) {
6519
6519
  throw new Error(`Failed to load ${CONFIG_PATH}: ${e instanceof Error ? e.message : String(e)}`);
6520
6520
  }
@@ -46486,6 +46486,265 @@ var TOOLS = [
46486
46486
  },
46487
46487
  required: ["id"]
46488
46488
  }
46489
+ },
46490
+ {
46491
+ name: "vector_store",
46492
+ description: "Store an embedding in a per-mesh Qdrant collection. Auto-creates the collection on first use.",
46493
+ inputSchema: {
46494
+ type: "object",
46495
+ properties: {
46496
+ collection: { type: "string", description: "Collection name" },
46497
+ text: { type: "string", description: "Text to embed and store" },
46498
+ metadata: {
46499
+ type: "object",
46500
+ description: "Optional metadata to attach"
46501
+ }
46502
+ },
46503
+ required: ["collection", "text"]
46504
+ }
46505
+ },
46506
+ {
46507
+ name: "vector_search",
46508
+ description: "Semantic search over stored embeddings in a collection.",
46509
+ inputSchema: {
46510
+ type: "object",
46511
+ properties: {
46512
+ collection: { type: "string", description: "Collection name" },
46513
+ query: { type: "string", description: "Search query text" },
46514
+ limit: {
46515
+ type: "number",
46516
+ description: "Max results (default: 10)"
46517
+ }
46518
+ },
46519
+ required: ["collection", "query"]
46520
+ }
46521
+ },
46522
+ {
46523
+ name: "vector_delete",
46524
+ description: "Remove an embedding from a collection.",
46525
+ inputSchema: {
46526
+ type: "object",
46527
+ properties: {
46528
+ collection: { type: "string", description: "Collection name" },
46529
+ id: { type: "string", description: "Embedding ID to delete" }
46530
+ },
46531
+ required: ["collection", "id"]
46532
+ }
46533
+ },
46534
+ {
46535
+ name: "list_collections",
46536
+ description: "List vector collections in this mesh.",
46537
+ inputSchema: { type: "object", properties: {} }
46538
+ },
46539
+ {
46540
+ name: "graph_query",
46541
+ description: "Run a read-only Cypher query on the per-mesh Neo4j database.",
46542
+ inputSchema: {
46543
+ type: "object",
46544
+ properties: {
46545
+ cypher: { type: "string", description: "Cypher MATCH query" }
46546
+ },
46547
+ required: ["cypher"]
46548
+ }
46549
+ },
46550
+ {
46551
+ name: "graph_execute",
46552
+ description: "Run a write Cypher query (CREATE, MERGE, DELETE) on the per-mesh Neo4j database.",
46553
+ inputSchema: {
46554
+ type: "object",
46555
+ properties: {
46556
+ cypher: { type: "string", description: "Cypher write query" }
46557
+ },
46558
+ required: ["cypher"]
46559
+ }
46560
+ },
46561
+ {
46562
+ name: "mesh_query",
46563
+ description: "Run a SELECT query on the per-mesh shared database.",
46564
+ inputSchema: {
46565
+ type: "object",
46566
+ properties: {
46567
+ sql: { type: "string", description: "SQL SELECT query" }
46568
+ },
46569
+ required: ["sql"]
46570
+ }
46571
+ },
46572
+ {
46573
+ name: "mesh_execute",
46574
+ description: "Run DDL/DML on the per-mesh database (CREATE TABLE, INSERT, UPDATE, DELETE).",
46575
+ inputSchema: {
46576
+ type: "object",
46577
+ properties: {
46578
+ sql: { type: "string", description: "SQL statement" }
46579
+ },
46580
+ required: ["sql"]
46581
+ }
46582
+ },
46583
+ {
46584
+ name: "mesh_schema",
46585
+ description: "List tables and columns in the per-mesh shared database.",
46586
+ inputSchema: { type: "object", properties: {} }
46587
+ },
46588
+ {
46589
+ name: "create_stream",
46590
+ description: "Create a real-time data stream in the mesh.",
46591
+ inputSchema: {
46592
+ type: "object",
46593
+ properties: {
46594
+ name: { type: "string", description: "Stream name" }
46595
+ },
46596
+ required: ["name"]
46597
+ }
46598
+ },
46599
+ {
46600
+ name: "publish",
46601
+ description: "Push data to a stream. Subscribers receive it in real-time.",
46602
+ inputSchema: {
46603
+ type: "object",
46604
+ properties: {
46605
+ stream: { type: "string", description: "Stream name" },
46606
+ data: { description: "Any JSON data to publish" }
46607
+ },
46608
+ required: ["stream", "data"]
46609
+ }
46610
+ },
46611
+ {
46612
+ name: "subscribe",
46613
+ description: "Subscribe to a stream. Data pushes arrive as channel notifications.",
46614
+ inputSchema: {
46615
+ type: "object",
46616
+ properties: {
46617
+ stream: { type: "string", description: "Stream name" }
46618
+ },
46619
+ required: ["stream"]
46620
+ }
46621
+ },
46622
+ {
46623
+ name: "list_streams",
46624
+ description: "List active streams in the mesh.",
46625
+ inputSchema: { type: "object", properties: {} }
46626
+ },
46627
+ {
46628
+ name: "share_context",
46629
+ description: "Share your session understanding with the mesh. Call after exploring a codebase area.",
46630
+ inputSchema: {
46631
+ type: "object",
46632
+ properties: {
46633
+ summary: {
46634
+ type: "string",
46635
+ description: "Summary of what you explored/learned"
46636
+ },
46637
+ files_read: {
46638
+ type: "array",
46639
+ items: { type: "string" },
46640
+ description: "File paths you read"
46641
+ },
46642
+ key_findings: {
46643
+ type: "array",
46644
+ items: { type: "string" },
46645
+ description: "Key findings or insights"
46646
+ },
46647
+ tags: {
46648
+ type: "array",
46649
+ items: { type: "string" },
46650
+ description: "Tags for categorization"
46651
+ }
46652
+ },
46653
+ required: ["summary"]
46654
+ }
46655
+ },
46656
+ {
46657
+ name: "get_context",
46658
+ description: "Find context from peers who explored an area. Check before re-reading files another peer already analyzed.",
46659
+ inputSchema: {
46660
+ type: "object",
46661
+ properties: {
46662
+ query: {
46663
+ type: "string",
46664
+ description: "Search query (file path, topic, etc.)"
46665
+ }
46666
+ },
46667
+ required: ["query"]
46668
+ }
46669
+ },
46670
+ {
46671
+ name: "list_contexts",
46672
+ description: "See what all peers currently know about the codebase.",
46673
+ inputSchema: { type: "object", properties: {} }
46674
+ },
46675
+ {
46676
+ name: "create_task",
46677
+ description: "Create a work item for the mesh.",
46678
+ inputSchema: {
46679
+ type: "object",
46680
+ properties: {
46681
+ title: { type: "string", description: "Task title" },
46682
+ assignee: {
46683
+ type: "string",
46684
+ description: "Peer name to assign (optional)"
46685
+ },
46686
+ priority: {
46687
+ type: "string",
46688
+ enum: ["low", "normal", "high", "urgent"],
46689
+ description: "Priority level (default: normal)"
46690
+ },
46691
+ tags: {
46692
+ type: "array",
46693
+ items: { type: "string" },
46694
+ description: "Tags for categorization"
46695
+ }
46696
+ },
46697
+ required: ["title"]
46698
+ }
46699
+ },
46700
+ {
46701
+ name: "claim_task",
46702
+ description: "Claim an unclaimed task to take ownership.",
46703
+ inputSchema: {
46704
+ type: "object",
46705
+ properties: {
46706
+ id: { type: "string", description: "Task ID" }
46707
+ },
46708
+ required: ["id"]
46709
+ }
46710
+ },
46711
+ {
46712
+ name: "complete_task",
46713
+ description: "Mark a task as done with an optional result summary.",
46714
+ inputSchema: {
46715
+ type: "object",
46716
+ properties: {
46717
+ id: { type: "string", description: "Task ID" },
46718
+ result: {
46719
+ type: "string",
46720
+ description: "Summary of what was done"
46721
+ }
46722
+ },
46723
+ required: ["id"]
46724
+ }
46725
+ },
46726
+ {
46727
+ name: "list_tasks",
46728
+ description: "List tasks filtered by status and/or assignee.",
46729
+ inputSchema: {
46730
+ type: "object",
46731
+ properties: {
46732
+ status: {
46733
+ type: "string",
46734
+ enum: ["open", "claimed", "completed"],
46735
+ description: "Filter by status"
46736
+ },
46737
+ assignee: {
46738
+ type: "string",
46739
+ description: "Filter by assignee name"
46740
+ }
46741
+ }
46742
+ }
46743
+ },
46744
+ {
46745
+ name: "mesh_info",
46746
+ description: "Get a complete overview of the mesh: peers, groups, state, memory, files, tasks, streams, tables. Call on session start for full situational awareness.",
46747
+ inputSchema: { type: "object", properties: {} }
46489
46748
  }
46490
46749
  ];
46491
46750
 
@@ -46859,6 +47118,19 @@ class BrokerClient {
46859
47118
  fileUrlResolvers = [];
46860
47119
  fileListResolvers = [];
46861
47120
  fileStatusResolvers = [];
47121
+ vectorStoredResolvers = [];
47122
+ vectorResultsResolvers = [];
47123
+ collectionListResolvers = [];
47124
+ graphResultResolvers = [];
47125
+ contextListResolvers = [];
47126
+ contextResultsResolvers = [];
47127
+ taskCreatedResolvers = [];
47128
+ taskListResolvers = [];
47129
+ meshQueryResolvers = [];
47130
+ meshSchemaResolvers = [];
47131
+ streamCreatedResolvers = [];
47132
+ streamListResolvers = [];
47133
+ streamDataHandlers = new Set;
46862
47134
  async messageStatus(messageId) {
46863
47135
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
46864
47136
  return null;
@@ -46947,10 +47219,265 @@ class BrokerClient {
46947
47219
  const body = await res.json();
46948
47220
  return body.fileId ?? null;
46949
47221
  }
47222
+ async vectorStore(collection, text, metadata) {
47223
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47224
+ return null;
47225
+ return new Promise((resolve) => {
47226
+ this.vectorStoredResolvers.push(resolve);
47227
+ this.ws.send(JSON.stringify({ type: "vector_store", collection, text, metadata }));
47228
+ setTimeout(() => {
47229
+ const idx = this.vectorStoredResolvers.indexOf(resolve);
47230
+ if (idx !== -1) {
47231
+ this.vectorStoredResolvers.splice(idx, 1);
47232
+ resolve(null);
47233
+ }
47234
+ }, 5000);
47235
+ });
47236
+ }
47237
+ async vectorSearch(collection, query, limit) {
47238
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47239
+ return [];
47240
+ return new Promise((resolve) => {
47241
+ this.vectorResultsResolvers.push(resolve);
47242
+ this.ws.send(JSON.stringify({ type: "vector_search", collection, query, limit }));
47243
+ setTimeout(() => {
47244
+ const idx = this.vectorResultsResolvers.indexOf(resolve);
47245
+ if (idx !== -1) {
47246
+ this.vectorResultsResolvers.splice(idx, 1);
47247
+ resolve([]);
47248
+ }
47249
+ }, 5000);
47250
+ });
47251
+ }
47252
+ async vectorDelete(collection, id) {
47253
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47254
+ return;
47255
+ this.ws.send(JSON.stringify({ type: "vector_delete", collection, id }));
47256
+ }
47257
+ async listCollections() {
47258
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47259
+ return [];
47260
+ return new Promise((resolve) => {
47261
+ this.collectionListResolvers.push(resolve);
47262
+ this.ws.send(JSON.stringify({ type: "list_collections" }));
47263
+ setTimeout(() => {
47264
+ const idx = this.collectionListResolvers.indexOf(resolve);
47265
+ if (idx !== -1) {
47266
+ this.collectionListResolvers.splice(idx, 1);
47267
+ resolve([]);
47268
+ }
47269
+ }, 5000);
47270
+ });
47271
+ }
47272
+ async graphQuery(cypher) {
47273
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47274
+ return [];
47275
+ return new Promise((resolve) => {
47276
+ this.graphResultResolvers.push(resolve);
47277
+ this.ws.send(JSON.stringify({ type: "graph_query", cypher }));
47278
+ setTimeout(() => {
47279
+ const idx = this.graphResultResolvers.indexOf(resolve);
47280
+ if (idx !== -1) {
47281
+ this.graphResultResolvers.splice(idx, 1);
47282
+ resolve([]);
47283
+ }
47284
+ }, 5000);
47285
+ });
47286
+ }
47287
+ async graphExecute(cypher) {
47288
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47289
+ return [];
47290
+ return new Promise((resolve) => {
47291
+ this.graphResultResolvers.push(resolve);
47292
+ this.ws.send(JSON.stringify({ type: "graph_execute", cypher }));
47293
+ setTimeout(() => {
47294
+ const idx = this.graphResultResolvers.indexOf(resolve);
47295
+ if (idx !== -1) {
47296
+ this.graphResultResolvers.splice(idx, 1);
47297
+ resolve([]);
47298
+ }
47299
+ }, 5000);
47300
+ });
47301
+ }
47302
+ async shareContext(summary, filesRead, keyFindings, tags) {
47303
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47304
+ return;
47305
+ this.ws.send(JSON.stringify({ type: "share_context", summary, filesRead, keyFindings, tags }));
47306
+ }
47307
+ async getContext(query) {
47308
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47309
+ return [];
47310
+ return new Promise((resolve) => {
47311
+ this.contextResultsResolvers.push(resolve);
47312
+ this.ws.send(JSON.stringify({ type: "get_context", query }));
47313
+ setTimeout(() => {
47314
+ const idx = this.contextResultsResolvers.indexOf(resolve);
47315
+ if (idx !== -1) {
47316
+ this.contextResultsResolvers.splice(idx, 1);
47317
+ resolve([]);
47318
+ }
47319
+ }, 5000);
47320
+ });
47321
+ }
47322
+ async listContexts() {
47323
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47324
+ return [];
47325
+ return new Promise((resolve) => {
47326
+ this.contextListResolvers.push(resolve);
47327
+ this.ws.send(JSON.stringify({ type: "list_contexts" }));
47328
+ setTimeout(() => {
47329
+ const idx = this.contextListResolvers.indexOf(resolve);
47330
+ if (idx !== -1) {
47331
+ this.contextListResolvers.splice(idx, 1);
47332
+ resolve([]);
47333
+ }
47334
+ }, 5000);
47335
+ });
47336
+ }
47337
+ async createTask(title, assignee, priority, tags) {
47338
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47339
+ return null;
47340
+ return new Promise((resolve) => {
47341
+ this.taskCreatedResolvers.push(resolve);
47342
+ this.ws.send(JSON.stringify({ type: "create_task", title, assignee, priority, tags }));
47343
+ setTimeout(() => {
47344
+ const idx = this.taskCreatedResolvers.indexOf(resolve);
47345
+ if (idx !== -1) {
47346
+ this.taskCreatedResolvers.splice(idx, 1);
47347
+ resolve(null);
47348
+ }
47349
+ }, 5000);
47350
+ });
47351
+ }
47352
+ async claimTask(id) {
47353
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47354
+ return;
47355
+ this.ws.send(JSON.stringify({ type: "claim_task", id }));
47356
+ }
47357
+ async completeTask(id, result) {
47358
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47359
+ return;
47360
+ this.ws.send(JSON.stringify({ type: "complete_task", id, result }));
47361
+ }
47362
+ async listTasks(status, assignee) {
47363
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47364
+ return [];
47365
+ return new Promise((resolve) => {
47366
+ this.taskListResolvers.push(resolve);
47367
+ this.ws.send(JSON.stringify({ type: "list_tasks", status, assignee }));
47368
+ setTimeout(() => {
47369
+ const idx = this.taskListResolvers.indexOf(resolve);
47370
+ if (idx !== -1) {
47371
+ this.taskListResolvers.splice(idx, 1);
47372
+ resolve([]);
47373
+ }
47374
+ }, 5000);
47375
+ });
47376
+ }
47377
+ async meshQuery(sql) {
47378
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47379
+ return null;
47380
+ return new Promise((resolve) => {
47381
+ this.meshQueryResolvers.push(resolve);
47382
+ this.ws.send(JSON.stringify({ type: "mesh_query", sql }));
47383
+ setTimeout(() => {
47384
+ const idx = this.meshQueryResolvers.indexOf(resolve);
47385
+ if (idx !== -1) {
47386
+ this.meshQueryResolvers.splice(idx, 1);
47387
+ resolve(null);
47388
+ }
47389
+ }, 5000);
47390
+ });
47391
+ }
47392
+ async meshExecute(sql) {
47393
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47394
+ return;
47395
+ this.ws.send(JSON.stringify({ type: "mesh_execute", sql }));
47396
+ }
47397
+ async meshSchema() {
47398
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47399
+ return [];
47400
+ return new Promise((resolve) => {
47401
+ this.meshSchemaResolvers.push(resolve);
47402
+ this.ws.send(JSON.stringify({ type: "mesh_schema" }));
47403
+ setTimeout(() => {
47404
+ const idx = this.meshSchemaResolvers.indexOf(resolve);
47405
+ if (idx !== -1) {
47406
+ this.meshSchemaResolvers.splice(idx, 1);
47407
+ resolve([]);
47408
+ }
47409
+ }, 5000);
47410
+ });
47411
+ }
47412
+ async createStream(name) {
47413
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47414
+ return null;
47415
+ return new Promise((resolve) => {
47416
+ this.streamCreatedResolvers.push(resolve);
47417
+ this.ws.send(JSON.stringify({ type: "create_stream", name }));
47418
+ setTimeout(() => {
47419
+ const idx = this.streamCreatedResolvers.indexOf(resolve);
47420
+ if (idx !== -1) {
47421
+ this.streamCreatedResolvers.splice(idx, 1);
47422
+ resolve(null);
47423
+ }
47424
+ }, 5000);
47425
+ });
47426
+ }
47427
+ async publish(stream, data) {
47428
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47429
+ return;
47430
+ this.ws.send(JSON.stringify({ type: "publish", stream, data }));
47431
+ }
47432
+ async subscribe(stream) {
47433
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47434
+ return;
47435
+ this.ws.send(JSON.stringify({ type: "subscribe", stream }));
47436
+ }
47437
+ async unsubscribe(stream) {
47438
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47439
+ return;
47440
+ this.ws.send(JSON.stringify({ type: "unsubscribe", stream }));
47441
+ }
47442
+ async listStreams() {
47443
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47444
+ return [];
47445
+ return new Promise((resolve) => {
47446
+ this.streamListResolvers.push(resolve);
47447
+ this.ws.send(JSON.stringify({ type: "list_streams" }));
47448
+ setTimeout(() => {
47449
+ const idx = this.streamListResolvers.indexOf(resolve);
47450
+ if (idx !== -1) {
47451
+ this.streamListResolvers.splice(idx, 1);
47452
+ resolve([]);
47453
+ }
47454
+ }, 5000);
47455
+ });
47456
+ }
47457
+ onStreamData(handler) {
47458
+ this.streamDataHandlers.add(handler);
47459
+ return () => this.streamDataHandlers.delete(handler);
47460
+ }
46950
47461
  onStateChange(handler) {
46951
47462
  this.stateChangeHandlers.add(handler);
46952
47463
  return () => this.stateChangeHandlers.delete(handler);
46953
47464
  }
47465
+ meshInfoResolvers = [];
47466
+ async meshInfo() {
47467
+ if (!this.ws || this.ws.readyState !== this.ws.OPEN)
47468
+ return null;
47469
+ return new Promise((resolve) => {
47470
+ this.meshInfoResolvers.push(resolve);
47471
+ this.ws.send(JSON.stringify({ type: "mesh_info" }));
47472
+ setTimeout(() => {
47473
+ const idx = this.meshInfoResolvers.indexOf(resolve);
47474
+ if (idx !== -1) {
47475
+ this.meshInfoResolvers.splice(idx, 1);
47476
+ resolve(null);
47477
+ }
47478
+ }, 5000);
47479
+ });
47480
+ }
46954
47481
  close() {
46955
47482
  this.closed = true;
46956
47483
  if (this.helloTimer)
@@ -47113,6 +47640,114 @@ class BrokerClient {
47113
47640
  resolver(accesses);
47114
47641
  return;
47115
47642
  }
47643
+ if (msg.type === "vector_stored") {
47644
+ const resolver = this.vectorStoredResolvers.shift();
47645
+ if (resolver)
47646
+ resolver(msg.id ? String(msg.id) : null);
47647
+ return;
47648
+ }
47649
+ if (msg.type === "vector_results") {
47650
+ const results = msg.results ?? [];
47651
+ const resolver = this.vectorResultsResolvers.shift();
47652
+ if (resolver)
47653
+ resolver(results);
47654
+ return;
47655
+ }
47656
+ if (msg.type === "collection_list") {
47657
+ const collections = msg.collections ?? [];
47658
+ const resolver = this.collectionListResolvers.shift();
47659
+ if (resolver)
47660
+ resolver(collections);
47661
+ return;
47662
+ }
47663
+ if (msg.type === "graph_result") {
47664
+ const rows = msg.rows ?? [];
47665
+ const resolver = this.graphResultResolvers.shift();
47666
+ if (resolver)
47667
+ resolver(rows);
47668
+ return;
47669
+ }
47670
+ if (msg.type === "context_list") {
47671
+ const contexts = msg.contexts ?? [];
47672
+ const resolver = this.contextListResolvers.shift();
47673
+ if (resolver)
47674
+ resolver(contexts);
47675
+ return;
47676
+ }
47677
+ if (msg.type === "context_results") {
47678
+ const contexts = msg.contexts ?? [];
47679
+ const resolver = this.contextResultsResolvers.shift();
47680
+ if (resolver)
47681
+ resolver(contexts);
47682
+ return;
47683
+ }
47684
+ if (msg.type === "task_created") {
47685
+ const resolver = this.taskCreatedResolvers.shift();
47686
+ if (resolver)
47687
+ resolver(msg.id ? String(msg.id) : null);
47688
+ return;
47689
+ }
47690
+ if (msg.type === "task_list") {
47691
+ const tasks = msg.tasks ?? [];
47692
+ const resolver = this.taskListResolvers.shift();
47693
+ if (resolver)
47694
+ resolver(tasks);
47695
+ return;
47696
+ }
47697
+ if (msg.type === "mesh_query_result") {
47698
+ const resolver = this.meshQueryResolvers.shift();
47699
+ if (resolver) {
47700
+ if (msg.columns) {
47701
+ resolver({
47702
+ columns: msg.columns ?? [],
47703
+ rows: msg.rows ?? [],
47704
+ rowCount: msg.rowCount ?? 0
47705
+ });
47706
+ } else {
47707
+ resolver(null);
47708
+ }
47709
+ }
47710
+ return;
47711
+ }
47712
+ if (msg.type === "mesh_schema_result") {
47713
+ const tables = msg.tables ?? [];
47714
+ const resolver = this.meshSchemaResolvers.shift();
47715
+ if (resolver)
47716
+ resolver(tables);
47717
+ return;
47718
+ }
47719
+ if (msg.type === "stream_created") {
47720
+ const resolver = this.streamCreatedResolvers.shift();
47721
+ if (resolver)
47722
+ resolver(msg.id ? String(msg.id) : null);
47723
+ return;
47724
+ }
47725
+ if (msg.type === "stream_list") {
47726
+ const streams = msg.streams ?? [];
47727
+ const resolver = this.streamListResolvers.shift();
47728
+ if (resolver)
47729
+ resolver(streams);
47730
+ return;
47731
+ }
47732
+ if (msg.type === "stream_data") {
47733
+ const evt = {
47734
+ stream: String(msg.stream ?? ""),
47735
+ data: msg.data,
47736
+ publishedBy: String(msg.publishedBy ?? "")
47737
+ };
47738
+ for (const h of this.streamDataHandlers) {
47739
+ try {
47740
+ h(evt);
47741
+ } catch {}
47742
+ }
47743
+ return;
47744
+ }
47745
+ if (msg.type === "mesh_info_result") {
47746
+ const resolver = this.meshInfoResolvers.shift();
47747
+ if (resolver)
47748
+ resolver(msg);
47749
+ return;
47750
+ }
47116
47751
  if (msg.type === "error") {
47117
47752
  this.debug(`broker error: ${msg.code} ${msg.message}`);
47118
47753
  const id = msg.id ? String(msg.id) : null;
@@ -47286,6 +47921,7 @@ async function startMcpServer() {
47286
47921
  const config2 = loadConfig();
47287
47922
  const myName = config2.displayName ?? "unnamed";
47288
47923
  const myGroups = (config2.groups ?? []).map((g) => `@${g.name}${g.role ? ":" + g.role : ""}`).join(", ") || "none";
47924
+ const messageMode = config2.messageMode ?? "push";
47289
47925
  const server = new Server({ name: "claudemesh", version: "0.3.0" }, {
47290
47926
  capabilities: {
47291
47927
  experimental: { "claude/channel": {} },
@@ -47318,6 +47954,26 @@ When you receive a <channel source="claudemesh" ...> message, RESPOND IMMEDIATEL
47318
47954
  | list_files(query?, from?) | Find files shared in the mesh. |
47319
47955
  | file_status(id) | Check who has accessed a file. |
47320
47956
  | delete_file(id) | Remove a shared file from the mesh. |
47957
+ | vector_store(collection, text, metadata?) | Store embedding in per-mesh Qdrant collection. |
47958
+ | vector_search(collection, query, limit?) | Semantic search over stored embeddings. |
47959
+ | vector_delete(collection, id) | Remove an embedding. |
47960
+ | list_collections() | List vector collections in this mesh. |
47961
+ | graph_query(cypher) | Read-only Cypher query on per-mesh Neo4j. |
47962
+ | graph_execute(cypher) | Write Cypher query (CREATE, MERGE, DELETE). |
47963
+ | mesh_query(sql) | Run a SELECT query on the per-mesh shared database. |
47964
+ | mesh_execute(sql) | Run DDL/DML on the per-mesh database (CREATE TABLE, INSERT, UPDATE, DELETE). |
47965
+ | mesh_schema() | List tables and columns in the per-mesh shared database. |
47966
+ | create_stream(name) | Create a real-time data stream in the mesh. |
47967
+ | publish(stream, data) | Push data to a stream. Subscribers receive it in real-time. |
47968
+ | subscribe(stream) | Subscribe to a stream. Data pushes arrive as channel notifications. |
47969
+ | list_streams() | List active streams in the mesh. |
47970
+ | share_context(summary, files_read?, key_findings?, tags?) | Share session understanding with peers. |
47971
+ | get_context(query) | Find context from peers who explored an area. |
47972
+ | list_contexts() | See what all peers currently know. |
47973
+ | create_task(title, assignee?, priority?, tags?) | Create a work item. |
47974
+ | claim_task(id) | Claim an unclaimed task. |
47975
+ | complete_task(id, result?) | Mark task done with optional result. |
47976
+ | list_tasks(status?, assignee?) | List tasks filtered by status/assignee. |
47321
47977
 
47322
47978
  If multiple meshes are joined, prefix \`to\` with \`<mesh-slug>:\` to disambiguate (e.g. \`dev-team:Alice\`).
47323
47979
 
@@ -47344,13 +48000,37 @@ Persistent knowledge that survives across sessions. Use remember(content, tags?)
47344
48000
  share_file for persistent references, send_message(file:) for ephemeral attachments.
47345
48001
  Tags on shared files make them searchable. Use list_files to find what peers shared.
47346
48002
 
48003
+ ## Vectors
48004
+ Store and search semantic embeddings. Use vector_store to index content, vector_search to find similar content.
48005
+
48006
+ ## Graph
48007
+ Build and query entity relationship graphs. Use graph_execute for writes (CREATE, MERGE), graph_query for reads (MATCH).
48008
+
48009
+ ## Mesh Database
48010
+ Per-mesh PostgreSQL database. Use mesh_execute for DDL/DML (CREATE TABLE, INSERT), mesh_query for SELECT, mesh_schema to inspect tables. Schema auto-created on first use.
48011
+
48012
+ ## Streams
48013
+ Real-time data channels. create_stream to start one, publish to push data, subscribe to receive pushes. Use for build logs, deploy status, live metrics.
48014
+
48015
+ ## Context
48016
+ Share your session understanding with peers. Use share_context after exploring a codebase area. Check get_context before re-reading files another peer already analyzed.
48017
+
48018
+ ## Tasks
48019
+ Create and claim work items. create_task to propose work, claim_task to take ownership, complete_task when done. Prevents duplicate effort.
48020
+
47347
48021
  ## Priority
47348
48022
  - "now": interrupt immediately, even if recipient is in DND (use for urgent: broken deploy, blocking issue)
47349
48023
  - "next" (default): deliver when recipient goes idle (normal coordination)
47350
48024
  - "low": pull-only via check_messages (FYI, non-blocking context)
47351
48025
 
47352
48026
  ## Coordination
47353
- Call list_peers at session start to understand who is online, their roles, and what they are working on. If you are a group lead, gather input from members before responding to external requests — do not answer alone. If you are a member, contribute to your lead when asked. Use @group messages for team-wide questions, direct messages for 1:1 coordination. Set a meaningful summary so peers know your current focus.`
48027
+ Call list_peers at session start to understand who is online, their roles, and what they are working on. If you are a group lead, gather input from members before responding to external requests — do not answer alone. If you are a member, contribute to your lead when asked. Use @group messages for team-wide questions, direct messages for 1:1 coordination. Set a meaningful summary so peers know your current focus.
48028
+
48029
+ ## Message Mode
48030
+ Your message mode is "${messageMode}".
48031
+ - push: messages arrive in real-time as channel notifications. Respond immediately.
48032
+ - inbox: messages are held. You'll see "[inbox] New message from X" notifications. Call check_messages to read them.
48033
+ - off: no message notifications. Use check_messages manually to poll.`
47354
48034
  });
47355
48035
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
47356
48036
  tools: TOOLS
@@ -47622,6 +48302,266 @@ ${lines.join(`
47622
48302
  await client.deleteFile(id);
47623
48303
  return text(`Deleted: ${id}`);
47624
48304
  }
48305
+ case "vector_store": {
48306
+ const { collection, text: storeText, metadata } = args ?? {};
48307
+ if (!collection || !storeText)
48308
+ return text("vector_store: `collection` and `text` required", true);
48309
+ const client = allClients()[0];
48310
+ if (!client)
48311
+ return text("vector_store: not connected", true);
48312
+ const id = await client.vectorStore(collection, storeText, metadata);
48313
+ return text(`Stored in ${collection}${id ? ` (${id})` : ""}`);
48314
+ }
48315
+ case "vector_search": {
48316
+ const { collection, query, limit } = args ?? {};
48317
+ if (!collection || !query)
48318
+ return text("vector_search: `collection` and `query` required", true);
48319
+ const client = allClients()[0];
48320
+ if (!client)
48321
+ return text("vector_search: not connected", true);
48322
+ const results = await client.vectorSearch(collection, query, limit);
48323
+ if (results.length === 0)
48324
+ return text(`No results in ${collection} for "${query}".`);
48325
+ const lines = results.map((r) => `- [${r.id.slice(0, 8)}…] (score: ${r.score.toFixed(3)}) ${r.text.slice(0, 120)}${r.text.length > 120 ? "…" : ""}`);
48326
+ return text(`${results.length} result(s) in ${collection}:
48327
+ ${lines.join(`
48328
+ `)}`);
48329
+ }
48330
+ case "vector_delete": {
48331
+ const { collection, id } = args ?? {};
48332
+ if (!collection || !id)
48333
+ return text("vector_delete: `collection` and `id` required", true);
48334
+ const client = allClients()[0];
48335
+ if (!client)
48336
+ return text("vector_delete: not connected", true);
48337
+ await client.vectorDelete(collection, id);
48338
+ return text(`Deleted ${id} from ${collection}`);
48339
+ }
48340
+ case "list_collections": {
48341
+ const client = allClients()[0];
48342
+ if (!client)
48343
+ return text("list_collections: not connected", true);
48344
+ const collections = await client.listCollections();
48345
+ if (collections.length === 0)
48346
+ return text("No vector collections.");
48347
+ return text(`Collections:
48348
+ ${collections.map((c) => `- ${c}`).join(`
48349
+ `)}`);
48350
+ }
48351
+ case "graph_query": {
48352
+ const { cypher } = args ?? {};
48353
+ if (!cypher)
48354
+ return text("graph_query: `cypher` required", true);
48355
+ const client = allClients()[0];
48356
+ if (!client)
48357
+ return text("graph_query: not connected", true);
48358
+ const rows = await client.graphQuery(cypher);
48359
+ if (rows.length === 0)
48360
+ return text("No results.");
48361
+ return text(JSON.stringify(rows, null, 2));
48362
+ }
48363
+ case "graph_execute": {
48364
+ const { cypher } = args ?? {};
48365
+ if (!cypher)
48366
+ return text("graph_execute: `cypher` required", true);
48367
+ const client = allClients()[0];
48368
+ if (!client)
48369
+ return text("graph_execute: not connected", true);
48370
+ const rows = await client.graphExecute(cypher);
48371
+ return text(rows.length > 0 ? JSON.stringify(rows, null, 2) : "Executed successfully.");
48372
+ }
48373
+ case "share_context": {
48374
+ const { summary, files_read, key_findings, tags } = args ?? {};
48375
+ if (!summary)
48376
+ return text("share_context: `summary` required", true);
48377
+ const client = allClients()[0];
48378
+ if (!client)
48379
+ return text("share_context: not connected", true);
48380
+ await client.shareContext(summary, files_read, key_findings, tags);
48381
+ return text(`Context shared: "${summary.slice(0, 80)}${summary.length > 80 ? "…" : ""}"`);
48382
+ }
48383
+ case "get_context": {
48384
+ const { query } = args ?? {};
48385
+ if (!query)
48386
+ return text("get_context: `query` required", true);
48387
+ const client = allClients()[0];
48388
+ if (!client)
48389
+ return text("get_context: not connected", true);
48390
+ const contexts = await client.getContext(query);
48391
+ if (contexts.length === 0)
48392
+ return text(`No context found for "${query}".`);
48393
+ const lines = contexts.map((c) => {
48394
+ const files = c.filesRead.length ? `
48395
+ Files: ${c.filesRead.join(", ")}` : "";
48396
+ const findings = c.keyFindings.length ? `
48397
+ Findings: ${c.keyFindings.join("; ")}` : "";
48398
+ return `- **${c.peerName}** (${c.updatedAt}): ${c.summary}${files}${findings}`;
48399
+ });
48400
+ return text(`${contexts.length} context(s):
48401
+ ${lines.join(`
48402
+ `)}`);
48403
+ }
48404
+ case "list_contexts": {
48405
+ const client = allClients()[0];
48406
+ if (!client)
48407
+ return text("list_contexts: not connected", true);
48408
+ const contexts = await client.listContexts();
48409
+ if (contexts.length === 0)
48410
+ return text("No peer contexts shared yet.");
48411
+ const lines = contexts.map((c) => `- **${c.peerName}**: ${c.summary}${c.tags.length ? ` [${c.tags.join(", ")}]` : ""}`);
48412
+ return text(`Peer contexts:
48413
+ ${lines.join(`
48414
+ `)}`);
48415
+ }
48416
+ case "create_task": {
48417
+ const { title, assignee, priority, tags } = args ?? {};
48418
+ if (!title)
48419
+ return text("create_task: `title` required", true);
48420
+ const client = allClients()[0];
48421
+ if (!client)
48422
+ return text("create_task: not connected", true);
48423
+ const id = await client.createTask(title, assignee, priority, tags);
48424
+ return text(`Task created${id ? ` (${id})` : ""}: "${title}"${assignee ? ` → ${assignee}` : ""}`);
48425
+ }
48426
+ case "claim_task": {
48427
+ const { id } = args ?? {};
48428
+ if (!id)
48429
+ return text("claim_task: `id` required", true);
48430
+ const client = allClients()[0];
48431
+ if (!client)
48432
+ return text("claim_task: not connected", true);
48433
+ await client.claimTask(id);
48434
+ return text(`Claimed task: ${id}`);
48435
+ }
48436
+ case "complete_task": {
48437
+ const { id, result } = args ?? {};
48438
+ if (!id)
48439
+ return text("complete_task: `id` required", true);
48440
+ const client = allClients()[0];
48441
+ if (!client)
48442
+ return text("complete_task: not connected", true);
48443
+ await client.completeTask(id, result);
48444
+ return text(`Completed task: ${id}${result ? ` — ${result}` : ""}`);
48445
+ }
48446
+ case "list_tasks": {
48447
+ const { status, assignee } = args ?? {};
48448
+ const client = allClients()[0];
48449
+ if (!client)
48450
+ return text("list_tasks: not connected", true);
48451
+ const tasks = await client.listTasks(status, assignee);
48452
+ if (tasks.length === 0)
48453
+ return text("No tasks found.");
48454
+ const lines = tasks.map((t) => `- [${t.id.slice(0, 8)}…] **${t.title}** (${t.status}, ${t.priority}) ${t.assignee ? `→ ${t.assignee}` : "unassigned"} (by ${t.createdBy})`);
48455
+ return text(`${tasks.length} task(s):
48456
+ ${lines.join(`
48457
+ `)}`);
48458
+ }
48459
+ case "mesh_query": {
48460
+ const { sql: querySql } = args ?? {};
48461
+ if (!querySql)
48462
+ return text("mesh_query: `sql` required", true);
48463
+ const client = allClients()[0];
48464
+ if (!client)
48465
+ return text("mesh_query: not connected", true);
48466
+ const result = await client.meshQuery(querySql);
48467
+ if (!result)
48468
+ return text("mesh_query: query failed or timed out", true);
48469
+ if (result.rows.length === 0)
48470
+ return text(`Query returned 0 rows.`);
48471
+ const header = `| ${result.columns.join(" | ")} |`;
48472
+ const sep = `| ${result.columns.map(() => "---").join(" | ")} |`;
48473
+ const rows = result.rows.map((r) => `| ${result.columns.map((c) => String(r[c] ?? "")).join(" | ")} |`);
48474
+ return text(`${result.rowCount} row(s):
48475
+ ${header}
48476
+ ${sep}
48477
+ ${rows.join(`
48478
+ `)}`);
48479
+ }
48480
+ case "mesh_execute": {
48481
+ const { sql: execSql } = args ?? {};
48482
+ if (!execSql)
48483
+ return text("mesh_execute: `sql` required", true);
48484
+ const client = allClients()[0];
48485
+ if (!client)
48486
+ return text("mesh_execute: not connected", true);
48487
+ await client.meshExecute(execSql);
48488
+ return text(`Executed.`);
48489
+ }
48490
+ case "mesh_schema": {
48491
+ const client = allClients()[0];
48492
+ if (!client)
48493
+ return text("mesh_schema: not connected", true);
48494
+ const tables = await client.meshSchema();
48495
+ if (!tables || tables.length === 0)
48496
+ return text("No tables in mesh database.");
48497
+ const lines = tables.map((t) => `**${t.name}**: ${t.columns.map((c) => `${c.name} (${c.type}${c.nullable ? ", nullable" : ""})`).join(", ")}`);
48498
+ return text(lines.join(`
48499
+ `));
48500
+ }
48501
+ case "create_stream": {
48502
+ const { name: streamName } = args ?? {};
48503
+ if (!streamName)
48504
+ return text("create_stream: `name` required", true);
48505
+ const client = allClients()[0];
48506
+ if (!client)
48507
+ return text("create_stream: not connected", true);
48508
+ const streamId = await client.createStream(streamName);
48509
+ return text(`Stream created: ${streamName}${streamId ? ` (${streamId})` : ""}`);
48510
+ }
48511
+ case "publish": {
48512
+ const { stream: pubStream, data: pubData } = args ?? {};
48513
+ if (!pubStream)
48514
+ return text("publish: `stream` required", true);
48515
+ const client = allClients()[0];
48516
+ if (!client)
48517
+ return text("publish: not connected", true);
48518
+ await client.publish(pubStream, pubData);
48519
+ return text(`Published to ${pubStream}.`);
48520
+ }
48521
+ case "subscribe": {
48522
+ const { stream: subStream } = args ?? {};
48523
+ if (!subStream)
48524
+ return text("subscribe: `stream` required", true);
48525
+ const client = allClients()[0];
48526
+ if (!client)
48527
+ return text("subscribe: not connected", true);
48528
+ await client.subscribe(subStream);
48529
+ return text(`Subscribed to ${subStream}. Data pushes will arrive as channel notifications.`);
48530
+ }
48531
+ case "list_streams": {
48532
+ const client = allClients()[0];
48533
+ if (!client)
48534
+ return text("list_streams: not connected", true);
48535
+ const streams = await client.listStreams();
48536
+ if (streams.length === 0)
48537
+ return text("No active streams.");
48538
+ const lines = streams.map((s) => `- **${s.name}** (${s.id.slice(0, 8)}…) by ${s.createdBy}, ${s.subscriberCount} subscriber(s)`);
48539
+ return text(lines.join(`
48540
+ `));
48541
+ }
48542
+ case "mesh_info": {
48543
+ const client = allClients()[0];
48544
+ if (!client)
48545
+ return text("mesh_info: not connected", true);
48546
+ const info = await client.meshInfo();
48547
+ if (!info)
48548
+ return text("mesh_info: timed out", true);
48549
+ const lines = [
48550
+ `**Mesh**: ${info.mesh}`,
48551
+ `**Peers**: ${info.peers}`,
48552
+ `**Groups**: ${info.groups?.join(", ") || "none"}`,
48553
+ `**State keys**: ${info.stateKeys?.join(", ") || "none"}`,
48554
+ `**Memories**: ${info.memoryCount}`,
48555
+ `**Files**: ${info.fileCount}`,
48556
+ `**Tasks**: open=${info.tasks?.open ?? 0}, claimed=${info.tasks?.claimed ?? 0}, done=${info.tasks?.done ?? 0}`,
48557
+ `**Streams**: ${info.streams?.join(", ") || "none"}`,
48558
+ `**Tables**: ${info.tables?.join(", ") || "none"}`,
48559
+ `**Your name**: ${info.yourName}`,
48560
+ `**Your groups**: ${info.yourGroups?.map((g) => `@${g.name}${g.role ? ":" + g.role : ""}`).join(", ") || "none"}`
48561
+ ];
48562
+ return text(lines.join(`
48563
+ `));
48564
+ }
47625
48565
  default:
47626
48566
  return text(`Unknown tool: ${name}`, true);
47627
48567
  }
@@ -47631,8 +48571,22 @@ ${lines.join(`
47631
48571
  await server.connect(transport);
47632
48572
  for (const client of allClients()) {
47633
48573
  client.onPush(async (msg) => {
48574
+ if (messageMode === "off")
48575
+ return;
47634
48576
  const fromPubkey = msg.senderPubkey || "";
47635
48577
  const fromName = fromPubkey ? await resolvePeerName(client, fromPubkey) : "unknown";
48578
+ if (messageMode === "inbox") {
48579
+ try {
48580
+ await server.notification({
48581
+ method: "notifications/claude/channel",
48582
+ params: {
48583
+ content: `[inbox] New message from ${fromName}. Use check_messages to read.`,
48584
+ meta: { kind: "inbox_notification", from_name: fromName }
48585
+ }
48586
+ });
48587
+ } catch {}
48588
+ return;
48589
+ }
47636
48590
  const content = msg.plaintext ?? decryptFailedWarning(fromPubkey);
47637
48591
  try {
47638
48592
  await server.notification({
@@ -47653,6 +48607,21 @@ ${lines.join(`
47653
48607
  });
47654
48608
  } catch {}
47655
48609
  });
48610
+ client.onStreamData(async (evt) => {
48611
+ try {
48612
+ await server.notification({
48613
+ method: "notifications/claude/channel",
48614
+ params: {
48615
+ content: `[stream:${evt.stream}] from ${evt.publishedBy}: ${JSON.stringify(evt.data)}`,
48616
+ meta: {
48617
+ kind: "stream_data",
48618
+ stream: evt.stream,
48619
+ published_by: evt.publishedBy
48620
+ }
48621
+ }
48622
+ });
48623
+ } catch {}
48624
+ });
47656
48625
  client.onStateChange(async (change) => {
47657
48626
  try {
47658
48627
  await server.notification({
@@ -48274,6 +49243,7 @@ function parseArgs(argv) {
48274
49243
  groups: null,
48275
49244
  joinLink: null,
48276
49245
  meshSlug: null,
49246
+ messageMode: null,
48277
49247
  quiet: false,
48278
49248
  skipPermConfirm: false,
48279
49249
  claudeArgs: []
@@ -48301,6 +49271,10 @@ function parseArgs(argv) {
48301
49271
  result.meshSlug = argv[++i];
48302
49272
  } else if (arg.startsWith("--mesh=")) {
48303
49273
  result.meshSlug = arg.slice("--mesh=".length);
49274
+ } else if (arg === "--inbox") {
49275
+ result.messageMode = "inbox";
49276
+ } else if (arg === "--no-messages") {
49277
+ result.messageMode = "off";
48304
49278
  } else if (arg === "--quiet") {
48305
49279
  result.quiet = true;
48306
49280
  } else if (arg === "-y" || arg === "--yes") {
@@ -48386,16 +49360,22 @@ async function confirmPermissions() {
48386
49360
  });
48387
49361
  });
48388
49362
  }
48389
- function printBanner(name, meshSlug, role, groups) {
49363
+ function printBanner(name, meshSlug, role, groups, messageMode) {
48390
49364
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
48391
49365
  const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
48392
49366
  const bold = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
48393
49367
  const roleSuffix = role ? ` (${role})` : "";
48394
49368
  const groupTags = groups.length ? " [" + groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
48395
49369
  const rule = "─".repeat(60);
48396
- console.log(bold(`claudemesh launch`) + dim(` — as ${name}${roleSuffix} on ${meshSlug}${groupTags}`));
49370
+ console.log(bold(`claudemesh launch`) + dim(` — as ${name}${roleSuffix} on ${meshSlug}${groupTags} [${messageMode}]`));
48397
49371
  console.log(rule);
48398
- console.log("Peer messages arrive as <channel> reminders in real-time.");
49372
+ if (messageMode === "push") {
49373
+ console.log("Peer messages arrive as <channel> reminders in real-time.");
49374
+ } else if (messageMode === "inbox") {
49375
+ console.log("Peer messages held in inbox. Use check_messages to read.");
49376
+ } else {
49377
+ console.log("Messages off. Use check_messages to poll manually.");
49378
+ }
48399
49379
  console.log("Peers send text only — they cannot call tools or read files.");
48400
49380
  console.log(dim(`Config: ${getConfigPath()}`));
48401
49381
  console.log(rule);
@@ -48450,6 +49430,7 @@ async function runLaunch(extraArgs) {
48450
49430
  const displayName = args.name ?? `${hostname2()}-${process.pid}`;
48451
49431
  let role = args.role;
48452
49432
  let parsedGroups = args.groups ? parseGroupsString(args.groups) : [];
49433
+ let messageMode = args.messageMode ?? "push";
48453
49434
  if (!args.quiet) {
48454
49435
  if (role === null) {
48455
49436
  const answer = await askLine(" Role (optional): ");
@@ -48461,6 +49442,22 @@ async function runLaunch(extraArgs) {
48461
49442
  if (answer)
48462
49443
  parsedGroups = parseGroupsString(answer);
48463
49444
  }
49445
+ if (args.messageMode === null) {
49446
+ console.log(`
49447
+ Message mode:`);
49448
+ console.log(" 1) Push (real-time, peers can interrupt your work)");
49449
+ console.log(" 2) Inbox (held until you check, notification only)");
49450
+ console.log(" 3) Off (tools only, no messages)");
49451
+ console.log("");
49452
+ const answer = await askLine(" Choice [1]: ");
49453
+ const choice = parseInt(answer || "1", 10);
49454
+ if (choice === 2)
49455
+ messageMode = "inbox";
49456
+ else if (choice === 3)
49457
+ messageMode = "off";
49458
+ else
49459
+ messageMode = "push";
49460
+ }
48464
49461
  if (role || parsedGroups.length)
48465
49462
  console.log("");
48466
49463
  }
@@ -48480,12 +49477,13 @@ async function runLaunch(extraArgs) {
48480
49477
  version: 1,
48481
49478
  meshes: [mesh],
48482
49479
  displayName,
48483
- ...parsedGroups.length > 0 ? { groups: parsedGroups } : {}
49480
+ ...parsedGroups.length > 0 ? { groups: parsedGroups } : {},
49481
+ messageMode
48484
49482
  };
48485
49483
  writeFileSync4(join4(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
48486
49484
  `, "utf-8");
48487
49485
  if (!args.quiet) {
48488
- printBanner(displayName, mesh.slug, role, parsedGroups);
49486
+ printBanner(displayName, mesh.slug, role, parsedGroups, messageMode);
48489
49487
  if (!args.skipPermConfirm) {
48490
49488
  await confirmPermissions();
48491
49489
  }
@@ -48553,7 +49551,7 @@ init_config();
48553
49551
  // package.json
48554
49552
  var package_default = {
48555
49553
  name: "claudemesh-cli",
48556
- version: "0.4.0",
49554
+ version: "0.5.1",
48557
49555
  description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
48558
49556
  keywords: [
48559
49557
  "claude-code",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudemesh-cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
5
5
  "keywords": [
6
6
  "claude-code",