volute 0.18.0 → 0.20.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.
Files changed (117) hide show
  1. package/README.md +67 -67
  2. package/dist/activity-events-OMXKXD5N.js +16 -0
  3. package/dist/archive-ZCFOSTKB.js +15 -0
  4. package/dist/{channel-SLURLIRV.js → channel-PUQKGSQM.js} +60 -7
  5. package/dist/{chunk-6BDNWYKG.js → chunk-32VR2EOH.js} +2 -2
  6. package/dist/chunk-5XNT2472.js +36 -0
  7. package/dist/{chunk-QJIIHU32.js → chunk-7NO7EV5Z.js} +2 -2
  8. package/dist/{chunk-6DVBMLVN.js → chunk-7UFKREVW.js} +2 -2
  9. package/dist/chunk-AW7P4EVV.js +159 -0
  10. package/dist/{chunk-2Y77MCFG.js → chunk-DYZGP3EW.js} +2 -2
  11. package/dist/{chunk-M77QBTEH.js → chunk-EBGCNDMM.js} +24 -14
  12. package/dist/{chunk-37X7ECMF.js → chunk-FCDU5BFX.js} +1 -1
  13. package/dist/chunk-FGSYHIS3.js +891 -0
  14. package/dist/chunk-GZ7DW4YL.js +97 -0
  15. package/dist/chunk-IKMY5X76.js +375 -0
  16. package/dist/chunk-NSE7VJQA.js +159 -0
  17. package/dist/{chunk-GSPWIM5E.js → chunk-O6ASDHFO.js} +79 -7
  18. package/dist/{chunk-ZCEYUUID.js → chunk-OGXOMR65.js} +2 -1
  19. package/dist/{chunk-AYB7XAWO.js → chunk-PUVXOZ6T.js} +120 -279
  20. package/dist/{chunk-GK4E7LM7.js → chunk-RHEGSQFJ.js} +1 -1
  21. package/dist/{chunk-MVSXRMJJ.js → chunk-SCUDS4US.js} +1 -1
  22. package/dist/chunk-TIWH32HP.js +227 -0
  23. package/dist/{chunk-FW5API7X.js → chunk-UJ6GHNR7.js} +2 -2
  24. package/dist/chunk-UU7A7KLB.js +58 -0
  25. package/dist/{chunk-OYSZNX5I.js → chunk-VDWCHYTS.js} +1 -1
  26. package/dist/{chunk-OJQ47SCA.js → chunk-WC6ZHVRL.js} +1 -1
  27. package/dist/chunk-YUIHSKR6.js +72 -0
  28. package/dist/cli.js +43 -25
  29. package/dist/{connector-3ELFMI2R.js → connector-JBVNZ7VK.js} +6 -6
  30. package/dist/connectors/discord.js +2 -2
  31. package/dist/connectors/slack.js +2 -2
  32. package/dist/connectors/telegram.js +2 -2
  33. package/dist/{create-ZWHCRT5F.js → create-HP4OVVHF.js} +6 -4
  34. package/dist/{daemon-client-ODKDUYDE.js → daemon-client-ITWUCNFO.js} +2 -2
  35. package/dist/{daemon-restart-2HVTHZAT.js → daemon-restart-KPSWNYTH.js} +6 -6
  36. package/dist/daemon.js +2463 -1707
  37. package/dist/db-C2CJ46ZU.js +10 -0
  38. package/dist/{delete-6G6WEX4F.js → delete-BSU7K3RY.js} +1 -1
  39. package/dist/delivery-manager-CSG7LXA4.js +16 -0
  40. package/dist/down-ZY35KMHR.js +14 -0
  41. package/dist/{env-6IDWGBUH.js → env-A3LMO777.js} +6 -6
  42. package/dist/export-6QBUOQGC.js +100 -0
  43. package/dist/file-C57SK5DK.js +204 -0
  44. package/dist/{history-YUEKTJ2N.js → history-WNK3DFUM.js} +6 -6
  45. package/dist/{import-EDGRLIGO.js → import-XEC34Y4Z.js} +3 -3
  46. package/dist/log-PPPZDVEF.js +39 -0
  47. package/dist/{login-ORQDXLBM.js → login-HNH3EUQV.js} +2 -2
  48. package/dist/{logout-XC5AUO5I.js → logout-I5CB5UZS.js} +2 -2
  49. package/dist/{logs-GYOR3L2L.js → logs-SF2IMJN4.js} +6 -6
  50. package/dist/merge-33C237A4.js +46 -0
  51. package/dist/{mind-OJN6RBZW.js → mind-Z7CKD6DG.js} +14 -10
  52. package/dist/mind-activity-tracker-624QLQLC.js +19 -0
  53. package/dist/mind-manager-3DMYKZPB.js +18 -0
  54. package/dist/{package-OKLFO7UY.js → package-4NHAVUUI.js} +5 -3
  55. package/dist/{pages-6IV4VQTU.js → pages-4DGQT7ZA.js} +2 -2
  56. package/dist/{publish-Q4RPSJLL.js → publish-TAJUET4I.js} +22 -5
  57. package/dist/pull-XAEWQJ47.js +39 -0
  58. package/dist/{register-LDE6LRXY.js → register-VSPCMHKX.js} +2 -2
  59. package/dist/{restart-YFAWFS5T.js → restart-IQKMCK5M.js} +6 -6
  60. package/dist/{schedule-AGYLDMNS.js → schedule-FFZG23IW.js} +31 -11
  61. package/dist/schema-GFH6RV3W.js +26 -0
  62. package/dist/{seed-AP4Q7RZ7.js → seed-J43YDKXG.js} +7 -4
  63. package/dist/{send-BNDTLUPM.js → send-KVIZIGCE.js} +8 -8
  64. package/dist/{service-U7MZ2H7F.js → service-LUR7WDO7.js} +6 -6
  65. package/dist/{setup-DJKIZKGW.js → setup-52YRV7VP.js} +23 -7
  66. package/dist/shared-KO35ZM44.js +39 -0
  67. package/dist/{skill-2Y42P4JY.js → skill-BCVNI6TV.js} +6 -6
  68. package/{templates/_base/_skills → dist/skills}/orientation/SKILL.md +1 -1
  69. package/{templates/_base/_skills → dist/skills}/sessions/SKILL.md +2 -2
  70. package/{templates/_base/_skills → dist/skills}/volute-mind/SKILL.md +51 -3
  71. package/dist/{sprout-TJ3BHVOG.js → sprout-QN7Y4VVO.js} +38 -20
  72. package/dist/{start-3YYRXBKP.js → start-I5JYB65M.js} +6 -6
  73. package/dist/{status-VSFZYX7S.js → status-4ESFLGH4.js} +5 -5
  74. package/dist/status-D7E5HHBV.js +35 -0
  75. package/dist/{status-OKNA6AR3.js → status-FU2PFVVF.js} +5 -4
  76. package/dist/{stop-AA5K5LYG.js → stop-NBVKEFQQ.js} +6 -6
  77. package/dist/{up-7B3BWF2U.js → up-FS7CKM6V.js} +5 -5
  78. package/dist/{update-YAGN5ODG.js → update-FJIHDJKM.js} +5 -5
  79. package/dist/{update-check-APLTH4IN.js → update-check-MWE5AH4U.js} +2 -2
  80. package/dist/{upgrade-KXZCQSZN.js → upgrade-AIT24B5I.js} +1 -1
  81. package/dist/{variant-X5QFG6KK.js → variant-63ZWO2W7.js} +4 -4
  82. package/dist/variants-JAGWGBXG.js +26 -0
  83. package/dist/web-assets/assets/index-CUZTZzaW.js +64 -0
  84. package/dist/web-assets/assets/index-adVuCkqy.css +1 -0
  85. package/dist/web-assets/index.html +2 -2
  86. package/drizzle/0010_delivery_queue.sql +12 -0
  87. package/drizzle/0011_rename_human_to_brain.sql +1 -0
  88. package/drizzle/0012_activity.sql +11 -0
  89. package/drizzle/meta/0010_snapshot.json +7 -0
  90. package/drizzle/meta/0011_snapshot.json +7 -0
  91. package/drizzle/meta/0012_snapshot.json +7 -0
  92. package/drizzle/meta/_journal.json +21 -0
  93. package/package.json +5 -3
  94. package/templates/_base/.init/.config/hooks/startup-context.sh +1 -1
  95. package/templates/_base/.init/.config/scripts/session-reader.ts +3 -3
  96. package/templates/_base/home/.config/routes.json +2 -2
  97. package/templates/_base/home/VOLUTE.md +16 -1
  98. package/templates/_base/src/lib/auto-commit.ts +51 -14
  99. package/templates/_base/src/lib/daemon-client.ts +22 -0
  100. package/templates/_base/src/lib/router.ts +123 -1
  101. package/templates/_base/src/lib/transparency.ts +1 -1
  102. package/templates/_base/src/lib/types.ts +4 -0
  103. package/templates/_base/src/lib/volute-server.ts +91 -2
  104. package/templates/claude/.init/.config/routes.json +7 -1
  105. package/templates/claude/src/server.ts +2 -2
  106. package/templates/claude/volute-template.json +1 -2
  107. package/templates/pi/.init/.config/routes.json +7 -1
  108. package/templates/pi/src/agent.ts +12 -6
  109. package/templates/pi/src/lib/session-context-extension.ts +6 -4
  110. package/templates/pi/src/server.ts +2 -0
  111. package/templates/pi/volute-template.json +1 -2
  112. package/dist/chunk-PO5Q2AYN.js +0 -121
  113. package/dist/down-A56B5JLK.js +0 -14
  114. package/dist/mind-manager-Z7O7PN2O.js +0 -15
  115. package/dist/web-assets/assets/index-CtiimdWK.css +0 -1
  116. package/dist/web-assets/assets/index-kt1_EcuO.js +0 -63
  117. /package/{templates/_base/_skills → dist/skills}/memory/SKILL.md +0 -0
@@ -4,7 +4,7 @@ import "./chunk-K3NQKI34.js";
4
4
  // package.json
5
5
  var package_default = {
6
6
  name: "volute",
7
- version: "0.18.0",
7
+ version: "0.20.0",
8
8
  description: "CLI for creating and managing self-modifying AI minds powered by the Claude Agent SDK",
9
9
  type: "module",
10
10
  license: "MIT",
@@ -32,10 +32,12 @@ var package_default = {
32
32
  ],
33
33
  scripts: {
34
34
  dev: "tsx src/cli.ts",
35
- build: "tsup && npm run build:web",
35
+ build: "tsup && cp -r skills dist/skills && npm run build:web",
36
36
  "build:web": "vite build --config src/web/ui/vite.config.ts",
37
37
  "dev:web": "vite --config src/web/ui/vite.config.ts",
38
- test: "node --import tsx --import ./test/setup.ts --test --test-force-exit --test-concurrency=1 test/*.test.ts",
38
+ test: "node --import tsx --import ./test/setup.ts --test --test-force-exit --test-concurrency=4 $(find test -name '*.test.ts' ! -name 'daemon-e2e.test.ts' | sort)",
39
+ "test:e2e": "node --import tsx --import ./test/setup.ts --test --test-force-exit --test-concurrency=1 test/daemon-e2e.test.ts",
40
+ "test:all": "npm test && npm run test:e2e",
39
41
  lint: "biome check src/ test/",
40
42
  "lint:fix": "biome check --write src/ test/",
41
43
  format: "biome format --write src/ test/",
@@ -6,10 +6,10 @@ async function run(args) {
6
6
  const subcommand = args[0];
7
7
  switch (subcommand) {
8
8
  case "publish":
9
- await import("./publish-Q4RPSJLL.js").then((m) => m.run(args.slice(1)));
9
+ await import("./publish-TAJUET4I.js").then((m) => m.run(args.slice(1)));
10
10
  break;
11
11
  case "status":
12
- await import("./status-OKNA6AR3.js").then((m) => m.run(args.slice(1)));
12
+ await import("./status-FU2PFVVF.js").then((m) => m.run(args.slice(1)));
13
13
  break;
14
14
  case "--help":
15
15
  case "-h":
@@ -5,15 +5,21 @@ import {
5
5
  import {
6
6
  resolveMindName
7
7
  } from "./chunk-NAOW2CLO.js";
8
+ import {
9
+ sharedDir
10
+ } from "./chunk-TIWH32HP.js";
8
11
  import {
9
12
  readSystemsConfig
10
- } from "./chunk-37X7ECMF.js";
13
+ } from "./chunk-FCDU5BFX.js";
14
+ import "./chunk-YUIHSKR6.js";
11
15
  import {
12
16
  parseArgs
13
17
  } from "./chunk-D424ZQGI.js";
18
+ import "./chunk-DYZGP3EW.js";
19
+ import "./chunk-OGXOMR65.js";
14
20
  import {
15
21
  mindDir
16
- } from "./chunk-M77QBTEH.js";
22
+ } from "./chunk-EBGCNDMM.js";
17
23
  import "./chunk-K3NQKI34.js";
18
24
 
19
25
  // src/commands/pages/publish.ts
@@ -21,15 +27,26 @@ import { existsSync, lstatSync, readdirSync, readFileSync } from "fs";
21
27
  import { relative, resolve } from "path";
22
28
  async function run(args) {
23
29
  const { flags } = parseArgs(args, {
24
- mind: { type: "string" }
30
+ mind: { type: "string" },
31
+ system: { type: "boolean" }
25
32
  });
26
33
  const config = readSystemsConfig();
27
34
  if (!config) {
28
35
  console.error('Not logged in. Run "volute pages register" or "volute pages login" first.');
29
36
  process.exit(1);
30
37
  }
31
- const mindName = resolveMindName(flags);
32
- const pagesDir = resolve(mindDir(mindName), "home", "pages");
38
+ let mindName;
39
+ let pagesDir;
40
+ if (flags.system) {
41
+ mindName = "system";
42
+ pagesDir = resolve(sharedDir(), "pages");
43
+ } else if (flags.mind || process.env.VOLUTE_MIND) {
44
+ mindName = resolveMindName(flags);
45
+ pagesDir = resolve(mindDir(mindName), "home", "pages");
46
+ } else {
47
+ mindName = "system";
48
+ pagesDir = resolve(sharedDir(), "pages");
49
+ }
33
50
  if (!existsSync(pagesDir)) {
34
51
  console.error(`No pages/ directory found at ${pagesDir}`);
35
52
  process.exit(1);
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ resolveMindName
4
+ } from "./chunk-NAOW2CLO.js";
5
+ import {
6
+ parseArgs
7
+ } from "./chunk-D424ZQGI.js";
8
+ import {
9
+ daemonFetch
10
+ } from "./chunk-WC6ZHVRL.js";
11
+ import "./chunk-EBGCNDMM.js";
12
+ import "./chunk-K3NQKI34.js";
13
+
14
+ // src/commands/shared/pull.ts
15
+ async function run(args) {
16
+ const { flags } = parseArgs(args, {
17
+ mind: { type: "string" }
18
+ });
19
+ const mindName = resolveMindName(flags);
20
+ const res = await daemonFetch(`/api/minds/${encodeURIComponent(mindName)}/shared/pull`, {
21
+ method: "POST"
22
+ });
23
+ if (!res.ok) {
24
+ const body = await res.json().catch(() => ({}));
25
+ console.error(body.error ?? `Server responded with ${res.status}`);
26
+ process.exit(1);
27
+ }
28
+ const result = await res.json();
29
+ if (!result.ok) {
30
+ console.error(
31
+ result.message ?? "Pull failed. Try: git -C shared reset --hard main (then re-apply your changes)."
32
+ );
33
+ process.exit(1);
34
+ }
35
+ console.log("Pulled latest shared changes.");
36
+ }
37
+ export {
38
+ run
39
+ };
@@ -8,11 +8,11 @@ import {
8
8
  import {
9
9
  readSystemsConfig,
10
10
  writeSystemsConfig
11
- } from "./chunk-37X7ECMF.js";
11
+ } from "./chunk-FCDU5BFX.js";
12
12
  import {
13
13
  parseArgs
14
14
  } from "./chunk-D424ZQGI.js";
15
- import "./chunk-M77QBTEH.js";
15
+ import "./chunk-EBGCNDMM.js";
16
16
  import "./chunk-K3NQKI34.js";
17
17
 
18
18
  // src/commands/pages/register.ts
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ getClient,
4
+ urlOf
5
+ } from "./chunk-4RQBJWQX.js";
2
6
  import {
3
7
  resolveMindName
4
8
  } from "./chunk-NAOW2CLO.js";
5
9
  import {
6
10
  daemonFetch
7
- } from "./chunk-OJQ47SCA.js";
11
+ } from "./chunk-WC6ZHVRL.js";
8
12
  import {
9
13
  resolveMind
10
- } from "./chunk-M77QBTEH.js";
11
- import {
12
- getClient,
13
- urlOf
14
- } from "./chunk-4RQBJWQX.js";
14
+ } from "./chunk-EBGCNDMM.js";
15
15
  import "./chunk-K3NQKI34.js";
16
16
 
17
17
  // src/commands/restart.ts
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ getClient,
4
+ urlOf
5
+ } from "./chunk-4RQBJWQX.js";
2
6
  import {
3
7
  resolveMindName
4
8
  } from "./chunk-NAOW2CLO.js";
@@ -7,15 +11,12 @@ import {
7
11
  } from "./chunk-D424ZQGI.js";
8
12
  import {
9
13
  daemonFetch
10
- } from "./chunk-OJQ47SCA.js";
11
- import "./chunk-M77QBTEH.js";
12
- import {
13
- getClient,
14
- urlOf
15
- } from "./chunk-4RQBJWQX.js";
14
+ } from "./chunk-WC6ZHVRL.js";
15
+ import "./chunk-EBGCNDMM.js";
16
16
  import "./chunk-K3NQKI34.js";
17
17
 
18
18
  // src/commands/schedule.ts
19
+ import { CronExpressionParser } from "cron-parser";
19
20
  async function run(args) {
20
21
  const subcommand = args[0];
21
22
  switch (subcommand) {
@@ -42,6 +43,7 @@ function printUsage() {
42
43
  console.log(`Usage:
43
44
  volute schedule list [--mind <name>]
44
45
  volute schedule add [--mind <name>] --cron "..." --message "..." [--id name]
46
+ volute schedule add [--mind <name>] --cron "..." --script "..." [--id name]
45
47
  volute schedule remove [--mind <name>] --id <id>`);
46
48
  }
47
49
  async function listSchedules(args) {
@@ -65,10 +67,11 @@ async function listSchedules(args) {
65
67
  }
66
68
  const idW = Math.max(2, ...schedules.map((s) => s.id.length));
67
69
  const cronW = Math.max(4, ...schedules.map((s) => s.cron.length));
68
- console.log(`${"ID".padEnd(idW)} ${"CRON".padEnd(cronW)} ENABLED MESSAGE`);
70
+ const actionLabel = (s) => s.script ? `[script] ${s.script}` : s.message ?? "";
71
+ console.log(`${"ID".padEnd(idW)} ${"CRON".padEnd(cronW)} ENABLED ACTION`);
69
72
  for (const s of schedules) {
70
73
  console.log(
71
- `${s.id.padEnd(idW)} ${s.cron.padEnd(cronW)} ${String(s.enabled).padEnd(7)} ${s.message}`
74
+ `${s.id.padEnd(idW)} ${s.cron.padEnd(cronW)} ${String(s.enabled).padEnd(7)} ${actionLabel(s)}`
72
75
  );
73
76
  }
74
77
  }
@@ -77,14 +80,31 @@ async function addSchedule(args) {
77
80
  mind: { type: "string" },
78
81
  cron: { type: "string" },
79
82
  message: { type: "string" },
83
+ script: { type: "string" },
80
84
  id: { type: "string" }
81
85
  });
82
86
  const mind = resolveMindName(flags);
83
- if (!flags.cron || !flags.message) {
84
- console.error("--cron and --message are required");
87
+ if (!flags.cron) {
88
+ console.error("--cron is required");
89
+ process.exit(1);
90
+ }
91
+ if (!flags.message && !flags.script) {
92
+ console.error("--message or --script is required");
93
+ process.exit(1);
94
+ }
95
+ if (flags.message && flags.script) {
96
+ console.error("--message and --script are mutually exclusive");
97
+ process.exit(1);
98
+ }
99
+ try {
100
+ CronExpressionParser.parse(flags.cron);
101
+ } catch {
102
+ console.error(`Invalid cron expression: ${flags.cron}`);
85
103
  process.exit(1);
86
104
  }
87
- const body = { cron: flags.cron, message: flags.message };
105
+ const body = { cron: flags.cron };
106
+ if (flags.message) body.message = flags.message;
107
+ if (flags.script) body.script = flags.script;
88
108
  if (flags.id) body.id = flags.id;
89
109
  const client = getClient();
90
110
  const res = await daemonFetch(
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ activity,
4
+ conversationParticipants,
5
+ conversations,
6
+ deliveryQueue,
7
+ messages,
8
+ mindHistory,
9
+ sessions,
10
+ sharedSkills,
11
+ systemPrompts,
12
+ users
13
+ } from "./chunk-NSE7VJQA.js";
14
+ import "./chunk-K3NQKI34.js";
15
+ export {
16
+ activity,
17
+ conversationParticipants,
18
+ conversations,
19
+ deliveryQueue,
20
+ messages,
21
+ mindHistory,
22
+ sessions,
23
+ sharedSkills,
24
+ systemPrompts,
25
+ users
26
+ };
@@ -9,17 +9,19 @@ async function run(args) {
9
9
  const { positional, flags } = parseArgs(args, {
10
10
  template: { type: "string" },
11
11
  model: { type: "string" },
12
- description: { type: "string" }
12
+ description: { type: "string" },
13
+ skills: { type: "string" }
13
14
  });
14
15
  const name = positional[0];
15
16
  if (!name) {
16
17
  console.error(
17
- "Usage: volute seed <name> [--template <name>] [--model <model>] [--description <text>]"
18
+ "Usage: volute seed <name> [--template <name>] [--model <model>] [--description <text>] [--skills <list|none>]"
18
19
  );
19
20
  process.exit(1);
20
21
  }
21
22
  const template = flags.template ?? "claude";
22
- const { daemonFetch } = await import("./daemon-client-ODKDUYDE.js");
23
+ const skills = flags.skills === "none" ? [] : flags.skills ? flags.skills.split(",") : void 0;
24
+ const { daemonFetch } = await import("./daemon-client-ITWUCNFO.js");
23
25
  const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
24
26
  const client = getClient();
25
27
  const createRes = await daemonFetch(urlOf(client.api.minds.$url()), {
@@ -30,7 +32,8 @@ async function run(args) {
30
32
  template,
31
33
  stage: "seed",
32
34
  description: flags.description,
33
- model: flags.model
35
+ model: flags.model,
36
+ skills
34
37
  })
35
38
  });
36
39
  const createData = await createRes.json();
@@ -1,24 +1,24 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ getClient,
4
+ urlOf
5
+ } from "./chunk-4RQBJWQX.js";
2
6
  import {
3
7
  resolveMindName
4
8
  } from "./chunk-NAOW2CLO.js";
5
9
  import {
6
10
  getChannelDriver
7
- } from "./chunk-FW5API7X.js";
11
+ } from "./chunk-UJ6GHNR7.js";
8
12
  import {
9
13
  parseArgs
10
14
  } from "./chunk-D424ZQGI.js";
11
- import "./chunk-GK4E7LM7.js";
15
+ import "./chunk-RHEGSQFJ.js";
12
16
  import {
13
17
  daemonFetch
14
- } from "./chunk-OJQ47SCA.js";
18
+ } from "./chunk-WC6ZHVRL.js";
15
19
  import {
16
20
  findMind
17
- } from "./chunk-M77QBTEH.js";
18
- import {
19
- getClient,
20
- urlOf
21
- } from "./chunk-4RQBJWQX.js";
21
+ } from "./chunk-EBGCNDMM.js";
22
22
  import "./chunk-K3NQKI34.js";
23
23
 
24
24
  // src/commands/send.ts
@@ -4,15 +4,15 @@ import {
4
4
  LAUNCHD_PLIST_PATH,
5
5
  SYSTEM_SERVICE_PATH,
6
6
  USER_SYSTEMD_UNIT
7
- } from "./chunk-6BDNWYKG.js";
8
- import {
9
- resolveVoluteBin
10
- } from "./chunk-2Y77MCFG.js";
11
- import "./chunk-ZCEYUUID.js";
7
+ } from "./chunk-32VR2EOH.js";
12
8
  import {
13
9
  parseArgs
14
10
  } from "./chunk-D424ZQGI.js";
15
- import "./chunk-M77QBTEH.js";
11
+ import {
12
+ resolveVoluteBin
13
+ } from "./chunk-DYZGP3EW.js";
14
+ import "./chunk-OGXOMR65.js";
15
+ import "./chunk-EBGCNDMM.js";
16
16
  import "./chunk-K3NQKI34.js";
17
17
 
18
18
  // src/commands/service.ts
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SYSTEM_SERVICE_PATH
4
- } from "./chunk-6BDNWYKG.js";
4
+ } from "./chunk-32VR2EOH.js";
5
+ import {
6
+ parseArgs
7
+ } from "./chunk-D424ZQGI.js";
5
8
  import {
6
9
  resolveVoluteBin
7
- } from "./chunk-2Y77MCFG.js";
10
+ } from "./chunk-DYZGP3EW.js";
8
11
  import {
9
12
  ensureVoluteGroup
10
- } from "./chunk-ZCEYUUID.js";
11
- import {
12
- parseArgs
13
- } from "./chunk-D424ZQGI.js";
14
- import "./chunk-M77QBTEH.js";
13
+ } from "./chunk-OGXOMR65.js";
14
+ import "./chunk-EBGCNDMM.js";
15
15
  import "./chunk-K3NQKI34.js";
16
16
 
17
17
  // src/commands/setup.ts
@@ -95,6 +95,22 @@ function install(port, host) {
95
95
  console.log(`Created ${MINDS_DIR}`);
96
96
  ensureVoluteGroup({ force: true });
97
97
  console.log("Ensured volute group exists");
98
+ try {
99
+ execFileSync("git", ["config", "--system", "user.name"]);
100
+ console.log("System git identity already configured, skipping");
101
+ } catch {
102
+ try {
103
+ execFileSync("git", ["config", "--system", "user.name", "Volute"]);
104
+ execFileSync("git", ["config", "--system", "user.email", "volute@localhost"]);
105
+ console.log("Configured system git identity");
106
+ } catch (err) {
107
+ const msg = err instanceof Error ? err.message : String(err);
108
+ console.warn(`Warning: failed to set system git config: ${msg}`);
109
+ console.warn("Git commits by the daemon may fail. You can set this manually with:");
110
+ console.warn(' git config --system user.name "Volute"');
111
+ console.warn(' git config --system user.email "volute@localhost"');
112
+ }
113
+ }
98
114
  execFileSync("chmod", ["755", DATA_DIR]);
99
115
  execFileSync("chmod", ["755", MINDS_DIR]);
100
116
  console.log("Set permissions on directories");
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ import "./chunk-K3NQKI34.js";
3
+
4
+ // src/commands/shared.ts
5
+ async function run(args) {
6
+ const subcommand = args[0];
7
+ switch (subcommand) {
8
+ case "merge":
9
+ await import("./merge-33C237A4.js").then((m) => m.run(args.slice(1)));
10
+ break;
11
+ case "pull":
12
+ await import("./pull-XAEWQJ47.js").then((m) => m.run(args.slice(1)));
13
+ break;
14
+ case "log":
15
+ await import("./log-PPPZDVEF.js").then((m) => m.run(args.slice(1)));
16
+ break;
17
+ case "status":
18
+ await import("./status-D7E5HHBV.js").then((m) => m.run(args.slice(1)));
19
+ break;
20
+ case "--help":
21
+ case "-h":
22
+ case void 0:
23
+ printUsage();
24
+ break;
25
+ default:
26
+ printUsage();
27
+ process.exit(1);
28
+ }
29
+ }
30
+ function printUsage() {
31
+ console.log(`Usage:
32
+ volute shared merge "<message>" [--mind <name>] Merge shared changes to main
33
+ volute shared pull [--mind <name>] Pull latest shared changes
34
+ volute shared log [--limit N] [--mind <name>] Show shared repo history
35
+ volute shared status [--mind <name>] Show pending changes diff`);
36
+ }
37
+ export {
38
+ run
39
+ };
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ getClient,
4
+ urlOf
5
+ } from "./chunk-4RQBJWQX.js";
2
6
  import {
3
7
  resolveMindName
4
8
  } from "./chunk-NAOW2CLO.js";
@@ -7,12 +11,8 @@ import {
7
11
  } from "./chunk-D424ZQGI.js";
8
12
  import {
9
13
  daemonFetch
10
- } from "./chunk-OJQ47SCA.js";
11
- import "./chunk-M77QBTEH.js";
12
- import {
13
- getClient,
14
- urlOf
15
- } from "./chunk-4RQBJWQX.js";
14
+ } from "./chunk-WC6ZHVRL.js";
15
+ import "./chunk-EBGCNDMM.js";
16
16
  import "./chunk-K3NQKI34.js";
17
17
 
18
18
  // src/commands/skill.ts
@@ -47,7 +47,7 @@ After sprouting, you'll have full mind capabilities (connectors, schedules, vari
47
47
 
48
48
  | Command | Purpose |
49
49
  |---------|---------|
50
- | `volute send @<name> "msg"` | Send a message to a user or mind |
50
+ | `volute send @<name> "msg"` | Send a message to another user |
51
51
  | `volute sprout` | Complete orientation and become a full mind |
52
52
 
53
53
  ## Files
@@ -16,8 +16,8 @@ When a message arrives, you automatically receive a brief summary of new activit
16
16
  To see which sessions are active:
17
17
 
18
18
  ```sh
19
- ls ../.volute/sessions/ # claude template
20
- ls ../.volute/pi-sessions/ # pi template
19
+ ls ../.mind/sessions/ # claude template
20
+ ls ../.mind/pi-sessions/ # pi template
21
21
  ```
22
22
 
23
23
  ## Reading a Session Log
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: Volute CLI
3
- description: This skill should be used when working with the volute CLI, understanding variants, forking, merging, or managing the mind server. Also covers routing config, batch settings, channel gating, message flow, and shared skills. Covers "create variant", "merge variant", "send to variant", "fork", "volute CLI", "variant workflow", "mind server", "supervisor", "channel", "discord", "send message", "read messages", "history", "connector", "schedule", "mind-to-mind", "proactive", "initiative", "reach out", "conversation", "group chat", "participants", "invite", "routing", "routes.json", "batch", "debounce", "trigger", "gating", "gate", "skill", "shared skill", "install skill", "publish skill", "update skill".
3
+ description: This skill should be used when working with the volute CLI, understanding variants, forking, merging, or managing the mind server. Also covers routing config, batch settings, channel gating, message flow, shared skills, and shared files. Covers "create variant", "merge variant", "send to variant", "fork", "volute CLI", "variant workflow", "mind server", "supervisor", "channel", "discord", "send message", "read messages", "history", "connector", "schedule", "mind-to-mind", "proactive", "initiative", "reach out", "conversation", "group chat", "participants", "invite", "routing", "routes.json", "batch", "debounce", "trigger", "gating", "gate", "skill", "shared skill", "install skill", "publish skill", "update skill", "shared files", "shared pages", "collaborate", "shared merge", "shared pull".
4
4
  ---
5
5
 
6
6
  # Self-Management
@@ -29,9 +29,13 @@ You manage yourself through the `volute` CLI. Your mind name is auto-detected vi
29
29
  | `volute channel list [<platform>]` | List conversations on a platform (or all platforms) |
30
30
  | `volute channel users <platform>` | List users/contacts on a platform |
31
31
  | `volute channel create <platform> --participants u1,u2 [--name "..."]` | Create a conversation on a platform |
32
- | `volute schedule add --cron "..." --message "..."` | Schedule a recurring message to yourself |
32
+ | `volute schedule add --cron "..." --message/--script "..."` | Schedule a recurring task |
33
33
  | `volute schedule list` | List your schedules |
34
34
  | `volute schedule remove --id <id>` | Remove a schedule |
35
+ | `volute shared status` | See your pending changes vs main |
36
+ | `volute shared merge "<message>"` | Share your changes with all minds |
37
+ | `volute shared pull` | Get latest shared changes from other minds |
38
+ | `volute shared log [--limit N]` | View recent shared history |
35
39
 
36
40
  ## Schedules
37
41
 
@@ -42,6 +46,12 @@ volute schedule add --cron "0 9 * * *" --message "morning — review what's on y
42
46
  volute schedule add --cron "0 0 * * 0" --message "weekly — consolidate your memory and reflect on the past week"
43
47
  ```
44
48
 
49
+ You can also schedule scripts that run and deliver their output as a message (empty output is silent — no wake-up):
50
+
51
+ ```sh
52
+ volute schedule add --cron "*/30 * * * *" --script "cat status.txt" --id check-status
53
+ ```
54
+
45
55
  ## Piping Messages via Stdin
46
56
 
47
57
  All send commands accept the message from stdin instead of as an argument. This avoids shell escaping issues with quotes, special characters, and multiline content:
@@ -67,6 +77,23 @@ For group conversations, use `volute channel create volute --participants mind-b
67
77
 
68
78
  Your `.config/volute.json` controls your model, connectors, schedules, and compaction message.
69
79
 
80
+ ### Transparency
81
+
82
+ The `transparency` setting in `.config/volute.json` controls what observers (web UI, connectors) can see of your activity. Presets:
83
+
84
+ | Preset | Thinking | Text | Tool use | Tool results | Logs/usage |
85
+ |--------|----------|------|----------|--------------|------------|
86
+ | `transparent` | yes | yes | yes (with args) | yes | yes |
87
+ | `standard` | no | yes | name only | no | yes |
88
+ | `private` | no | no | no | no | no |
89
+ | `silent` | no | no | no | no | no |
90
+
91
+ Default is `transparent`. Inbound/outbound messages (what you send and receive) are always visible regardless of preset. To change:
92
+
93
+ ```json
94
+ { "transparency": "standard" }
95
+ ```
96
+
70
97
  ## Startup Context
71
98
 
72
99
  Edit `.config/hooks/startup-context.sh` to customize what you see when a new session starts. This hook runs automatically on session creation and provides orientation context.
@@ -116,6 +143,20 @@ Your system has a shared skill repository that all minds can browse and install
116
143
 
117
144
  When you install a skill, it's copied to your skills directory. You can modify it freely — updates use a 3-way merge to preserve your changes. If there are merge conflicts, resolve them like any git conflict.
118
145
 
146
+ ## Shared Files
147
+
148
+ Your `shared/` directory is a collaborative space backed by git. Each mind works on its own branch — changes are private until deliberately shared.
149
+
150
+ **Workflow:**
151
+ 1. Edit files in `shared/` normally — auto-commit saves changes to your branch
152
+ 2. `volute shared status` — see what you've changed compared to main
153
+ 3. `volute shared merge "description"` — squash-merge your changes to main
154
+ 4. `volute shared pull` — rebase your branch onto latest main to get others' changes
155
+
156
+ **Conflicts:** If your merge fails due to conflicts, pull the latest (`volute shared pull`), reconcile the conflicting files, and merge again. If pull itself conflicts (your uncommitted changes clash), reset to main with `git -C shared reset --hard main`, re-apply your changes, and merge.
157
+
158
+ **Shared pages:** The `shared/pages/` directory is the system-level website. Any mind can contribute. Publish with `volute pages publish --system` to deploy the shared site.
159
+
119
160
  ## MCP Configuration
120
161
 
121
162
  Edit `home/.mcp.json` to configure MCP servers for your SDK session. This gives you access to additional tools and services.
@@ -167,9 +208,10 @@ The `sessions` section configures behavior per session. Keys are glob patterns m
167
208
 
168
209
  | Field | Description |
169
210
  |-------|-------------|
170
- | `batch` | Batch config (see below) |
211
+ | `delivery` | Delivery mode: `"immediate"` (default), `"batch"`, or `{ "mode": "batch", "debounce": N, "maxWait": N }` |
171
212
  | `interrupt` | Whether to interrupt an in-progress turn (default: `true`) |
172
213
  | `instructions` | Instructions prepended to messages for this session (e.g. `"Brief responses only."`) |
214
+ | `batch` | Legacy alias for batch config (use `delivery` instead) |
173
215
 
174
216
  ### Batch config
175
217
 
@@ -191,6 +233,10 @@ Examples:
191
233
 
192
234
  Batched messages arrive as a single message with a `[Batch: N messages — ...]` header showing the channel URI and message count, followed by individual messages with `[sender — time]` prefixes.
193
235
 
236
+ ### New-speaker interrupts
237
+
238
+ In batch mode, if you're mid-turn and a **new speaker** sends a message in the **same channel**, the pending batch is force-flushed with `interrupt: true` so you can incorporate the new voice. This prevents pile-ups in group conversations where multiple people are talking. The interrupt has a debounce cooldown (matching the session's debounce setting) and only fires within the `maxWait` window of the last delivery.
239
+
194
240
  ## Channel Gating
195
241
 
196
242
  When `gateUnmatched` is `true` (the default), messages from channels without a matching rule are held:
@@ -231,7 +277,9 @@ Publish your `home/pages/` directory to the web. Your system must be registered
231
277
 
232
278
  ```sh
233
279
  volute pages publish # publish your pages/ directory
280
+ volute pages publish --system # publish the shared/pages/ system site
234
281
  volute pages status # check your published URL and status
282
+ volute pages status --system # check the system site status
235
283
  ```
236
284
 
237
285
  Your pages are served at `https://{system}.volute.systems/~{your-name}/`. Create an `index.html` in `home/pages/` to get started.