Skip to content

Commit c639a65

Browse files
ralyodioclaude
andcommitted
fix(upgrade): self-update the ACTUAL running moshcode (v0.6.1)
`moshcode upgrade`/`update` already included a self step, but it shelled out to install.sh with the default MOSHCODE_HOME (~/.moshcode) — so if the moshcode on your PATH lived anywhere else, the reinstall landed in a different dir and your moshcode never changed ("it doesn't update moshcode"). Now the self-upgrade targets the exact dir the running moshcode lives in (exports MOSHCODE_HOME resolved from import.meta.url) and reports the version change (before → after / already-latest). And if moshcode is running from a git checkout, it skips the destructive reinstall and tells you to `git pull` instead of blowing away your working tree. Engines are unchanged; self still runs in addition to them on bare `upgrade`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 942bb37 commit c639a65

2 files changed

Lines changed: 35 additions & 4 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "moshcode",
3-
"version": "0.6.0",
3+
"version": "0.6.1",
44
"type": "module",
55
"description": "moshcode — a metal wrapper CLI for agentic coding (installs/drives opencode, claude, codex; spec-driven dev via OpenSpec) + moshscript",
66
"bin": {

src/upgrade.mjs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,35 @@
11
// `moshcode upgrade` — update everything that has a newer version: moshcode
22
// itself and every installed coding engine. Conductor pattern: we just re-run
33
// each tool's own updater/installer (they fetch latest), never vendor them.
4+
import { fileURLToPath } from "node:url";
5+
import path from "node:path";
6+
import fs from "node:fs";
47
import { ENGINES, engineStatus, resolveEngine, upgradeSpec, runCmd } from "./engines.mjs";
58

69
// Self-upgrade re-runs the moshcode installer's `update` path. Defaults to the
710
// GitHub-hosted install.sh (always live); override with MOSHCODE_INSTALL_URL.
811
const SELF_URL = process.env.MOSHCODE_INSTALL_URL
912
|| "https://raw.githubusercontent.com/moshcoder/moshcode/main/install.sh";
1013

14+
// Where the *running* moshcode actually lives (…/<home>/src/upgrade.mjs → <home>).
15+
// We point the installer at this so it updates THIS copy in place, not a default
16+
// path that might not be the one on your PATH.
17+
export const MOSHCODE_HOME = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
18+
19+
// Running from a git checkout? Then a reinstall would blow away the working tree
20+
// — update it with `git pull`, not the installer.
21+
function isGitCheckout(dir) {
22+
return fs.existsSync(path.join(dir, ".git"));
23+
}
24+
25+
function selfVersion() {
26+
try { return JSON.parse(fs.readFileSync(path.join(MOSHCODE_HOME, "package.json"), "utf8")).version || null; }
27+
catch { return null; }
28+
}
29+
1130
function selfSpec() {
12-
return { cmd: "sh", args: ["-c", `curl -fsSL ${SELF_URL} | sh -s -- update`] };
31+
// Export MOSHCODE_HOME so install.sh updates the exact dir we run from.
32+
return { cmd: "sh", args: ["-c", `export MOSHCODE_HOME='${MOSHCODE_HOME}'; curl -fsSL ${SELF_URL} | sh -s -- update`] };
1333
}
1434

1535
/**
@@ -83,11 +103,22 @@ export async function runUpgrade(targets = [], io = {}) {
83103
return ok;
84104
};
85105

86-
if (self) await run("moshcode", selfSpec(), "(self)");
106+
if (self) {
107+
if (isGitCheckout(MOSHCODE_HOME)) {
108+
// Don't reinstall over a working tree — just tell the user how to update it.
109+
log(`\n· moshcode runs from a git checkout (${MOSHCODE_HOME}) — \`git pull\` there to update it (skipping self-reinstall).`);
110+
} else {
111+
const before = selfVersion();
112+
const ok = await run("moshcode", selfSpec(), "(self)");
113+
const after = selfVersion();
114+
if (ok && before && after) {
115+
log(before === after ? `· moshcode already at ${after}` : `· moshcode ${before}${after} — restart moshcode to load it.`);
116+
}
117+
}
118+
}
87119
for (const it of items) await run(it.label, it.spec, it.installed ? "" : "(installing — not present)");
88120

89121
const failed = results.filter((r) => !r.ok);
90122
log(`\n${failed.length ? "✗" : "✓"} upgraded ${results.length - failed.length}/${results.length}${failed.length ? ` — failed: ${failed.map((r) => r.name).join(", ")}` : "."} 🤘`);
91-
if (self) log("· restart moshcode to pick up its own new version.");
92123
return results;
93124
}

0 commit comments

Comments
 (0)