# How to Define Custom Model Scopes Using Minimatch in Pi Web

> Learn how to define custom model scopes in Pi Web using minimatch glob patterns to filter available language models by provider and modelId. Enhance your session control.

- Repository: [Alex Yang/pi-web](https://github.com/agegr/pi-web)
- Tags: how-to-guide
- Published: 2026-08-10

---

**Pi Web uses minimatch glob patterns in [`lib/model-scope.ts`](https://github.com/agegr/pi-web/blob/main/lib/model-scope.ts) to filter which language models are available to a session by matching against `provider/modelId` strings.**

The `agegr/pi-web` repository implements a flexible model scoping system that lets you control exactly which AI models appear in your sessions. By leveraging the **minimatch** pattern matching library—the same engine powering the Pi SDK's `--models` CLI flag—you can define precise inclusion rules using wildcards, provider prefixes, and thinking-level suffixes.

## What Are Model Scopes in Pi Web?

A **model scope** is a list of glob patterns that Pi Web evaluates to determine which models should be visible to a specific session. When you define a custom scope, the server-side resolver filters the full catalog of available models, ensuring only matching providers and model IDs are presented in the UI.

Scopes support complex matching against the canonical `provider/modelId` format. For example, the pattern `anthropic/**` matches every Anthropic model in the catalog, while `openai/gpt-4*:medium` matches GPT-4 variants with a specific thinking level.

## How Model Scope Resolution Works

The resolution pipeline in [`lib/model-scope.ts`](https://github.com/agegr/pi-web/blob/main/lib/model-scope.ts) processes scope definitions through three distinct phases before rendering the final model list.

### Collecting Raw Scope Strings

Pi Web aggregates scope patterns from three sources in order of precedence:

1. **Global configuration** – The `~/.pi/agent/models.json` file persists your default scope across sessions and is editable via the Models modal.
2. **Session-specific overrides** – The `POST /api/agent/new` endpoint accepts a `modelScope` array in the request body for one-time filtering.
3. **Fallback defaults** – If no patterns resolve to valid models, the system defaults to exposing all discovered models.

### Resolving Glob Patterns

The `resolveModelScopeWithDiagnostics()` function delegates to the Pi SDK's resolver, which runs **minimatch** against each model's `provider/modelId` string. Pattern syntax includes:

- **Simple matches** – `"gpt-4"` matches exact model IDs.
- **Provider scoping** – `"anthropic/*"` limits matches to a specific provider.
- **Wildcards** – `*`, `?`, and `**` operators match groups (e.g., `"google/**"` matches all Google models).
- **Thinking levels** – Suffixes like `:low`, `:medium`, or `:high` pin the reasoning intensity for specific models.

### Applying the Filtered List

After resolution, the `scopedModels` array is stored in the `AgentSession` wrapper by [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) and transmitted to the frontend. The [`components/ModelsConfig.tsx`](https://github.com/agegr/pi-web/blob/main/components/ModelsConfig.tsx) component renders only these curated models, while malformed patterns trigger diagnostic warnings displayed in the Models modal.

## Defining Custom Model Scopes

You can configure scopes interactively through the UI or programmatically via the API.

### Via the Models Modal UI

The frontend provides a JSON editor for global scope configuration:

1. Click the **Models** button in the bottom-left sidebar to open [`components/ModelsConfig.tsx`](https://github.com/agegr/pi-web/blob/main/components/ModelsConfig.tsx).
2. Locate the `enabledModels` array and replace it with your minimatch patterns.
3. Save your changes – the UI sends a `PUT` request to [`app/api/models-config/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/models-config/route.ts), which writes to `~/.pi/agent/models.json` and triggers model rediscovery.

### Programmatically via API

For session-specific scoping, include a `modelScope` array when creating an agent session:

```json
{
  "cwd": "/home/user/project",
  "message": "Explain the code",
  "modelScope": ["openai/gpt-4*", "anthropic/**", "google/**:low"]
}

```

The backend merges this array with the persisted global scope before calling the resolver in [`lib/model-scope.ts`](https://github.com/agegr/pi-web/blob/main/lib/model-scope.ts).

## Minimatch Pattern Syntax Reference

Pi Web supports the full minimatch syntax for precise model selection:

- **Single wildcards** – `openai/gpt-4?` matches `gpt-4o` and `gpt-4t` but not `gpt-4-turbo`.
- **Star wildcards** – `openai/gpt-4*` matches all GPT-4 variants including prefixes.
- **Globstars** – `anthropic/**` matches all Anthropic models regardless of depth.
- **Thinking modifiers** – Append `:high`, `:medium`, or `:low` to set the reasoning level (e.g., `google/gemini-1.5-pro:high`).

## Practical Examples

### Example 1: Configuring Scope via the UI

Update your global configuration to enable only high-performance models:

```json
[
  "openai/gpt-4*",
  "anthropic/**",
  "google/**:low"
]

```

After saving in the Models modal, [`app/api/models-config/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/models-config/route.ts) persists this to `~/.pi/agent/models.json`.

### Example 2: API Request with Custom Scope

Create a session limited to specific OpenAI and Anthropic models:

```bash
curl -X POST https://your-pi-web.local/api/agent/new \
  -H "Content-Type: application/json" \
  -d '{
        "cwd": "/home/user/project",
        "message": "Summarize the repo",
        "modelScope": ["openai/gpt-4*", "anthropic/**"]
      }'

```

The server resolves these globs to concrete IDs like `["openai/gpt-4-1106-preview", "anthropic/claude-sonnet-3.5"]` using `resolveModelScopeWithDiagnostics()`.

### Example 3: Pinning Thinking Levels

Require maximum reasoning for specific models while allowing others to use defaults:

```json
{
  "modelScope": ["google/gemini-1.5-pro:high", "openai/gpt-4o", "anthropic/claude-3-opus:medium"]
}

```

The resolver parses the `:high` and `:medium` suffixes and stores the thinking level alongside the resolved model ID.

## Summary

- **Model scopes** in Pi Web are defined using **minimatch glob patterns** evaluated against `provider/modelId` strings.
- The resolution logic lives in [`lib/model-scope.ts`](https://github.com/agegr/pi-web/blob/main/lib/model-scope.ts), specifically the `resolveModelScopeWithDiagnostics()` function.
- Scopes can be set globally via `~/.pi/agent/models.json` (edited through [`components/ModelsConfig.tsx`](https://github.com/agegr/pi-web/blob/main/components/ModelsConfig.tsx)) or per-session via the `modelScope` parameter in `POST /api/agent/new`.
- Patterns support wildcards (`*`, `?`, `**`) and thinking-level suffixes (`:low`, `:medium`, `:high`).
- The `AgentSession` wrapper in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) stores the resolved list, which [`lib/model-discovery.ts`](https://github.com/agegr/pi-web/blob/main/lib/model-discovery.ts) uses to filter the available catalog.

## Frequently Asked Questions

### What file handles the minimatch resolution for model scopes?

The [`lib/model-scope.ts`](https://github.com/agegr/pi-web/blob/main/lib/model-scope.ts) file contains the core resolution logic. It exports `resolveModelScopeWithDiagnostics()`, which delegates to the Pi SDK's resolver to match glob patterns against the full model catalog.

### Can I combine multiple patterns in a single scope?

Yes. The `modelScope` field accepts an array of strings, and the resolver treats this as a union of patterns. For example, `["openai/gpt-4*", "anthropic/claude-*"]` includes any model matching either pattern.

### How do thinking level suffixes work with glob patterns?

When you append a thinking level like `:high` or `:low` to a pattern (e.g., `google/**:high`), the resolver matches the base pattern against model IDs and then applies the specified reasoning level to all matches. The suffix is parsed after the glob match succeeds.

### Where is the global models configuration stored?

Global scope settings are persisted in `~/.pi/agent/models.json` on the server. The [`app/api/models-config/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/models-config/route.ts) API route handles read and write operations for this file, while [`components/ModelsConfig.tsx`](https://github.com/agegr/pi-web/blob/main/components/ModelsConfig.tsx) provides the frontend editing interface.