@skein-code/cli 0.3.0 → 0.3.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/README.md +5 -0
- package/dist/cli.js +129 -14
- package/dist/cli.js.map +1 -1
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -85,6 +85,10 @@ To install the published package from npm:
|
|
|
85
85
|
npm install -g @skein-code/cli
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
Once installed, upgrade in place with `skein update` (it detects your package
|
|
89
|
+
manager and runs the matching global install). Add `--check` to only report a
|
|
90
|
+
newer version, or `--yes` to skip the confirmation prompt.
|
|
91
|
+
|
|
88
92
|
`skein` is the primary command. Existing installations can continue using
|
|
89
93
|
`mosaic` or `mosaic-code`; the `.mosaic/` project state and `MOSAIC_*`
|
|
90
94
|
environment variables remain compatible with this release.
|
|
@@ -224,6 +228,7 @@ skein --print [prompt] headless agent run
|
|
|
224
228
|
skein init project setup
|
|
225
229
|
skein doctor prerequisite and fallback checks
|
|
226
230
|
skein doctor --visual terminal rendering and input calibration
|
|
231
|
+
skein update upgrade to the latest release
|
|
227
232
|
skein config show resolved, redacted configuration
|
|
228
233
|
skein index build/update the selected index
|
|
229
234
|
skein search <query> ranked grounded spans
|
package/dist/cli.js
CHANGED
|
@@ -220,7 +220,7 @@ function isSqliteBusy(error) {
|
|
|
220
220
|
// package.json
|
|
221
221
|
var package_default = {
|
|
222
222
|
name: "@skein-code/cli",
|
|
223
|
-
version: "0.3.
|
|
223
|
+
version: "0.3.2",
|
|
224
224
|
description: "A context-first, model-agnostic coding agent with an auditable terminal workspace.",
|
|
225
225
|
type: "module",
|
|
226
226
|
license: "MIT",
|
|
@@ -236,9 +236,8 @@ var package_default = {
|
|
|
236
236
|
},
|
|
237
237
|
skein: {
|
|
238
238
|
releaseNotes: [
|
|
239
|
-
"
|
|
240
|
-
"
|
|
241
|
-
"Update notices now include a bounded summary of what changed"
|
|
239
|
+
"New: skein update self-upgrades to the latest release",
|
|
240
|
+
"Detects npm/pnpm/yarn/bun; --check reports only, --yes skips the prompt"
|
|
242
241
|
]
|
|
243
242
|
},
|
|
244
243
|
bin: {
|
|
@@ -11438,6 +11437,12 @@ function sliceDisplay(value, maxWidth) {
|
|
|
11438
11437
|
}
|
|
11439
11438
|
return output2;
|
|
11440
11439
|
}
|
|
11440
|
+
function padDisplay(value, width) {
|
|
11441
|
+
if (width <= 0) return "";
|
|
11442
|
+
const truncated = truncateDisplay(value, width);
|
|
11443
|
+
const pad = Math.max(0, width - displayWidth(truncated));
|
|
11444
|
+
return truncated + " ".repeat(pad);
|
|
11445
|
+
}
|
|
11441
11446
|
function compactDisplayPath(path, maxWidth = 54) {
|
|
11442
11447
|
if (displayWidth(path) <= maxWidth) return path;
|
|
11443
11448
|
const parts = path.split("/").filter(Boolean);
|
|
@@ -12531,23 +12536,21 @@ function ListPanel({ title, entries, width = 80, glyphMode = "auto", hideTitle =
|
|
|
12531
12536
|
const labelLimit = entryDetail ? Math.max(1, Math.min(28, innerWidth - 4)) : innerWidth;
|
|
12532
12537
|
const label = truncateDisplay(`${glyphs.bullet} ${entryLabel}`, labelLimit);
|
|
12533
12538
|
if (rowWidth < 52 && entryDetail) {
|
|
12539
|
+
const detailText2 = ` ${truncateDisplay(entryDetail, Math.max(1, innerWidth - 2))}`;
|
|
12534
12540
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
12535
|
-
/* @__PURE__ */ jsx(Text, { color, children: label }),
|
|
12536
|
-
/* @__PURE__ */ jsx(Text, { color: theme.muted, children:
|
|
12541
|
+
/* @__PURE__ */ jsx(Text, { color, children: padDisplay(label, innerWidth) }),
|
|
12542
|
+
/* @__PURE__ */ jsx(Text, { color: theme.muted, children: padDisplay(detailText2, innerWidth) })
|
|
12537
12543
|
] }, `${entry.label}-${index}`);
|
|
12538
12544
|
}
|
|
12539
12545
|
const detailLimit = Math.max(1, innerWidth - displayWidth(label) - 2);
|
|
12546
|
+
const detailText = entryDetail ? truncateDisplay(entryDetail, detailLimit) : "";
|
|
12547
|
+
const trailing = Math.max(0, innerWidth - displayWidth(label) - (entryDetail ? 2 + displayWidth(detailText) : 0));
|
|
12540
12548
|
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
12541
12549
|
/* @__PURE__ */ jsx(Text, { color, children: label }),
|
|
12542
|
-
entryDetail ? /* @__PURE__ */
|
|
12543
|
-
|
|
12544
|
-
truncateDisplay(entryDetail, detailLimit)
|
|
12545
|
-
] }) : null
|
|
12550
|
+
entryDetail ? /* @__PURE__ */ jsx(Text, { color: theme.muted, children: ` ${detailText}` }) : null,
|
|
12551
|
+
trailing > 0 ? /* @__PURE__ */ jsx(Text, { children: " ".repeat(trailing) }) : null
|
|
12546
12552
|
] }, `${entry.label}-${index}`);
|
|
12547
|
-
}) : /* @__PURE__ */
|
|
12548
|
-
glyphs.bullet,
|
|
12549
|
-
" none"
|
|
12550
|
-
] })
|
|
12553
|
+
}) : /* @__PURE__ */ jsx(Text, { color: theme.dim, children: padDisplay(`${glyphs.bullet} none`, innerWidth) })
|
|
12551
12554
|
] });
|
|
12552
12555
|
}
|
|
12553
12556
|
function MeterBar({ segments, total, width, glyphs }) {
|
|
@@ -17148,6 +17151,61 @@ function escapeXml2(value) {
|
|
|
17148
17151
|
})[character] ?? character);
|
|
17149
17152
|
}
|
|
17150
17153
|
|
|
17154
|
+
// src/utils/self-update.ts
|
|
17155
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
17156
|
+
import { realpathSync } from "node:fs";
|
|
17157
|
+
var GLOBAL_INSTALL_ARGS = {
|
|
17158
|
+
npm: (spec) => ["install", "-g", spec],
|
|
17159
|
+
pnpm: (spec) => ["add", "-g", spec],
|
|
17160
|
+
yarn: (spec) => ["global", "add", spec],
|
|
17161
|
+
bun: (spec) => ["add", "-g", spec]
|
|
17162
|
+
};
|
|
17163
|
+
function detectPackageManager(binaryPath = process.argv[1], env = process.env) {
|
|
17164
|
+
const fromAgent = parseUserAgent(env.npm_config_user_agent);
|
|
17165
|
+
if (fromAgent) return fromAgent;
|
|
17166
|
+
let resolved = binaryPath ?? "";
|
|
17167
|
+
try {
|
|
17168
|
+
if (resolved) resolved = realpathSync(resolved);
|
|
17169
|
+
} catch {
|
|
17170
|
+
}
|
|
17171
|
+
const path = resolved.replace(/\\/g, "/").toLowerCase();
|
|
17172
|
+
if (/(^|\/)\.bun\/|(^|\/)bun\//.test(path)) return "bun";
|
|
17173
|
+
if (/(^|\/)pnpm(\/|-global\/|$)/.test(path)) return "pnpm";
|
|
17174
|
+
if (/(^|\/)yarn\//.test(path)) return "yarn";
|
|
17175
|
+
return "npm";
|
|
17176
|
+
}
|
|
17177
|
+
function parseUserAgent(agent) {
|
|
17178
|
+
if (!agent) return null;
|
|
17179
|
+
const name = agent.trim().split("/")[0]?.toLowerCase();
|
|
17180
|
+
if (name === "pnpm" || name === "yarn" || name === "bun" || name === "npm") return name;
|
|
17181
|
+
return null;
|
|
17182
|
+
}
|
|
17183
|
+
function resolveUpgradePlan(options = {}) {
|
|
17184
|
+
const env = options.env ?? process.env;
|
|
17185
|
+
const spec = `${PACKAGE_NAME}@${options.version ?? "latest"}`;
|
|
17186
|
+
const manager = detectPackageManager(options.binaryPath, env);
|
|
17187
|
+
const args = GLOBAL_INSTALL_ARGS[manager](spec);
|
|
17188
|
+
return { command: manager, args, manager, display: `${manager} ${args.join(" ")}` };
|
|
17189
|
+
}
|
|
17190
|
+
function upgradeCommandOverride(env = process.env) {
|
|
17191
|
+
const raw = env.SKEIN_UPDATE_COMMAND ?? env.MOSAIC_UPDATE_COMMAND;
|
|
17192
|
+
const trimmed = raw?.trim();
|
|
17193
|
+
return trimmed ? trimmed : void 0;
|
|
17194
|
+
}
|
|
17195
|
+
function runUpgrade(plan) {
|
|
17196
|
+
return new Promise((resolve24) => {
|
|
17197
|
+
const child = spawn2(plan.command, plan.args, {
|
|
17198
|
+
stdio: "inherit",
|
|
17199
|
+
shell: plan.shell ?? false
|
|
17200
|
+
});
|
|
17201
|
+
child.on("error", () => resolve24({ ok: false, exitCode: 127, display: plan.display }));
|
|
17202
|
+
child.on("close", (code) => {
|
|
17203
|
+
const exitCode = code ?? 1;
|
|
17204
|
+
resolve24({ ok: exitCode === 0, exitCode, display: plan.display });
|
|
17205
|
+
});
|
|
17206
|
+
});
|
|
17207
|
+
}
|
|
17208
|
+
|
|
17151
17209
|
// src/cli.tsx
|
|
17152
17210
|
var cliGlyphs = resolveCliGlyphs();
|
|
17153
17211
|
var defaultWarningListeners = process.listeners("warning");
|
|
@@ -17251,6 +17309,63 @@ program.command("doctor").description("Diagnose prerequisites and safe fallbacks
|
|
|
17251
17309
|
const ok = await runDoctor(config, { json: options.json === true, visual: options.visual === true });
|
|
17252
17310
|
if (!ok) process.exitCode = 1;
|
|
17253
17311
|
});
|
|
17312
|
+
program.command("update").description("Update to the latest published release").option("--check", "only report whether a newer version is available").option("--yes", "skip the confirmation prompt and upgrade immediately").option("--json", "print the result as JSON").action(async (options) => {
|
|
17313
|
+
const json = options.json === true;
|
|
17314
|
+
const current = package_default.version;
|
|
17315
|
+
const notice = await refreshUpdateCache(current, { force: true }).catch(() => void 0);
|
|
17316
|
+
if (!notice) {
|
|
17317
|
+
if (json) printObject({ current, latest: current, upToDate: true }, true);
|
|
17318
|
+
else process.stdout.write(`${chalk4.green(cliGlyphs.success)} Already on the latest release (v${current}).
|
|
17319
|
+
`);
|
|
17320
|
+
return;
|
|
17321
|
+
}
|
|
17322
|
+
const override = upgradeCommandOverride();
|
|
17323
|
+
const plan = override ? { command: override, args: [], manager: "custom", display: override, shell: true } : { ...resolveUpgradePlan({ version: notice.latest }), shell: false };
|
|
17324
|
+
if (json && options.check === true) {
|
|
17325
|
+
printObject({ current, latest: notice.latest, upToDate: false, command: plan.display, ...notice.highlights ? { highlights: notice.highlights } : {} }, true);
|
|
17326
|
+
return;
|
|
17327
|
+
}
|
|
17328
|
+
process.stdout.write(`${chalk4.cyan(cliGlyphs.brand)} Update available ${chalk4.dim(`v${current}`)} ${cliGlyphs.separator} ${chalk4.green(`v${notice.latest}`)}
|
|
17329
|
+
`);
|
|
17330
|
+
for (const highlight of notice.highlights ?? []) {
|
|
17331
|
+
process.stdout.write(` ${cliGlyphs.separator} ${highlight}
|
|
17332
|
+
`);
|
|
17333
|
+
}
|
|
17334
|
+
if (options.check === true) {
|
|
17335
|
+
process.stdout.write(` Run ${chalk4.cyan(`${PRODUCT_COMMAND} update`)} to install ${chalk4.dim(`(${plan.display})`)}.
|
|
17336
|
+
`);
|
|
17337
|
+
return;
|
|
17338
|
+
}
|
|
17339
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
17340
|
+
if (options.yes !== true) {
|
|
17341
|
+
if (!interactive) {
|
|
17342
|
+
process.stdout.write(` Re-run with ${chalk4.cyan(`${PRODUCT_COMMAND} update --yes`)} to install ${chalk4.dim(`(${plan.display})`)}.
|
|
17343
|
+
`);
|
|
17344
|
+
return;
|
|
17345
|
+
}
|
|
17346
|
+
const rl = createInterface2({ input, output });
|
|
17347
|
+
try {
|
|
17348
|
+
const answer = (await rl.question(` Install ${chalk4.dim(plan.display)}? [Y/n] `)).trim().toLowerCase();
|
|
17349
|
+
if (answer === "n" || answer === "no") {
|
|
17350
|
+
process.stdout.write(" Update cancelled.\n");
|
|
17351
|
+
return;
|
|
17352
|
+
}
|
|
17353
|
+
} finally {
|
|
17354
|
+
rl.close();
|
|
17355
|
+
}
|
|
17356
|
+
}
|
|
17357
|
+
process.stdout.write(`${chalk4.dim(`${cliGlyphs.running} ${plan.display}`)}
|
|
17358
|
+
`);
|
|
17359
|
+
const result = await runUpgrade(plan);
|
|
17360
|
+
if (result.ok) {
|
|
17361
|
+
process.stdout.write(`${chalk4.green(cliGlyphs.success)} Updated to v${notice.latest}. Restart ${PRODUCT_COMMAND} to use it.
|
|
17362
|
+
`);
|
|
17363
|
+
} else {
|
|
17364
|
+
process.stdout.write(`${chalk4.red(cliGlyphs.error)} Update failed (exit ${result.exitCode}). Run ${chalk4.cyan(plan.display)} manually.
|
|
17365
|
+
`);
|
|
17366
|
+
process.exitCode = 1;
|
|
17367
|
+
}
|
|
17368
|
+
});
|
|
17254
17369
|
program.command("migrate").description("Inspect or migrate legacy .mosaic state into .skein").option("-w, --workspace <path>", "workspace root").option("--json", "print a migration manifest as JSON").option("--yes", "perform the migration after conflict checks").option("--rollback", "verify and roll back a completed migration").option("--recover", "inspect or recover interrupted migration/rollback state").option("--home", "operate on the user-level Skein/Mosaic namespace").action(async (options) => {
|
|
17255
17370
|
if (options.home && options.workspace) throw new Error("--workspace cannot be combined with --home.");
|
|
17256
17371
|
if (options.recover && options.rollback) throw new Error("--recover and --rollback cannot be combined.");
|