UNPKG

@agentled/cli

Version:

CLI for Agentled — manage workflows, apps, and knowledge from the command line. Zero context-window cost for AI agents.

103 lines 4.57 kB
/* eslint-disable no-console */ import { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'; import { join, dirname, resolve } from 'node:path'; import { homedir } from 'node:os'; import { fileURLToPath } from 'node:url'; function resolveBundledScaffoldsDir() { const here = fileURLToPath(import.meta.url); // dist/commands/scaffold.js → package root is two levels up const pkgRoot = resolve(dirname(here), '..', '..'); return join(pkgRoot, 'scaffolds'); } function resolveLocalScaffoldDirs() { const dirs = []; if (process.env.AGENTLED_SCAFFOLDS_DIR) dirs.push(process.env.AGENTLED_SCAFFOLDS_DIR); dirs.push(join(homedir(), '.agentled', 'scaffolds')); return dirs.filter(existsSync); } function readDir(dir, source) { if (!existsSync(dir)) return []; return readdirSync(dir) .filter(f => f.endsWith('.json')) .map(file => { const path = join(dir, file); const slug = file.replace(/\.json$/, ''); try { const obj = JSON.parse(readFileSync(path, 'utf-8')); return { slug, name: obj.name ?? slug, goal: obj.goal ?? '', path, source }; } catch { return { slug, name: slug, goal: '(invalid JSON)', path, source }; } }); } function loadScaffolds() { // Local scaffolds shadow bundled ones with the same slug. Enables a // workspace / customer / team to ship their own scaffold library without // waiting on a CLI release, while keeping the bundled patterns as a // canonical fallback. const bundled = readDir(resolveBundledScaffoldsDir(), 'bundled'); const local = []; for (const dir of resolveLocalScaffoldDirs()) local.push(...readDir(dir, 'local')); const bySlug = new Map(); for (const s of bundled) bySlug.set(s.slug, s); for (const s of local) bySlug.set(s.slug, s); // local wins return [...bySlug.values()].sort((a, b) => a.slug.localeCompare(b.slug)); } function findScaffold(scaffolds, query) { const q = query.toLowerCase(); return (scaffolds.find(s => s.slug.toLowerCase() === q) ?? scaffolds.find(s => s.slug.toLowerCase().includes(q)) ?? null); } export function registerScaffoldCommand(workflows) { workflows .command('scaffold [pattern]') .description('Emit a working pipeline JSON skeleton for a named pattern. Run without args to list available scaffolds.') .option('--list', 'List available scaffolds') .option('--out <path>', 'Write the scaffold JSON to this path instead of stdout') .action((pattern, opts) => { const scaffolds = loadScaffolds(); if (scaffolds.length === 0) { console.error('No scaffolds bundled with this CLI version.'); process.exit(1); } if (!pattern || opts.list) { console.log('Available scaffolds:\n'); for (const s of scaffolds) { const tag = s.source === 'local' ? ' [local]' : ''; console.log(` ${s.slug.padEnd(28)}${tag.padEnd(8)} ${s.name}`); if (s.goal) console.log(` ${' '.repeat(36)} ${s.goal}`); } console.log('\nUsage:'); console.log(' agentled workflows scaffold <pattern> # print JSON to stdout'); console.log(' agentled workflows scaffold <pattern> --out x.json # write to file'); console.log(' agentled workflows validate --file x.json # preflight before create'); console.log(' agentled workflows create --file x.json # create + auto-validate'); console.log('\nBring your own: drop JSON files in ~/.agentled/scaffolds/ or set'); console.log('$AGENTLED_SCAFFOLDS_DIR. Local slugs shadow bundled ones with the same name.'); return; } const found = findScaffold(scaffolds, pattern); if (!found) { console.error(`Scaffold "${pattern}" not found. Run \`agentled workflows scaffold --list\` for available scaffolds.`); process.exit(1); } const content = readFileSync(found.path, 'utf-8'); if (opts.out) { writeFileSync(opts.out, content); console.error(` ✓ Wrote ${found.slug} to ${opts.out}`); console.error(` Next: agentled workflows validate --file ${opts.out}`); } else { process.stdout.write(content); } }); } //# sourceMappingURL=scaffold.js.map