Chapter 3: Installation Sources and Trust Model

April 13, 2026 ยท View on GitHub

Welcome to Chapter 3: Installation Sources and Trust Model. In this part of OpenSkills Tutorial: Universal Skill Loading for Coding Agents, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.

OpenSkills can install from public repos, private repos, and local paths. Trust boundaries should be explicit.

Source Types

SourceRisk Consideration
public GitHubprovenance and maintenance quality
private Gitaccess controls and branch policy
local pathinternal review quality

Summary

You now have a trust model for safe skill installation.

Next: Chapter 4: Sync and AGENTS.md Integration

Source Code Walkthrough

src/commands/install.ts

The isGitUrl function in src/commands/install.ts handles a key part of this chapter's functionality:

 * Check if source is a git URL (SSH, git://, or HTTPS)
 */
function isGitUrl(source: string): boolean {
  return (
    source.startsWith('git@') ||
    source.startsWith('git://') ||
    source.startsWith('http://') ||
    source.startsWith('https://') ||
    source.endsWith('.git')
  );
}

/**
 * Extract repo name from a git URL
 */
function getRepoName(repoUrl: string): string | null {
  const cleaned = repoUrl.replace(/\.git$/, '');
  const lastPart = cleaned.split('/').pop();
  if (!lastPart) return null;
  const maybeRepo = lastPart.includes(':') ? lastPart.split(':').pop() : lastPart;
  return maybeRepo || null;
}

/**
 * Expand ~ to home directory
 */
function expandPath(source: string): string {
  if (source.startsWith('~/')) {
    return join(homedir(), source.slice(2));
  }
  return resolve(source);
}

This function is important because it defines how OpenSkills Tutorial: Universal Skill Loading for Coding Agents implements the patterns covered in this chapter.

src/commands/install.ts

The getRepoName function in src/commands/install.ts handles a key part of this chapter's functionality:

 * Extract repo name from a git URL
 */
function getRepoName(repoUrl: string): string | null {
  const cleaned = repoUrl.replace(/\.git$/, '');
  const lastPart = cleaned.split('/').pop();
  if (!lastPart) return null;
  const maybeRepo = lastPart.includes(':') ? lastPart.split(':').pop() : lastPart;
  return maybeRepo || null;
}

/**
 * Expand ~ to home directory
 */
function expandPath(source: string): string {
  if (source.startsWith('~/')) {
    return join(homedir(), source.slice(2));
  }
  return resolve(source);
}

/**
 * Ensure target path stays within target directory
 */
function isPathInside(targetPath: string, targetDir: string): boolean {
  const resolvedTargetPath = resolve(targetPath);
  const resolvedTargetDir = resolve(targetDir);
  const resolvedTargetDirWithSep = resolvedTargetDir.endsWith(sep)
    ? resolvedTargetDir
    : resolvedTargetDir + sep;
  return resolvedTargetPath.startsWith(resolvedTargetDirWithSep);
}

This function is important because it defines how OpenSkills Tutorial: Universal Skill Loading for Coding Agents implements the patterns covered in this chapter.

src/commands/install.ts

The expandPath function in src/commands/install.ts handles a key part of this chapter's functionality:

 * Expand ~ to home directory
 */
function expandPath(source: string): string {
  if (source.startsWith('~/')) {
    return join(homedir(), source.slice(2));
  }
  return resolve(source);
}

/**
 * Ensure target path stays within target directory
 */
function isPathInside(targetPath: string, targetDir: string): boolean {
  const resolvedTargetPath = resolve(targetPath);
  const resolvedTargetDir = resolve(targetDir);
  const resolvedTargetDirWithSep = resolvedTargetDir.endsWith(sep)
    ? resolvedTargetDir
    : resolvedTargetDir + sep;
  return resolvedTargetPath.startsWith(resolvedTargetDirWithSep);
}

/**
 * Install skill from local path, GitHub, or Git URL
 */
export async function installSkill(source: string, options: InstallOptions): Promise<void> {
  const folder = options.universal ? '.agent/skills' : '.claude/skills';
  const isProject = !options.global; // Default to project unless --global specified
  const targetDir = isProject
    ? join(process.cwd(), folder)
    : join(homedir(), folder);

  const location = isProject

This function is important because it defines how OpenSkills Tutorial: Universal Skill Loading for Coding Agents implements the patterns covered in this chapter.

src/commands/install.ts

The isPathInside function in src/commands/install.ts handles a key part of this chapter's functionality:

 * Ensure target path stays within target directory
 */
function isPathInside(targetPath: string, targetDir: string): boolean {
  const resolvedTargetPath = resolve(targetPath);
  const resolvedTargetDir = resolve(targetDir);
  const resolvedTargetDirWithSep = resolvedTargetDir.endsWith(sep)
    ? resolvedTargetDir
    : resolvedTargetDir + sep;
  return resolvedTargetPath.startsWith(resolvedTargetDirWithSep);
}

/**
 * Install skill from local path, GitHub, or Git URL
 */
export async function installSkill(source: string, options: InstallOptions): Promise<void> {
  const folder = options.universal ? '.agent/skills' : '.claude/skills';
  const isProject = !options.global; // Default to project unless --global specified
  const targetDir = isProject
    ? join(process.cwd(), folder)
    : join(homedir(), folder);

  const location = isProject
    ? chalk.blue(`project (${folder})`)
    : chalk.dim(`global (~/${folder})`);

  const projectLocation = `./${folder}`;
  const globalLocation = `~/${folder}`;

  console.log(`Installing from: ${chalk.cyan(source)}`);
  console.log(`Location: ${location}`);
  if (isProject) {
    console.log(

This function is important because it defines how OpenSkills Tutorial: Universal Skill Loading for Coding Agents implements the patterns covered in this chapter.

How These Components Connect

flowchart TD
    A[isGitUrl]
    B[getRepoName]
    C[expandPath]
    D[isPathInside]
    E[installSkill]
    A --> B
    B --> C
    C --> D
    D --> E