# How the Skills CLI Differentiates Between Symlink and Copy Installation Modes

> Learn how the skills CLI differentiates symlink vs copy installation modes. Discover the default symlink mode and fallback to copy for seamless installations.

- Repository: [Vercel Labs/skills](https://github.com/vercel-labs/skills)
- Tags: internals
- Published: 2026-04-23

---

**The `skills` CLI distinguishes between **symlink** and **copy** installation modes through explicit `--mode` flags, with symlink as the default that gracefully falls back to copy when filesystem permissions block symlink creation.**

The **skills** CLI from [vercel-labs/skills](https://github.com/vercel-labs/skills) provides two fundamentally different ways to install AI agent skills: **symlink mode** creates a central canonical copy with agent-specific links, while **copy mode** duplicates files directly into each agent directory. Understanding how the skills CLI differentiates between symlink and copy installation modes helps you optimize for development workflows, disk space, and cross-platform compatibility.

## The Core Distinction: Canonical Storage vs. Direct Duplication

The skills CLI's installation mode differentiation centers on one architectural decision: whether to maintain a **canonical centralized copy** of each skill.

### Symlink Mode (Default)

In `symlink` mode, the CLI:

1. Copies skill files **once** to a canonical directory at `~/.agents/skills/<skill>`
2. Creates a **filesystem symlink** from the agent-specific directory (e.g., `~/.claude/skills/<skill>`) to that canonical location
3. **Falls back automatically** to copy mode if symlink creation fails, recording `symlinkFailed: true`

This mode is selected when no `--mode` flag is provided, or when explicitly passing `--mode symlink`.

### Copy Mode

In `copy` mode, the CLI:

- **Bypasses the canonical directory entirely**
- Copies skill files **directly** into each agent-specific directory
- Creates no symlinks whatsoever

This mode is selected via `--mode copy` or `-m copy`.

## Where the Differentiation Logic Lives

The skills CLI differentiates between symlink and copy installation modes in [`src/installer.ts`](https://github.com/vercel-labs/skills/blob/main/src/installer.ts), with four key implementation points.

### 1. Type Definition

The valid modes are strictly typed:

```typescript
export type InstallMode = 'symlink' | 'copy';

```

*Source: [`src/installer.ts`](https://github.com/vercel-labs/skills/blob/main/src/installer.ts) lines 23-24*

### 2. Default Resolution

All installation entry points—`installSkillForAgent`, `installRemoteSkillForAgent`, `installWellKnownSkillForAgent`, and `installBlobSkillForAgent`—resolve the mode with a simple fallback:

```typescript
const installMode = options.mode ?? 'symlink';

```

*Source: [`src/installer.ts`](https://github.com/vercel-labs/skills/blob/main/src/installer.ts) lines 43-45*

### 3. Copy Mode Branch

When `installMode === 'copy'`, the code takes an early return path that skips all canonical directory logic:

```typescript
if (installMode === 'copy') {
  await cleanAndCreateDirectory(agentDir);
  await copyDirectory(skill.path, agentDir);
  return { success: true, path: agentDir, mode: 'copy' };
}

```

*Source: [`src/installer.ts`](https://github.com/vercel-labs/skills/blob/main/src/installer.ts) lines 64-71*

### 4. Symlink Mode with Fallback

The symlink path first establishes the canonical copy, then attempts symlink creation:

```typescript
await cleanAndCreateDirectory(canonicalDir);
await copyDirectory(skill.path, canonicalDir);
// ...
const symlinkCreated = await createSymlink(canonicalDir, agentDir);

```

If `createSymlink` fails, the CLI automatically falls back to copy mode while preserving the canonical path information:

```typescript
if (!symlinkCreated) {
  await cleanAndCreateDirectory(agentDir);
  await copyDirectory(skill.path, agentDir);
  return {
    success: true,
    path: agentDir,
    canonicalPath: canonicalDir,
    mode: 'symlink',
    symlinkFailed: true,
  };
}

```

*Source: [`src/installer.ts`](https://github.com/vercel-labs/skills/blob/main/src/installer.ts) lines 92-107*

## Special Case: Universal Agents

The skills CLI includes an optimization for **universal agents** like `Claude` and `Cursor`. When installing globally for these agents, the canonical directory *is* the agent directory, making symlinks redundant.

This check occurs in [`src/installer.ts`](https://github.com/vercel-labs/skills/blob/main/src/installer.ts):

```typescript
if (isGlobal && isUniversalAgent(agentType)) {
  return { success: true, path: canonicalDir, canonicalPath: canonicalDir, mode: 'symlink' };
}

```

*Source: [`src/installer.ts`](https://github.com/vercel-labs/skills/blob/main/src/installer.ts) lines 81-84*

The `isUniversalAgent` determination comes from [`src/agents.ts`](https://github.com/vercel-labs/skills/blob/main/src/agents.ts), which defines which agent types support global skill sharing.

## Practical Usage Examples

### Default Symlink Installation

```bash

# Installs skill with symlink to canonical location

skills add my-skill

```

### Explicit Copy Mode

```bash

# Bypasses canonical directory, copies files directly

skills add my-skill --mode copy

# or

skills add my-skill -m copy

```

### Detecting Symlink Failures Programmatically

The CLI returns structured results that reveal when fallback occurred:

```json
{
  "success": true,
  "path": "/home/user/.claude/skills/my-skill",
  "canonicalPath": "/home/user/.agents/skills/my-skill",
  "mode": "symlink",
  "symlinkFailed": true
}

```

When `symlinkFailed: true` appears, the files were copied directly despite the `mode: "symlink"` designation—typically due to Windows without Developer Mode or insufficient filesystem permissions.

## Summary

- **Symlink mode** (default) creates a canonical copy at `~/.agents/skills/<skill>` and links agent directories to it, falling back to copy automatically on failure
- **Copy mode** bypasses the canonical directory entirely, duplicating files directly into agent-specific locations
- The differentiation logic resides primarily in [`src/installer.ts`](https://github.com/vercel-labs/skills/blob/main/src/installer.ts), with type definitions in [`src/types.ts`](https://github.com/vercel-labs/skills/blob/main/src/types.ts) and agent classification in [`src/agents.ts`](https://github.com/vercel-labs/skills/blob/main/src/agents.ts)
- Universal agents like Claude and Cursor receive optimized handling where the canonical directory equals the agent directory, eliminating redundant symlinks

## Frequently Asked Questions

### How do I force copy mode instead of symlink?

Pass the `--mode copy` or `-m copy` flag to any `skills add` command. The CLI will bypass the canonical directory and copy files directly to the agent-specific location.

### What happens when symlinks fail on Windows?

The skills CLI automatically detects symlink creation failures—common on Windows without Developer Mode—and falls back to copy mode. The result includes `symlinkFailed: true` so you can identify when this occurred.

### Where does the canonical directory get created?

The canonical directory defaults to `~/.agents/skills/<skill-name>` on Unix systems, with equivalent paths on Windows. This location is controlled by constants in [`src/constants.ts`](https://github.com/vercel-labs/skills/blob/main/src/constants.ts) defining `AGENTS_DIR` and `SKILLS_SUBDIR`.