@agentled/cli
Version:
CLI for Agentled — manage workflows, apps, and knowledge from the command line. Zero context-window cost for AI agents.
159 lines • 7.96 kB
JavaScript
/* eslint-disable no-console */
import { describeSkillsInstall, getSkillsTargetDir, getCodexSkillsDir, getOpenClawSkillsDir, getHermesSkillsDir, installSkills, resolveBundledSkillsDir, exportSkillToTarget, buildCodexPlugin, listSkillModules, NON_NATIVE_TARGETS, } from '../utils/skills.js';
import { existsSync, readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
function parseSkillVersion(skillMdPath) {
try {
const content = readFileSync(skillMdPath, 'utf-8');
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
if (!fmMatch)
return null;
const versionMatch = fmMatch[1].match(/^version:\s*(.+)$/m);
return versionMatch ? versionMatch[1].trim() : null;
}
catch {
return null;
}
}
export function registerSkillsCommands(program) {
const skills = program
.command('skills')
.description('Manage Claude Code skills bundled with the CLI');
skills
.command('install')
.description('Install the bundled Agentled skill (Claude Code by default; also Codex, OpenClaw, Hermes, Cursor, Gemini, AGENTS.md, codex-plugin)')
.option('--project', 'Install into the current project\'s .claude/skills/ instead of the user-global location')
.option('--force', 'Overwrite existing skill files even if they contain local edits')
.option('--target <target>', 'Where to install: claude | codex | openclaw | hermes | cursor | agents | gemini | codex-plugin', 'claude')
.action((opts) => {
try {
const target = String(opts.target).toLowerCase();
// Codex plugin package — scaffold a directory with a manifest + skill bundle.
if (target === 'codex-plugin') {
const skillDir = join(resolveBundledSkillsDir(), 'agentled');
const { pluginDir, manifestPath } = buildCodexPlugin(skillDir, process.cwd());
console.log(` ✓ agentled Codex plugin scaffolded → ${pluginDir}`);
console.log(` manifest: ${manifestPath}`);
console.log(` Install it in Codex via "Install plugin" → local path, or add it to a local marketplace.`);
return;
}
// Single-file exports for agents that read one markdown context file
// (Cursor / Gemini / AGENTS.md).
if (NON_NATIVE_TARGETS.includes(target)) {
const sourceDir = resolveBundledSkillsDir();
const skillDir = join(sourceDir, 'agentled');
const result = exportSkillToTarget(target, skillDir, process.cwd(), { force: opts.force });
if (result.action === 'written-sidecar') {
const conventional = target === 'agents' ? 'AGENTS.md' : 'GEMINI.md';
console.log(` ✓ agentled exported → ${result.path}`);
console.log(` • ${conventional} already exists — wrote a sidecar instead of overwriting. Include it, or re-run with --force to replace.`);
}
else {
console.log(` ✓ agentled exported → ${result.path}`);
}
return;
}
// Native skill-directory installs (Claude Code, Codex, OpenClaw, Hermes).
// These all read `<dir>/<skill>/SKILL.md`, so we copy the full bundle.
const skillDirTargets = {
codex: getCodexSkillsDir(),
openclaw: getOpenClawSkillsDir(),
hermes: getHermesSkillsDir(),
};
const explicitDir = skillDirTargets[target];
if (explicitDir) {
const results = installSkills({ targetDir: explicitDir, force: opts.force });
console.log(describeSkillsInstall(results, explicitDir));
return;
}
if (target !== 'claude') {
console.error(`Error: unknown --target "${opts.target}". Use one of: claude, codex, openclaw, hermes, cursor, agents, gemini, codex-plugin.`);
process.exit(1);
}
const isGlobal = !opts.project;
const targetDir = getSkillsTargetDir(isGlobal);
const results = installSkills({ global: isGlobal, force: opts.force });
console.log(describeSkillsInstall(results, targetDir));
}
catch (e) {
console.error(`Error: ${e.message}`);
process.exit(1);
}
});
skills
.command('list')
.description('List the composable reference modules inside the Agentled skill')
.action(() => {
const skillDir = join(resolveBundledSkillsDir(), 'agentled');
const modules = listSkillModules(skillDir);
if (modules.length === 0) {
console.log('No reference modules bundled with this CLI version.');
return;
}
console.log('Agentled skill — composable reference modules (loaded on demand):\n');
for (const m of modules) {
console.log(` ${m.file}`);
console.log(` ${m.title}`);
if (m.loadWhen)
console.log(` ↳ ${m.loadWhen}`);
console.log('');
}
console.log('The router (SKILL.md) points the agent at these by task. Export all of them');
console.log('as one file for other agents with: agentled skills install --target cursor|agents|gemini');
});
skills
.command('update')
.description('Refresh the installed skill to the version bundled with this CLI')
.option('--project', 'Update the project-level skill (default: user-global)')
.option('--force', 'Overwrite even if the installed skill has local edits')
.action((opts) => {
try {
const isGlobal = !opts.project;
const targetDir = getSkillsTargetDir(isGlobal);
const results = installSkills({ global: isGlobal, force: opts.force });
console.log(describeSkillsInstall(results, targetDir));
}
catch (e) {
console.error(`Error: ${e.message}`);
process.exit(1);
}
});
skills
.command('status')
.description('Show bundled vs installed skill versions')
.option('--project', 'Check the project-level skills (default: user-global)')
.action((opts) => {
const isGlobal = !opts.project;
const targetDir = getSkillsTargetDir(isGlobal);
const sourceDir = resolveBundledSkillsDir();
if (!existsSync(sourceDir)) {
console.log(`No bundled skills found (${sourceDir}). Reinstall @agentled/cli.`);
return;
}
const bundled = readdirSync(sourceDir, { withFileTypes: true })
.filter(d => d.isDirectory())
.map(d => d.name);
if (bundled.length === 0) {
console.log('No skills bundled with this CLI version.');
return;
}
for (const name of bundled) {
const bundledVersion = parseSkillVersion(join(sourceDir, name, 'SKILL.md')) ?? '?';
const installedSkillMd = join(targetDir, name, 'SKILL.md');
const installedVersion = existsSync(installedSkillMd)
? (parseSkillVersion(installedSkillMd) ?? 'unknown')
: null;
if (installedVersion === null) {
console.log(` ${name}: bundled v${bundledVersion}, not installed`);
}
else if (installedVersion === bundledVersion) {
console.log(` ${name}: bundled v${bundledVersion}, installed v${installedVersion} (up to date)`);
}
else {
console.log(` ${name}: bundled v${bundledVersion}, installed v${installedVersion}`);
}
}
console.log(`\nSkills directory: ${targetDir}`);
});
}
//# sourceMappingURL=skills.js.map