mover-os 4.4.1 → 4.4.3
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 +260 -172
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -182,7 +182,17 @@ async function printHeader(animate = IS_TTY) {
|
|
|
182
182
|
}
|
|
183
183
|
} catch {}
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
const pkgVer = require("./package.json").version;
|
|
186
|
+
ln(` ${dim(`v${pkgVer}`)} ${gray("the agentic operating system for obsidian")}${infoRight ? ` ${infoRight}` : ""}`);
|
|
187
|
+
|
|
188
|
+
// Non-blocking update check
|
|
189
|
+
try {
|
|
190
|
+
const latest = execSync("npm view mover-os version", { encoding: "utf8", timeout: 5000 }).trim();
|
|
191
|
+
if (latest && latest !== pkgVer && compareVersions(latest, pkgVer) > 0) {
|
|
192
|
+
ln(` ${yellow(`Update available: v${pkgVer} → v${latest}`)} ${dim(`run ${bold("moveros update")}`)}`);
|
|
193
|
+
}
|
|
194
|
+
} catch {}
|
|
195
|
+
|
|
186
196
|
ln();
|
|
187
197
|
ln(gray(" ─────────────────────────────────────────────"));
|
|
188
198
|
ln();
|
|
@@ -343,7 +353,16 @@ function textInput({ label = "", initial = "", mask = null, placeholder = "" })
|
|
|
343
353
|
value = value.slice(0, pos) + value.slice(pos + 1);
|
|
344
354
|
}
|
|
345
355
|
}
|
|
346
|
-
else if (data
|
|
356
|
+
else if (data === "\x1b") {
|
|
357
|
+
// Escape — cancel input
|
|
358
|
+
stdin.removeListener("data", handler);
|
|
359
|
+
stdin.setRawMode(false);
|
|
360
|
+
stdin.pause();
|
|
361
|
+
ln();
|
|
362
|
+
resolve(null);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
else if (data.startsWith("\x1b")) { /* ignore other escape sequences */ }
|
|
347
366
|
else {
|
|
348
367
|
for (const ch of data) {
|
|
349
368
|
if (ch.charCodeAt(0) >= 32) {
|
|
@@ -3024,6 +3043,7 @@ async function cmdCapture(opts) {
|
|
|
3024
3043
|
if (!type) return;
|
|
3025
3044
|
}
|
|
3026
3045
|
content = await textInput({ label: `Enter ${type}:` });
|
|
3046
|
+
if (content === null) return;
|
|
3027
3047
|
}
|
|
3028
3048
|
if (!type) type = "task";
|
|
3029
3049
|
|
|
@@ -3536,7 +3556,9 @@ async function cmdPrayer(opts) {
|
|
|
3536
3556
|
if (choice === "fetch") {
|
|
3537
3557
|
barLn();
|
|
3538
3558
|
const city = await textInput({ label: "City", placeholder: "London" });
|
|
3559
|
+
if (city === null) return;
|
|
3539
3560
|
const country = await textInput({ label: "Country", placeholder: "United Kingdom" });
|
|
3561
|
+
if (country === null) return;
|
|
3540
3562
|
barLn();
|
|
3541
3563
|
|
|
3542
3564
|
if (city && country) {
|
|
@@ -3562,7 +3584,7 @@ async function cmdPrayer(opts) {
|
|
|
3562
3584
|
barLn(dim(" Format examples:"));
|
|
3563
3585
|
barLn(dim(" 2026-03-08 05:20 13:00 16:15 18:01 19:45"));
|
|
3564
3586
|
barLn(dim(" March 8: Fajr 05:20, Dhuhr 13:00, Asr 16:15, Maghrib 18:01, Isha 19:45"));
|
|
3565
|
-
barLn(dim(" Type 'done' on
|
|
3587
|
+
barLn(dim(" Type 'done' or press Enter on empty line to finish. 'back' to cancel."));
|
|
3566
3588
|
barLn();
|
|
3567
3589
|
|
|
3568
3590
|
const lines = [];
|
|
@@ -3570,7 +3592,14 @@ async function cmdPrayer(opts) {
|
|
|
3570
3592
|
await new Promise((resolve) => {
|
|
3571
3593
|
const ask = () => {
|
|
3572
3594
|
rl.question(`${BAR_COLOR}\u2502${S.reset} `, (line) => {
|
|
3573
|
-
|
|
3595
|
+
const t = line.trim().toLowerCase();
|
|
3596
|
+
if (t === "done" || t === "") {
|
|
3597
|
+
rl.close();
|
|
3598
|
+
resolve();
|
|
3599
|
+
return;
|
|
3600
|
+
}
|
|
3601
|
+
if (t === "back" || t === "cancel") {
|
|
3602
|
+
lines.length = 0; // clear
|
|
3574
3603
|
rl.close();
|
|
3575
3604
|
resolve();
|
|
3576
3605
|
return;
|
|
@@ -3828,230 +3857,270 @@ async function cmdRestore(opts) {
|
|
|
3828
3857
|
|
|
3829
3858
|
// ─── moveros help ──────────────────────────────────────────────────────────
|
|
3830
3859
|
async function cmdHelp(opts) {
|
|
3831
|
-
//
|
|
3860
|
+
// Animated typing helper
|
|
3861
|
+
const typeOut = async (text, speed = 12) => {
|
|
3862
|
+
if (!IS_TTY) { ln(text); return; }
|
|
3863
|
+
const raw = strip(text);
|
|
3864
|
+
let rawIdx = 0, ansiIdx = 0;
|
|
3865
|
+
// Build mapping of raw char positions to the styled string slices
|
|
3866
|
+
while (rawIdx < raw.length) {
|
|
3867
|
+
w(text[ansiIdx] || "");
|
|
3868
|
+
if (text[ansiIdx] && text[ansiIdx] !== "\x1b" && !text.slice(Math.max(0, ansiIdx - 10), ansiIdx).match(/\x1b\[[^m]*$/)) {
|
|
3869
|
+
rawIdx++;
|
|
3870
|
+
}
|
|
3871
|
+
ansiIdx++;
|
|
3872
|
+
if (rawIdx % 2 === 0) await sleep(speed);
|
|
3873
|
+
}
|
|
3874
|
+
// flush remaining ANSI codes
|
|
3875
|
+
while (ansiIdx < text.length) { w(text[ansiIdx]); ansiIdx++; }
|
|
3876
|
+
w("\n");
|
|
3877
|
+
};
|
|
3878
|
+
|
|
3879
|
+
const typeLine = async (text, speed = 8) => {
|
|
3880
|
+
if (!IS_TTY) { ln(` ${text}`); return; }
|
|
3881
|
+
w(" ");
|
|
3882
|
+
for (let i = 0; i < text.length; i++) {
|
|
3883
|
+
w(text[i]);
|
|
3884
|
+
if (text[i] !== "\x1b" && i % 3 === 0) await sleep(speed);
|
|
3885
|
+
}
|
|
3886
|
+
w("\n");
|
|
3887
|
+
};
|
|
3888
|
+
|
|
3832
3889
|
const pages = [
|
|
3833
3890
|
{
|
|
3834
|
-
title: "
|
|
3891
|
+
title: "What is Mover OS?",
|
|
3835
3892
|
body: [
|
|
3836
|
-
`${bold("
|
|
3893
|
+
`${bold("Your second brain, but it actually works.")}`,
|
|
3894
|
+
"",
|
|
3895
|
+
"Most productivity systems fail because you have to maintain them.",
|
|
3896
|
+
"Mover OS is different — your AI agents maintain it for you.",
|
|
3837
3897
|
"",
|
|
3838
|
-
"
|
|
3839
|
-
"It
|
|
3840
|
-
"Copilot, Codex, and more. Same brain, every editor.",
|
|
3898
|
+
"You tell your AI who you are, what you're building, and where",
|
|
3899
|
+
"you're going. It remembers across every session, every editor.",
|
|
3841
3900
|
"",
|
|
3842
|
-
`${dim("
|
|
3843
|
-
` ${cyan("1.")}
|
|
3844
|
-
` ${cyan("2.")} ${bold("Workflows")} run your day
|
|
3845
|
-
` ${cyan("3.")} ${bold("Skills")}
|
|
3846
|
-
` ${cyan("4.")} The system ${bold("learns")} from your behavior and adapts`,
|
|
3901
|
+
`${dim("Three things make it work:")}`,
|
|
3902
|
+
` ${cyan("1.")} The ${bold("Engine")} — files that store your identity, strategy, goals`,
|
|
3903
|
+
` ${cyan("2.")} ${bold("Workflows")} — 23 commands that run your day (plan, build, log, repeat)`,
|
|
3904
|
+
` ${cyan("3.")} ${bold("Skills")} — 61 packs that make your AI genuinely useful`,
|
|
3847
3905
|
"",
|
|
3848
|
-
|
|
3906
|
+
`Works across 16 agents. Claude Code, Cursor, Gemini, all of them.`,
|
|
3907
|
+
`Same context, every editor. ${dim("Press → to continue.")}`,
|
|
3849
3908
|
],
|
|
3850
3909
|
},
|
|
3851
3910
|
{
|
|
3852
|
-
title: "The Engine
|
|
3911
|
+
title: "The Engine",
|
|
3853
3912
|
body: [
|
|
3854
|
-
`${dim("
|
|
3913
|
+
`${dim("Your identity, stored as markdown. Read by every AI session.")}`,
|
|
3855
3914
|
"",
|
|
3856
|
-
|
|
3915
|
+
` ${cyan("Identity_Prime.md")} Who you are — values, strengths, anti-patterns`,
|
|
3916
|
+
` ${cyan("Strategy.md")} What you're betting on right now`,
|
|
3917
|
+
` ${cyan("Active_Context.md")} What's happening today — focus, blockers, energy`,
|
|
3918
|
+
` ${cyan("Goals.md")} Where you're heading — 90 days to 10 years`,
|
|
3919
|
+
` ${cyan("Mover_Dossier.md")} What you've got — skills, audience, assets`,
|
|
3920
|
+
` ${cyan("Auto_Learnings.md")} What the AI has noticed about your behavior`,
|
|
3857
3921
|
"",
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
` ${cyan("Active_Context.md")} What's happening NOW — blockers, focus, state`,
|
|
3861
|
-
` ${cyan("Goals.md")} Where you're going — 90d, 1yr, 10yr targets`,
|
|
3862
|
-
` ${cyan("Mover_Dossier.md")} What you have — skills, capital, network`,
|
|
3863
|
-
` ${cyan("Auto_Learnings.md")} What the AI notices — behavioral patterns`,
|
|
3922
|
+
"These files are yours. The system never overwrites them.",
|
|
3923
|
+
"Every workflow reads them. They evolve as you do.",
|
|
3864
3924
|
"",
|
|
3865
|
-
|
|
3866
|
-
"Every AI session reads them. Every workflow updates them.",
|
|
3867
|
-
`Your Engine ${bold("evolves")} as you do.`,
|
|
3925
|
+
`${dim("Location:")} 02_Areas/Engine/`,
|
|
3868
3926
|
],
|
|
3869
3927
|
},
|
|
3870
3928
|
{
|
|
3871
|
-
title: "Daily
|
|
3929
|
+
title: "Your Daily Loop",
|
|
3872
3930
|
body: [
|
|
3873
|
-
`${
|
|
3931
|
+
`${dim("The rhythm that makes it stick:")}`,
|
|
3874
3932
|
"",
|
|
3875
|
-
` ${green("→")} ${bold("/morning")}
|
|
3876
|
-
` ${green("→")} ${bold("[WORK]")} Build, ship, create
|
|
3877
|
-
` ${green("→")} ${bold("/log")} Capture what happened
|
|
3878
|
-
` ${green("→")} ${bold("/analyse-day")}
|
|
3879
|
-
` ${green("→")} ${bold("/plan-tomorrow")}
|
|
3933
|
+
` ${green("→")} ${bold("/morning")} Check in. Set your one thing for the day.`,
|
|
3934
|
+
` ${green("→")} ${bold("[WORK]")} Build, ship, create.`,
|
|
3935
|
+
` ${green("→")} ${bold("/log")} Capture what happened. Plan syncs automatically.`,
|
|
3936
|
+
` ${green("→")} ${bold("/analyse-day")} Honest audit. What worked, what didn't.`,
|
|
3937
|
+
` ${green("→")} ${bold("/plan-tomorrow")} Set up tomorrow before you close the laptop.`,
|
|
3880
3938
|
"",
|
|
3881
|
-
|
|
3882
|
-
` ${green("→")} ${bold("/review-week")} Sunday deep review + strategy validation`,
|
|
3939
|
+
` ${dim("Sundays:")} ${bold("/review-week")} — zoom out, validate strategy, clean the system.`,
|
|
3883
3940
|
"",
|
|
3884
|
-
|
|
3885
|
-
"
|
|
3886
|
-
`Every workflow hands off to the next — ${bold("no dead ends")}.`,
|
|
3941
|
+
"Miss a day, the system notices. Miss three, /reboot kicks in.",
|
|
3942
|
+
"Each workflow hands off to the next. No dead ends.",
|
|
3887
3943
|
],
|
|
3888
3944
|
},
|
|
3889
3945
|
{
|
|
3890
|
-
title: "
|
|
3946
|
+
title: "23 Workflows",
|
|
3891
3947
|
body: [
|
|
3892
|
-
`${
|
|
3893
|
-
`${bold("Build:")} /ignite /overview /refactor-plan /capture /debrief`,
|
|
3894
|
-
`${bold("Think:")} /debug-resistance /pivot-strategy /mover-ideas /screenshot`,
|
|
3895
|
-
`${bold("Grow:")} /harvest /history /reboot`,
|
|
3896
|
-
`${bold("Meta:")} /setup /update /walkthrough /migrate /mover-check /mover-report`,
|
|
3948
|
+
`${dim("Slash commands inside your AI agent. Type / and go.")}`,
|
|
3897
3949
|
"",
|
|
3898
|
-
`${
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
` ${cyan("•")} ${bold("/screenshot")} does meta-analysis of your AI session patterns`,
|
|
3950
|
+
`${bold("Daily:")} /morning /log /analyse-day /plan-tomorrow /review-week`,
|
|
3951
|
+
`${bold("Projects:")} /ignite /overview /refactor-plan /capture /debrief`,
|
|
3952
|
+
`${bold("Strategy:")} /debug-resistance /pivot-strategy /mover-ideas /screenshot`,
|
|
3953
|
+
`${bold("Growth:")} /harvest /history /reboot`,
|
|
3954
|
+
`${bold("System:")} /setup /update /walkthrough /migrate /mover-check`,
|
|
3904
3955
|
"",
|
|
3905
|
-
"
|
|
3956
|
+
`${dim("Highlights:")}`,
|
|
3957
|
+
` ${bold("/ignite")} Starts any project — interrogation, brief, plan`,
|
|
3958
|
+
` ${bold("/debug-resistance")} Figures out WHY you're avoiding something`,
|
|
3959
|
+
` ${bold("/harvest")} Turns conversations into permanent knowledge`,
|
|
3960
|
+
` ${bold("/screenshot")} Meta-analysis of how you actually use AI`,
|
|
3906
3961
|
],
|
|
3907
3962
|
},
|
|
3908
3963
|
{
|
|
3909
|
-
title: "
|
|
3964
|
+
title: "61 Skill Packs",
|
|
3910
3965
|
body: [
|
|
3911
|
-
`${
|
|
3966
|
+
`${dim("Specialized knowledge your AI loads automatically.")}`,
|
|
3912
3967
|
"",
|
|
3913
|
-
|
|
3914
|
-
` ${cyan("
|
|
3915
|
-
` ${cyan("
|
|
3916
|
-
` ${cyan("
|
|
3917
|
-
` ${cyan("
|
|
3918
|
-
` ${cyan("seo")} Audits, schema markup, programmatic SEO, content`,
|
|
3919
|
-
` ${cyan("design")} UI/UX, frontend design, Obsidian markdown/canvas`,
|
|
3920
|
-
` ${cyan("obsidian")} JSON Canvas, Bases, Obsidian CLI, markdown`,
|
|
3968
|
+
` ${cyan("dev")} TDD, debugging, refactoring, error handling, React`,
|
|
3969
|
+
` ${cyan("marketing")} Copywriting, SEO, CRO, social media, email sequences`,
|
|
3970
|
+
` ${cyan("strategy")} Pricing, launch strategy, competitor analysis`,
|
|
3971
|
+
` ${cyan("design")} UI/UX, frontend patterns, accessibility`,
|
|
3972
|
+
` ${cyan("obsidian")} Canvas, Bases, markdown, CLI automation`,
|
|
3921
3973
|
"",
|
|
3922
|
-
`${dim("System skills (always
|
|
3923
|
-
` friction-enforcer
|
|
3924
|
-
`
|
|
3974
|
+
`${dim("System skills (always watching):")}`,
|
|
3975
|
+
` ${bold("friction-enforcer")} Pushes back when you drift from your plan`,
|
|
3976
|
+
` ${bold("pattern-detector")} Spots recurring behavior across sessions`,
|
|
3977
|
+
` ${bold("plan-md-guardian")} Protects your roadmap from corruption`,
|
|
3978
|
+
` ${bold("workflow-router")} Suggests the right workflow for the moment`,
|
|
3925
3979
|
"",
|
|
3926
|
-
"
|
|
3980
|
+
"You choose categories during install. Skills activate on context.",
|
|
3927
3981
|
],
|
|
3928
3982
|
},
|
|
3929
3983
|
{
|
|
3930
3984
|
title: "The Friction System",
|
|
3931
3985
|
body: [
|
|
3932
|
-
`${
|
|
3986
|
+
`${dim("Your AI has opinions. That's the point.")}`,
|
|
3933
3987
|
"",
|
|
3934
|
-
` ${dim("Level 1")} ${cyan("Surface")}
|
|
3935
|
-
` ${dim("Level 2")} ${yellow("Justify")}
|
|
3936
|
-
` ${dim("Level 3")} ${red("Earn It")}
|
|
3937
|
-
` ${dim("Level 4")} ${red("Hard Block")}
|
|
3988
|
+
` ${dim("Level 1")} ${cyan("Surface")} "Your plan says X. You're doing Y. Intentional?"`,
|
|
3989
|
+
` ${dim("Level 2")} ${yellow("Justify")} "Why is this more important than your Single Test?"`,
|
|
3990
|
+
` ${dim("Level 3")} ${red("Earn It")} Stops helping with off-plan work entirely.`,
|
|
3991
|
+
` ${dim("Level 4")} ${red("Hard Block")} Won't delete Engine files without a reason.`,
|
|
3938
3992
|
"",
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
"when you're avoiding the hard thing.",
|
|
3993
|
+
"You can always push through. It's awareness, not a wall.",
|
|
3994
|
+
"But if you're avoiding the hard thing, the AI won't pretend.",
|
|
3942
3995
|
"",
|
|
3943
|
-
`${dim("
|
|
3944
|
-
`
|
|
3996
|
+
`${dim("Smart gate:")} If the work is genuinely useful (compound value,`,
|
|
3997
|
+
`exploration), it logs ${dim("[COMPOUND]")} and doesn't escalate.`,
|
|
3945
3998
|
],
|
|
3946
3999
|
},
|
|
3947
4000
|
{
|
|
3948
|
-
title: "
|
|
4001
|
+
title: "What is this CLI?",
|
|
3949
4002
|
body: [
|
|
3950
|
-
`${bold("
|
|
4003
|
+
`${bold("Terminal utilities that don't need an AI session.")}`,
|
|
3951
4004
|
"",
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
` ${cyan("3.")} Patterns surface proactively in workflows`,
|
|
3956
|
-
` ${cyan("4.")} You confirm or dismiss — the system adapts`,
|
|
4005
|
+
"Your AI agents handle the complex stuff — planning, analysis,",
|
|
4006
|
+
"writing. This CLI handles everything else: quick lookups, status",
|
|
4007
|
+
"checks, maintenance, things you want instantly.",
|
|
3957
4008
|
"",
|
|
3958
|
-
`${dim("
|
|
3959
|
-
` ${
|
|
3960
|
-
` ${
|
|
3961
|
-
` ${
|
|
3962
|
-
` ${yellow("Scope Creep")} Tasks growing beyond plan boundaries`,
|
|
3963
|
-
` ${yellow("Energy Cycles")} Performance tied to sleep/food/time`,
|
|
4009
|
+
`${dim("How it fits together:")}`,
|
|
4010
|
+
` ${cyan("Workflows")} Run inside AI agents (/morning, /log, /ignite)`,
|
|
4011
|
+
` ${cyan("Skills")} Loaded by AI agents automatically`,
|
|
4012
|
+
` ${cyan("CLI")} Runs in your terminal, no AI needed`,
|
|
3964
4013
|
"",
|
|
3965
|
-
|
|
4014
|
+
"The CLI supplements your agents. It never replaces them.",
|
|
4015
|
+
`Think of it as ${bold("htop for your productivity")} — instant, free, always there.`,
|
|
3966
4016
|
],
|
|
3967
4017
|
},
|
|
3968
4018
|
{
|
|
3969
|
-
title: "
|
|
4019
|
+
title: "CLI — Status & Insight",
|
|
3970
4020
|
body: [
|
|
3971
|
-
`${
|
|
4021
|
+
`${dim("See what's happening without opening an AI session.")}`,
|
|
3972
4022
|
"",
|
|
3973
|
-
|
|
3974
|
-
`
|
|
3975
|
-
` Copilot Amazon Q OpenCode Kilo Code`,
|
|
4023
|
+
` ${cyan("pulse")} Dashboard — tasks, streaks, energy, blockers`,
|
|
4024
|
+
` ${dim("Like htop for your day. One glance.")}`,
|
|
3976
4025
|
"",
|
|
3977
|
-
|
|
3978
|
-
`
|
|
4026
|
+
` ${cyan("replay")} Session replay — what you did, when, drift analysis`,
|
|
4027
|
+
` ${dim("\"You planned 4 tasks, completed 2, drifted into 3.\"")}`,
|
|
3979
4028
|
"",
|
|
3980
|
-
|
|
3981
|
-
`
|
|
4029
|
+
` ${cyan("diff")} Engine evolution — how your strategy changed over time`,
|
|
4030
|
+
` ${dim("Git-powered. Shows exactly when and why.")}`,
|
|
4031
|
+
"",
|
|
4032
|
+
` ${cyan("context")} What each agent sees — loaded rules, skills, token count`,
|
|
4033
|
+
` ${dim("Debug why an agent is behaving differently.")}`,
|
|
3982
4034
|
"",
|
|
3983
|
-
"
|
|
3984
|
-
`follow you everywhere. The ${bold("Engine is the constant")}.`,
|
|
3985
|
-
`Run ${cyan("moveros sync")} to update all agents at once.`,
|
|
4035
|
+
` ${cyan("doctor")} Health check — are all agents configured correctly?`,
|
|
3986
4036
|
],
|
|
3987
4037
|
},
|
|
3988
4038
|
{
|
|
3989
|
-
title: "CLI
|
|
4039
|
+
title: "CLI — Quick Actions",
|
|
3990
4040
|
body: [
|
|
3991
|
-
`${
|
|
4041
|
+
`${dim("Do things fast without starting a session.")}`,
|
|
3992
4042
|
"",
|
|
3993
|
-
` ${cyan("
|
|
3994
|
-
`
|
|
3995
|
-
|
|
3996
|
-
` ${cyan("
|
|
3997
|
-
`
|
|
3998
|
-
|
|
3999
|
-
` ${cyan("
|
|
4000
|
-
`
|
|
4001
|
-
|
|
4002
|
-
` ${cyan("
|
|
4003
|
-
`
|
|
4004
|
-
` ${cyan("moveros warm")} Pre-warm an AI session with context`,
|
|
4043
|
+
` ${cyan("capture")} Quick capture — task, idea, link, brain dump`,
|
|
4044
|
+
` ${dim("moveros capture --task \"Fix the login bug\"")}`,
|
|
4045
|
+
"",
|
|
4046
|
+
` ${cyan("who")} Entity lookup — search People, Orgs, Places`,
|
|
4047
|
+
` ${dim("moveros who \"Ishaaq\" → everything you know about them")}`,
|
|
4048
|
+
"",
|
|
4049
|
+
` ${cyan("warm")} Pre-warm an AI session with fresh context`,
|
|
4050
|
+
` ${dim("Run before opening Claude/Cursor. Eliminates cold start.")}`,
|
|
4051
|
+
"",
|
|
4052
|
+
` ${cyan("prayer")} Mosque timetable — next prayer in your status line`,
|
|
4053
|
+
` ${dim("Paste or fetch. Shows countdown. Optional.")}`,
|
|
4005
4054
|
],
|
|
4006
4055
|
},
|
|
4007
4056
|
{
|
|
4008
|
-
title: "
|
|
4057
|
+
title: "CLI — Maintenance",
|
|
4009
4058
|
body: [
|
|
4010
|
-
`${
|
|
4059
|
+
`${dim("Keep everything in sync without thinking about it.")}`,
|
|
4060
|
+
"",
|
|
4061
|
+
` ${cyan("sync")} Update all agents to latest rules and skills`,
|
|
4062
|
+
` ${dim("One command updates 16 agents. Shows what changed.")}`,
|
|
4063
|
+
"",
|
|
4064
|
+
` ${cyan("backup")} Backup Engine, Areas, or agent configs`,
|
|
4065
|
+
` ${dim("With manifest. Knows what's in each backup.")}`,
|
|
4066
|
+
"",
|
|
4067
|
+
` ${cyan("restore")} Restore from any backup — selective, safe`,
|
|
4068
|
+
` ${dim("Creates a safety backup before restoring.")}`,
|
|
4069
|
+
"",
|
|
4070
|
+
` ${cyan("settings")} View/edit config from terminal`,
|
|
4071
|
+
` ${dim("moveros settings set review_day sunday")}`,
|
|
4072
|
+
"",
|
|
4073
|
+
` ${cyan("update")} Update CLI + workflows + skills in one go`,
|
|
4074
|
+
` ${dim("Self-updates the CLI, then pulls latest payload.")}`,
|
|
4075
|
+
],
|
|
4076
|
+
},
|
|
4077
|
+
{
|
|
4078
|
+
title: "16 Agents, One Brain",
|
|
4079
|
+
body: [
|
|
4080
|
+
`${dim("Install once. Every agent gets the same context.")}`,
|
|
4081
|
+
"",
|
|
4082
|
+
`${dim("Full tier")} ${dim("(rules + skills + commands + hooks):")}`,
|
|
4083
|
+
` Claude Code Cursor Cline Windsurf Gemini CLI`,
|
|
4084
|
+
` Copilot Amazon Q OpenCode Kilo Code`,
|
|
4011
4085
|
"",
|
|
4012
|
-
|
|
4013
|
-
`
|
|
4014
|
-
` ${dim("Line 3:")} Rate limits (5hr + 7day + extra usage)`,
|
|
4086
|
+
`${dim("Enhanced tier")} ${dim("(rules + skills):")}`,
|
|
4087
|
+
` Codex Amp Roo Code Antigravity`,
|
|
4015
4088
|
"",
|
|
4016
|
-
`${dim("
|
|
4017
|
-
`
|
|
4018
|
-
` ${cyan("•")} Strategic task count (vitality excluded)`,
|
|
4019
|
-
` ${cyan("•")} Vitality slot machine — rotates reminders every minute`,
|
|
4020
|
-
` ${cyan("•")} Next prayer time (if ${dim("show_prayer_times: true")} in settings)`,
|
|
4021
|
-
` ${cyan("•")} Time since last /log — so you never forget`,
|
|
4022
|
-
` ${cyan("•")} Rate limit bars with reset times`,
|
|
4089
|
+
`${dim("Basic tier")} ${dim("(rules only):")}`,
|
|
4090
|
+
` Continue Aider`,
|
|
4023
4091
|
"",
|
|
4024
|
-
|
|
4092
|
+
"Switch editors whenever. Your Engine follows you.",
|
|
4093
|
+
`${cyan("moveros sync")} keeps them all current.`,
|
|
4025
4094
|
],
|
|
4026
4095
|
},
|
|
4027
4096
|
{
|
|
4028
|
-
title: "
|
|
4097
|
+
title: "Get Started",
|
|
4029
4098
|
body: [
|
|
4030
|
-
`${bold("
|
|
4099
|
+
`${bold("Five minutes to a system that remembers everything.")}`,
|
|
4031
4100
|
"",
|
|
4032
|
-
` ${cyan("1.")} Run ${bold("/setup")} in
|
|
4101
|
+
` ${cyan("1.")} Run ${bold("/setup")} in your AI agent — it'll interview you`,
|
|
4033
4102
|
` ${cyan("2.")} Run ${bold("/morning")} to start your first session`,
|
|
4034
4103
|
` ${cyan("3.")} Work. Build. Ship.`,
|
|
4035
|
-
` ${cyan("4.")} Run ${bold("/log")}
|
|
4104
|
+
` ${cyan("4.")} Run ${bold("/log")} when you're done — captures everything`,
|
|
4036
4105
|
` ${cyan("5.")} Run ${bold("/plan-tomorrow")} before bed`,
|
|
4037
4106
|
"",
|
|
4038
|
-
`${dim("
|
|
4039
|
-
` ${
|
|
4040
|
-
` ${
|
|
4041
|
-
` ${cyan("•")} The system gets smarter the more you use it`,
|
|
4042
|
-
` ${cyan("•")} Trust the Engine files — they're your memory between sessions`,
|
|
4107
|
+
`${dim("Two things to know:")}`,
|
|
4108
|
+
` ${bold("Single Test")} — the one thing that makes today a win`,
|
|
4109
|
+
` ${bold("Sacrifice")} — what you won't do (just as important)`,
|
|
4043
4110
|
"",
|
|
4044
|
-
|
|
4111
|
+
"The system learns from you. The more you use it, the sharper it gets.",
|
|
4112
|
+
"",
|
|
4113
|
+
`${dim("moveros.dev")}`,
|
|
4045
4114
|
],
|
|
4046
4115
|
},
|
|
4047
4116
|
];
|
|
4048
4117
|
|
|
4049
4118
|
// Paginated display with keyboard navigation
|
|
4050
4119
|
let page = 0;
|
|
4120
|
+
const seen = new Set();
|
|
4051
4121
|
|
|
4052
|
-
function renderPage() {
|
|
4122
|
+
async function renderPage(animate) {
|
|
4053
4123
|
const p = pages[page];
|
|
4054
|
-
// Clear screen area
|
|
4055
4124
|
w("\x1b[2J\x1b[H"); // clear screen, cursor to top
|
|
4056
4125
|
ln();
|
|
4057
4126
|
|
|
@@ -4067,9 +4136,14 @@ async function cmdHelp(opts) {
|
|
|
4067
4136
|
ln(` ${S.cyan}└${"─".repeat(56)}┘${S.reset}`);
|
|
4068
4137
|
ln();
|
|
4069
4138
|
|
|
4070
|
-
// Body
|
|
4071
|
-
|
|
4072
|
-
|
|
4139
|
+
// Body — animate on first visit, instant on revisit
|
|
4140
|
+
if (animate && !seen.has(page)) {
|
|
4141
|
+
for (const line of p.body) {
|
|
4142
|
+
await typeLine(line, 6);
|
|
4143
|
+
}
|
|
4144
|
+
seen.add(page);
|
|
4145
|
+
} else {
|
|
4146
|
+
for (const line of p.body) ln(` ${line}`);
|
|
4073
4147
|
}
|
|
4074
4148
|
ln();
|
|
4075
4149
|
ln();
|
|
@@ -4084,7 +4158,6 @@ async function cmdHelp(opts) {
|
|
|
4084
4158
|
|
|
4085
4159
|
return new Promise((resolve) => {
|
|
4086
4160
|
if (!IS_TTY) {
|
|
4087
|
-
// Non-interactive: dump all pages
|
|
4088
4161
|
for (const p of pages) {
|
|
4089
4162
|
ln(bold(`\n## ${p.title}\n`));
|
|
4090
4163
|
for (const line of p.body) ln(` ${line}`);
|
|
@@ -4099,22 +4172,32 @@ async function cmdHelp(opts) {
|
|
|
4099
4172
|
stdin.setEncoding("utf8");
|
|
4100
4173
|
w(S.hide);
|
|
4101
4174
|
|
|
4102
|
-
|
|
4175
|
+
let navigating = false;
|
|
4176
|
+
const go = async (newPage) => {
|
|
4177
|
+
if (navigating) return;
|
|
4178
|
+
navigating = true;
|
|
4179
|
+
page = newPage;
|
|
4180
|
+
await renderPage(true);
|
|
4181
|
+
navigating = false;
|
|
4182
|
+
};
|
|
4183
|
+
|
|
4184
|
+
go(0); // initial render with animation
|
|
4103
4185
|
|
|
4104
4186
|
const handler = (data) => {
|
|
4187
|
+
if (navigating) return; // ignore input during animation
|
|
4105
4188
|
if (data === "\x1b[C" || data === "l" || data === " ") {
|
|
4106
|
-
if (page < pages.length - 1)
|
|
4189
|
+
if (page < pages.length - 1) go(page + 1);
|
|
4107
4190
|
} else if (data === "\x1b[D" || data === "h") {
|
|
4108
|
-
if (page > 0)
|
|
4191
|
+
if (page > 0) go(page - 1);
|
|
4109
4192
|
} else if (data === "q" || data === "\x1b" || data === "\x03") {
|
|
4110
4193
|
stdin.removeListener("data", handler);
|
|
4111
4194
|
stdin.setRawMode(false);
|
|
4112
4195
|
stdin.pause();
|
|
4113
4196
|
w(S.show);
|
|
4114
|
-
w("\x1b[2J\x1b[H");
|
|
4197
|
+
w("\x1b[2J\x1b[H");
|
|
4115
4198
|
resolve();
|
|
4116
4199
|
} else if (data === "\r" || data === "\n") {
|
|
4117
|
-
if (page < pages.length - 1)
|
|
4200
|
+
if (page < pages.length - 1) go(page + 1);
|
|
4118
4201
|
else {
|
|
4119
4202
|
stdin.removeListener("data", handler);
|
|
4120
4203
|
stdin.setRawMode(false);
|
|
@@ -4135,27 +4218,20 @@ async function cmdTest(opts) { barLn(yellow("moveros test — not yet implemente
|
|
|
4135
4218
|
|
|
4136
4219
|
// ─── Interactive Main Menu ────────────────────────────────────────────────────
|
|
4137
4220
|
async function cmdMainMenu() {
|
|
4138
|
-
const
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4221
|
+
const menuOrder = [
|
|
4222
|
+
"install", "update",
|
|
4223
|
+
"pulse", "replay", "diff",
|
|
4224
|
+
"doctor", "sync", "context", "warm",
|
|
4225
|
+
"capture", "who",
|
|
4226
|
+
"settings", "prayer", "backup", "restore", "help",
|
|
4144
4227
|
];
|
|
4145
4228
|
|
|
4146
|
-
const menuItems =
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
menuItems.push({
|
|
4153
|
-
id: cmd,
|
|
4154
|
-
name: `${cmd.padEnd(12)} ${dim(meta.desc)}`,
|
|
4155
|
-
tier: `${cat.header}`,
|
|
4156
|
-
});
|
|
4157
|
-
}
|
|
4158
|
-
}
|
|
4229
|
+
const menuItems = menuOrder
|
|
4230
|
+
.filter(cmd => { const m = CLI_COMMANDS[cmd]; return m && !m.hidden; })
|
|
4231
|
+
.map(cmd => ({
|
|
4232
|
+
id: cmd,
|
|
4233
|
+
name: `${cmd.padEnd(12)} ${dim(CLI_COMMANDS[cmd].desc)}`,
|
|
4234
|
+
}));
|
|
4159
4235
|
|
|
4160
4236
|
question(`${bold("moveros")} ${dim("— choose a command")}`);
|
|
4161
4237
|
barLn();
|
|
@@ -4410,6 +4486,7 @@ async function main() {
|
|
|
4410
4486
|
mask: "\u25AA",
|
|
4411
4487
|
placeholder: "MOVER-XXXX-XXXX",
|
|
4412
4488
|
});
|
|
4489
|
+
if (key === null) return;
|
|
4413
4490
|
|
|
4414
4491
|
const sp = spinner("Validating...");
|
|
4415
4492
|
const valid = await validateKey(key);
|
|
@@ -4503,6 +4580,7 @@ async function main() {
|
|
|
4503
4580
|
label: "Where is your Obsidian vault?",
|
|
4504
4581
|
initial: path.join(os.homedir(), "Mover-OS"),
|
|
4505
4582
|
});
|
|
4583
|
+
if (vaultPath === null) return;
|
|
4506
4584
|
} else {
|
|
4507
4585
|
vaultPath = selected;
|
|
4508
4586
|
}
|
|
@@ -4511,6 +4589,7 @@ async function main() {
|
|
|
4511
4589
|
label: "Where is your Obsidian vault?",
|
|
4512
4590
|
initial: path.join(os.homedir(), "Mover-OS"),
|
|
4513
4591
|
});
|
|
4592
|
+
if (vaultPath === null) return;
|
|
4514
4593
|
}
|
|
4515
4594
|
} else {
|
|
4516
4595
|
barLn(dim(`Vault: ${vaultPath}`));
|
|
@@ -4958,7 +5037,7 @@ async function main() {
|
|
|
4958
5037
|
barLn(dim(" 2026-03-08 05:20 13:00 16:15 18:01 19:45"));
|
|
4959
5038
|
barLn(dim(" March 8: Fajr 05:20, Dhuhr 13:00, Asr 16:15, Maghrib 18:01, Isha 19:45"));
|
|
4960
5039
|
barLn(dim(" Or paste a whole table — the system will parse it."));
|
|
4961
|
-
barLn(dim("
|
|
5040
|
+
barLn(dim(" Type 'done' or press Enter on empty line to finish. 'back' to cancel."));
|
|
4962
5041
|
barLn();
|
|
4963
5042
|
|
|
4964
5043
|
const lines = [];
|
|
@@ -4966,7 +5045,14 @@ async function main() {
|
|
|
4966
5045
|
await new Promise((resolve) => {
|
|
4967
5046
|
const ask = () => {
|
|
4968
5047
|
rl.question(`${BAR_COLOR}\u2502${S.reset} `, (line) => {
|
|
4969
|
-
|
|
5048
|
+
const t = line.trim().toLowerCase();
|
|
5049
|
+
if (t === "done" || t === "") {
|
|
5050
|
+
rl.close();
|
|
5051
|
+
resolve();
|
|
5052
|
+
return;
|
|
5053
|
+
}
|
|
5054
|
+
if (t === "back" || t === "cancel") {
|
|
5055
|
+
lines.length = 0;
|
|
4970
5056
|
rl.close();
|
|
4971
5057
|
resolve();
|
|
4972
5058
|
return;
|
|
@@ -4991,7 +5077,9 @@ async function main() {
|
|
|
4991
5077
|
} else if (method === "fetch") {
|
|
4992
5078
|
barLn();
|
|
4993
5079
|
const city = await textInput({ label: "City (e.g. London, Watford, Istanbul)", placeholder: "London" });
|
|
5080
|
+
if (city === null) return;
|
|
4994
5081
|
const country = await textInput({ label: "Country", placeholder: "United Kingdom" });
|
|
5082
|
+
if (country === null) return;
|
|
4995
5083
|
barLn();
|
|
4996
5084
|
|
|
4997
5085
|
if (city && country) {
|