skillmds 1.0.3 → 1.0.4

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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to `skillmds` are documented here. Versions follow [semver](https://semver.org).
4
4
 
5
+ ## 1.0.4
6
+
7
+ - `skillmd lint`/`scan` print a progress line to stderr and warn when scanning a home directory, so a directory scan never looks like a frozen blank screen.
8
+ - Directory scans skip large build/OS directories (`AppData`, `node_modules`, `target`, …) and cap recursion depth, so `lint .` in a big tree terminates quickly.
9
+ - Clearer message when no `SKILL.md` is found.
10
+ - Bare `skillmd` (no command) prints help.
11
+
5
12
  ## 1.0.3
6
13
 
7
14
  - CLI (`skillmd`) and MCP server (`skillmds`) now report their version from `package.json` instead of a hardcoded string.
package/dist/cli.js CHANGED
@@ -5,6 +5,8 @@ import { readFileSync as readFileSync4 } from "fs";
5
5
  // ../cli/src/commands/lint.ts
6
6
  import { Command } from "commander";
7
7
  import { writeFileSync } from "fs";
8
+ import { homedir } from "os";
9
+ import { resolve } from "path";
8
10
 
9
11
  // ../../packages/core/src/parse.ts
10
12
  import { parse as parseYaml } from "yaml";
@@ -273,9 +275,35 @@ function toGithub(results) {
273
275
  import { existsSync, statSync, readFileSync, readdirSync, mkdtempSync } from "fs";
274
276
  import { tmpdir } from "os";
275
277
  import { join, basename, dirname } from "path";
276
- var IGNORE_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".wrangler"]);
277
- function findSkillFiles(dir) {
278
+ var IGNORE_DIRS = /* @__PURE__ */ new Set([
279
+ // build/dependency dirs
280
+ "node_modules",
281
+ ".git",
282
+ "dist",
283
+ "build",
284
+ "out",
285
+ ".next",
286
+ ".wrangler",
287
+ ".cache",
288
+ ".npm",
289
+ ".pnpm-store",
290
+ ".venv",
291
+ "venv",
292
+ "__pycache__",
293
+ "target",
294
+ "vendor",
295
+ // large OS / user dirs (mostly relevant when run from a home directory)
296
+ "AppData",
297
+ "Library",
298
+ "$Recycle.Bin",
299
+ "System Volume Information",
300
+ "Windows",
301
+ "Program Files"
302
+ ]);
303
+ var MAX_DEPTH = 12;
304
+ function findSkillFiles(dir, depth = 0) {
278
305
  const out = [];
306
+ if (depth > MAX_DEPTH) return out;
279
307
  let entries;
280
308
  try {
281
309
  entries = readdirSync(dir, { withFileTypes: true });
@@ -285,7 +313,7 @@ function findSkillFiles(dir) {
285
313
  for (const entry of entries) {
286
314
  if (entry.isDirectory()) {
287
315
  if (IGNORE_DIRS.has(entry.name)) continue;
288
- out.push(...findSkillFiles(join(dir, entry.name)));
316
+ out.push(...findSkillFiles(join(dir, entry.name), depth + 1));
289
317
  } else if (entry.name === "SKILL.md") {
290
318
  out.push(join(dir, entry.name));
291
319
  }
@@ -304,7 +332,9 @@ async function resolveSource(arg) {
304
332
  const st = statSync(arg);
305
333
  if (st.isFile()) return [loadLocal(arg)];
306
334
  const files2 = findSkillFiles(arg);
307
- if (files2.length === 0) throw new Error(`No SKILL.md found under ${arg}`);
335
+ if (files2.length === 0) {
336
+ throw new Error(`No SKILL.md found under ${arg}. Point at a skill directory, e.g. "skillmd lint ./my-skill", or run "skillmd init" to create one.`);
337
+ }
308
338
  return files2.map(loadLocal);
309
339
  }
310
340
  const { downloadTemplate } = await import("giget");
@@ -389,6 +419,11 @@ async function runLint(target, flags) {
389
419
  }
390
420
  function lintCommand() {
391
421
  return new Command("lint").alias("check").description("Validate SKILL.md file(s) against the spec and report a quality score").argument("[target]", "local path or GitHub source", ".").option("--format <fmt>", "text | json | sarif | github", "text").option("--strict", "treat warnings as errors").option("--fail-on-warning", "exit non-zero when warnings exist").option("--fix", "apply safe automatic fixes (e.g. add missing license)").action(async (target, opts) => {
422
+ if (resolve(target) === homedir()) {
423
+ process.stderr.write("Warning: scanning your entire home directory. Pass a narrower path, e.g. skillmd lint ./my-skill\n");
424
+ }
425
+ process.stderr.write(`Looking for SKILL.md under ${target} \u2026
426
+ `);
392
427
  const run = await runLint(target, opts);
393
428
  console.log(run.output);
394
429
  process.exitCode = run.exitCode;
@@ -522,11 +557,11 @@ import pc4 from "picocolors";
522
557
 
523
558
  // ../cli/src/config.ts
524
559
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
525
- import { homedir } from "os";
560
+ import { homedir as homedir2 } from "os";
526
561
  import { join as join3 } from "path";
527
562
  var DEFAULT_API = "https://skillmd-api.vinoor.workers.dev";
528
563
  function configPath() {
529
- return join3(homedir(), ".skillmd", "config.json");
564
+ return join3(homedir2(), ".skillmd", "config.json");
530
565
  }
531
566
  function readConfig() {
532
567
  try {
@@ -536,7 +571,7 @@ function readConfig() {
536
571
  }
537
572
  }
538
573
  function writeConfig(cfg) {
539
- const dir = join3(homedir(), ".skillmd");
574
+ const dir = join3(homedir2(), ".skillmd");
540
575
  mkdirSync2(dir, { recursive: true });
541
576
  writeFileSync3(configPath(), JSON.stringify(cfg, null, 2), { encoding: "utf8", mode: 384 });
542
577
  }
@@ -605,8 +640,8 @@ import pc5 from "picocolors";
605
640
 
606
641
  // ../cli/src/agents.ts
607
642
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, rmSync, symlinkSync, existsSync as existsSync3, readdirSync as readdirSync2, statSync as statSync2, readFileSync as readFileSync3 } from "fs";
608
- import { homedir as homedir2 } from "os";
609
- import { join as join4, resolve, dirname as dirname2 } from "path";
643
+ import { homedir as homedir3 } from "os";
644
+ import { join as join4, resolve as resolve2, dirname as dirname2 } from "path";
610
645
  var AGENTS = [
611
646
  { id: "claude-code", segments: [".claude", "skills"] },
612
647
  { id: "cursor", segments: [".cursor", "skills"] },
@@ -617,7 +652,7 @@ var AGENTS = [
617
652
  function agentDir(agentId, opts = {}) {
618
653
  const agent = AGENTS.find((a) => a.id === agentId);
619
654
  if (!agent) throw new Error(`Unknown agent: ${agentId}. Known: ${AGENTS.map((a) => a.id).join(", ")}`);
620
- const root = opts.global ? homedir2() : opts.cwd ?? process.cwd();
655
+ const root = opts.global ? homedir3() : opts.cwd ?? process.cwd();
621
656
  return join4(root, ...agent.segments);
622
657
  }
623
658
  function detectAgents(opts = {}) {
@@ -628,7 +663,7 @@ function writeSkill(skillName, files, targetDir, opts = {}) {
628
663
  if (opts.mode === "symlink" && opts.canonicalDir) {
629
664
  mkdirSync3(dirname2(dest), { recursive: true });
630
665
  rmSync(dest, { recursive: true, force: true });
631
- symlinkSync(resolve(opts.canonicalDir), dest, "dir");
666
+ symlinkSync(resolve2(opts.canonicalDir), dest, "dir");
632
667
  return dest;
633
668
  }
634
669
  mkdirSync3(dest, { recursive: true });
@@ -939,6 +974,10 @@ program.addCommand(updateCommand());
939
974
  program.addCommand(publishCommand());
940
975
  program.addCommand(loginCommand());
941
976
  program.addCommand(logoutCommand());
977
+ if (process.argv.slice(2).length === 0) {
978
+ program.outputHelp();
979
+ process.exit(0);
980
+ }
942
981
  program.parseAsync(process.argv).catch((err) => {
943
982
  console.error(err instanceof Error ? err.message : String(err));
944
983
  process.exitCode = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillmds",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "SkillMD for agents: the `skillmds` MCP server + the `skillmd` CLI (lint, scan, search, install, publish Agent Skills) from skillmd.com.",
5
5
  "type": "module",
6
6
  "bin": {