@meltstudio/meltctl 5.15.0 → 5.17.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 +29 -21
- 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.17.0";
|
|
7454
7454
|
}
|
|
7455
7455
|
});
|
|
7456
7456
|
|
|
@@ -26583,7 +26583,7 @@ function createPlansResource(config2) {
|
|
|
26583
26583
|
const path10 = `/plans${query ? `?${query}` : ""}`;
|
|
26584
26584
|
const { data, status } = await apiFetch(config2, path10);
|
|
26585
26585
|
if (status === 403)
|
|
26586
|
-
throw new Error(
|
|
26586
|
+
throw new Error(`Access denied. ${data.error ?? ""}`.trim());
|
|
26587
26587
|
if (status !== 200)
|
|
26588
26588
|
throw new Error(data.error ?? `Failed to list plans (${status})`);
|
|
26589
26589
|
return data;
|
|
@@ -26591,7 +26591,7 @@ function createPlansResource(config2) {
|
|
|
26591
26591
|
async get(id) {
|
|
26592
26592
|
const { data, status } = await apiFetch(config2, `/plans/${id}`);
|
|
26593
26593
|
if (status === 403)
|
|
26594
|
-
throw new Error(
|
|
26594
|
+
throw new Error(`Access denied. ${data.error ?? ""}`.trim());
|
|
26595
26595
|
if (status === 404)
|
|
26596
26596
|
throw new Error(`Plan not found: ${id}`);
|
|
26597
26597
|
if (status !== 200)
|
|
@@ -27211,8 +27211,9 @@ function createBoardAuditsResource(config2) {
|
|
|
27211
27211
|
// ../sdk/dist/resources/pm.js
|
|
27212
27212
|
function unwrap(label, response, okStatus = 200) {
|
|
27213
27213
|
const okStatuses = Array.isArray(okStatus) ? okStatus : [okStatus];
|
|
27214
|
-
if (response.status === 403)
|
|
27215
|
-
throw new Error(`Access denied (${label})`);
|
|
27214
|
+
if (response.status === 403) {
|
|
27215
|
+
throw new Error(response.data.error ? `Access denied (${label}): ${response.data.error}` : `Access denied (${label})`);
|
|
27216
|
+
}
|
|
27216
27217
|
if (!okStatuses.includes(response.status)) {
|
|
27217
27218
|
throw new Error(response.data.error ?? `Failed: ${label} (${response.status})`);
|
|
27218
27219
|
}
|
|
@@ -42621,6 +42622,10 @@ async function getClient() {
|
|
|
42621
42622
|
// src/commands/skills.ts
|
|
42622
42623
|
var MARKER_FILE = ".melt-skills.json";
|
|
42623
42624
|
function getSkillsRoot() {
|
|
42625
|
+
const configDir = process.env["CLAUDE_CONFIG_DIR"];
|
|
42626
|
+
if (configDir) {
|
|
42627
|
+
return path5.join(configDir, "skills");
|
|
42628
|
+
}
|
|
42624
42629
|
return path5.join(os5.homedir(), ".claude", "skills");
|
|
42625
42630
|
}
|
|
42626
42631
|
function getSkillsRoots() {
|
|
@@ -42732,7 +42737,7 @@ async function skillsInstallCommand(opts) {
|
|
|
42732
42737
|
);
|
|
42733
42738
|
process.exit(1);
|
|
42734
42739
|
}
|
|
42735
|
-
const roots = getSkillsRoots();
|
|
42740
|
+
const roots = opts.path ? [path5.resolve(opts.path)] : getSkillsRoots();
|
|
42736
42741
|
const stale = opts.force ? roots : roots.filter((root) => readMarker(root)?.version !== manifest.version);
|
|
42737
42742
|
if (stale.length === 0) {
|
|
42738
42743
|
console.log(
|
|
@@ -53253,7 +53258,7 @@ function createPlansResource2(config2) {
|
|
|
53253
53258
|
const path22 = `/plans${query ? `?${query}` : ""}`;
|
|
53254
53259
|
const { data, status } = await apiFetch2(config2, path22);
|
|
53255
53260
|
if (status === 403)
|
|
53256
|
-
throw new Error(
|
|
53261
|
+
throw new Error(`Access denied. ${data.error ?? ""}`.trim());
|
|
53257
53262
|
if (status !== 200)
|
|
53258
53263
|
throw new Error(data.error ?? `Failed to list plans (${status})`);
|
|
53259
53264
|
return data;
|
|
@@ -53261,7 +53266,7 @@ function createPlansResource2(config2) {
|
|
|
53261
53266
|
async get(id) {
|
|
53262
53267
|
const { data, status } = await apiFetch2(config2, `/plans/${id}`);
|
|
53263
53268
|
if (status === 403)
|
|
53264
|
-
throw new Error(
|
|
53269
|
+
throw new Error(`Access denied. ${data.error ?? ""}`.trim());
|
|
53265
53270
|
if (status === 404)
|
|
53266
53271
|
throw new Error(`Plan not found: ${id}`);
|
|
53267
53272
|
if (status !== 200)
|
|
@@ -53855,8 +53860,9 @@ function createBoardAuditsResource2(config2) {
|
|
|
53855
53860
|
}
|
|
53856
53861
|
function unwrap2(label, response, okStatus = 200) {
|
|
53857
53862
|
const okStatuses = Array.isArray(okStatus) ? okStatus : [okStatus];
|
|
53858
|
-
if (response.status === 403)
|
|
53859
|
-
throw new Error(`Access denied (${label})`);
|
|
53863
|
+
if (response.status === 403) {
|
|
53864
|
+
throw new Error(response.data.error ? `Access denied (${label}): ${response.data.error}` : `Access denied (${label})`);
|
|
53865
|
+
}
|
|
53860
53866
|
if (!okStatuses.includes(response.status)) {
|
|
53861
53867
|
throw new Error(response.data.error ?? `Failed: ${label} (${response.status})`);
|
|
53862
53868
|
}
|
|
@@ -55246,7 +55252,7 @@ function registerProjectTools(server, getClient2) {
|
|
|
55246
55252
|
"list_projects",
|
|
55247
55253
|
{
|
|
55248
55254
|
title: "List projects",
|
|
55249
|
-
description: "Lists Melt projects the authenticated user can see. Defaults: hasPM=true (only actively-managed projects), includeInternal=false (Melt's own internal projects hidden). Use this to resolve a project's name to its numeric `projectId` before calling any other tool. Returns id, name, client, project manager, and repo count per project.",
|
|
55255
|
+
description: "Lists Melt projects the authenticated user can see. Managers see every project; non-managers (devs) see only the projects they're assigned to, PM, or recently worked on \u2014 a project missing from this list is out of their scope, not nonexistent. Defaults: hasPM=true (only actively-managed projects), includeInternal=false (Melt's own internal projects hidden). Use this to resolve a project's name to its numeric `projectId` before calling any other tool. Returns id, name, client, project manager, and repo count per project.",
|
|
55250
55256
|
inputSchema: {
|
|
55251
55257
|
hasPM: external_exports.boolean().optional().describe(
|
|
55252
55258
|
"Default true. When true, only projects with a project manager assigned are returned (recommended for AI agent flows). Set false to include unmanaged projects."
|
|
@@ -55262,7 +55268,7 @@ function registerProjectTools(server, getClient2) {
|
|
|
55262
55268
|
"get_project_settings",
|
|
55263
55269
|
{
|
|
55264
55270
|
title: "Get project settings",
|
|
55265
|
-
description: 'Returns the project\'s PM-skills settings: cadence (weekly/biweekly/monthly), start_day, demo_day, team_size, velocity_override, Linear workspace, Notion URLs, code repo path, tech-support contact, default language, project glossary, project stage, default jump duration weeks. Includes a `warnings` array flagging settings whose absence breaks downstream behavior (e.g., "calculator: missing teamSize"). Returns sensible defaults if no settings row exists yet (cadence=weekly, start_day=Monday, demo_day=Friday, defaultLanguage=English, defaultJumpDurationWeeks=1).',
|
|
55271
|
+
description: 'Returns the project\'s PM-skills settings: cadence (weekly/biweekly/monthly), start_day, demo_day, team_size, velocity_override, Linear workspace, Notion URLs, code repo path, tech-support contact, default language, project glossary, project stage, default jump duration weeks. Includes a `warnings` array flagging settings whose absence breaks downstream behavior (e.g., "calculator: missing teamSize"). Returns sensible defaults if no settings row exists yet (cadence=weekly, start_day=Monday, demo_day=Friday, defaultLanguage=English, defaultJumpDurationWeeks=1). Non-managers get a 403 for projects outside their assigned/recently-worked scope \u2014 explain the scoping to the user instead of retrying.',
|
|
55266
55272
|
inputSchema: {
|
|
55267
55273
|
projectId: external_exports.number().int().positive().describe("Strapi project id from list_projects.")
|
|
55268
55274
|
}
|
|
@@ -55318,7 +55324,7 @@ function registerProjectTools(server, getClient2) {
|
|
|
55318
55324
|
"get_project_context",
|
|
55319
55325
|
{
|
|
55320
55326
|
title: "Get project context",
|
|
55321
|
-
description: "Read-only project identity + the PM-owned canonical project stage. Returns: projectId, projectName, client, pmEmail, repos[], projectStage (prototype | early_revenue | growth | scale | null), projectStageSetBy, projectStageSetAt. Call this at the start of an audit run instead of trusting AGENTS.md self-declaration \u2014 the stage drives audit calibration. Auth-only (no manager check), so devs running the audit skill from their own machine can call it directly.",
|
|
55327
|
+
description: "Read-only project identity + the PM-owned canonical project stage. Returns: projectId, projectName, client, pmEmail, repos[], projectStage (prototype | early_revenue | growth | scale | null), projectStageSetBy, projectStageSetAt. Call this at the start of an audit run instead of trusting AGENTS.md self-declaration \u2014 the stage drives audit calibration. Auth-only (no manager check), so devs running the audit skill from their own machine can call it directly for their own projects; a 403 means the project is outside the dev's assigned/recently-worked scope \u2014 explain the scoping instead of retrying.",
|
|
55322
55328
|
inputSchema: {
|
|
55323
55329
|
projectId: external_exports.number().int().positive().describe("Strapi project id from list_projects.")
|
|
55324
55330
|
}
|
|
@@ -55372,7 +55378,7 @@ function registerPhaseTools(server, getClient2) {
|
|
|
55372
55378
|
"list_phases",
|
|
55373
55379
|
{
|
|
55374
55380
|
title: "List phases",
|
|
55375
|
-
description: "Lists phases on a project. Each entry includes target_shape, computed current_shape, primary flag, active flag, the assigned features (with their stage_snapshot at join time + live current_stage), and timestamps. Includes closed phases when includeClosed=true.",
|
|
55381
|
+
description: "Lists phases on a project. Each entry includes target_shape, computed current_shape, primary flag, active flag, the assigned features (with their stage_snapshot at join time + live current_stage), and timestamps. Includes closed phases when includeClosed=true. Non-managers get a 403 for projects outside their assigned/recently-worked scope \u2014 explain the scoping to the user instead of retrying.",
|
|
55376
55382
|
inputSchema: {
|
|
55377
55383
|
projectId: external_exports.number().int().positive(),
|
|
55378
55384
|
includeClosed: external_exports.boolean().optional().describe("Default false. Set true to include closed phases as history.")
|
|
@@ -55574,7 +55580,7 @@ function registerFeatureTools(server, getClient2) {
|
|
|
55574
55580
|
"list_features",
|
|
55575
55581
|
{
|
|
55576
55582
|
title: "List features",
|
|
55577
|
-
description: "Lists features on the project. Each entry has id, name, category, description, current_stage, status, prd_path, client_notes, and starting_point. Per-phase target stage + Linear epic live on the phase membership (see list_phases), not the feature row. Optional filters narrow server-side: phaseId returns only features assigned to that phase; status / category / currentStage filter on the matching column.",
|
|
55583
|
+
description: "Lists features on the project. Each entry has id, name, category, description, current_stage, status, prd_path, client_notes, and starting_point. Per-phase target stage + Linear epic live on the phase membership (see list_phases), not the feature row. Optional filters narrow server-side: phaseId returns only features assigned to that phase; status / category / currentStage filter on the matching column. Non-managers get a 403 for projects outside their assigned/recently-worked scope \u2014 explain the scoping to the user instead of retrying.",
|
|
55578
55584
|
inputSchema: {
|
|
55579
55585
|
projectId: external_exports.number().int().positive(),
|
|
55580
55586
|
phaseId: external_exports.string().uuid().optional().describe("Limit to features assigned to this phase (phase_features join)."),
|
|
@@ -55690,7 +55696,7 @@ function registerPlanTools(server, getClient2) {
|
|
|
55690
55696
|
"list_plans",
|
|
55691
55697
|
{
|
|
55692
55698
|
title: "List plans",
|
|
55693
|
-
description: "Lists recent dev-submitted plans (list view \u2014 no plan content). Each entry has id, project, repository, author email, branch, commit, ticket id, status, and the aggregate rubric score if scored. Filterable by projectId, status, author (email), ticket id, repository. Defaults to no filters; pass `limit` to cap the return size. Use `get_plan` to read a plan's full markdown content.",
|
|
55699
|
+
description: "Lists recent dev-submitted plans (list view \u2014 no plan content). Each entry has id, project, repository, author email, branch, commit, ticket id, status, and the aggregate rubric score if scored. Filterable by projectId, status, author (email), ticket id, repository. Defaults to no filters; pass `limit` to cap the return size. Use `get_plan` to read a plan's full markdown content. Managers see every plan; non-managers see plans they authored plus plans on repos of their assigned/recently-worked projects.",
|
|
55694
55700
|
inputSchema: {
|
|
55695
55701
|
projectId: external_exports.number().int().positive().optional().describe("Strapi project id from list_projects. Omit to list across all projects."),
|
|
55696
55702
|
status: external_exports.string().optional().describe("Common values: 'submitted', 'in_review', 'completed'."),
|
|
@@ -55708,7 +55714,7 @@ function registerPlanTools(server, getClient2) {
|
|
|
55708
55714
|
"get_plan",
|
|
55709
55715
|
{
|
|
55710
55716
|
title: "Get plan",
|
|
55711
|
-
description: "Returns one plan's full detail including the markdown `content`, `scoreSummary` (per-rubric-dimension scoring output), and any metadata the dev submitted. Use this after `list_plans` when the agent needs to read what the plan actually says.",
|
|
55717
|
+
description: "Returns one plan's full detail including the markdown `content`, `scoreSummary` (per-rubric-dimension scoring output), and any metadata the dev submitted. Use this after `list_plans` when the agent needs to read what the plan actually says. Non-managers can read their own plans plus plans on repos of their assigned/recently-worked projects; anything else returns a 403 \u2014 explain the scoping to the user instead of retrying.",
|
|
55712
55718
|
inputSchema: {
|
|
55713
55719
|
planId: external_exports.string().uuid()
|
|
55714
55720
|
}
|
|
@@ -55783,7 +55789,7 @@ function registerProjectHealthTools(server, getClient2) {
|
|
|
55783
55789
|
"get_project_health",
|
|
55784
55790
|
{
|
|
55785
55791
|
title: "Get project health",
|
|
55786
|
-
description: "Composite read-only snapshot of one project's health: 0-100 score; `issues` \u2014 the full list of open health issues (each with label, dimension, severity, and a one-line howToFix), which are the EXACT items shown on the project's dashboard health card (e.g. 'PM silent in active cycle', 'Roadmap status differs from Linear', 'No roadmap'); audit-freshness numbers, findings (critical/high/missing/warning counts), board-audit aggregate + age, ticket counts (open/started/overdue), standup compliance (last 14 days), plan recency, last CLI activity, and the project's RSK risks (open/mitigated counts, red-zone count, top 3 open risks with impact \xD7 probability scores AND the PM's latest weekly status comment on each one). Risks + comments come from a weekly mirror of the RSK Linear board, refreshed every Tuesday evening right after the team's risk-review meeting \u2014 so 'latestComment' is normally the just-logged update for the week. Use this for 'how's project X doing?' / 'what needs attention on X?' questions \u2014 prefer surfacing the `issues` list (worst severity first) over just the score. Pulls in one round trip what would otherwise be 8+ separate tool calls; score + issues match the dashboard's project cards.",
|
|
55792
|
+
description: "Composite read-only snapshot of one project's health: 0-100 score; `issues` \u2014 the full list of open health issues (each with label, dimension, severity, and a one-line howToFix), which are the EXACT items shown on the project's dashboard health card (e.g. 'PM silent in active cycle', 'Roadmap status differs from Linear', 'No roadmap'); audit-freshness numbers, findings (critical/high/missing/warning counts), board-audit aggregate + age, ticket counts (open/started/overdue), standup compliance (last 14 days), plan recency, last CLI activity, and the project's RSK risks (open/mitigated counts, red-zone count, top 3 open risks with impact \xD7 probability scores AND the PM's latest weekly status comment on each one). Risks + comments come from a weekly mirror of the RSK Linear board, refreshed every Tuesday evening right after the team's risk-review meeting \u2014 so 'latestComment' is normally the just-logged update for the week. Use this for 'how's project X doing?' / 'what needs attention on X?' questions \u2014 prefer surfacing the `issues` list (worst severity first) over just the score. Pulls in one round trip what would otherwise be 8+ separate tool calls; score + issues match the dashboard's project cards. Non-managers get a 403 for projects outside their assigned/recently-worked scope \u2014 explain the scoping to the user instead of retrying.",
|
|
55787
55793
|
inputSchema: {
|
|
55788
55794
|
projectId: external_exports.number().int().positive().describe(
|
|
55789
55795
|
"Strapi project id from list_projects. The project must have at least one linked repository \u2014 otherwise the score is undefined and the tool returns 422."
|
|
@@ -55836,7 +55842,7 @@ function registerFindingsTools(server, getClient2) {
|
|
|
55836
55842
|
"list_findings",
|
|
55837
55843
|
{
|
|
55838
55844
|
title: "List audit findings",
|
|
55839
|
-
description: "Lists code/security/UX audit findings. Each finding carries its check code, category, status (pass/warning/missing/na), severity (critical/high/medium/low), effort (low/medium/high \u2014 how much work the fix is, independent of severity), repository, and evidence (file/symbol) so you can see exactly what to fix. Filter by projectId, repository, status, severity, effort, or auditType. Results are ordered worst-first (missing > warning, then critical > high > \u2026). Use this to answer 'what's open on the app I'm working on?' \u2014 pass status='missing' or severity='critical' to focus on what matters, or effort='low' with severity='high'/'critical' to find cheap high-leverage wins. Read-only
|
|
55845
|
+
description: "Lists code/security/UX audit findings. Each finding carries its check code, category, status (pass/warning/missing/na), severity (critical/high/medium/low), effort (low/medium/high \u2014 how much work the fix is, independent of severity), repository, and evidence (file/symbol) so you can see exactly what to fix. Filter by projectId, repository, status, severity, effort, or auditType. Results are ordered worst-first (missing > warning, then critical > high > \u2026). Use this to answer 'what's open on the app I'm working on?' \u2014 pass status='missing' or severity='critical' to focus on what matters, or effort='low' with severity='high'/'critical' to find cheap high-leverage wins. Read-only; managers see every finding, while non-managers see only findings on repos of their assigned/recently-worked projects (an empty result may mean out-of-scope, not clean).",
|
|
55840
55846
|
inputSchema: {
|
|
55841
55847
|
projectId: external_exports.number().int().positive().optional().describe("Strapi project id \u2014 scopes findings to that project\u2019s repos."),
|
|
55842
55848
|
repository: external_exports.string().optional().describe("Full repo slug, e.g. 'MeltStudio/atlas-api'. Scopes to a single repo."),
|
|
@@ -56050,7 +56056,7 @@ ${source_default.dim(" /melt-dev-security-audit Run a security posture audit
|
|
|
56050
56056
|
${source_default.dim(" /melt-dev-help Answer questions about the development playbook")}
|
|
56051
56057
|
|
|
56052
56058
|
${source_default.bold("Setup")}
|
|
56053
|
-
${source_default.dim(" skills install Install the dev skills (/melt-dev-*) into Claude Code (+ Cursor)")}
|
|
56059
|
+
${source_default.dim(" skills install Install the dev skills (/melt-dev-*) into Claude Code (+ Cursor; respects CLAUDE_CONFIG_DIR, or --path <dir>)")}
|
|
56054
56060
|
|
|
56055
56061
|
${source_default.bold("Admin Commands")} ${source_default.dim("(used by skills and team managers):")}
|
|
56056
56062
|
${source_default.dim(" audit submit [file] Submit an audit report")}
|
|
@@ -56091,7 +56097,9 @@ program2.command("mcp").description(
|
|
|
56091
56097
|
await mcpCommand();
|
|
56092
56098
|
});
|
|
56093
56099
|
var skills = program2.command("skills").description("install the Melt dev skills (/melt-dev-*) into Claude Code");
|
|
56094
|
-
skills.command("install").description(
|
|
56100
|
+
skills.command("install").description(
|
|
56101
|
+
"install the Melt dev skills into ~/.claude/skills/ (re-run to update; respects CLAUDE_CONFIG_DIR)"
|
|
56102
|
+
).option("--force", "reinstall even if already up to date").option("--path <dir>", "install into this directory only (overrides CLAUDE_CONFIG_DIR)").action(async (options) => {
|
|
56095
56103
|
await skillsInstallCommand(options);
|
|
56096
56104
|
});
|
|
56097
56105
|
var project = program2.command("project").description("manage project configuration").addHelpText(
|
package/package.json
CHANGED