# How Skills Are Installed and Model Invocation Is Toggled in pi-web

> Learn how to install skills and toggle model invocation in pi-web. Discover the simple, npx-based CLI and front-matter flag for managing reusable plugins.

- Repository: [Alex Yang/pi-web](https://github.com/agegr/pi-web)
- Tags: internals
- Published: 2026-07-26

---

**Pi-web treats skills as reusable plugins managed via [`SKILL.md`](https://github.com/agegr/pi-web/blob/main/SKILL.md) files, using an `npx`-based CLI for installation and a front-matter flag to toggle LLM invocation.**

In the `agegr/pi-web` framework, skills function as modular extensions that enhance project capabilities through markdown-based configuration. Understanding how skills are installed and how model invocation is toggled reveals the architecture behind pi-web's extensible agent system. This guide examines the specific API endpoints, file operations, and source code implementations that manage these workflows.

## Skill Installation Architecture

Pi-web installs skills by treating each one as a standalone package that gets written into the project's local file system. The installation process relies on the Node.js package runner to execute CLI commands that fetch and configure skill definitions.

### The npx Execution Flow

When you trigger an installation, pi-web delegates package management to the **`npx`** runner. The system invokes the `skills` CLI through the internal `runNpx()` function defined in [`lib/npx.ts`](https://github.com/agegr/pi-web/blob/main/lib/npx.ts). This executes the command `npx skills add … --agent pi`, which downloads the skill package and generates the corresponding [`SKILL.md`](https://github.com/agegr/pi-web/blob/main/SKILL.md) file within `./.agents/`.

After the CLI completes successfully, pi-web calls **`DefaultResourceLoader.reload()`** to refresh the resource loader. This ensures the newly installed skill appears immediately in the user interface without requiring a page refresh.

### Installation API Endpoint

The entry point for skill installation is the **`POST /api/skills/install`** route, implemented in [`app/api/skills/install/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/skills/install/route.ts). This endpoint receives the package identifier and orchestrates the npx execution chain through [`lib/npx.ts`](https://github.com/agegr/pi-web/blob/main/lib/npx.ts).

## Controlling Model Invocation

Beyond installation, pi-web provides granular control over whether a skill can invoke language models through a simple configuration toggle.

### The disable-model-invocation Flag

Model invocation is governed by a YAML front-matter key inside each skill's markdown file:

```yaml
disable-model-invocation: true

```

When this flag is present and set to `true`, the backend logic in **[`lib/skill-lock.ts`](https://github.com/agegr/pi-web/blob/main/lib/skill-lock.ts)** intercepts skill execution and strips model-related prompts before sending requests to the LLM. This effectively prevents the skill from consuming model resources while keeping the skill itself installed and functional for other operations.

### Toggling via PATCH Requests

The UI modifies this flag through the skills API at **`PATCH /api/skills/[skillId]`**, handled by `app/api/skills/[id]/route.ts`. The system updates the [`SKILL.md`](https://github.com/agegr/pi-web/blob/main/SKILL.md) front-matter and relies on **`loadSkillsWithInstallInfo()`** from [`lib/skills-service.ts`](https://github.com/agegr/pi-web/blob/main/lib/skills-service.ts) to reread the file and reflect the updated configuration state.

## Implementation Examples

The following snippets demonstrate how to interact with these systems programmatically.

### Installing a Skill

To install a skill such as `@example/hello-world`:

```javascript
await fetch('/api/skills/install', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ package: '@example/hello-world' })
});

```

### Disabling Model Invocation

To prevent a skill from calling the LLM:

```javascript
await fetch('/api/skills/hello-world', {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ disableModelInvocation: true })
});

```

### Re-enabling Model Access

To restore model invocation capabilities:

```javascript
await fetch('/api/skills/hello-world', {
  method: 'PATCH',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ disableModelInvocation: false })
});

```

## Key Source Files

Understanding these components requires familiarity with the specific files that handle skill lifecycle management:

- **[`lib/skills-service.ts`](https://github.com/agegr/pi-web/blob/main/lib/skills-service.ts)**: Contains `loadSkillsWithInstallInfo()`, which loads skills and annotates them with installation metadata.
- **[`lib/skill-lock.ts`](https://github.com/agegr/pi-web/blob/main/lib/skill-lock.ts)**: Manages the `disable-model-invocation` front-matter flag and synchronizes UI state with file system changes.
- **[`lib/npx.ts`](https://github.com/agegr/pi-web/blob/main/lib/npx.ts)**: Provides the `runNpx()` utility that executes npx commands for skill installation.
- **[`app/api/skills/install/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/skills/install/route.ts)**: The API route handling `POST` requests to install new skills.
- **`app/api/skills/[id]/route.ts`**: The API route handling `PATCH` requests to update skill configuration, including model invocation settings.

## Summary

- Pi-web installs skills via the `npx skills` CLI, writing [`SKILL.md`](https://github.com/agegr/pi-web/blob/main/SKILL.md) files to `./.agents/skills/` and refreshing the `DefaultResourceLoader` to update the UI.
- The `POST /api/skills/install` endpoint in [`app/api/skills/install/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/skills/install/route.ts) triggers installation through [`lib/npx.ts`](https://github.com/agegr/pi-web/blob/main/lib/npx.ts).
- Model invocation is controlled by the `disable-model-invocation` front-matter flag in skill markdown files.
- The `PATCH /api/skills/[skillId]` endpoint updates this flag, with [`lib/skill-lock.ts`](https://github.com/agegr/pi-web/blob/main/lib/skill-lock.ts) handling the file system operations and prompt stripping.
- Both workflows maintain state through [`SKILL.md`](https://github.com/agegr/pi-web/blob/main/SKILL.md) files and reflect changes immediately without page reloads.

## Frequently Asked Questions

### Where are skill files stored after installation?

After installation, pi-web writes skill definitions to [`SKILL.md`](https://github.com/agegr/pi-web/blob/main/SKILL.md) files within the `./.agents/skills/` directory of your project. These markdown files contain both the skill configuration in YAML front-matter and the operational logic or prompts in the body.

### Can I install skills without using the web interface?

Yes. You can call the `POST /api/skills/install` endpoint directly with the package name, or execute the underlying `npx skills add … --agent pi` command manually. However, using the API ensures that `DefaultResourceLoader.reload()` is called to refresh the UI state automatically.

### What happens when model invocation is disabled for a skill?

When `disable-model-invocation` is set to `true` in a skill's front-matter, [`lib/skill-lock.ts`](https://github.com/agegr/pi-web/blob/main/lib/skill-lock.ts) intercepts execution and strips all model-related prompts before they reach the LLM. The skill remains installed and can perform non-model operations, but it cannot consume language model tokens or generate AI responses.

### Is the skill installation persistent across sessions?

Yes. Because skills are written to the file system as [`SKILL.md`](https://github.com/agegr/pi-web/blob/main/SKILL.md) files in `./.agents/skills/`, they persist across application restarts and browser sessions. The `loadSkillsWithInstallInfo()` function in [`lib/skills-service.ts`](https://github.com/agegr/pi-web/blob/main/lib/skills-service.ts) reads these files on startup to reconstruct the available skill set.