jackwener/OpenCLI · error

Invalid plugin source: "${source}" Supported formats: gith

Error message

Invalid plugin source: "${source}"
Supported formats:
  github:user/repo
  github:user/repo/subplugin
  https://github.com/user/repo
  https://<host>/<path>/repo.git
  ssh://git@<host>/<path>/repo.git
  git@<host>:user/repo.git

What it means

installPlugin first parses the source string with parseSource, which recognizes github: shorthand, GitHub HTTPS URLs, ssh://, SCP-style git@, generic HTTPS git URLs, file:// and absolute local paths. If nothing matches, a plain Error listing all supported formats is thrown so the caller can correct the input.

Source

Thrown at src/plugin.ts:697

    writeLock?.(commitHash);
  });
}

/**
 * Install a plugin from a source.
 * Supports:
 *   "github:user/repo"            — single plugin or full monorepo
 *   "github:user/repo/subplugin"  — specific sub-plugin from a monorepo
 *   "https://github.com/user/repo"
 *   "file:///absolute/path"       — local plugin directory (symlinked)
 *   "/absolute/path"              — local plugin directory (symlinked)
 *
 * Returns the installed plugin name(s).
 */
export function installPlugin(source: string): string | string[] {
  const parsed = parseSource(source);
  if (!parsed) {
    throw new Error(
      `Invalid plugin source: "${source}"\n` +
      `Supported formats:\n` +
      `  github:user/repo\n` +
      `  github:user/repo/subplugin\n` +
      `  https://github.com/user/repo\n` +
      `  https://<host>/<path>/repo.git\n` +
      `  ssh://git@<host>/<path>/repo.git\n` +
      `  git@<host>:user/repo.git\n` +
      `  file:///absolute/path\n` +
      `  /absolute/path`
    );
  }

  const { name: repoName, subPlugin } = parsed;

  if (parsed.type === 'local') {
    return installLocalPlugin(parsed.localPath!, repoName);
  }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use a supported format, e.g. installPlugin('github:user/repo') or an absolute local path.
  2. For local development, pass an absolute path ('/abs/path/to/plugin') or file:///absolute/path — relative paths are rejected.
  3. Add a .git suffix or use https://github.com/user/repo for GitHub repos.
  4. For other git hosts use ssh://git@<host>/<path>/repo.git or git@<host>:user/repo.git.
  5. Trim whitespace and remove trailing slashes/query strings from the source string.

Example fix

// before
installPlugin('my-plugin');            // bare name
installPlugin('./plugins/my-plugin');  // relative path
// after
installPlugin('github:user/my-plugin');
installPlugin('/abs/path/plugins/my-plugin');
Defensive patterns

Strategy: validation

Validate before calling

const SOURCE_RE = /^(github:[\w.-]+\/[\w.-]+(\/[\w.-]+)?|https?:\/\/github\.com\/[\w.-]+\/[\w.-]+?(\.git)?|ssh:\/\/[^/]+\/.+|git@[^:]+:.+|https?:\/\/[^/]+\/.+|file:\/\/.+|\/.+)$/;
if (!SOURCE_RE.test(source)) throw new Error(`Unsupported plugin source: ${source}`);

Try / catch

try {
  installPlugin(source);
} catch (err) {
  if (err.message.startsWith('Invalid plugin source')) {
    // normalize the source string (add scheme/absolute path) and retry
  } else throw err;
}

Prevention

When it happens

Trigger: installPlugin('my-plugin') (bare name), installPlugin('git://host/repo'), installPlugin('github:user') (missing repo segment), relative local paths like './my-plugin', URLs with extra path/query segments, or whitespace/typos in the source string.

Common situations: Passing a plugin NAME instead of a source; using a git:// protocol URL (unsupported); relative directory path instead of absolute; trailing slash or extra URL components; scp-style without .git and non-matching host prefix.

Related errors


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