Skip to content

Commit 0302c7c

Browse files
authored
Improve storm cli. (#93) (#111)
1 parent d744419 commit 0302c7c

1 file changed

Lines changed: 23 additions & 10 deletions

File tree

storm-cli/storm.mjs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Zero dependencies. Requires Node.js 18+.
66

77
import { writeFileSync, appendFileSync, mkdirSync, existsSync, readFileSync, readdirSync, unlinkSync, rmdirSync, statSync } from 'fs';
8-
import { join, dirname } from 'path';
8+
import { basename, join, dirname } from 'path';
99
import { homedir } from 'os';
1010
import { execSync } from 'child_process';
1111

@@ -546,7 +546,7 @@ async function textInput({ message, defaultValue = '', mask = false }) {
546546
// ─── Content (fetched from orm.st at runtime) ───────────────────────────────
547547

548548
const SKILLS_BASE_URL = 'https://orm.st/skills';
549-
const STORM_SKILL_MARKER = '<!-- storm-managed:';
549+
const STORM_SKILL_MARKER = '<!-- storm-managed: storm-docs -->';
550550

551551
async function fetchRules() {
552552
try {
@@ -575,7 +575,7 @@ async function fetchSkill(name) {
575575
const res = await fetch(url);
576576
if (!res.ok) throw new Error(`${res.status}`);
577577
const content = await res.text();
578-
return `${STORM_SKILL_MARKER} ${name} -->\n${content}`;
578+
return content.trimEnd() + '\n\n' + STORM_SKILL_MARKER + '\n';
579579
} catch {
580580
return null;
581581
}
@@ -584,6 +584,7 @@ async function fetchSkill(name) {
584584
function installSkill(name, content, toolConfig, created) {
585585
const cwd = process.cwd();
586586
const fullPath = join(cwd, toolConfig.skillPath(name));
587+
if (existsSync(fullPath) && readFileSync(fullPath, 'utf-8') === content) return;
587588
mkdirSync(dirname(fullPath), { recursive: true });
588589
writeFileSync(fullPath, content);
589590
created.push(toolConfig.skillPath(name));
@@ -621,8 +622,15 @@ function cleanStaleSkills(toolConfigs, installedSkillNames, skipped) {
621622
for (const candidate of candidates) {
622623
try {
623624
const content = readFileSync(candidate, 'utf-8');
624-
const match = content.match(/^<!-- storm-managed: (\S+) -->/);
625-
if (match && !installed.has(match[1])) {
625+
const isStormManaged = content.trimEnd().endsWith(STORM_SKILL_MARKER)
626+
|| /^<!-- storm-managed: \S+ -->/.test(content);
627+
if (!isStormManaged) continue;
628+
629+
// Derive skill name from path.
630+
const name = candidate.endsWith('SKILL.md')
631+
? basename(dirname(candidate))
632+
: basename(candidate).replace(/\.(instructions\.)?md$/, '');
633+
if (!installed.has(name)) {
626634
unlinkSync(candidate);
627635
// Remove empty parent directory for nested layout.
628636
const parentDir = dirname(candidate);
@@ -632,7 +640,7 @@ function cleanStaleSkills(toolConfigs, installedSkillNames, skipped) {
632640
if (remaining.length === 0) rmdirSync(parentDir);
633641
} catch {}
634642
}
635-
skipped.push(`${match[1]} (removed, no longer available)`);
643+
skipped.push(`${name} (removed, no longer available)`);
636644
}
637645
} catch {}
638646
}
@@ -1334,7 +1342,7 @@ async function update() {
13341342
if (!existing.includes('Database Schema Access')) {
13351343
const endMarker = existing.indexOf(MARKER_END);
13361344
if (endMarker !== -1) {
1337-
const updated = existing.substring(0, endMarker) + '\n' + schemaRules.replace(/^<!-- storm-managed: \S+ -->\n/, '') + '\n' + existing.substring(endMarker);
1345+
const updated = existing.substring(0, endMarker) + '\n' + schemaRules.replace('\n' + STORM_SKILL_MARKER, '') + '\n' + existing.substring(endMarker);
13381346
writeFileSync(rulesPath, updated);
13391347
if (!appended.includes(config.rulesFile)) appended.push(config.rulesFile);
13401348
}
@@ -1420,8 +1428,13 @@ async function updateMcp() {
14201428
console.log(boltYellow(' Updated:'));
14211429
appended.forEach(f => console.log(boltYellow(` ~ ${f}`)));
14221430
}
1423-
console.log();
1424-
console.log(bold(' MCP configuration updated.'));
1431+
if (created.length > 0 || appended.length > 0) {
1432+
console.log();
1433+
console.log(bold(' MCP configuration updated.'));
1434+
} else {
1435+
const toolNames = tools.map(t => TOOL_CONFIGS[t]?.name).filter(Boolean).join(', ');
1436+
console.log(dimText(` MCP already configured for ${toolNames}. No changes needed.`));
1437+
}
14251438
console.log();
14261439
}
14271440

@@ -1570,7 +1583,7 @@ async function setup() {
15701583
if (!existing.includes('Database Schema Access')) {
15711584
const endMarker = existing.indexOf(MARKER_END);
15721585
if (endMarker !== -1) {
1573-
const updated = existing.substring(0, endMarker) + '\n' + schemaRules.replace(/^<!-- storm-managed: \S+ -->\n/, '') + '\n' + existing.substring(endMarker);
1586+
const updated = existing.substring(0, endMarker) + '\n' + schemaRules.replace('\n' + STORM_SKILL_MARKER, '') + '\n' + existing.substring(endMarker);
15741587
writeFileSync(rulesPath, updated);
15751588
appended.push(config.rulesFile);
15761589
}

0 commit comments

Comments
 (0)