jackwener/OpenCLI · error · ArgumentError

Unknown OpenCLI skill: ${name}

Error message

Unknown OpenCLI skill: ${name}

What it means

readOpenCliSkill first parses the target into a skill name and requires it to start with the 'opencli-' prefix, since only built-in OpenCLI skills are resolvable through this API. A name without the prefix cannot be an OpenCLI skill, so it throws an ArgumentError immediately with a hint to run 'opencli skills list'.

Source

Thrown at src/skills.ts:47

export function getSkillsRoot(packageRoot: string = findPackageRoot(MODULE_FILE)): string {
  return path.join(packageRoot, 'skills');
}

export function listOpenCliSkills(packageRoot?: string): OpenCliSkillInfo[] {
  const skillsRoot = getSkillsRoot(packageRoot);
  if (!fs.existsSync(skillsRoot)) return [];

  return fs.readdirSync(skillsRoot, { withFileTypes: true })
    .filter((entry) => entry.isDirectory() && entry.name.startsWith('opencli-'))
    .map((entry) => readSkillInfo(skillsRoot, entry.name))
    .filter((entry): entry is OpenCliSkillInfo => entry !== null)
    .sort((a, b) => a.name.localeCompare(b.name));
}

export function readOpenCliSkill(target: string, relpath = '', packageRoot?: string): OpenCliSkillReadResult {
  const { name, pathInSkill } = parseSkillTarget(target, relpath);
  if (!name.startsWith('opencli-')) {
    throw new ArgumentError(`Unknown OpenCLI skill: ${name}`, 'Run "opencli skills list" to see available OpenCLI skills.');
  }

  const skillsRoot = getSkillsRoot(packageRoot);
  const skillRoot = path.join(skillsRoot, name);
  if (!isDirectory(skillRoot) || !fs.existsSync(path.join(skillRoot, 'SKILL.md'))) {
    throw new ArgumentError(`Unknown OpenCLI skill: ${name}`, 'Run "opencli skills list" to see available OpenCLI skills.');
  }

  const relativePath = normalizeSkillPath(pathInSkill || 'SKILL.md');
  const absolutePath = path.resolve(skillRoot, relativePath);
  const relativeToRoot = path.relative(skillRoot, absolutePath);
  if (relativeToRoot.startsWith('..') || path.isAbsolute(relativeToRoot)) {
    throw new ArgumentError(`Invalid skill path: ${relativePath}`, 'Skill paths must stay inside the selected OpenCLI skill.');
  }
  if (!fs.existsSync(absolutePath) || !fs.statSync(absolutePath).isFile()) {
    throw new ArgumentError(`Skill file not found: ${name}/${relativePath}`, 'Run "opencli skills list <skill>" is not supported yet; read SKILL.md or a known references/... file.');
  }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Prefix the skill name with 'opencli-' (e.g. "opencli-commit") and retry.
  2. Run "opencli skills list" to see valid OpenCLI skill names and pick the exact one.
  3. If the target is a user/community skill, use the general skill read API instead of readOpenCliSkill.
  4. Validate the name in code before calling: name.startsWith('opencli-').

Example fix

// before
readOpenCliSkill("commit-helper");
// after
readOpenCliSkill("opencli-commit-helper");
Defensive patterns

Strategy: validation

Validate before calling

function isOpenCliTarget(target: string): boolean {
  const { name } = parseSkillTarget(target, "");
  return name.startsWith("opencli-");
}
if (isOpenCliTarget(target)) readOpenCliSkill(target);

Try / catch

import { ArgumentError } from "./errors";
try {
  readOpenCliSkill(target);
} catch (e) {
  if (e instanceof ArgumentError && e.message.startsWith("Unknown OpenCLI skill:")) {
    // fall back to the general skill reader or show `opencli skills list`
  } else throw e;
}

Prevention

When it happens

Trigger: Calling readOpenCliSkill(target) where parseSkillTarget(target, relpath).name does not start with 'opencli-' — e.g. target "git-fix" or "my-skill" instead of "opencli-git-fix"; also passing a bare path with no name segment.

Common situations: Users passing a community/user skill name to the OpenCLI-specific reader; forgetting the 'opencli-' prefix in scripts or agent prompts; confusing readOpenCliSkill with the general skill reader.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/3ff2c93809494858. Report an issue: GitHub.