mover-os 4.5.4 → 4.5.6

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 (2) hide show
  1. package/install.js +85 -11
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -4739,10 +4739,11 @@ async function cmdUpdateComprehensive(opts, bundleDir, startTime) {
4739
4739
  try {
4740
4740
  execSync("npm i -g mover-os", { stdio: "ignore", timeout: 60000 });
4741
4741
  } catch {
4742
- // Retry with sudo (macOS/Linux where global npm needs root)
4743
- execSync("sudo npm i -g mover-os", { stdio: "ignore", timeout: 60000 });
4742
+ // Retry with sudo use inherit so password prompt shows
4743
+ sp.stop(dim("Needs elevated permissions..."));
4744
+ execSync("sudo npm i -g mover-os", { stdio: "inherit", timeout: 120000 });
4744
4745
  }
4745
- sp.stop(`CLI updated to ${npmVer}`);
4746
+ barLn(`${green("\u2713")} CLI updated to ${npmVer}`);
4746
4747
  barLn(dim(" Re-running with updated CLI..."));
4747
4748
  barLn();
4748
4749
  const args = process.argv.slice(2).concat("--_self-updated");
@@ -4883,17 +4884,90 @@ async function cmdUpdateComprehensive(opts, bundleDir, startTime) {
4883
4884
  return;
4884
4885
  }
4885
4886
 
4886
- // Stage confirmation
4887
- barLn();
4888
- statusLine("ok", "Staged", `${totalChanged} updated files at ${dim("~/.mover/src/")}`);
4887
+ // ── Apply safe system files directly (no user customizations in these) ──
4888
+ const home = os.homedir();
4889
+ let appliedCount = 0;
4890
+
4891
+ // Hooks (shell scripts — users don't customize)
4892
+ const hooksSrc = path.join(bundleDir, "src", "hooks");
4893
+ if (fs.existsSync(hooksSrc) && selectedIds.some((id) => expandTargetIds([id]).includes("claude-code"))) {
4894
+ const hooksDest = path.join(home, ".claude", "hooks");
4895
+ fs.mkdirSync(hooksDest, { recursive: true });
4896
+ for (const file of fs.readdirSync(hooksSrc).filter((f) => f.endsWith(".sh"))) {
4897
+ fs.copyFileSync(path.join(hooksSrc, file), path.join(hooksDest, file));
4898
+ try { fs.chmodSync(path.join(hooksDest, file), 0o755); } catch {}
4899
+ appliedCount++;
4900
+ }
4901
+ statusLine("ok", "Hooks", `${appliedCount} updated`);
4902
+ }
4903
+
4904
+ // Statusline (single JS file — no user data)
4905
+ const slSrc = path.join(bundleDir, "src", "hooks", "statusline.js");
4906
+ const slDest = path.join(home, ".claude", "statusline.js");
4907
+ if (fs.existsSync(slSrc)) {
4908
+ fs.copyFileSync(slSrc, slDest);
4909
+ // Ensure settings.json has statusLine config
4910
+ const globalSettings = path.join(home, ".claude", "settings.json");
4911
+ try {
4912
+ const settings = fs.existsSync(globalSettings)
4913
+ ? JSON.parse(fs.readFileSync(globalSettings, "utf8"))
4914
+ : {};
4915
+ if (!settings.statusLine) {
4916
+ settings.statusLine = { type: "command", command: "node ~/.claude/statusline.js" };
4917
+ fs.writeFileSync(globalSettings, JSON.stringify(settings, null, 2), "utf8");
4918
+ }
4919
+ } catch {}
4920
+ statusLine("ok", "Statusline", "updated");
4921
+ appliedCount++;
4922
+ }
4923
+
4924
+ // /update workflow (must always be current — it drives the rest of the update)
4925
+ const updateSrc = path.join(bundleDir, "src", "workflows", "update.md");
4926
+ if (fs.existsSync(updateSrc)) {
4927
+ const cmdDirs = [
4928
+ path.join(home, ".claude", "commands"),
4929
+ path.join(home, ".cursor", "commands"),
4930
+ path.join(home, ".gemini", "antigravity", "global_workflows"),
4931
+ ];
4932
+ for (const dir of cmdDirs) {
4933
+ const dest = path.join(dir, "update.md");
4934
+ if (fs.existsSync(dir)) {
4935
+ fs.copyFileSync(updateSrc, dest);
4936
+ }
4937
+ }
4938
+ statusLine("ok", "/update", "workflow synced");
4939
+ }
4940
+
4941
+ // Vault structure + templates (safe scaffolding)
4942
+ createVaultStructure(vaultPath);
4943
+ installTemplateFiles(bundleDir, vaultPath);
4944
+
4945
+ // Update version marker
4946
+ fs.writeFileSync(path.join(vaultPath, ".mover-version"), `${require("./package.json").version}\n`, "utf8");
4947
+
4948
+ // Stage confirmation for user-customizable files
4949
+ const userFileChanges = changes.workflows.filter((f) => f.status !== "unchanged").length
4950
+ + (changes.rules === "changed" ? 1 : 0)
4951
+ + (changes.skills || []).filter((f) => f.status !== "unchanged").length;
4952
+
4889
4953
  barLn();
4890
- barLn(bold(" Next step:"));
4891
- barLn(` Run ${bold("/update")} in your AI agent to apply changes.`);
4892
- barLn(dim(" The AI will compare each file against your local version,"));
4893
- barLn(dim(" preserve your customizations, and merge new content."));
4954
+ if (userFileChanges > 0) {
4955
+ statusLine("ok", "Staged", `${userFileChanges} workflow/rule/skill updates at ${dim("~/.mover/src/")}`);
4956
+ barLn();
4957
+ barLn(bold(" Next step:"));
4958
+ barLn(` Run ${bold("/update")} in your AI agent to apply workflow & rule changes.`);
4959
+ barLn(dim(" Your customizations will be preserved — new version is the base,"));
4960
+ barLn(dim(" your additions get carried forward."));
4961
+ } else {
4962
+ statusLine("ok", "System files", "all updated");
4963
+ }
4894
4964
  barLn();
4895
4965
  const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
4896
- outro(`Files staged. Run ${bold("/update")} to apply. ${dim(`(${elapsed}s)`)}`);
4966
+ if (userFileChanges > 0) {
4967
+ outro(`System updated. Run ${bold("/update")} for workflows & rules. ${dim(`(${elapsed}s)`)}`);
4968
+ } else {
4969
+ outro(`${green("Done.")} All files up to date. ${dim(`(${elapsed}s)`)}`);
4970
+ }
4897
4971
  }
4898
4972
 
4899
4973
  // ─── Vault Resolution Helper ─────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mover-os",
3
- "version": "4.5.4",
3
+ "version": "4.5.6",
4
4
  "description": "The self-improving OS for AI agents. Turns Obsidian into an execution engine.",
5
5
  "bin": {
6
6
  "moveros": "install.js"