# How to Work with Internal Skills Using the `INSTALL_INTERNAL_SKILLS` Environment Variable

> Learn how to work with internal skills by setting the INSTALL_INTERNAL_SKILLS environment variable. Easily reveal and install skills marked as internal true in SKILL.md.

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

---

**Set `INSTALL_INTERNAL_SKILLS=1` or `INSTALL_INTERNAL_SKILLS=true` before running Skills CLI commands to reveal and install skills marked as `internal: true` in their [`SKILL.md`](https://github.com/vercel-labs/skills/blob/main/SKILL.md) metadata.**

The Skills CLI from vercel-labs/skills filters out internal skills by default to prevent accidental installation of experimental or organization-specific tools. Understanding how to use the `INSTALL_INTERNAL_SKILLS` environment variable gives you controlled access to these hidden capabilities when needed.

## How the `INSTALL_INTERNAL_SKILLS` Flag Works Internally

The opt-in mechanism is implemented across three layers in the source code: environment detection, skill filtering, and CLI integration.

### Environment Variable Detection

In [`src/skills.ts`](https://github.com/vercel-labs/skills/blob/main/src/skills.ts), the `shouldInstallInternalSkills()` function parses the environment variable with strict value checking:

```ts
// src/skills.ts, lines 14-17
export function shouldInstallInternalSkills(): boolean {
  const envValue = process.env.INSTALL_INTERNAL_SKILLS;
  return envValue === '1' || envValue === 'true';
}

```

Only the exact strings `'1'` or `'true'` enable internal skills. Values like `'yes'`, `'on'`, `'TRUE'`, or `'0'` are treated as disabled.

### Skill Filtering Logic

When parsing a [`SKILL.md`](https://github.com/vercel-labs/skills/blob/main/SKILL.md) file, the code checks the `metadata.internal` flag against both the environment variable and optional parameters:

```ts
// src/skills.ts, lines 46-52
const isInternal = data.metadata?.internal === true;
if (isInternal && !shouldInstallInternalSkills() && !options?.includeInternal) {
  return null;   // skill omitted from results
}

```

A skill is **excluded** only when all three conditions are true: it's marked internal, the environment variable is not set, and no explicit `includeInternal` option was passed.

### CLI-Wide Consistency

All discovery functions—`discoverSkills`, `parseSkillMd`, and their callers—share this filtering logic. This ensures uniform behavior across `skills list`, `skills add`, and any future commands that enumerate skills.

## Setting `INSTALL_INTERNAL_SKILLS` for Different Scenarios

Choose the method that matches your workflow:

| Scenario | Command or Configuration |
|----------|--------------------------|
| **Single command** | Prefix: `INSTALL_INTERNAL_SKILLS=1 npx skills list` |
| **Session-wide** | Export: `export INSTALL_INTERNAL_SKILLS=1` in shell |
| **Permanent** | Add export to `~/.bashrc`, `~/.zshrc`, or `~/.bash_profile` |
| **Programmatic** | Set `process.env.INSTALL_INTERNAL_SKILLS = 'true'` before API calls |

## Practical Code Examples

### List All Skills Including Internal Ones

```bash

# Show hidden internal skills in the repository

INSTALL_INTERNAL_SKILLS=1 npx skills list

```

### Add a Specific Internal Skill

```bash

# "beta-tool" has internal: true in its SKILL.md metadata

INSTALL_INTERNAL_SKILLS=true npx skills add vercel-labs/beta-tool

```

### Enable for Entire Terminal Session

```bash

# Add to shell configuration file

echo 'export INSTALL_INTERNAL_SKILLS=1' >> ~/.zshrc

# Or set for current session only

export INSTALL_INTERNAL_SKILLS=1

# Now all skills commands include internal skills

npx skills list
npx skills add some-org/internal-util

```

### Using the Library Programmatically

```ts
import { discoverSkills } from './src/skills.js';

// Opt-in via environment before calling discovery
process.env.INSTALL_INTERNAL_SKILLS = 'true';

const skills = await discoverSkills('/path/to/repo');
console.log(skills.map(s => s.name));
// Output includes internal skills

```

### Bypass Environment Variable for Single Call

For one-time inclusion without modifying the environment, pass the `includeInternal` option:

```ts
import { discoverSkills } from './src/skills.js';

const allSkills = await discoverSkills('/path/to/repo', undefined, {
  includeInternal: true,  // forces inclusion regardless of env
});

// This override is used internally when a user explicitly
// requests a skill by exact name

```

## Key Source Files and Their Roles

| File | Purpose | GitHub Link |
|------|---------|-------------|
| [`src/skills.ts`](https://github.com/vercel-labs/skills/blob/main/src/skills.ts) | Core logic: `shouldInstallInternalSkills()`, discovery, and filtering | [view](https://github.com/vercel-labs/skills/blob/main/src/skills.ts) |
| [`src/add.test.ts`](https://github.com/vercel-labs/skills/blob/main/src/add.test.ts) | Test suite validating environment variable handling (lines 311-333) | [view](https://github.com/vercel-labs/skills/blob/main/src/add.test.ts) |
| [`README.md`](https://github.com/vercel-labs/skills/blob/main/README.md) | User documentation mentioning the variable in environment settings | [view](https://github.com/vercel-labs/skills/blob/main/README.md) |
| [`src/add.ts`](https://github.com/vercel-labs/skills/blob/main/src/add.ts) | CLI command implementation that relies on shared filtering helpers | [view](https://github.com/vercel-labs/skills/blob/main/src/add.ts) |

## Summary

- **Internal skills** are hidden by default when `internal: true` appears in [`SKILL.md`](https://github.com/vercel-labs/skills/blob/main/SKILL.md) metadata
- **Enable access** by setting `INSTALL_INTERNAL_SKILLS=1` or `INSTALL_INTERNAL_SKILLS=true`
- **Strict parsing** in `shouldInstallInternalSkills()` rejects all other values
- **Override per-call** with the `includeInternal` option in programmatic usage
- **Consistent behavior** across all CLI commands via shared logic in [`src/skills.ts`](https://github.com/vercel-labs/skills/blob/main/src/skills.ts)

## Frequently Asked Questions

### What happens if I set `INSTALL_INTERNAL_SKILLS=yes`?

The value `yes` is **not recognized** as valid. The `shouldInstallInternalSkills()` function in [`src/skills.ts`](https://github.com/vercel-labs/skills/blob/main/src/skills.ts) explicitly checks for `'1'` or `'true'` only, so internal skills remain hidden. Use `INSTALL_INTERNAL_SKILLS=1` or `INSTALL_INTERNAL_SKILLS=true` instead.

### Can I enable internal skills for just one specific command?

Yes. Prefix the command with the environment variable: `INSTALL_INTERNAL_SKILLS=1 npx skills list`. This sets the variable only for that command execution without affecting your shell session or other commands.

### What's the difference between using the environment variable and the `includeInternal` option?

The environment variable `INSTALL_INTERNAL_SKILLS` is the **user-facing opt-in mechanism** for CLI usage. The `includeInternal` option is a **programmatic bypass** used in code when calling functions like `discoverSkills()` directly. The CLI internally uses `includeInternal: true` when a user explicitly specifies a skill by name, bypassing the need for the environment variable in that specific case.