heygen-com/hyperframes · error

No skills manifest found at: ${source}

Error message

No skills manifest found at: ${source}

What it means

Thrown by resolveLocalManifest when neither a manifest JSON file nor a skills/ directory can be found at the given local path. The function first checks for a direct .json file (or <source>/skills-manifest.json), then falls back to computing a manifest from a skills/ subdirectory. If neither exists, this error fires.

Source

Thrown at packages/cli/src/utils/skillsManifest.ts:681

      "git",
      ["ls-remote", `https://github.com/${repoSlug}.git`, "refs/heads/main"],
      { timeout: FETCH_TIMEOUT_MS, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" } },
    );
    const sha = stdout.split(/\s+/)[0]?.trim() ?? "";
    return /^[0-9a-f]{40}$/.test(sha) ? sha : null;
  } catch {
    return null;
  }
}

/** Read a manifest from a local path — a manifest file or a repo root. */
function resolveLocalManifest(source: string): SkillsManifest {
  const direct = source.endsWith(".json") ? source : join(source, MANIFEST_FILE);
  if (existsSync(direct)) return JSON.parse(readFileSync(direct, "utf8")) as SkillsManifest;
  // Fall back to computing from a skills/ tree on disk.
  const skillsRoot = source.endsWith("skills") ? source : join(source, "skills");
  if (existsSync(skillsRoot)) return buildManifest(skillsRoot, { source: skillsRoot });
  throw new Error(`No skills manifest found at: ${source}`);
}

/**
 * Fetch the manifest from GitHub. A full URL is fetched directly; an
 * `owner/repo` slug (or the default repo) is SHA-pinned via `git ls-remote` to
 * dodge raw-CDN lag, falling back to the branch URL when git is unavailable.
 */
async function fetchRemoteManifest(source?: string): Promise<SkillsManifest> {
  if (source?.startsWith("http")) return fetchManifest(source);

  const repoSlug = source ?? DEFAULT_REPO_SLUG;
  const sha = await remoteHeadSha(repoSlug);
  if (sha) {
    try {
      return await fetchManifest(
        `https://raw.githubusercontent.com/${repoSlug}/${sha}/${MANIFEST_FILE}`,
      );
    } catch {

View on GitHub (pinned to c2996c8626)

Solutions

  1. Verify the path exists and contains either a skills-manifest.json or a skills/ directory.
  2. If pointing at a repo checkout, use the repo root, not a subdirectory.
  3. Run npx hyperframes skills update from the project root to regenerate the manifest from the skills/ tree.
  4. Use an absolute path to avoid working-directory ambiguity.

Example fix

// before: hyperframes skills diff --source ./packages/cli
// after:  hyperframes skills diff --source /abs/path/to/repo-root
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from "node:fs";
import { join } from "node:path";

function validateLocalManifestSource(source: string): string | null {
  if (source.endsWith(".json") && existsSync(source)) return source;
  if (existsSync(join(source, "skills-manifest.json"))) return join(source, "skills-manifest.json");
  if (existsSync(join(source, "skills"))) return join(source, "skills");
  return null;
}

Try / catch

try {
  const manifest = resolveLocalManifest(source);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("No skills manifest found")) {
    console.error(`${err.message}. Ensure the path has skills-manifest.json or a skills/ directory.`);
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing a local directory path to a skills command (--source ./my-repo) where that directory has no skills-manifest.json and no skills/ subdirectory; passing a .json path that doesn't exist on disk.

Common situations: Pointing --source at the wrong directory (e.g. a subpackage instead of repo root); the manifest file was deleted or not generated yet; typo in the path; using a relative path from the wrong working directory.

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/0b1687a44ed6bfea. Report an issue: GitHub.