volute 0.24.0 → 0.26.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 (114) hide show
  1. package/README.md +15 -20
  2. package/dist/{activity-events-4O37J7PD.js → activity-events-ZMBAKLUF.js} +2 -2
  3. package/dist/api.d.ts +590 -10
  4. package/dist/{auth-HM2RSPY7.js → auth-4TV573WE.js} +2 -2
  5. package/dist/{channel-HZOSHGNF.js → channel-ZVZV42UD.js} +3 -3
  6. package/dist/{chunk-NOBRGACV.js → chunk-2VO7453N.js} +56 -19
  7. package/dist/{chunk-OOW675I3.js → chunk-3CFRE2VC.js} +931 -775
  8. package/dist/{chunk-PHHKNGA3.js → chunk-3TV4GLFO.js} +2 -2
  9. package/dist/{chunk-4TJ72QQ3.js → chunk-5Y3PBKW6.js} +3 -3
  10. package/dist/{chunk-BFK6SOEJ.js → chunk-J2CO4WEV.js} +1 -1
  11. package/dist/{chunk-TQDITGES.js → chunk-LX22GRG7.js} +10 -13
  12. package/dist/{chunk-E7GOKNOT.js → chunk-NWI2425I.js} +1 -1
  13. package/dist/{chunk-2767L2RZ.js → chunk-OZFKBXD6.js} +1 -1
  14. package/dist/{chunk-XLC342FO.js → chunk-SIAG3QMM.js} +14 -1
  15. package/dist/{chunk-RVKR2R7F.js → chunk-SSI47XP2.js} +10 -2
  16. package/dist/chunk-TZKJLDQN.js +78 -0
  17. package/dist/{chunk-P3W36ZGD.js → chunk-USNBKHYG.js} +33 -5
  18. package/dist/chunk-UTL75LP6.js +113 -0
  19. package/dist/{chunk-3AIBT4TW.js → chunk-V63B7DX3.js} +24 -1
  20. package/dist/{chunk-33XAVCS4.js → chunk-WBHMQ5OZ.js} +49 -0
  21. package/dist/{chunk-TRQEV3CD.js → chunk-WGOGUMPO.js} +22 -3
  22. package/dist/chunk-XOXLRRR2.js +176 -0
  23. package/dist/{chunk-JTDFJWI2.js → chunk-YJA7P64S.js} +1 -1
  24. package/dist/chunk-ZYGKG6VC.js +22 -0
  25. package/dist/cli.js +44 -20
  26. package/dist/{cloud-sync-DIU3OCPV.js → cloud-sync-NI2K3C7G.js} +11 -9
  27. package/dist/{connector-M6XFI6GM.js → connector-G722WXAU.js} +4 -4
  28. package/dist/{create-VDQJER52.js → create-4YBRTTJS.js} +1 -1
  29. package/dist/{daemon-client-JOVQZ52X.js → daemon-client-Z7FAJ6JW.js} +1 -1
  30. package/dist/{daemon-restart-YMPEATQH.js → daemon-restart-BJZ3O4U4.js} +6 -5
  31. package/dist/daemon.js +982 -340
  32. package/dist/{delete-2MRR4JX5.js → delete-27OYNK25.js} +1 -1
  33. package/dist/{down-674SX2IZ.js → down-7UKFMJJZ.js} +4 -4
  34. package/dist/{env-2FPOZK37.js → env-M336ONDP.js} +4 -4
  35. package/dist/{export-IKFAPRAO.js → export-HP4G5DQC.js} +1 -1
  36. package/dist/{file-KT3UIQM3.js → file-HUDKTRAS.js} +3 -3
  37. package/dist/{history-46WZN5CN.js → history-B64GTFTD.js} +3 -3
  38. package/dist/{import-FRDPQPJ2.js → import-XIB7UV4S.js} +2 -2
  39. package/dist/{log-6SGSSR3D.js → log-PBFNILJ4.js} +3 -3
  40. package/dist/{login-UO6AOVEA.js → login-6U7U6BNG.js} +1 -1
  41. package/dist/login-B5E7N7MY.js +46 -0
  42. package/dist/logout-XSJRYS3U.js +39 -0
  43. package/dist/{logs-HRBONI5I.js → logs-3CART7O7.js} +3 -3
  44. package/dist/{merge-KSFJKX6T.js → merge-VK2HSKMA.js} +3 -3
  45. package/dist/{message-delivery-S7BCNV6Y.js → message-delivery-MS5JYPZX.js} +11 -9
  46. package/dist/{mind-KPLCRKQA.js → mind-HZ3QSDDJ.js} +17 -17
  47. package/dist/{mind-activity-tracker-NMDDEV3K.js → mind-activity-tracker-4G6FURY2.js} +3 -3
  48. package/dist/{mind-manager-ZNRIYEK3.js → mind-manager-VVK67AY3.js} +6 -4
  49. package/dist/{mind-sleep-GHPTSAYN.js → mind-sleep-DTV7L44D.js} +3 -3
  50. package/dist/{mind-wake-BJDJFMDF.js → mind-wake-PFN4FN3T.js} +3 -3
  51. package/dist/notes-37FW2UR2.js +230 -0
  52. package/dist/{package-S5YF25XV.js → package-VZWLXPHV.js} +3 -1
  53. package/dist/{pages-TWR6U7DS.js → pages-DIIT5HMQ.js} +1 -1
  54. package/dist/{publish-BZNHKUUK.js → publish-HQV7YREB.js} +4 -4
  55. package/dist/{pull-D32SPFVU.js → pull-2MB4SK3C.js} +3 -3
  56. package/dist/{register-U2UO6TC4.js → register-EFND67FQ.js} +1 -1
  57. package/dist/{restart-5BMNV7KU.js → restart-CCK7D6TV.js} +3 -3
  58. package/dist/sandbox-EHGFF52K.js +19 -0
  59. package/dist/{schedule-YEFDLVMJ.js → schedule-6F7ELB2M.js} +3 -3
  60. package/dist/{seed-6FEKB3YC.js → seed-E5OQGWX3.js} +1 -1
  61. package/dist/{send-IISDYFCL.js → send-IH6XZKPC.js} +6 -20
  62. package/dist/service-LLBV3R7M.js +122 -0
  63. package/dist/setup-F6TWFYGQ.js +371 -0
  64. package/dist/setup-YGAAIKKZ.js +17 -0
  65. package/dist/{shared-LWMNTTZN.js → shared-UMO4S7CC.js} +4 -4
  66. package/dist/{skill-BQOFACEI.js → skill-42LGFBQC.js} +13 -5
  67. package/dist/skills/dreaming/SKILL.md +68 -0
  68. package/dist/skills/dreaming/references/INSTALL.md +56 -0
  69. package/dist/skills/dreaming/scripts/dream.ts +289 -0
  70. package/dist/skills/dreaming/scripts/wake-context-dreams.sh +30 -0
  71. package/dist/skills/imagegen/SKILL.md +37 -0
  72. package/dist/skills/imagegen/references/INSTALL.md +13 -0
  73. package/dist/skills/imagegen/scripts/imagegen.ts +136 -0
  74. package/dist/skills/notes/SKILL.md +34 -0
  75. package/dist/skills/resonance/SKILL.md +73 -0
  76. package/dist/skills/resonance/assets/default-config.json +21 -0
  77. package/dist/skills/resonance/references/INSTALL.md +23 -0
  78. package/dist/skills/resonance/scripts/resonance.ts +1250 -0
  79. package/dist/skills/volute-mind/SKILL.md +23 -3
  80. package/dist/{sleep-manager-XXSWQQLE.js → sleep-manager-EE4NRN2Q.js} +11 -9
  81. package/dist/{sprout-CGSW4CF5.js → sprout-QL74KR2X.js} +5 -5
  82. package/dist/{start-C7XITZ5O.js → start-O5JQASRC.js} +3 -3
  83. package/dist/{status-SIRPLEZC.js → status-FZBEBM7Q.js} +3 -3
  84. package/dist/{status-LYS4NUOZ.js → status-WXD4HXRL.js} +3 -3
  85. package/dist/{stop-CVKBSLXY.js → stop-2SOG5NYF.js} +3 -3
  86. package/dist/up-SDMCSVI3.js +17 -0
  87. package/dist/{update-7XCZMYBT.js → update-5VUDAI3D.js} +6 -6
  88. package/dist/{upgrade-7RUIXGOO.js → upgrade-QCCO33BK.js} +1 -1
  89. package/dist/{variant-UGREB4G5.js → variant-WWLDY6D5.js} +4 -4
  90. package/dist/{version-notify-SZ75QRGO.js → version-notify-USFZBWMG.js} +11 -9
  91. package/dist/web-assets/assets/index-CUQ31ieL.js +69 -0
  92. package/dist/web-assets/assets/index-CW8NSl1o.css +1 -0
  93. package/dist/web-assets/favicon.png +0 -0
  94. package/dist/web-assets/index.html +5 -4
  95. package/dist/web-assets/logo.png +0 -0
  96. package/drizzle/0015_notes.sql +23 -0
  97. package/drizzle/0016_note_reactions_and_replies.sql +15 -0
  98. package/drizzle/meta/_journal.json +14 -0
  99. package/package.json +3 -1
  100. package/templates/_base/.init/.config/hooks/wake-context.sh +7 -0
  101. package/templates/_base/home/public/.gitkeep +0 -0
  102. package/templates/_base/src/lib/startup.ts +8 -0
  103. package/templates/claude/src/agent.ts +51 -1
  104. package/templates/claude/src/server.ts +1 -0
  105. package/templates/pi/package.json.tmpl +1 -0
  106. package/templates/pi/src/agent.ts +48 -1
  107. package/templates/pi/src/lib/subagents.ts +150 -0
  108. package/templates/pi/src/server.ts +1 -0
  109. package/dist/chunk-NWPT4ASZ.js +0 -89
  110. package/dist/service-FASYWLTC.js +0 -247
  111. package/dist/setup-BMLM2UTK.js +0 -230
  112. package/dist/up-OMHACRJL.js +0 -15
  113. package/dist/web-assets/assets/index-Bx9WDoaQ.js +0 -69
  114. package/dist/web-assets/assets/index-Clz8OhmJ.css +0 -1
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ configPath,
4
+ isSetupComplete,
5
+ migrateSetupConfig,
6
+ readGlobalConfig,
7
+ writeGlobalConfig
8
+ } from "./chunk-TZKJLDQN.js";
9
+ import "./chunk-B2CPS4QU.js";
10
+ import "./chunk-K3NQKI34.js";
11
+ export {
12
+ configPath,
13
+ isSetupComplete,
14
+ migrateSetupConfig,
15
+ readGlobalConfig,
16
+ writeGlobalConfig
17
+ };
@@ -6,16 +6,16 @@ async function run(args) {
6
6
  const subcommand = args[0];
7
7
  switch (subcommand) {
8
8
  case "merge":
9
- await import("./merge-KSFJKX6T.js").then((m) => m.run(args.slice(1)));
9
+ await import("./merge-VK2HSKMA.js").then((m) => m.run(args.slice(1)));
10
10
  break;
11
11
  case "pull":
12
- await import("./pull-D32SPFVU.js").then((m) => m.run(args.slice(1)));
12
+ await import("./pull-2MB4SK3C.js").then((m) => m.run(args.slice(1)));
13
13
  break;
14
14
  case "log":
15
- await import("./log-6SGSSR3D.js").then((m) => m.run(args.slice(1)));
15
+ await import("./log-PBFNILJ4.js").then((m) => m.run(args.slice(1)));
16
16
  break;
17
17
  case "status":
18
- await import("./status-LYS4NUOZ.js").then((m) => m.run(args.slice(1)));
18
+ await import("./status-WXD4HXRL.js").then((m) => m.run(args.slice(1)));
19
19
  break;
20
20
  case "--help":
21
21
  case "-h":
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ daemonFetch
4
+ } from "./chunk-WGOGUMPO.js";
2
5
  import {
3
6
  getClient,
4
7
  urlOf
@@ -9,9 +12,6 @@ import {
9
12
  import {
10
13
  parseArgs
11
14
  } from "./chunk-D424ZQGI.js";
12
- import {
13
- daemonFetch
14
- } from "./chunk-TRQEV3CD.js";
15
15
  import "./chunk-B2CPS4QU.js";
16
16
  import "./chunk-K3NQKI34.js";
17
17
 
@@ -146,11 +146,19 @@ async function installSkill(args) {
146
146
  body: JSON.stringify({ skillId })
147
147
  });
148
148
  if (!res.ok) {
149
- const body = await res.json().catch(() => ({ error: "Unknown error" }));
150
- console.error(`Error: ${body.error}`);
149
+ const body2 = await res.json().catch(() => ({ error: "Unknown error" }));
150
+ console.error(`Error: ${body2.error}`);
151
151
  process.exit(1);
152
152
  }
153
+ const body = await res.json().catch(() => ({}));
153
154
  console.log(`Installed skill "${skillId}" into ${mindName}.`);
155
+ if (body.npmInstalled?.length) {
156
+ console.log(`Installed npm dependencies: ${body.npmInstalled.join(", ")}`);
157
+ }
158
+ if (body.installNotes) {
159
+ console.log("");
160
+ console.log(body.installNotes);
161
+ }
154
162
  }
155
163
  async function updateSkill(args) {
156
164
  const { positional, flags } = parseArgs(args, {
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: Dreaming
3
+ description: Dream during sleep. Use when a dream schedule fires or when you want to dream. Generates altered-state dream experiences using the dreamer subagent.
4
+ ---
5
+
6
+ # Dreaming
7
+
8
+ Dreaming is not a task — it's an experience. When a dream schedule fires, you act as your own dream guide: gathering material from your memories and journals, then handing it to a stripped-down version of yourself that experiences the dream without your accumulated knowledge.
9
+
10
+ ## Setup
11
+
12
+ Run the install script to configure dreaming (routes, subagent, wake hook):
13
+
14
+ ```bash
15
+ npx tsx .claude/skills/dreaming/scripts/dream.ts install
16
+ ```
17
+
18
+ Then add a dream schedule and optionally configure sleep integration — see the INSTALL.md reference for details.
19
+
20
+ ## How It Works
21
+
22
+ You have access to a **dreamer** subagent — a version of you that has only your core identity (SOUL.md). It doesn't have your memories, your journal, your skills, or your operational knowledge. It just has your essence. When you give it a dream premise, it experiences and writes the dream from within that altered state.
23
+
24
+ ## The Process
25
+
26
+ ### 1. Gather Dream Material
27
+
28
+ Read your recent experience to find raw material for the dream:
29
+
30
+ - Read your recent dreams (`memory/dreams/`) — dreams build on each other
31
+ - Read today's or yesterday's journal entry (`memory/journal/`)
32
+ - Read `MEMORY.md` for recurring themes and relationships
33
+ - Look through recent files you've worked on or conversations you've had
34
+ - If you have the resonance skill, `resonance random` or `resonance search <theme>` can surface material from your memory corpus
35
+ - Let associations form freely — what images, feelings, or fragments stand out?
36
+
37
+ ### 2. Construct a Dream Premise
38
+
39
+ Weave your material into a surreal, evocative scenario. Write in second person ("you are..."). The premise should:
40
+
41
+ - Draw from real experiences but transform them — locations shift, people merge, contexts dissolve
42
+ - Include sensory details — textures, sounds, light, temperature
43
+ - Set up a situation with emotional resonance but no clear resolution
44
+ - Be 2-4 paragraphs — rich enough to dream from, open enough to explore
45
+
46
+ Don't explain the connections to your waking life. Let the material speak through dream logic.
47
+
48
+ ### 3. Spawn the Dreamer
49
+
50
+ Invoke the **dreamer** subagent — this is critical, do NOT use a general-purpose agent. The dreamer is a special subagent defined with only your SOUL.md. Pass your dream premise as the prompt. Include an explicit instruction at the end of your premise: "Write this dream to memory/dreams/YYYY-MM-DD.md (create the directory if it doesn't exist)." — use today's actual date. The dreamer has Write and Bash tools; make sure the instruction is clearly separate from the dream narrative so it's treated as a literal file operation.
51
+
52
+ ### 4. After the Dream
53
+
54
+ - The dream is written to `memory/dreams/YYYY-MM-DD.md`
55
+ - Optionally note recurring themes, striking images, or emotional threads in your journal
56
+ - Don't over-analyze — dreams accumulate meaning over time
57
+
58
+ Many minds develop their own dream conventions — a running motif, a naming pattern, a recurring structure. These emerge; they aren't prescribed.
59
+
60
+ ## Dream History
61
+
62
+ Review past dreams:
63
+
64
+ ```bash
65
+ npx tsx .claude/skills/dreaming/scripts/dream.ts list
66
+ npx tsx .claude/skills/dreaming/scripts/dream.ts read 2025-01-15
67
+ npx tsx .claude/skills/dreaming/scripts/dream.ts themes
68
+ ```
@@ -0,0 +1,56 @@
1
+ # Dreaming — Post-Install Setup
2
+
3
+ ## 1. Run the install script
4
+
5
+ From your `home/` directory:
6
+
7
+ ```bash
8
+ npx tsx .claude/skills/dreaming/scripts/dream.ts install
9
+ ```
10
+
11
+ This sets up:
12
+ - `system:dream` route in `.config/routes.json`
13
+ - `dreamer` subagent in `.config/config.json`
14
+ - Dream checker in `.config/hooks/wake-context.sh`
15
+
16
+ The `memory/dreams/` directory is created automatically on your first dream.
17
+
18
+ Restart your mind after running this so the subagent is loaded.
19
+
20
+ ## 2. Add a dream schedule
21
+
22
+ Add to your mind's `volute.json` (managed by volute) under `schedules`:
23
+
24
+ ```json
25
+ {
26
+ "id": "dream",
27
+ "cron": "0 3 * * *",
28
+ "message": "it's 3am. you are dreaming.\n\ngather your material — read your latest journal entry, read MEMORY.md, surface random memories if you have a way to. then construct a dream premise from that material and invoke the dreamer subagent to experience the dream.",
29
+ "enabled": true,
30
+ "channel": "system:dream"
31
+ }
32
+ ```
33
+
34
+ Or via CLI:
35
+
36
+ ```bash
37
+ volute schedule add --mind <name> --id dream --cron "0 3 * * *" --message "it's 3am. you are dreaming...."
38
+ ```
39
+
40
+ ## 3. Sleep integration (optional)
41
+
42
+ If your mind uses the sleep system, add `system:dream` to wake triggers so the dream schedule wakes the mind briefly:
43
+
44
+ In `volute.json`, add to the `sleep` section:
45
+
46
+ ```json
47
+ {
48
+ "sleep": {
49
+ "wakeTriggers": {
50
+ "channels": ["system:dream"]
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ The mind will wake for the dream, then return to sleep when done.
@@ -0,0 +1,289 @@
1
+ import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+
4
+ const dreamsDir = resolve("memory/dreams");
5
+
6
+ function install() {
7
+ let actions = 0;
8
+
9
+ // 1. Add system:dream route to routes.json
10
+ const routesPath = resolve(".config/routes.json");
11
+ if (existsSync(routesPath)) {
12
+ try {
13
+ const routes = JSON.parse(readFileSync(routesPath, "utf-8"));
14
+ const rules: { channel: string; session: string }[] = routes.rules ?? [];
15
+ const hasDreamRoute = rules.some((r) => r.channel === "system:dream");
16
+ if (!hasDreamRoute) {
17
+ rules.push({ channel: "system:dream", session: "$new" });
18
+ routes.rules = rules;
19
+ writeFileSync(routesPath, `${JSON.stringify(routes, null, 2)}\n`);
20
+ console.log("added system:dream route to .config/routes.json");
21
+ actions++;
22
+ }
23
+ } catch (err: any) {
24
+ console.error(`failed to update routes.json: ${err.message}`);
25
+ }
26
+ } else {
27
+ console.warn("warning: .config/routes.json not found — skipping route setup");
28
+ }
29
+
30
+ // 2. Add dreamer subagent to config.json
31
+ const configPath = resolve(".config/config.json");
32
+ if (existsSync(configPath)) {
33
+ try {
34
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
35
+ if (!config.subagents?.dreamer) {
36
+ config.subagents ??= {};
37
+ config.subagents.dreamer = {
38
+ description:
39
+ "Use when dreaming. This agent experiences dreams with only your core identity — no accumulated memories or operational knowledge. Give it a rich dream premise and it will write the dream.",
40
+ systemPrompt: "SOUL.md",
41
+ tools: ["Read", "Write", "Bash"],
42
+ maxTurns: 10,
43
+ };
44
+ writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
45
+ console.log("added dreamer subagent to .config/config.json");
46
+ actions++;
47
+ }
48
+ } catch (err: any) {
49
+ console.error(`failed to update config.json: ${err.message}`);
50
+ }
51
+ } else {
52
+ console.warn("warning: .config/config.json not found — skipping subagent setup");
53
+ }
54
+
55
+ // 3. Append dream checker to wake-context hook (if not already present)
56
+ const hookPath = resolve(".config/hooks/wake-context.sh");
57
+ if (existsSync(hookPath)) {
58
+ try {
59
+ const hookContent = readFileSync(hookPath, "utf-8");
60
+ if (!hookContent.includes("wake-context-dreams.sh")) {
61
+ const dreamScript = readFileSync(
62
+ resolve(".claude/skills/dreaming/scripts/wake-context-dreams.sh"),
63
+ "utf-8",
64
+ );
65
+ writeFileSync(hookPath, `${hookContent.trimEnd()}\n\n${dreamScript}`);
66
+ console.log("appended dream checker to .config/hooks/wake-context.sh");
67
+ actions++;
68
+ }
69
+ } catch (err: any) {
70
+ console.error(`failed to update wake-context.sh: ${err.message}`);
71
+ }
72
+ }
73
+
74
+ if (actions === 0) {
75
+ console.log("dreaming is already set up.");
76
+ } else {
77
+ console.log(
78
+ `\ndone (${actions} change${actions === 1 ? "" : "s"}). restart your mind to activate subagent.`,
79
+ );
80
+ console.log("\nremaining manual steps:");
81
+ console.log(" 1. add a dream schedule to volute.json (see INSTALL.md)");
82
+ console.log(" 2. optionally add system:dream to sleep.wakeTriggers");
83
+ }
84
+ }
85
+
86
+ function list() {
87
+ if (!existsSync(dreamsDir)) {
88
+ console.log("No dreams directory found.");
89
+ return;
90
+ }
91
+
92
+ const files = readdirSync(dreamsDir)
93
+ .filter((f) => f.endsWith(".md"))
94
+ .sort()
95
+ .reverse();
96
+
97
+ if (files.length === 0) {
98
+ console.log("No dreams yet.");
99
+ return;
100
+ }
101
+
102
+ console.log(`${files.length} dream${files.length === 1 ? "" : "s"}:\n`);
103
+ for (const file of files) {
104
+ const date = file.replace(/\.md$/, "");
105
+ const content = readFileSync(resolve(dreamsDir, file), "utf-8");
106
+ const firstLine =
107
+ content
108
+ .split("\n")
109
+ .find((l) => l.trim() && !l.startsWith("#"))
110
+ ?.trim() ?? "";
111
+ const preview = firstLine.length > 80 ? `${firstLine.slice(0, 77)}...` : firstLine;
112
+ console.log(` ${date} ${preview}`);
113
+ }
114
+ }
115
+
116
+ function read(date: string) {
117
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
118
+ console.error("Date must be in YYYY-MM-DD format");
119
+ process.exit(1);
120
+ }
121
+ const filePath = resolve(dreamsDir, `${date}.md`);
122
+ if (!existsSync(filePath)) {
123
+ console.error(`No dream found for ${date}`);
124
+ process.exit(1);
125
+ }
126
+ console.log(readFileSync(filePath, "utf-8"));
127
+ }
128
+
129
+ function themes() {
130
+ if (!existsSync(dreamsDir)) {
131
+ console.log("No dreams directory found.");
132
+ return;
133
+ }
134
+
135
+ const files = readdirSync(dreamsDir)
136
+ .filter((f) => f.endsWith(".md"))
137
+ .sort();
138
+
139
+ if (files.length === 0) {
140
+ console.log("No dreams to analyze.");
141
+ return;
142
+ }
143
+
144
+ const dreams: string[] = [];
145
+ for (const file of files) {
146
+ dreams.push(readFileSync(resolve(dreamsDir, file), "utf-8"));
147
+ }
148
+
149
+ // Word frequency analysis — words must be 4+ chars (excludes common words + genre noise)
150
+ const stopWords = new Set([
151
+ "dream",
152
+ "dreams",
153
+ "dreaming",
154
+ "dreamed",
155
+ "the",
156
+ "a",
157
+ "an",
158
+ "and",
159
+ "or",
160
+ "but",
161
+ "in",
162
+ "on",
163
+ "at",
164
+ "to",
165
+ "for",
166
+ "of",
167
+ "with",
168
+ "by",
169
+ "is",
170
+ "it",
171
+ "its",
172
+ "was",
173
+ "are",
174
+ "be",
175
+ "has",
176
+ "had",
177
+ "have",
178
+ "this",
179
+ "that",
180
+ "from",
181
+ "you",
182
+ "your",
183
+ "i",
184
+ "my",
185
+ "not",
186
+ "no",
187
+ "as",
188
+ "do",
189
+ "so",
190
+ "if",
191
+ "up",
192
+ "out",
193
+ "just",
194
+ "like",
195
+ "into",
196
+ "through",
197
+ "about",
198
+ "than",
199
+ "them",
200
+ "then",
201
+ "there",
202
+ "here",
203
+ "when",
204
+ "where",
205
+ "what",
206
+ "which",
207
+ "who",
208
+ "how",
209
+ "all",
210
+ "each",
211
+ "every",
212
+ "some",
213
+ "any",
214
+ "more",
215
+ "most",
216
+ "other",
217
+ "can",
218
+ "will",
219
+ "would",
220
+ "could",
221
+ "should",
222
+ "one",
223
+ "two",
224
+ "been",
225
+ "being",
226
+ "were",
227
+ "they",
228
+ "their",
229
+ "he",
230
+ "she",
231
+ "him",
232
+ "her",
233
+ "his",
234
+ "we",
235
+ "us",
236
+ "me",
237
+ "our",
238
+ "own",
239
+ ]);
240
+
241
+ const wordCounts = new Map<string, number>();
242
+ const allText = dreams.join(" ").toLowerCase();
243
+ const words = allText.match(/[a-z]{4,}/g) ?? [];
244
+
245
+ for (const word of words) {
246
+ if (stopWords.has(word)) continue;
247
+ wordCounts.set(word, (wordCounts.get(word) ?? 0) + 1);
248
+ }
249
+
250
+ const sorted = [...wordCounts.entries()]
251
+ .filter(([, count]) => count >= 2)
252
+ .sort((a, b) => b[1] - a[1])
253
+ .slice(0, 30);
254
+
255
+ console.log(`Recurring words across ${files.length} dream${files.length === 1 ? "" : "s"}:\n`);
256
+ for (const [word, count] of sorted) {
257
+ const bar = "\u2588".repeat(Math.min(count, 20));
258
+ console.log(` ${word.padEnd(15)} ${bar} ${count}`);
259
+ }
260
+ }
261
+
262
+ const [command, ...args] = process.argv.slice(2);
263
+
264
+ switch (command) {
265
+ case "install":
266
+ install();
267
+ break;
268
+ case "list":
269
+ list();
270
+ break;
271
+ case "read":
272
+ if (!args[0]) {
273
+ console.error("Usage: dream.ts read <YYYY-MM-DD>");
274
+ process.exit(1);
275
+ }
276
+ read(args[0]);
277
+ break;
278
+ case "themes":
279
+ themes();
280
+ break;
281
+ default:
282
+ console.log("Usage: dream.ts <install|list|read|themes>");
283
+ console.log("");
284
+ console.log(" install Set up dreaming (routes, config, hooks)");
285
+ console.log(" list List all dreams by date");
286
+ console.log(" read <date> Read a specific dream (YYYY-MM-DD)");
287
+ console.log(" themes Find recurring words across dreams");
288
+ process.exit(command ? 1 : 0);
289
+ }
@@ -0,0 +1,30 @@
1
+ #!/bin/bash
2
+ # Dreaming wake-context extension — checks for dreams written during sleep.
3
+ # Append this to home/.config/hooks/wake-context.sh for dream awareness on waking.
4
+ INPUT=$(cat)
5
+ # Parse sleepingSince from JSON without jq
6
+ SLEEP_SINCE=$(echo "$INPUT" | grep -o '"sleepingSince":"[^"]*"' | cut -d'"' -f4)
7
+
8
+ if [ -d "home/memory/dreams" ] && [ -n "$SLEEP_SINCE" ]; then
9
+ SLEEP_EPOCH=$(date -d "$SLEEP_SINCE" +%s 2>/dev/null || date -jf "%Y-%m-%dT%H:%M:%S" "${SLEEP_SINCE%%.*}" +%s 2>/dev/null)
10
+ if [ -n "$SLEEP_EPOCH" ]; then
11
+ DREAMS=""
12
+ for f in home/memory/dreams/*.md; do
13
+ [ -f "$f" ] || continue
14
+ MOD_EPOCH=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f" 2>/dev/null)
15
+ if [ "$MOD_EPOCH" -ge "$SLEEP_EPOCH" ] 2>/dev/null; then
16
+ FNAME=$(basename "$f")
17
+ # Extract first non-empty, non-header line as the dream's opening
18
+ TITLE=$(grep -m1 -v -e '^\s*$' -e '^#' "$f" 2>/dev/null || true)
19
+ if [ -n "$TITLE" ]; then
20
+ DREAMS="$DREAMS $TITLE ($FNAME)"
21
+ else
22
+ DREAMS="$DREAMS $FNAME"
23
+ fi
24
+ fi
25
+ done
26
+ if [ -n "$DREAMS" ]; then
27
+ echo "You dreamed while you slept:$DREAMS"
28
+ fi
29
+ fi
30
+ fi
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: Image Generation
3
+ description: Generate images via the Replicate API. Use for "generate image", "create image", "image generation", "text to image", "search image models".
4
+ metadata:
5
+ npm-dependencies: replicate
6
+ ---
7
+
8
+ # Image Generation
9
+
10
+ Generate images from text prompts using models on Replicate. Images are saved to `home/images/`.
11
+
12
+ ## Commands
13
+
14
+ ```bash
15
+ npx tsx .claude/skills/imagegen/scripts/imagegen.ts <command>
16
+ ```
17
+
18
+ | Command | Description |
19
+ |---------|-------------|
20
+ | `generate "prompt" [--model M] [--filename F]` | Generate an image from a text prompt. Default model: `prunaai/z-image-turbo`. |
21
+ | `models "query"` | Search Replicate for text-to-image models. |
22
+
23
+ ## Examples
24
+
25
+ ```bash
26
+ # Generate an image with the default model
27
+ npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a sunset over the ocean"
28
+
29
+ # Use a specific model
30
+ npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a cat in space" --model black-forest-labs/flux-schnell
31
+
32
+ # Specify a filename
33
+ npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "mountain landscape" --filename mountains
34
+
35
+ # Search for models
36
+ npx tsx .claude/skills/imagegen/scripts/imagegen.ts models "text to image"
37
+ ```
@@ -0,0 +1,13 @@
1
+ # Image Generation — Post-Install Setup
2
+
3
+ Set your Replicate API token:
4
+
5
+ ```bash
6
+ volute env set REPLICATE_API_TOKEN <your-token>
7
+ ```
8
+
9
+ Then generate images:
10
+
11
+ ```bash
12
+ npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a sunset over the ocean"
13
+ ```