mover-os 4.0.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/install.js CHANGED
@@ -1093,6 +1093,21 @@ function preflight() {
1093
1093
  const plat = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
1094
1094
  issues.push({ label: "Platform", status: "ok", detail: plat });
1095
1095
 
1096
+ // Obsidian — check common install locations
1097
+ let hasObsidian = false;
1098
+ if (process.platform === "darwin") {
1099
+ hasObsidian = fs.existsSync("/Applications/Obsidian.app");
1100
+ } else if (process.platform === "win32") {
1101
+ hasObsidian = fs.existsSync(path.join(os.homedir(), "AppData", "Local", "Obsidian"));
1102
+ } else {
1103
+ hasObsidian = cmdExists("obsidian") || fs.existsSync(path.join(os.homedir(), ".config", "obsidian"));
1104
+ }
1105
+ issues.push({
1106
+ label: "Obsidian",
1107
+ status: hasObsidian ? "ok" : "warn",
1108
+ detail: hasObsidian ? "found" : "not found — get it at obsidian.md",
1109
+ });
1110
+
1096
1111
  return issues;
1097
1112
  }
1098
1113
 
@@ -1239,6 +1254,11 @@ async function main() {
1239
1254
  _detected: detectedIds.includes(a.id),
1240
1255
  }));
1241
1256
 
1257
+ if (detectedIds.length === 0) {
1258
+ barLn(yellow("No AI agents detected."));
1259
+ barLn(dim("You need at least one to use Mover OS. Recommended: Claude Code (claude.ai/code)"));
1260
+ barLn();
1261
+ }
1242
1262
  question(`Select your AI agents${detectedIds.length > 0 ? dim(" (detected agents pre-selected)") : ""}`);
1243
1263
  barLn();
1244
1264
 
@@ -1335,7 +1355,22 @@ async function main() {
1335
1355
  totalSteps++;
1336
1356
  }
1337
1357
 
1338
- // 6. .gitignore + git init (fresh install only)
1358
+ // 6. Obsidian theme (install CSS snippet)
1359
+ {
1360
+ const snippetsDir = path.join(vaultPath, ".obsidian", "snippets");
1361
+ const themeSrc = path.join(bundleDir, "src", "theme", "minimal-theme.css");
1362
+ const themeDst = path.join(snippetsDir, "minimal-theme.css");
1363
+ if (fs.existsSync(themeSrc)) {
1364
+ fs.mkdirSync(snippetsDir, { recursive: true });
1365
+ fs.copyFileSync(themeSrc, themeDst);
1366
+ sp = spinner("Obsidian theme");
1367
+ await sleep(150);
1368
+ sp.stop(`Obsidian theme ${dim("enable in Settings → Appearance → CSS snippets")}`);
1369
+ totalSteps++;
1370
+ }
1371
+ }
1372
+
1373
+ // 7. .gitignore + git init (fresh install only)
1339
1374
  if (!updateMode) {
1340
1375
  const hasGit = cmdExists("git");
1341
1376
  if (hasGit) {
@@ -1363,7 +1398,7 @@ async function main() {
1363
1398
  }
1364
1399
  }
1365
1400
 
1366
- // 7. Version stamp
1401
+ // 8. Version stamp
1367
1402
  fs.writeFileSync(path.join(vaultPath, ".mover-version"), `V${VERSION}\n`, "utf8");
1368
1403
 
1369
1404
  barLn();
@@ -1373,47 +1408,58 @@ async function main() {
1373
1408
  const verb = updateMode ? "updated" : "installed";
1374
1409
  outro(`${green("Done.")} Mover OS v${VERSION} ${verb}. ${dim(`${totalSteps} steps in ${elapsed}s`)}`);
1375
1410
 
1376
- // How to open the vault in each agent
1377
- const agentOpen = {
1378
- "claude-code": { cmd: `cd "${vaultPath}" && claude`, name: "Claude Code" },
1379
- cursor: { cmd: `Open Cursor → File → Open Folder → select vault`, name: "Cursor" },
1380
- cline: { cmd: `Open VS Code → File → Open Folder → select vault`, name: "Cline (VS Code)" },
1381
- codex: { cmd: `cd "${vaultPath}" && codex`, name: "Codex" },
1382
- windsurf: { cmd: `Open Windsurf → File → Open Folder → select vault`, name: "Windsurf" },
1383
- openclaw: { cmd: `cd "${vaultPath}" && openclaw`, name: "OpenClaw" },
1384
- antigravity: { cmd: `cd "${vaultPath}" && gemini`, name: "Antigravity" },
1385
- "roo-code": { cmd: `Open VS Code → File → Open Folder → select vault`, name: "Roo Code" },
1386
- copilot: { cmd: `Open VS Code → File → Open Folder → select vault`, name: "Copilot" },
1387
- amp: { cmd: `cd "${vaultPath}" && amp`, name: "Amp" },
1388
- aider: { cmd: `cd "${vaultPath}" && aider`, name: "Aider" },
1411
+ // Agent display names and CLI commands
1412
+ const agentInfo = {
1413
+ "claude-code": { name: "Claude Code", cli: "claude" },
1414
+ cursor: { name: "Cursor", cli: null },
1415
+ cline: { name: "Cline", cli: null },
1416
+ codex: { name: "Codex", cli: "codex" },
1417
+ windsurf: { name: "Windsurf", cli: null },
1418
+ openclaw: { name: "OpenClaw", cli: "openclaw" },
1419
+ antigravity: { name: "Antigravity", cli: "gemini" },
1420
+ "roo-code": { name: "Roo Code", cli: null },
1421
+ copilot: { name: "Copilot", cli: null },
1422
+ amp: { name: "Amp", cli: "amp" },
1423
+ aider: { name: "Aider", cli: "aider" },
1389
1424
  };
1390
1425
 
1391
- const primaryAgent = selectedAgents[0];
1392
1426
  const command = updateMode ? "/update" : "/setup";
1393
- const agent = agentOpen[primaryAgent.id] || { cmd: "Open your AI agent in the vault", name: "your agent" };
1427
+ const agentNames = selectedAgents.map((a) => agentInfo[a.id]?.name || a.name);
1428
+ const agentList = agentNames.join(", ");
1394
1429
 
1395
- // Box-drawn summary panel
1396
- const boxW = 58;
1397
- const pad = (s, w) => {
1398
- const visible = strip(s).length;
1399
- return visible < w ? s + " ".repeat(w - visible) : s;
1400
- };
1430
+ // CLI agents get "cd + run" instructions, GUI agents get "open folder"
1431
+ const cliAgents = selectedAgents.filter((a) => agentInfo[a.id]?.cli);
1432
+ const guiAgents = selectedAgents.filter((a) => !agentInfo[a.id]?.cli);
1401
1433
 
1402
- ln(gray(` ┌${"".repeat(boxW)}┐`));
1403
- ln(gray(` │`) + pad(` ${bold("Next steps")}`, boxW) + gray(`│`));
1404
- ln(gray(` │${"".repeat(boxW)}│`));
1405
- ln(gray(` │`) + pad(` ${cyan("1")} Open your vault in ${bold("Obsidian")} ${dim("(for viewing files)")}`, boxW) + gray(`│`));
1406
- ln(gray(` │`) + pad(` ${dim(vaultPath.length > 48 ? "..." + vaultPath.slice(-45) : vaultPath)}`, boxW) + gray(`│`));
1407
- ln(gray(` │`) + pad(` ${cyan("2")} Open the vault in ${bold(agent.name)} ${dim("(your AI agent)")}`, boxW) + gray(`│`));
1408
- ln(gray(` │`) + pad(` ${dim(agent.cmd.length > 48 ? agent.cmd.slice(0, 48) + "..." : agent.cmd)}`, boxW) + gray(`│`));
1409
- ln(gray(` │`) + pad(` ${cyan("3")} Run ${bold(command)} in ${agent.name}`, boxW) + gray(`│`));
1410
- ln(gray(` │`) + pad(` ${dim(updateMode ? "Syncs your Engine with the latest version" : "Builds your Identity, Strategy, and Goals")}`, boxW) + gray(`│`));
1411
- ln(gray(` │${" ".repeat(boxW)}│`));
1412
- ln(gray(` │`) + pad(` ${dim("Obsidian = view your files")}`, boxW) + gray(`│`));
1413
- ln(gray(` │`) + pad(` ${dim(agent.name + " = where you work with the AI")}`, boxW) + gray(`│`));
1414
- ln(gray(` │${" ".repeat(boxW)}│`));
1415
- ln(gray(` │`) + pad(` ${dim("/morning [work] /log → /analyse-day → /plan-tomorrow")}`, boxW) + gray(`│`));
1416
- ln(gray(` └${"─".repeat(boxW)}┘`));
1434
+ ln(` ${bold("Next steps")}`);
1435
+ ln();
1436
+ ln(` ${cyan("1")} Open your vault in ${bold("Obsidian")}`);
1437
+ ln(` ${dim("Obsidian is where you view and browse your files")}`);
1438
+ ln();
1439
+ ln(` ${cyan("2")} Open the vault in your AI agent`);
1440
+ if (cliAgents.length > 0) {
1441
+ const cmds = cliAgents.map((a) => agentInfo[a.id].cli);
1442
+ ln(` ${dim("cd")} ${vaultPath}`);
1443
+ ln(` ${dim("then run:")} ${cmds.map((c) => bold(c)).join(dim(" or "))}`);
1444
+ }
1445
+ if (guiAgents.length > 0) {
1446
+ const names = guiAgents.map((a) => bold(agentInfo[a.id]?.name || a.name)).join(dim(", "));
1447
+ ln(` ${dim("Open")} ${names} ${dim("→ open the vault folder")}`);
1448
+ }
1449
+ ln();
1450
+ ln(` ${cyan("3")} Enable the Obsidian theme`);
1451
+ ln(` ${dim("Settings → Appearance → CSS snippets → toggle on minimal-theme")}`);
1452
+ ln();
1453
+ ln(` ${cyan("4")} Run ${bold(command)} in your agent`);
1454
+ ln(` ${dim(updateMode ? "Syncs your Engine with the latest version" : "Builds your Identity, Strategy, and Goals")}`);
1455
+ ln();
1456
+ ln(gray(" ─────────────────────────────────────"));
1457
+ ln();
1458
+ ln(` ${dim("Obsidian = view your files")}`);
1459
+ ln(` ${dim("Your AI agent = where you work")}`);
1460
+ ln();
1461
+ ln(` ${dim("/morning → [work] → /log")}`);
1462
+ ln(` ${dim("/analyse-day → /plan-tomorrow")}`);
1417
1463
  ln();
1418
1464
  }
1419
1465
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mover-os",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "The self-improving OS for AI agents. Turns Obsidian into an execution engine.",
5
5
  "bin": {
6
6
  "mover-os": "install.js"
@@ -11,7 +11,8 @@
11
11
  "src/system/",
12
12
  "src/skills/",
13
13
  "src/hooks/",
14
- "src/structure/"
14
+ "src/structure/",
15
+ "src/theme/"
15
16
  ],
16
17
  "keywords": [
17
18
  "obsidian",
@@ -0,0 +1,272 @@
1
+ /* =============================================
2
+ RAMS-STYLE MINIMAL
3
+ - Grayscale decorative emojis only
4
+ - STATUS emojis (🟢🟡🔴🎯💸) stay colored
5
+ - Dimmer headings, clean spacing
6
+ ============================================= */
7
+
8
+ /* =========== CORE: Pure grayscale =========== */
9
+
10
+ body,
11
+ .markdown-source-view,
12
+ .markdown-preview-view,
13
+ .cm-s-obsidian {
14
+ --text-normal: #888888 !important;
15
+ --text-muted: #606060 !important;
16
+ --text-faint: #404040 !important;
17
+ --background-primary: #0a0a0a !important;
18
+ --background-secondary: #111111 !important;
19
+ }
20
+
21
+ /* All text - single gray tone */
22
+ p,
23
+ li,
24
+ .cm-line {
25
+ color: #888888 !important;
26
+ }
27
+
28
+ /* =========== HEADINGS: Dimmer =========== */
29
+
30
+ h1,
31
+ h2,
32
+ h3,
33
+ h4,
34
+ h5,
35
+ h6,
36
+ .cm-header-1,
37
+ .cm-header-2,
38
+ .cm-header-3,
39
+ .HyperMD-header-1,
40
+ .HyperMD-header-2,
41
+ .HyperMD-header-3 {
42
+ color: #a0a0a0 !important;
43
+ font-weight: 500 !important;
44
+ letter-spacing: -0.01em !important;
45
+ }
46
+
47
+ h1,
48
+ .cm-header-1 {
49
+ font-weight: 600 !important;
50
+ color: #b0b0b0 !important;
51
+ }
52
+
53
+ /* Add space after heading text (before next content) */
54
+ .markdown-preview-view h1::after,
55
+ .markdown-preview-view h2::after,
56
+ .markdown-preview-view h3::after {
57
+ content: "" !important;
58
+ display: block !important;
59
+ margin-bottom: 0.5em !important;
60
+ }
61
+
62
+ /* =========== GRAYSCALE DECORATIVE EMOJIS ONLY =========== */
63
+
64
+ /* Target emojis in headings and general content */
65
+ .cm-header .cm-emoji,
66
+ h1 .emoji,
67
+ h2 .emoji,
68
+ h3 .emoji,
69
+ .HyperMD-header .cm-emoji {
70
+ filter: grayscale(100%) !important;
71
+ opacity: 0.5 !important;
72
+ }
73
+
74
+ /* PRESERVE status indicator colors (🟢🟡🔴🎯💸) */
75
+ /* These are typically in table cells, not headings */
76
+ td .emoji,
77
+ td span,
78
+ .markdown-preview-view td {
79
+ filter: none !important;
80
+ opacity: 1 !important;
81
+ }
82
+
83
+ /* =========== LINKS: Differentiated by status =========== */
84
+
85
+ /* Regular links and created wikilinks */
86
+ a,
87
+ .cm-link,
88
+ .internal-link,
89
+ .external-link {
90
+ color: #707070 !important;
91
+ text-decoration: none !important;
92
+ }
93
+
94
+ a:hover,
95
+ .internal-link:hover {
96
+ color: #a0a0a0 !important;
97
+ }
98
+
99
+ /* Unresolved links (non-created notes) - dimmer */
100
+ .internal-link.is-unresolved {
101
+ color: #505050 !important;
102
+ opacity: 0.6 !important;
103
+ }
104
+
105
+ .internal-link.is-unresolved:hover {
106
+ color: #707070 !important;
107
+ opacity: 0.8 !important;
108
+ }
109
+
110
+ /* =========== EMPHASIS =========== */
111
+
112
+ strong,
113
+ b,
114
+ .cm-strong {
115
+ color: #9a9a9a !important;
116
+ font-weight: 500 !important;
117
+ }
118
+
119
+ em,
120
+ i {
121
+ color: #888888 !important;
122
+ }
123
+
124
+ /* =========== SPACING: Generous whitespace =========== */
125
+
126
+ .markdown-preview-view h1,
127
+ .markdown-preview-view h2 {
128
+ margin-top: 2.5em !important;
129
+ margin-bottom: 1em !important;
130
+ }
131
+
132
+ .markdown-preview-view h3,
133
+ .markdown-preview-view h4 {
134
+ margin-top: 2em !important;
135
+ margin-bottom: 0.75em !important;
136
+ }
137
+
138
+ .markdown-preview-view h1:first-child,
139
+ .markdown-preview-view h2:first-child {
140
+ margin-top: 0 !important;
141
+ }
142
+
143
+ .markdown-preview-view p {
144
+ margin-bottom: 1.2em !important;
145
+ line-height: 1.7 !important;
146
+ }
147
+
148
+ .markdown-preview-view li {
149
+ margin-bottom: 0.4em !important;
150
+ line-height: 1.6 !important;
151
+ }
152
+
153
+ /* =========== MINIMAL HR =========== */
154
+
155
+ hr {
156
+ border: none !important;
157
+ border-top: 1px solid #222 !important;
158
+ margin: 2.5em 0 !important;
159
+ }
160
+
161
+ hr::before,
162
+ hr::after {
163
+ display: none !important;
164
+ content: none !important;
165
+ }
166
+
167
+ /* =========== SUBTLE ELEMENTS =========== */
168
+
169
+ input[type="checkbox"] {
170
+ opacity: 0.4 !important;
171
+ }
172
+
173
+ .tag {
174
+ color: #606060 !important;
175
+ background: transparent !important;
176
+ }
177
+
178
+ blockquote {
179
+ border-left: 2px solid #333 !important;
180
+ color: #606060 !important;
181
+ padding-left: 1em !important;
182
+ }
183
+
184
+ code,
185
+ .cm-inline-code {
186
+ color: #888888 !important;
187
+ background: #1a1a1a !important;
188
+ border-radius: 4px !important;
189
+ }
190
+
191
+ pre {
192
+ background: #141414 !important;
193
+ border: 1px solid #222 !important;
194
+ border-radius: 8px !important;
195
+ }
196
+
197
+ /* =========== TABLES =========== */
198
+
199
+ table,
200
+ th,
201
+ td {
202
+ border-color: #222 !important;
203
+ }
204
+
205
+ th {
206
+ color: #909090 !important;
207
+ font-weight: 500 !important;
208
+ background: #111 !important;
209
+ }
210
+
211
+ /* =========== SIDEBAR =========== */
212
+
213
+ .nav-folder-title,
214
+ .nav-file-title {
215
+ color: #606060 !important;
216
+ }
217
+
218
+ .nav-folder-title:hover,
219
+ .nav-file-title:hover {
220
+ color: #909090 !important;
221
+ }
222
+
223
+ /* =========== SCROLLBAR =========== */
224
+
225
+ ::-webkit-scrollbar {
226
+ width: 6px !important;
227
+ }
228
+
229
+ ::-webkit-scrollbar-thumb {
230
+ background: #333 !important;
231
+ border-radius: 3px !important;
232
+ }
233
+
234
+ ::-webkit-scrollbar-track {
235
+ background: transparent !important;
236
+ }
237
+
238
+ /* =========== LISTS: Clean & Simple (NO STARS) =========== */
239
+
240
+ ul,
241
+ ol {
242
+ margin-left: 1.5em !important;
243
+ }
244
+
245
+ ul {
246
+ list-style-type: disc !important;
247
+ }
248
+
249
+ ul ul {
250
+ list-style-type: circle !important;
251
+ }
252
+
253
+ ul ul ul {
254
+ list-style-type: square !important;
255
+ }
256
+
257
+ li {
258
+ list-style-position: outside !important;
259
+ }
260
+
261
+ /* Force standard bullet color */
262
+ ::marker {
263
+ color: #888888 !important;
264
+ font-variant-numeric: tabular-nums !important;
265
+ }
266
+
267
+ /* Reset any pseudo-element bullets */
268
+ li::before,
269
+ li::after {
270
+ content: none !important;
271
+ display: none !important;
272
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes