@meltstudio/meltctl 5.8.0 → 5.9.0
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/dist/index.js +282 -142
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7450,7 +7450,7 @@ var CLI_VERSION;
|
|
|
7450
7450
|
var init_version = __esm({
|
|
7451
7451
|
"src/utils/version.ts"() {
|
|
7452
7452
|
"use strict";
|
|
7453
|
-
CLI_VERSION = "5.
|
|
7453
|
+
CLI_VERSION = "5.9.0";
|
|
7454
7454
|
}
|
|
7455
7455
|
});
|
|
7456
7456
|
|
|
@@ -42515,6 +42515,253 @@ async function logoutCommand() {
|
|
|
42515
42515
|
// src/index.ts
|
|
42516
42516
|
init_version_check();
|
|
42517
42517
|
|
|
42518
|
+
// src/utils/skills-sync.ts
|
|
42519
|
+
init_source();
|
|
42520
|
+
|
|
42521
|
+
// src/utils/debug.ts
|
|
42522
|
+
init_source();
|
|
42523
|
+
function debugLog(message) {
|
|
42524
|
+
if (process.env["MELTCTL_DEBUG"]) {
|
|
42525
|
+
console.error(source_default.dim(`[debug] ${message}`));
|
|
42526
|
+
}
|
|
42527
|
+
}
|
|
42528
|
+
|
|
42529
|
+
// src/commands/skills.ts
|
|
42530
|
+
init_source();
|
|
42531
|
+
var import_fs_extra3 = __toESM(require_lib(), 1);
|
|
42532
|
+
import { createHash } from "crypto";
|
|
42533
|
+
import os5 from "os";
|
|
42534
|
+
import path5 from "path";
|
|
42535
|
+
|
|
42536
|
+
// src/utils/api.ts
|
|
42537
|
+
init_source();
|
|
42538
|
+
async function getToken() {
|
|
42539
|
+
const envToken = process.env["MELTCTL_TOKEN"];
|
|
42540
|
+
if (envToken) {
|
|
42541
|
+
return envToken;
|
|
42542
|
+
}
|
|
42543
|
+
const auth = await getStoredAuth();
|
|
42544
|
+
if (!auth) {
|
|
42545
|
+
console.error(
|
|
42546
|
+
source_default.red(
|
|
42547
|
+
"Not authenticated. Run `npx @meltstudio/meltctl@latest login` or set MELTCTL_TOKEN for CI."
|
|
42548
|
+
)
|
|
42549
|
+
);
|
|
42550
|
+
process.exit(1);
|
|
42551
|
+
}
|
|
42552
|
+
if (new Date(auth.expiresAt) <= /* @__PURE__ */ new Date()) {
|
|
42553
|
+
console.error(
|
|
42554
|
+
source_default.red(
|
|
42555
|
+
"Session expired. Run `npx @meltstudio/meltctl@latest login` to re-authenticate, or set MELTCTL_TOKEN for CI."
|
|
42556
|
+
)
|
|
42557
|
+
);
|
|
42558
|
+
process.exit(1);
|
|
42559
|
+
}
|
|
42560
|
+
return auth.token;
|
|
42561
|
+
}
|
|
42562
|
+
async function getClient() {
|
|
42563
|
+
const token = await getToken();
|
|
42564
|
+
return createMeltClient({ baseUrl: API_BASE, token });
|
|
42565
|
+
}
|
|
42566
|
+
|
|
42567
|
+
// src/commands/skills.ts
|
|
42568
|
+
var MARKER_FILE = ".melt-skills.json";
|
|
42569
|
+
function getSkillsRoot() {
|
|
42570
|
+
return path5.join(os5.homedir(), ".claude", "skills");
|
|
42571
|
+
}
|
|
42572
|
+
function computeSkillHash(files) {
|
|
42573
|
+
const hash2 = createHash("sha256");
|
|
42574
|
+
for (const filePath of Object.keys(files).sort()) {
|
|
42575
|
+
hash2.update(filePath);
|
|
42576
|
+
hash2.update(files[filePath] ?? "");
|
|
42577
|
+
}
|
|
42578
|
+
return hash2.digest("hex").slice(0, 12);
|
|
42579
|
+
}
|
|
42580
|
+
function readMarker(skillsRoot) {
|
|
42581
|
+
const markerPath = path5.join(skillsRoot, MARKER_FILE);
|
|
42582
|
+
if (!import_fs_extra3.default.existsSync(markerPath)) return null;
|
|
42583
|
+
try {
|
|
42584
|
+
const raw = import_fs_extra3.default.readJsonSync(markerPath);
|
|
42585
|
+
const skills2 = Array.isArray(raw.skills) ? raw.skills.map((entry) => {
|
|
42586
|
+
if (typeof entry === "string") {
|
|
42587
|
+
return { name: entry, hash: "" };
|
|
42588
|
+
}
|
|
42589
|
+
if (entry && typeof entry === "object") {
|
|
42590
|
+
const e = entry;
|
|
42591
|
+
return {
|
|
42592
|
+
name: typeof e.name === "string" ? e.name : "",
|
|
42593
|
+
hash: typeof e.hash === "string" ? e.hash : ""
|
|
42594
|
+
};
|
|
42595
|
+
}
|
|
42596
|
+
return { name: "", hash: "" };
|
|
42597
|
+
}) : [];
|
|
42598
|
+
return {
|
|
42599
|
+
version: typeof raw.version === "string" ? raw.version : "",
|
|
42600
|
+
installedAt: typeof raw.installedAt === "string" ? raw.installedAt : "",
|
|
42601
|
+
lastCheckedAt: typeof raw.lastCheckedAt === "string" ? raw.lastCheckedAt : void 0,
|
|
42602
|
+
skills: skills2
|
|
42603
|
+
};
|
|
42604
|
+
} catch {
|
|
42605
|
+
return null;
|
|
42606
|
+
}
|
|
42607
|
+
}
|
|
42608
|
+
function computeDiff(previous, next) {
|
|
42609
|
+
const prevByName = new Map(previous.map((s) => [s.name, s]));
|
|
42610
|
+
const nextNames = new Set(next.map((s) => s.name));
|
|
42611
|
+
const added = [];
|
|
42612
|
+
const changed = [];
|
|
42613
|
+
for (const skill of next) {
|
|
42614
|
+
const prev = prevByName.get(skill.name);
|
|
42615
|
+
if (!prev) {
|
|
42616
|
+
added.push(skill.name);
|
|
42617
|
+
continue;
|
|
42618
|
+
}
|
|
42619
|
+
if (prev.hash && prev.hash !== skill.hash) {
|
|
42620
|
+
changed.push(skill.name);
|
|
42621
|
+
}
|
|
42622
|
+
}
|
|
42623
|
+
const removed = previous.filter((s) => s.name && !nextNames.has(s.name)).map((s) => s.name);
|
|
42624
|
+
return { added, changed, removed };
|
|
42625
|
+
}
|
|
42626
|
+
function applyDevSkills(manifest, skillsRoot) {
|
|
42627
|
+
const previous = readMarker(skillsRoot)?.skills ?? [];
|
|
42628
|
+
const nextEntries = manifest.skills.map((s) => ({
|
|
42629
|
+
name: s.name,
|
|
42630
|
+
hash: computeSkillHash(s.files)
|
|
42631
|
+
}));
|
|
42632
|
+
const diff = computeDiff(previous, nextEntries);
|
|
42633
|
+
for (const name of diff.removed) {
|
|
42634
|
+
import_fs_extra3.default.removeSync(path5.join(skillsRoot, name));
|
|
42635
|
+
}
|
|
42636
|
+
for (const skill of manifest.skills) {
|
|
42637
|
+
const dir = path5.join(skillsRoot, skill.name);
|
|
42638
|
+
import_fs_extra3.default.removeSync(dir);
|
|
42639
|
+
for (const [relPath, content] of Object.entries(skill.files)) {
|
|
42640
|
+
import_fs_extra3.default.outputFileSync(path5.join(dir, relPath), content);
|
|
42641
|
+
}
|
|
42642
|
+
}
|
|
42643
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42644
|
+
const marker = {
|
|
42645
|
+
version: manifest.version,
|
|
42646
|
+
installedAt: now,
|
|
42647
|
+
lastCheckedAt: now,
|
|
42648
|
+
skills: nextEntries
|
|
42649
|
+
};
|
|
42650
|
+
import_fs_extra3.default.outputFileSync(path5.join(skillsRoot, MARKER_FILE), `${JSON.stringify(marker, null, 2)}
|
|
42651
|
+
`);
|
|
42652
|
+
return diff;
|
|
42653
|
+
}
|
|
42654
|
+
function touchMarkerLastChecked(skillsRoot) {
|
|
42655
|
+
const marker = readMarker(skillsRoot);
|
|
42656
|
+
if (!marker) return;
|
|
42657
|
+
marker.lastCheckedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
42658
|
+
import_fs_extra3.default.outputFileSync(path5.join(skillsRoot, MARKER_FILE), `${JSON.stringify(marker, null, 2)}
|
|
42659
|
+
`);
|
|
42660
|
+
}
|
|
42661
|
+
async function skillsInstallCommand(opts) {
|
|
42662
|
+
const client = await getClient();
|
|
42663
|
+
let manifest;
|
|
42664
|
+
try {
|
|
42665
|
+
manifest = await client.skills.getDevSkills();
|
|
42666
|
+
} catch (error48) {
|
|
42667
|
+
console.error(
|
|
42668
|
+
source_default.red(
|
|
42669
|
+
`Failed to fetch Melt dev skills: ${error48 instanceof Error ? error48.message : "Unknown error"}`
|
|
42670
|
+
)
|
|
42671
|
+
);
|
|
42672
|
+
process.exit(1);
|
|
42673
|
+
}
|
|
42674
|
+
const skillsRoot = getSkillsRoot();
|
|
42675
|
+
const existing = readMarker(skillsRoot);
|
|
42676
|
+
if (existing && existing.version === manifest.version && !opts.force) {
|
|
42677
|
+
console.log(
|
|
42678
|
+
source_default.dim(
|
|
42679
|
+
`
|
|
42680
|
+
Melt dev skills already up to date (v${manifest.version}). Use --force to reinstall.
|
|
42681
|
+
`
|
|
42682
|
+
)
|
|
42683
|
+
);
|
|
42684
|
+
return;
|
|
42685
|
+
}
|
|
42686
|
+
applyDevSkills(manifest, skillsRoot);
|
|
42687
|
+
console.log(
|
|
42688
|
+
source_default.green(
|
|
42689
|
+
`
|
|
42690
|
+
\u2713 Installed ${manifest.skills.length} Melt dev skills (v${manifest.version}) to ~/.claude/skills/.`
|
|
42691
|
+
)
|
|
42692
|
+
);
|
|
42693
|
+
console.log(
|
|
42694
|
+
source_default.dim(
|
|
42695
|
+
" Restart Claude Code to load them (they appear as /melt-dev-plan, /melt-dev-review, \u2026).\n"
|
|
42696
|
+
)
|
|
42697
|
+
);
|
|
42698
|
+
}
|
|
42699
|
+
|
|
42700
|
+
// src/utils/skills-sync.ts
|
|
42701
|
+
var TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1e3;
|
|
42702
|
+
var SKIP_SYNC_COMMANDS = /* @__PURE__ */ new Set(["skills", "login", "logout", "update", "version"]);
|
|
42703
|
+
function formatSyncNotice(oldVersion, newVersion, diff) {
|
|
42704
|
+
const groups = [];
|
|
42705
|
+
if (diff.changed.length > 0) groups.push(`changed ${diff.changed.join(", ")}`);
|
|
42706
|
+
if (diff.added.length > 0) groups.push(`added ${diff.added.join(", ")}`);
|
|
42707
|
+
if (diff.removed.length > 0) groups.push(`removed ${diff.removed.join(", ")}`);
|
|
42708
|
+
const suffix = groups.length > 0 ? `: ${groups.join("; ")}` : "";
|
|
42709
|
+
return `\u2191 Melt dev skills updated (v${oldVersion} \u2192 v${newVersion})${suffix}`;
|
|
42710
|
+
}
|
|
42711
|
+
function isCheckDue(lastCheckedAt, now) {
|
|
42712
|
+
if (!lastCheckedAt) return true;
|
|
42713
|
+
const last = Date.parse(lastCheckedAt);
|
|
42714
|
+
if (Number.isNaN(last)) return true;
|
|
42715
|
+
return now - last >= TWENTY_FOUR_HOURS_MS;
|
|
42716
|
+
}
|
|
42717
|
+
async function maybeSyncSkills(commandName) {
|
|
42718
|
+
try {
|
|
42719
|
+
if (process.env["MELTCTL_SKIP_SKILLS_SYNC"]) {
|
|
42720
|
+
debugLog("Skills sync disabled via MELTCTL_SKIP_SKILLS_SYNC");
|
|
42721
|
+
return;
|
|
42722
|
+
}
|
|
42723
|
+
if (commandName && SKIP_SYNC_COMMANDS.has(commandName)) {
|
|
42724
|
+
debugLog(`Skills sync skipped for command "${commandName}"`);
|
|
42725
|
+
return;
|
|
42726
|
+
}
|
|
42727
|
+
const auth = await getStoredAuth();
|
|
42728
|
+
if (!auth || new Date(auth.expiresAt) <= /* @__PURE__ */ new Date()) {
|
|
42729
|
+
debugLog("Skills sync skipped: not authenticated or token expired");
|
|
42730
|
+
return;
|
|
42731
|
+
}
|
|
42732
|
+
const skillsRoot = getSkillsRoot();
|
|
42733
|
+
const marker = readMarker(skillsRoot);
|
|
42734
|
+
if (!marker) {
|
|
42735
|
+
debugLog("Skills sync skipped: no skills marker (not installed)");
|
|
42736
|
+
return;
|
|
42737
|
+
}
|
|
42738
|
+
if (!isCheckDue(marker.lastCheckedAt, Date.now())) {
|
|
42739
|
+
debugLog("Skills sync skipped: checked within the last 24h");
|
|
42740
|
+
return;
|
|
42741
|
+
}
|
|
42742
|
+
const client = createMeltClient({ baseUrl: API_BASE, token: auth.token });
|
|
42743
|
+
let manifest;
|
|
42744
|
+
try {
|
|
42745
|
+
manifest = await client.skills.getDevSkills();
|
|
42746
|
+
} catch (e) {
|
|
42747
|
+
touchMarkerLastChecked(skillsRoot);
|
|
42748
|
+
debugLog(`Skills sync fetch error: ${e instanceof Error ? e.message : e}`);
|
|
42749
|
+
return;
|
|
42750
|
+
}
|
|
42751
|
+
if (manifest.version === marker.version) {
|
|
42752
|
+
touchMarkerLastChecked(skillsRoot);
|
|
42753
|
+
debugLog("Skills sync: already up to date");
|
|
42754
|
+
return;
|
|
42755
|
+
}
|
|
42756
|
+
const oldVersion = marker.version;
|
|
42757
|
+
const diff = applyDevSkills(manifest, skillsRoot);
|
|
42758
|
+
console.log(source_default.dim(source_default.green(formatSyncNotice(oldVersion, manifest.version, diff))));
|
|
42759
|
+
debugLog(`Skills sync: updated ${oldVersion} \u2192 ${manifest.version}`);
|
|
42760
|
+
} catch (e) {
|
|
42761
|
+
debugLog(`Skills sync error: ${e instanceof Error ? e.message : e}`);
|
|
42762
|
+
}
|
|
42763
|
+
}
|
|
42764
|
+
|
|
42518
42765
|
// src/commands/version.ts
|
|
42519
42766
|
init_source();
|
|
42520
42767
|
init_version_check();
|
|
@@ -42611,39 +42858,6 @@ async function versionCheckCommand() {
|
|
|
42611
42858
|
// src/commands/standup.ts
|
|
42612
42859
|
init_source();
|
|
42613
42860
|
init_dist11();
|
|
42614
|
-
|
|
42615
|
-
// src/utils/api.ts
|
|
42616
|
-
init_source();
|
|
42617
|
-
async function getToken() {
|
|
42618
|
-
const envToken = process.env["MELTCTL_TOKEN"];
|
|
42619
|
-
if (envToken) {
|
|
42620
|
-
return envToken;
|
|
42621
|
-
}
|
|
42622
|
-
const auth = await getStoredAuth();
|
|
42623
|
-
if (!auth) {
|
|
42624
|
-
console.error(
|
|
42625
|
-
source_default.red(
|
|
42626
|
-
"Not authenticated. Run `npx @meltstudio/meltctl@latest login` or set MELTCTL_TOKEN for CI."
|
|
42627
|
-
)
|
|
42628
|
-
);
|
|
42629
|
-
process.exit(1);
|
|
42630
|
-
}
|
|
42631
|
-
if (new Date(auth.expiresAt) <= /* @__PURE__ */ new Date()) {
|
|
42632
|
-
console.error(
|
|
42633
|
-
source_default.red(
|
|
42634
|
-
"Session expired. Run `npx @meltstudio/meltctl@latest login` to re-authenticate, or set MELTCTL_TOKEN for CI."
|
|
42635
|
-
)
|
|
42636
|
-
);
|
|
42637
|
-
process.exit(1);
|
|
42638
|
-
}
|
|
42639
|
-
return auth.token;
|
|
42640
|
-
}
|
|
42641
|
-
async function getClient() {
|
|
42642
|
-
const token = await getToken();
|
|
42643
|
-
return createMeltClient({ baseUrl: API_BASE, token });
|
|
42644
|
-
}
|
|
42645
|
-
|
|
42646
|
-
// src/commands/standup.ts
|
|
42647
42861
|
var EDITOR_HINT = source_default.dim("(type \\e to open your editor)");
|
|
42648
42862
|
async function promptField(message, required2) {
|
|
42649
42863
|
const value = await dist_default7({ message: `${message} ${EDITOR_HINT}` });
|
|
@@ -42865,12 +43079,12 @@ async function showLeaderboard() {
|
|
|
42865
43079
|
|
|
42866
43080
|
// src/commands/audit.ts
|
|
42867
43081
|
init_source();
|
|
42868
|
-
var
|
|
42869
|
-
import
|
|
43082
|
+
var import_fs_extra5 = __toESM(require_lib(), 1);
|
|
43083
|
+
import path7 from "path";
|
|
42870
43084
|
|
|
42871
43085
|
// src/utils/git.ts
|
|
42872
|
-
var
|
|
42873
|
-
import
|
|
43086
|
+
var import_fs_extra4 = __toESM(require_lib(), 1);
|
|
43087
|
+
import path6 from "path";
|
|
42874
43088
|
import { execSync as execSync4 } from "child_process";
|
|
42875
43089
|
function getGitBranch() {
|
|
42876
43090
|
try {
|
|
@@ -42908,34 +43122,34 @@ function getGitRepository() {
|
|
|
42908
43122
|
function getProjectName() {
|
|
42909
43123
|
const cwd = process.cwd();
|
|
42910
43124
|
try {
|
|
42911
|
-
const pkgPath =
|
|
42912
|
-
if (
|
|
42913
|
-
const pkg =
|
|
43125
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
43126
|
+
if (import_fs_extra4.default.pathExistsSync(pkgPath)) {
|
|
43127
|
+
const pkg = import_fs_extra4.default.readJsonSync(pkgPath);
|
|
42914
43128
|
if (pkg.name) {
|
|
42915
43129
|
return pkg.name;
|
|
42916
43130
|
}
|
|
42917
43131
|
}
|
|
42918
43132
|
} catch {
|
|
42919
43133
|
}
|
|
42920
|
-
return
|
|
43134
|
+
return path6.basename(cwd);
|
|
42921
43135
|
}
|
|
42922
43136
|
function extractTicketId(branch) {
|
|
42923
43137
|
const match = branch.match(/([A-Z]+-\d+)/i);
|
|
42924
43138
|
return match ? match[1] : null;
|
|
42925
43139
|
}
|
|
42926
43140
|
async function findMdFiles(dir) {
|
|
42927
|
-
if (!await
|
|
43141
|
+
if (!await import_fs_extra4.default.pathExists(dir)) {
|
|
42928
43142
|
return [];
|
|
42929
43143
|
}
|
|
42930
43144
|
const results = [];
|
|
42931
43145
|
async function walk(current) {
|
|
42932
|
-
const entries = await
|
|
43146
|
+
const entries = await import_fs_extra4.default.readdir(current, { withFileTypes: true });
|
|
42933
43147
|
for (const entry of entries) {
|
|
42934
|
-
const fullPath =
|
|
43148
|
+
const fullPath = path6.join(current, entry.name);
|
|
42935
43149
|
if (entry.isDirectory()) {
|
|
42936
43150
|
await walk(fullPath);
|
|
42937
43151
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
42938
|
-
const stat = await
|
|
43152
|
+
const stat = await import_fs_extra4.default.stat(fullPath);
|
|
42939
43153
|
results.push({ path: fullPath, mtime: stat.mtimeMs });
|
|
42940
43154
|
}
|
|
42941
43155
|
}
|
|
@@ -42954,15 +43168,15 @@ function detectAuditType(filename) {
|
|
|
42954
43168
|
}
|
|
42955
43169
|
async function autoDetectAuditFile() {
|
|
42956
43170
|
const cwd = process.cwd();
|
|
42957
|
-
const auditsDir =
|
|
43171
|
+
const auditsDir = path7.join(cwd, ".audits");
|
|
42958
43172
|
const auditFiles = await findMdFiles(auditsDir);
|
|
42959
43173
|
if (auditFiles.length > 0) {
|
|
42960
43174
|
return auditFiles[0] ?? null;
|
|
42961
43175
|
}
|
|
42962
43176
|
const candidates = ["AUDIT.md", "UX-AUDIT.md", "SECURITY-AUDIT.md"];
|
|
42963
43177
|
for (const name of candidates) {
|
|
42964
|
-
const filePath =
|
|
42965
|
-
if (await
|
|
43178
|
+
const filePath = path7.join(cwd, name);
|
|
43179
|
+
if (await import_fs_extra5.default.pathExists(filePath)) {
|
|
42966
43180
|
return filePath;
|
|
42967
43181
|
}
|
|
42968
43182
|
}
|
|
@@ -42972,7 +43186,7 @@ async function auditSubmitCommand(file2) {
|
|
|
42972
43186
|
const client = await getClient();
|
|
42973
43187
|
let filePath;
|
|
42974
43188
|
if (file2) {
|
|
42975
|
-
filePath =
|
|
43189
|
+
filePath = path7.resolve(file2);
|
|
42976
43190
|
} else {
|
|
42977
43191
|
const detected = await autoDetectAuditFile();
|
|
42978
43192
|
if (!detected) {
|
|
@@ -42984,14 +43198,14 @@ async function auditSubmitCommand(file2) {
|
|
|
42984
43198
|
process.exit(1);
|
|
42985
43199
|
}
|
|
42986
43200
|
filePath = detected;
|
|
42987
|
-
console.log(source_default.dim(`Auto-detected audit file: ${
|
|
43201
|
+
console.log(source_default.dim(`Auto-detected audit file: ${path7.relative(process.cwd(), filePath)}`));
|
|
42988
43202
|
}
|
|
42989
|
-
if (!await
|
|
43203
|
+
if (!await import_fs_extra5.default.pathExists(filePath)) {
|
|
42990
43204
|
console.error(source_default.red(`File not found: ${filePath}`));
|
|
42991
43205
|
process.exit(1);
|
|
42992
43206
|
}
|
|
42993
|
-
const content = await
|
|
42994
|
-
const filename =
|
|
43207
|
+
const content = await import_fs_extra5.default.readFile(filePath, "utf-8");
|
|
43208
|
+
const filename = path7.basename(filePath);
|
|
42995
43209
|
const auditType = detectAuditType(filename);
|
|
42996
43210
|
const project2 = getProjectName();
|
|
42997
43211
|
const branch = getGitBranch();
|
|
@@ -43116,11 +43330,11 @@ async function auditViewCommand(id, options) {
|
|
|
43116
43330
|
try {
|
|
43117
43331
|
const audit2 = await client.audits.get(id);
|
|
43118
43332
|
if (options.output) {
|
|
43119
|
-
const outputPath =
|
|
43120
|
-
await
|
|
43121
|
-
await
|
|
43333
|
+
const outputPath = path7.resolve(options.output);
|
|
43334
|
+
await import_fs_extra5.default.ensureDir(path7.dirname(outputPath));
|
|
43335
|
+
await import_fs_extra5.default.writeFile(outputPath, audit2.content, "utf-8");
|
|
43122
43336
|
console.log(source_default.green(`
|
|
43123
|
-
\u2713 Audit saved to ${
|
|
43337
|
+
\u2713 Audit saved to ${path7.relative(process.cwd(), outputPath)}
|
|
43124
43338
|
`));
|
|
43125
43339
|
} else {
|
|
43126
43340
|
const typeLabels = {
|
|
@@ -43152,8 +43366,8 @@ async function auditViewCommand(id, options) {
|
|
|
43152
43366
|
|
|
43153
43367
|
// src/commands/plan.ts
|
|
43154
43368
|
init_source();
|
|
43155
|
-
var
|
|
43156
|
-
import
|
|
43369
|
+
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
43370
|
+
import path8 from "path";
|
|
43157
43371
|
function extractFrontmatterStatus(content) {
|
|
43158
43372
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
43159
43373
|
if (!match) return null;
|
|
@@ -43162,7 +43376,7 @@ function extractFrontmatterStatus(content) {
|
|
|
43162
43376
|
}
|
|
43163
43377
|
async function autoDetectPlanFile() {
|
|
43164
43378
|
const cwd = process.cwd();
|
|
43165
|
-
const plansDir =
|
|
43379
|
+
const plansDir = path8.join(cwd, ".plans");
|
|
43166
43380
|
const mdFiles = await findMdFiles(plansDir);
|
|
43167
43381
|
if (mdFiles.length === 0) {
|
|
43168
43382
|
return null;
|
|
@@ -43171,7 +43385,7 @@ async function autoDetectPlanFile() {
|
|
|
43171
43385
|
const ticketId = extractTicketId(branch);
|
|
43172
43386
|
if (ticketId) {
|
|
43173
43387
|
const ticketLower = ticketId.toLowerCase();
|
|
43174
|
-
const match = mdFiles.find((f) =>
|
|
43388
|
+
const match = mdFiles.find((f) => path8.basename(f).toLowerCase().includes(ticketLower));
|
|
43175
43389
|
if (match) {
|
|
43176
43390
|
return match;
|
|
43177
43391
|
}
|
|
@@ -43182,7 +43396,7 @@ async function planSubmitCommand(file2) {
|
|
|
43182
43396
|
const client = await getClient();
|
|
43183
43397
|
let filePath;
|
|
43184
43398
|
if (file2) {
|
|
43185
|
-
filePath =
|
|
43399
|
+
filePath = path8.resolve(file2);
|
|
43186
43400
|
} else {
|
|
43187
43401
|
const detected = await autoDetectPlanFile();
|
|
43188
43402
|
if (!detected) {
|
|
@@ -43194,14 +43408,14 @@ async function planSubmitCommand(file2) {
|
|
|
43194
43408
|
process.exit(1);
|
|
43195
43409
|
}
|
|
43196
43410
|
filePath = detected;
|
|
43197
|
-
console.log(source_default.dim(`Auto-detected plan file: ${
|
|
43411
|
+
console.log(source_default.dim(`Auto-detected plan file: ${path8.relative(process.cwd(), filePath)}`));
|
|
43198
43412
|
}
|
|
43199
|
-
if (!await
|
|
43413
|
+
if (!await import_fs_extra6.default.pathExists(filePath)) {
|
|
43200
43414
|
console.error(source_default.red(`File not found: ${filePath}`));
|
|
43201
43415
|
process.exit(1);
|
|
43202
43416
|
}
|
|
43203
|
-
const content = await
|
|
43204
|
-
const filename =
|
|
43417
|
+
const content = await import_fs_extra6.default.readFile(filePath, "utf-8");
|
|
43418
|
+
const filename = path8.basename(filePath);
|
|
43205
43419
|
const project2 = getProjectName();
|
|
43206
43420
|
const branch = getGitBranch();
|
|
43207
43421
|
const commit = getGitCommit();
|
|
@@ -43288,84 +43502,9 @@ async function planListCommand(options) {
|
|
|
43288
43502
|
}
|
|
43289
43503
|
}
|
|
43290
43504
|
|
|
43291
|
-
// src/commands/skills.ts
|
|
43292
|
-
init_source();
|
|
43293
|
-
var import_fs_extra6 = __toESM(require_lib(), 1);
|
|
43294
|
-
import os5 from "os";
|
|
43295
|
-
import path8 from "path";
|
|
43296
|
-
var MARKER_FILE = ".melt-skills.json";
|
|
43297
|
-
function readMarker(skillsRoot) {
|
|
43298
|
-
const markerPath = path8.join(skillsRoot, MARKER_FILE);
|
|
43299
|
-
if (!import_fs_extra6.default.existsSync(markerPath)) return null;
|
|
43300
|
-
try {
|
|
43301
|
-
return import_fs_extra6.default.readJsonSync(markerPath);
|
|
43302
|
-
} catch {
|
|
43303
|
-
return null;
|
|
43304
|
-
}
|
|
43305
|
-
}
|
|
43306
|
-
async function skillsInstallCommand(opts) {
|
|
43307
|
-
const client = await getClient();
|
|
43308
|
-
let manifest;
|
|
43309
|
-
try {
|
|
43310
|
-
manifest = await client.skills.getDevSkills();
|
|
43311
|
-
} catch (error48) {
|
|
43312
|
-
console.error(
|
|
43313
|
-
source_default.red(
|
|
43314
|
-
`Failed to fetch Melt dev skills: ${error48 instanceof Error ? error48.message : "Unknown error"}`
|
|
43315
|
-
)
|
|
43316
|
-
);
|
|
43317
|
-
process.exit(1);
|
|
43318
|
-
}
|
|
43319
|
-
const skillsRoot = path8.join(os5.homedir(), ".claude", "skills");
|
|
43320
|
-
const existing = readMarker(skillsRoot);
|
|
43321
|
-
if (existing && existing.version === manifest.version && !opts.force) {
|
|
43322
|
-
console.log(
|
|
43323
|
-
source_default.dim(
|
|
43324
|
-
`
|
|
43325
|
-
Melt dev skills already up to date (v${manifest.version}). Use --force to reinstall.
|
|
43326
|
-
`
|
|
43327
|
-
)
|
|
43328
|
-
);
|
|
43329
|
-
return;
|
|
43330
|
-
}
|
|
43331
|
-
for (const skill of manifest.skills) {
|
|
43332
|
-
const dir = path8.join(skillsRoot, skill.name);
|
|
43333
|
-
import_fs_extra6.default.removeSync(dir);
|
|
43334
|
-
for (const [relPath, content] of Object.entries(skill.files)) {
|
|
43335
|
-
import_fs_extra6.default.outputFileSync(path8.join(dir, relPath), content);
|
|
43336
|
-
}
|
|
43337
|
-
}
|
|
43338
|
-
const marker = {
|
|
43339
|
-
version: manifest.version,
|
|
43340
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43341
|
-
skills: manifest.skills.map((s) => s.name)
|
|
43342
|
-
};
|
|
43343
|
-
import_fs_extra6.default.outputFileSync(path8.join(skillsRoot, MARKER_FILE), `${JSON.stringify(marker, null, 2)}
|
|
43344
|
-
`);
|
|
43345
|
-
console.log(
|
|
43346
|
-
source_default.green(
|
|
43347
|
-
`
|
|
43348
|
-
\u2713 Installed ${manifest.skills.length} Melt dev skills (v${manifest.version}) to ~/.claude/skills/.`
|
|
43349
|
-
)
|
|
43350
|
-
);
|
|
43351
|
-
console.log(
|
|
43352
|
-
source_default.dim(
|
|
43353
|
-
" Restart Claude Code to load them (they appear as /melt-dev-plan, /melt-dev-review, \u2026).\n"
|
|
43354
|
-
)
|
|
43355
|
-
);
|
|
43356
|
-
}
|
|
43357
|
-
|
|
43358
43505
|
// src/index.ts
|
|
43359
43506
|
init_update();
|
|
43360
43507
|
|
|
43361
|
-
// src/utils/debug.ts
|
|
43362
|
-
init_source();
|
|
43363
|
-
function debugLog(message) {
|
|
43364
|
-
if (process.env["MELTCTL_DEBUG"]) {
|
|
43365
|
-
console.error(source_default.dim(`[debug] ${message}`));
|
|
43366
|
-
}
|
|
43367
|
-
}
|
|
43368
|
-
|
|
43369
43508
|
// src/utils/analytics.ts
|
|
43370
43509
|
init_version();
|
|
43371
43510
|
async function trackCommand(command, success2, errorMessage) {
|
|
@@ -55777,6 +55916,7 @@ ${source_default.dim(" event track --skill Track skill usage (called by skil
|
|
|
55777
55916
|
cmd = cmd.parent;
|
|
55778
55917
|
}
|
|
55779
55918
|
await checkAndEnforceUpdate(cmd.name());
|
|
55919
|
+
await maybeSyncSkills(cmd.name());
|
|
55780
55920
|
}).hook("postAction", async (_thisCommand, actionCommand) => {
|
|
55781
55921
|
try {
|
|
55782
55922
|
const parts = [];
|
package/package.json
CHANGED