mover-os 4.6.0 → 4.6.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 +137 -37
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -199,15 +199,23 @@ async function printHeader(animate = IS_TTY) {
|
|
|
199
199
|
ln(` ${dim(`v${pkgVer}`)} ${gray("the agentic operating system for obsidian")}${infoRight ? ` ${infoRight}` : ""}`);
|
|
200
200
|
|
|
201
201
|
// Non-blocking update check
|
|
202
|
+
let _updateAvailable = null;
|
|
202
203
|
try {
|
|
203
204
|
const latest = execSync("npm view mover-os version", { encoding: "utf8", timeout: 5000 }).trim();
|
|
204
205
|
if (latest && latest !== pkgVer && compareVersions(latest, pkgVer) > 0) {
|
|
205
|
-
|
|
206
|
+
_updateAvailable = latest;
|
|
206
207
|
}
|
|
207
208
|
} catch {}
|
|
208
209
|
|
|
209
210
|
ln();
|
|
210
|
-
|
|
211
|
+
if (_updateAvailable) {
|
|
212
|
+
ln(` ${yellow("┌──────────────────────────────────────────┐")}`);
|
|
213
|
+
ln(` ${yellow("│")} Update available: ${dim(`v${pkgVer}`)} ${dim("\u2192")} ${green(`v${_updateAvailable}`)}${" ".repeat(Math.max(0, 16 - _updateAvailable.length - pkgVer.length))}${yellow("│")}`);
|
|
214
|
+
ln(` ${yellow("│")} Run ${bold("moveros update")} to get the latest ${yellow("│")}`);
|
|
215
|
+
ln(` ${yellow("└──────────────────────────────────────────┘")}`);
|
|
216
|
+
} else {
|
|
217
|
+
ln(gray(" ─────────────────────────────────────────────"));
|
|
218
|
+
}
|
|
211
219
|
ln();
|
|
212
220
|
}
|
|
213
221
|
|
|
@@ -1670,9 +1678,14 @@ async function runUninstall(vaultPath) {
|
|
|
1670
1678
|
barLn(`${dim("Could not reach Polar — license not deactivated")}`);
|
|
1671
1679
|
}
|
|
1672
1680
|
}
|
|
1673
|
-
// Remove config file
|
|
1674
|
-
|
|
1675
|
-
|
|
1681
|
+
// Remove config file but preserve license key for reinstall
|
|
1682
|
+
if (cfg.licenseKey) {
|
|
1683
|
+
fs.writeFileSync(configPath, JSON.stringify({ licenseKey: cfg.licenseKey }, null, 2), "utf8");
|
|
1684
|
+
barLn(`${green("\u2713")} ${dim("~/.mover/config.json (license key preserved for reinstall)")}`);
|
|
1685
|
+
} else {
|
|
1686
|
+
fs.unlinkSync(configPath);
|
|
1687
|
+
barLn(`${green("\u2713")} ${dim("~/.mover/config.json")}`);
|
|
1688
|
+
}
|
|
1676
1689
|
removed++;
|
|
1677
1690
|
} catch {}
|
|
1678
1691
|
}
|
|
@@ -1880,13 +1893,14 @@ const AGENT_REGISTRY = {
|
|
|
1880
1893
|
},
|
|
1881
1894
|
};
|
|
1882
1895
|
|
|
1883
|
-
// User-selectable agents (
|
|
1896
|
+
// User-selectable agents (15 selections). Each maps to 1+ install targets.
|
|
1884
1897
|
const AGENT_SELECTIONS = [
|
|
1885
1898
|
{ id: "claude-code", targets: ["claude-code"], name: "Claude Code" },
|
|
1886
1899
|
{ id: "cursor", targets: ["cursor"], name: "Cursor" },
|
|
1887
1900
|
{ id: "cline", targets: ["cline"], name: "Cline" },
|
|
1888
1901
|
{ id: "windsurf", targets: ["windsurf"], name: "Windsurf" },
|
|
1889
|
-
{ id: "gemini-cli", targets: ["gemini-cli"
|
|
1902
|
+
{ id: "gemini-cli", targets: ["gemini-cli"], name: "Gemini CLI" },
|
|
1903
|
+
{ id: "antigravity", targets: ["antigravity"], name: "Antigravity" },
|
|
1890
1904
|
{ id: "copilot", targets: ["copilot"], name: "GitHub Copilot" },
|
|
1891
1905
|
{ id: "codex", targets: ["codex"], name: "Codex" },
|
|
1892
1906
|
{ id: "amazon-q", targets: ["amazon-q"], name: "Amazon Q Developer" },
|
|
@@ -5093,6 +5107,21 @@ async function cmdUpdateComprehensive(opts, bundleDir, startTime) {
|
|
|
5093
5107
|
return;
|
|
5094
5108
|
}
|
|
5095
5109
|
|
|
5110
|
+
// ── Confirmation gate ──
|
|
5111
|
+
barLn();
|
|
5112
|
+
const updateConfirm = await interactiveSelect(
|
|
5113
|
+
[
|
|
5114
|
+
{ id: "yes", name: "Apply updates", tier: `${totalChanged} file${totalChanged > 1 ? "s" : ""} will be updated` },
|
|
5115
|
+
{ id: "no", name: "Cancel", tier: "No changes will be made" },
|
|
5116
|
+
],
|
|
5117
|
+
{ multi: false, defaultIndex: 0 }
|
|
5118
|
+
);
|
|
5119
|
+
if (!updateConfirm || updateConfirm === "no") {
|
|
5120
|
+
outro("Update cancelled.");
|
|
5121
|
+
return;
|
|
5122
|
+
}
|
|
5123
|
+
barLn();
|
|
5124
|
+
|
|
5096
5125
|
// ── Apply safe system files directly (no user customizations in these) ──
|
|
5097
5126
|
const home = os.homedir();
|
|
5098
5127
|
let appliedCount = 0;
|
|
@@ -5677,8 +5706,9 @@ async function main() {
|
|
|
5677
5706
|
if (selectedIds.includes("claude-code")) {
|
|
5678
5707
|
barLn();
|
|
5679
5708
|
question("Install Claude Code status line?");
|
|
5680
|
-
barLn(dim("
|
|
5681
|
-
barLn(dim(" Example:
|
|
5709
|
+
barLn(dim(" Live status bar with model, context %, project, session cost, and Mover OS data."));
|
|
5710
|
+
barLn(dim(" Example: Opus 4.6 · 24% · my-project (main) · 2h14m · $12.50"));
|
|
5711
|
+
barLn(dim(" ▸ next task · 2/5 done · Sleep by 22:00 · logged 30m ago"));
|
|
5682
5712
|
barLn();
|
|
5683
5713
|
|
|
5684
5714
|
const slChoice = await interactiveSelect(
|
|
@@ -5805,37 +5835,107 @@ async function main() {
|
|
|
5805
5835
|
}
|
|
5806
5836
|
}
|
|
5807
5837
|
|
|
5808
|
-
// ──
|
|
5838
|
+
// ── Confirmation gate — review and optionally change selections ──
|
|
5809
5839
|
{
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
}
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5840
|
+
let confirmed = false;
|
|
5841
|
+
while (!confirmed) {
|
|
5842
|
+
barLn();
|
|
5843
|
+
question(bold("Review your selections") + dim(" (enter to change, esc to cancel)"));
|
|
5844
|
+
barLn();
|
|
5845
|
+
|
|
5846
|
+
const agentNames = selectedAgents.map((a) => a.name).join(", ");
|
|
5847
|
+
const skillsLabel = installSkills && selectedCategories
|
|
5848
|
+
? [...selectedCategories].join(", ")
|
|
5849
|
+
: installSkills ? "all categories" : "none";
|
|
5850
|
+
const slLabel = selectedIds.includes("claude-code") ? (installStatusLine ? "yes" : "no") : null;
|
|
5851
|
+
|
|
5852
|
+
const reviewItems = [
|
|
5853
|
+
{ id: "_install", name: green(bold(" Install")), tier: "Proceed with the selections above" },
|
|
5854
|
+
{ id: "agents", name: `Agents ${dim(agentNames)}`, tier: "Change which AI agents to install for" },
|
|
5855
|
+
{ id: "skills", name: `Skills ${dim(skillsLabel)}`, tier: "Change skill categories" },
|
|
5856
|
+
];
|
|
5857
|
+
if (slLabel !== null) {
|
|
5858
|
+
reviewItems.push({ id: "statusline", name: `Status line ${dim(slLabel)}`, tier: "Toggle Claude Code status line" });
|
|
5859
|
+
}
|
|
5860
|
+
reviewItems.push({ id: "settings", name: `Settings ${dim("enter to configure")}`, tier: "Configure review_day, tracking, friction level" });
|
|
5861
|
+
|
|
5862
|
+
const pick = await interactiveSelect(reviewItems, { defaultIndex: 0 });
|
|
5863
|
+
if (!pick) { outro("Cancelled."); return; }
|
|
5864
|
+
|
|
5865
|
+
if (pick === "_install") {
|
|
5866
|
+
confirmed = true;
|
|
5867
|
+
} else if (pick === "agents") {
|
|
5868
|
+
barLn();
|
|
5869
|
+
question("Select your AI agents");
|
|
5870
|
+
const agentItems = AGENTS.map((a) => {
|
|
5871
|
+
const detected = a.detect();
|
|
5872
|
+
return { id: a.id, name: `${a.name}${detected ? dim(" (detected)") : ""}`, tier: dim(a.tier), _detected: detected };
|
|
5873
|
+
});
|
|
5874
|
+
const newIds = await interactiveSelect(agentItems, { multi: true, preSelected: selectedIds });
|
|
5875
|
+
if (newIds && newIds.length > 0) {
|
|
5876
|
+
selectedIds.length = 0;
|
|
5877
|
+
newIds.forEach((id) => selectedIds.push(id));
|
|
5878
|
+
selectedAgents.length = 0;
|
|
5879
|
+
AGENTS.filter((a) => selectedIds.includes(a.id)).forEach((a) => selectedAgents.push(a));
|
|
5880
|
+
}
|
|
5881
|
+
} else if (pick === "skills") {
|
|
5882
|
+
barLn();
|
|
5883
|
+
const allSkills = findSkills(bundleDir);
|
|
5884
|
+
const catCounts = {};
|
|
5885
|
+
for (const sk of allSkills) catCounts[sk.category] = (catCounts[sk.category] || 0) + 1;
|
|
5886
|
+
const categoryItems = CATEGORY_META.map((c) => ({
|
|
5887
|
+
id: c.id, name: `${c.name} ${dim(`(${catCounts[c.id] || 0})`)}`, tier: dim(c.desc),
|
|
5888
|
+
}));
|
|
5889
|
+
question("Select skill categories:");
|
|
5890
|
+
const newCats = await interactiveSelect(categoryItems, { multi: true, preSelected: selectedCategories ? [...selectedCategories] : ["development", "obsidian"] });
|
|
5891
|
+
if (newCats) {
|
|
5892
|
+
installSkills = newCats.length > 0;
|
|
5893
|
+
selectedCategories = installSkills ? new Set(newCats) : null;
|
|
5894
|
+
}
|
|
5895
|
+
} else if (pick === "statusline") {
|
|
5896
|
+
installStatusLine = !installStatusLine;
|
|
5897
|
+
} else if (pick === "settings") {
|
|
5898
|
+
// Re-enter settings loop
|
|
5899
|
+
barLn();
|
|
5900
|
+
question("Configure settings " + dim("(enter to toggle/edit, esc to go back)"));
|
|
5901
|
+
barLn();
|
|
5902
|
+
const sCfgPath = path.join(os.homedir(), ".mover", "config.json");
|
|
5903
|
+
let sCfg = {};
|
|
5904
|
+
if (fs.existsSync(sCfgPath)) { try { sCfg = JSON.parse(fs.readFileSync(sCfgPath, "utf8")); } catch {} }
|
|
5905
|
+
if (!sCfg.settings) sCfg.settings = {};
|
|
5906
|
+
const installSettings = [
|
|
5907
|
+
{ key: "track_food", label: "Track food", desc: "Track meals in daily notes" },
|
|
5908
|
+
{ key: "track_sleep", label: "Track sleep", desc: "Track sleep in daily notes" },
|
|
5909
|
+
{ key: "friction_level", label: "Friction level", desc: "AI pushback intensity (1=gentle, 4=hard block)" },
|
|
5910
|
+
{ key: "review_day", label: "Review day", desc: "Day for weekly review" },
|
|
5911
|
+
];
|
|
5912
|
+
let sLoop = true;
|
|
5913
|
+
while (sLoop) {
|
|
5914
|
+
const sItems = installSettings.map((s) => {
|
|
5915
|
+
const meta = KNOWN_SETTINGS[s.key];
|
|
5916
|
+
const val = sCfg.settings[s.key] !== undefined ? sCfg.settings[s.key] : meta.defaults;
|
|
5917
|
+
const display = meta.type === "boolean" ? (val ? green("on") : dim("off")) : String(val);
|
|
5918
|
+
return { id: s.key, name: `${s.label.padEnd(18)}${display}`, tier: s.desc };
|
|
5919
|
+
});
|
|
5920
|
+
const sPick = await interactiveSelect(sItems);
|
|
5921
|
+
if (!sPick) { sLoop = false; break; }
|
|
5922
|
+
const sMeta = KNOWN_SETTINGS[sPick];
|
|
5923
|
+
if (sMeta) {
|
|
5924
|
+
if (sMeta.type === "boolean") {
|
|
5925
|
+
sCfg.settings[sPick] = !(sCfg.settings[sPick] !== undefined ? sCfg.settings[sPick] : sMeta.defaults);
|
|
5926
|
+
} else if (sPick === "friction_level") {
|
|
5927
|
+
const cur = sCfg.settings[sPick] || sMeta.defaults;
|
|
5928
|
+
sCfg.settings[sPick] = cur >= 4 ? 1 : cur + 1;
|
|
5929
|
+
} else if (sPick === "review_day") {
|
|
5930
|
+
const days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
5931
|
+
const cur = sCfg.settings[sPick] || sMeta.defaults;
|
|
5932
|
+
const idx = days.indexOf(cur);
|
|
5933
|
+
sCfg.settings[sPick] = days[(idx + 1) % days.length];
|
|
5934
|
+
}
|
|
5935
|
+
fs.mkdirSync(path.dirname(sCfgPath), { recursive: true });
|
|
5936
|
+
fs.writeFileSync(sCfgPath, JSON.stringify(sCfg, null, 2), "utf8");
|
|
5835
5937
|
}
|
|
5836
5938
|
}
|
|
5837
|
-
fs.mkdirSync(path.dirname(cfgPath), { recursive: true });
|
|
5838
|
-
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
|
|
5839
5939
|
}
|
|
5840
5940
|
}
|
|
5841
5941
|
}
|