Reapplies @MatrixNeoKozak's PR #47 onto current main (resolves the bin/cli.mjs conflict with the star-nudge changes): - resolve() the install target and refuse system-critical dirs (/, /usr, /etc, /root, ...) so a typo'd --target can't clobber the system - skillcheck frontmatter parser tolerates leading whitespace and CRLF/LF Claude-Session: https://claude.ai/code/session_016JWn5jRD5tcEFKrubjQ6Px Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: MatrixNeoKozak <MatrixNeoKozak@users.noreply.github.com>
This commit is contained in:
+10
-2
@@ -13,7 +13,7 @@
|
|||||||
// --link symlink instead of copy (native agents; falls back to copy)
|
// --link symlink instead of copy (native agents; falls back to copy)
|
||||||
// --dry-run print what would happen without writing
|
// --dry-run print what would happen without writing
|
||||||
import { readdirSync, existsSync, mkdirSync, rmSync, cpSync, symlinkSync, copyFileSync, statSync } from 'node:fs';
|
import { readdirSync, existsSync, mkdirSync, rmSync, cpSync, symlinkSync, copyFileSync, statSync } from 'node:fs';
|
||||||
import { join, dirname, basename } from 'node:path';
|
import { join, dirname, basename, resolve } from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import { homedir } from 'node:os';
|
import { homedir } from 'node:os';
|
||||||
import { createRequire } from 'node:module';
|
import { createRequire } from 'node:module';
|
||||||
@@ -79,7 +79,15 @@ function add(opts) {
|
|||||||
}
|
}
|
||||||
const skillsDir = join(PKG_ROOT, 'skills');
|
const skillsDir = join(PKG_ROOT, 'skills');
|
||||||
if (!existsSync(skillsDir)) { console.error(`Error: bundled skills/ not found at ${skillsDir}.`); process.exit(1); }
|
if (!existsSync(skillsDir)) { console.error(`Error: bundled skills/ not found at ${skillsDir}.`); process.exit(1); }
|
||||||
const target = opts.target || defaultTarget(agent);
|
const target = resolve(opts.target || defaultTarget(agent));
|
||||||
|
|
||||||
|
// Guard against installing into system-critical directories (e.g. a typo'd --target).
|
||||||
|
const criticalPaths = ['/', '/usr', '/bin', '/etc', '/var', '/root', '/boot', '/proc', '/sys', '/dev'];
|
||||||
|
if (criticalPaths.includes(target)) {
|
||||||
|
console.error(`Error: Cannot install into a system-critical directory: ${target}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
console.log(`${opts.dryRun ? '[dry-run] ' : ''}Installing for '${agent}' into ${target}`);
|
console.log(`${opts.dryRun ? '[dry-run] ' : ''}Installing for '${agent}' into ${target}`);
|
||||||
|
|||||||
@@ -22,10 +22,12 @@ const strict = args.includes('--strict');
|
|||||||
const asJson = args.includes('--json');
|
const asJson = args.includes('--json');
|
||||||
|
|
||||||
function parseFrontmatter(text) {
|
function parseFrontmatter(text) {
|
||||||
const m = text.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
// Tolerate optional leading whitespace and CRLF/LF line endings so authored-on-Windows
|
||||||
|
// files don't produce false negatives.
|
||||||
|
const m = text.match(/^\s*---\r?\n([\s\S]*?)\r?\n\s*---\r?\n?([\s\S]*)$/);
|
||||||
if (!m) return { meta: null, body: text };
|
if (!m) return { meta: null, body: text };
|
||||||
const meta = {};
|
const meta = {};
|
||||||
for (const line of m[1].split('\n')) {
|
for (const line of m[1].split(/\r?\n/)) {
|
||||||
const kv = line.match(/^(\w[\w-]*):\s*(.*)$/);
|
const kv = line.match(/^(\w[\w-]*):\s*(.*)$/);
|
||||||
if (kv) {
|
if (kv) {
|
||||||
let v = kv[2].trim();
|
let v = kv[2].trim();
|
||||||
|
|||||||
Reference in New Issue
Block a user