@mondoohq/skillcheck 0.3.2 → 0.3.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/README.md CHANGED
@@ -48,8 +48,9 @@ It fails open: a skill the database hasn't analyzed yet shows as clean and never
48
48
 
49
49
  If you publish skills, `validate` checks your repository against the
50
50
  [Agent Skills](https://agentskills.io/specification) and [AGENTS.md](https://agents.md/)
51
- specifications — catching bad skill names, oversized descriptions, and a missing
52
- `AGENTS.md` or marketplace manifest before your users do.
51
+ specifications — catching broken frontmatter, bad skill names, oversized descriptions,
52
+ and a missing `AGENTS.md` or marketplace manifest before your users do. It finds every
53
+ `SKILL.md` in the repository, including skills nested in plugin directories.
53
54
 
54
55
  ```bash
55
56
  npx @mondoohq/skillcheck validate . # current directory
@@ -60,15 +61,18 @@ npx @mondoohq/skillcheck validate ./my-skills --json # any path, JSON output
60
61
  Validating /path/to/repo
61
62
 
62
63
  Agent Skills spec (SKILL.md)
64
+ ✓ The repository contains at least one skill (a SKILL.md file)
65
+ ✓ Every SKILL.md starts with valid YAML frontmatter with correctly typed fields
63
66
  ✓ Every skill name is a lowercase slug (a-z0-9, single hyphens)
64
67
  ✓ Every skill name is 1-64 characters
65
68
  ✓ Every skill name equals its directory name
66
69
  ✓ Every skill description is 1-1024 characters
70
+ ✓ Every skill compatibility note is at most 500 characters
67
71
  Repository contract (agents.md + marketplace)
68
72
  ✓ A root AGENTS.md exists (agents.md convention)
69
73
  ✓ .claude-plugin/marketplace.json exists and lists plugins
70
74
 
71
- PASS 6 passed, 0 failed
75
+ PASS 9 passed, 0 failed
72
76
  ```
73
77
 
74
78
  It exits **1** if any check fails, so it drops straight into a skills repo's CI. The rules
package/bin/skillcheck.js CHANGED
@@ -44,36 +44,78 @@ function fail(message) {
44
44
  process.exit(EXIT_FAILURE);
45
45
  }
46
46
 
47
+ // candidateKeys lists the PLATFORM_PACKAGES keys to try, most preferred first.
48
+ //
49
+ // npm installs the optionalDependency matching the CPU of the Node that ran
50
+ // `npm install`, not the machine's, so switching Node builds afterwards leaves
51
+ // the "wrong" package on disk. Where the OS can run the other CPU's binary
52
+ // anyway, that package is an acceptable fallback:
53
+ //
54
+ // - win32: Windows on ARM64 runs both arm64 and x64 binaries (x64 under
55
+ // emulation), and an x64 Node there is common. arm64 <-> x64 both ways.
56
+ // - darwin: Apple Silicon runs x64 binaries under Rosetta, so an arm64 Node
57
+ // may use the x64 package. Not the reverse: an x64 Node may be on an Intel
58
+ // Mac, which cannot run arm64.
59
+ // - linux: strict. There is no general cross-CPU execution, and a binary
60
+ // that fails to exec is worse than a clear "not installed".
61
+ function candidateKeys(platform, arch) {
62
+ const keys = [`${platform}_${arch}`];
63
+ if (platform === 'win32') {
64
+ if (arch === 'arm64') keys.push('win32_x64');
65
+ else if (arch === 'x64') keys.push('win32_arm64');
66
+ } else if (platform === 'darwin' && arch === 'arm64') {
67
+ keys.push('darwin_x64');
68
+ }
69
+ return keys;
70
+ }
71
+
47
72
  // resolveBinary finds the platform binary, or explains why it cannot. Each
48
73
  // failure is something the user can act on, so each gets a sentence rather than
49
74
  // a module-resolution stack trace.
50
- function resolveBinary() {
51
- const key = `${process.platform}_${process.arch}`;
52
- const target = PLATFORM_PACKAGES[key];
53
- if (!target) {
75
+ //
76
+ // platform, arch and resolve default to the real process and require.resolve;
77
+ // tests inject them. Returns { path } on success or { error } with the message.
78
+ function resolveBinary({ platform = process.platform, arch = process.arch, resolve = require.resolve } = {}) {
79
+ const targets = candidateKeys(platform, arch)
80
+ .map((key) => PLATFORM_PACKAGES[key])
81
+ .filter(Boolean);
82
+ if (targets.length === 0) {
54
83
  const supported = Object.keys(PLATFORM_PACKAGES).sort().join(', ');
55
- fail(
56
- `no prebuilt binary for ${process.platform}/${process.arch}.\n` +
84
+ return {
85
+ error:
86
+ `no prebuilt binary for ${platform}/${arch}.\n` +
57
87
  ` supported: ${supported}\n` +
58
- ' other platforms: https://github.com/mondoohq/skillcheck/releases'
59
- );
88
+ ' other platforms: https://github.com/mondoohq/skillcheck/releases',
89
+ };
60
90
  }
61
- let pkgJson;
62
- try {
63
- pkgJson = require.resolve(path.posix.join(target.pkg, 'package.json'));
64
- } catch {
65
- fail(
66
- `the platform package ${target.pkg} is not installed.\n` +
67
- ' it ships as an optionalDependency, so this usually means the install ran with\n' +
68
- ' --no-optional / --omit=optional, or a lockfile from a different platform was used.\n' +
69
- ` fix: npm install ${target.pkg}`
70
- );
91
+ for (const target of targets) {
92
+ let pkgJson;
93
+ try {
94
+ pkgJson = resolve(path.posix.join(target.pkg, 'package.json'));
95
+ } catch {
96
+ continue;
97
+ }
98
+ return { path: path.join(path.dirname(pkgJson), target.bin) };
71
99
  }
72
- return path.join(path.dirname(pkgJson), target.bin);
100
+ const preferred = targets[0].pkg;
101
+ const fallbacks = targets.slice(1).map((t) => t.pkg);
102
+ const which =
103
+ `the platform package ${preferred} is not installed` +
104
+ (fallbacks.length ? `, and neither is the fallback ${fallbacks.join(', ')}.` : '.');
105
+ return {
106
+ error:
107
+ `${which}\n` +
108
+ ' it ships as an optionalDependency, so this usually means the install ran with\n' +
109
+ ' --no-optional / --omit=optional, or a lockfile from a different platform was used,\n' +
110
+ ` or node_modules was installed by a Node build for a different CPU than this one (${arch}).\n` +
111
+ ` fix: npm install ${preferred}`,
112
+ };
73
113
  }
74
114
 
75
115
  function main() {
76
- const child = spawn(resolveBinary(), process.argv.slice(2), {
116
+ const resolved = resolveBinary();
117
+ if (resolved.error) fail(resolved.error);
118
+ const child = spawn(resolved.path, process.argv.slice(2), {
77
119
  stdio: 'inherit',
78
120
  env: process.env,
79
121
  });
@@ -109,4 +151,10 @@ function main() {
109
151
  });
110
152
  }
111
153
 
112
- main();
154
+ // Run when executed as the `skillcheck` bin; export the resolution logic when
155
+ // required, so scripts/npm-launcher.test.mjs can test it without spawning.
156
+ if (require.main === module) {
157
+ main();
158
+ } else {
159
+ module.exports = { PLATFORM_PACKAGES, candidateKeys, resolveBinary };
160
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mondoohq/skillcheck",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "AI agent skill security scanner. Detects locally installed agent skills, computes SHA-256 checksums, and queries the Mondoo AI Agent Security database for known threats.",
5
5
  "keywords": [
6
6
  "ai-security",
@@ -33,11 +33,11 @@
33
33
  "node": ">=18"
34
34
  },
35
35
  "optionalDependencies": {
36
- "@mondoohq/skillcheck_darwin_amd64": "0.3.2",
37
- "@mondoohq/skillcheck_darwin_arm64": "0.3.2",
38
- "@mondoohq/skillcheck_linux_amd64": "0.3.2",
39
- "@mondoohq/skillcheck_linux_arm64": "0.3.2",
40
- "@mondoohq/skillcheck_windows_amd64": "0.3.2",
41
- "@mondoohq/skillcheck_windows_arm64": "0.3.2"
36
+ "@mondoohq/skillcheck_darwin_amd64": "0.3.4",
37
+ "@mondoohq/skillcheck_darwin_arm64": "0.3.4",
38
+ "@mondoohq/skillcheck_linux_amd64": "0.3.4",
39
+ "@mondoohq/skillcheck_linux_arm64": "0.3.4",
40
+ "@mondoohq/skillcheck_windows_amd64": "0.3.4",
41
+ "@mondoohq/skillcheck_windows_arm64": "0.3.4"
42
42
  }
43
43
  }