# How to Create Custom PAI Skills with Predictable, Deterministic Results

> Learn to build custom PAI skills with predictable, deterministic results. Follow the canonical skill structure and use CLI-first tools for consistent, reliable outputs.

- Repository: [Daniel Miessler 🛡️/Personal_AI_Infrastructure](https://github.com/danielmiessler/personal_ai_infrastructure)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Create custom PAI skills that produce identical outputs for identical inputs by adhering to the canonical skill structure, implementing CLI-first deterministic tools, and validating against the Skill System specifications.**

Personal AI Infrastructure (PAI) treats **skills** as the primary building blocks that the assistant routes to. When you create custom PAI skills with predictable, deterministic results, you ensure that every invocation—whether adding a recipe, querying a database, or formatting data—behaves exactly the same way given the same inputs. This reliability stems from PAI's CLI-first architecture and strict canonical structure defined in [`SKILLSYSTEM.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILLSYSTEM.md).

## Understanding the Deterministic Skill Architecture

PAI enforces determinism through five core architectural layers. Each layer removes ambiguity and hidden state, ensuring that custom skills behave as pure functions.

| Component | Role | Determinism Mechanism |
|-----------|------|----------------------|
| **Skill System** – [`SKILLSYSTEM.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILLSYSTEM.md) | Defines the required folder layout, naming conventions, and the mandatory `USE WHEN` clause that drives intent-based routing. | Enforces a flat, predictable directory hierarchy and a single-line description that Claude Code can parse reliably. |
| **CreateSkill** – [`CreateSkill/SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/CreateSkill/SKILL.md) | A built-in skill that scaffolds new skills, validates them against the system rules, and canonicalizes existing ones. | Guarantees that every custom skill starts from a known, deterministic template. |
| **CLI-First Architecture** – [`CLIFIRSTARCHITECTURE.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/CLIFIRSTARCHITECTURE.md) | All heavy-lifting is done by small, reusable command-line tools written in TypeScript (or Bash). | CLI tools run with explicit flags; no hidden randomness, so the same input always yields the same output. |
| **Dynamic Loading Pattern** – [`SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILL.md) (per-skill) | Keeps the top-level [`SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILL.md) tiny (30-50 lines) and loads additional context files only when a workflow asks for them. | Minimises token consumption and avoids nondeterministic model responses when the full documentation isn't needed. |
| **Voice/Notification System** – [`THENOTIFICATIONSYSTEM.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/THENOTIFICATIONSYSTEM.md) | Sends a deterministic curl-based voice cue before any workflow runs. | Guarantees consistent side-effects (audible cue) without reliance on AI-generated text. |

Together these layers ensure that a **custom skill** matches a stable intent pattern, executes a well-defined workflow that calls a deterministic CLI tool with explicit flags, and produces the same output for the same input because the tool's logic is pure and version-controlled.

## Step-by-Step Guide to Building Deterministic Custom PAI Skills

Follow this canonical workflow to create custom PAI skills that yield predictable, deterministic results every time.

### 1. Scaffold the Skill Using CreateSkill

Run the built-in `CreateSkill` workflow to generate the deterministic template:

```bash
bun ~/.claude/skills/CreateSkill/Workflows/CreateSkill.md

```

This creates a new directory under `~/.claude/skills/YourSkill/` with the correct layout:

- [`SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILL.md) (frontmatter + routing table)
- `Workflows/` (TitleCase `.md` files)
- `Tools/` (TitleCase `.ts` scripts)
- Any additional context files (e.g., [`Aesthetic.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/Aesthetic.md)) placed directly in the skill root

### 2. Enforce TitleCase Naming

Choose a TitleCase name for the skill and all files (e.g., `RecipeManager`). The [`SKILLSYSTEM.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILLSYSTEM.md) explicitly forbids lowercase, kebab-case, or snake_case variants to ensure deterministic file-system lookups.

### 3. Define the USE WHEN Clause

Write a single-line description with an embedded `USE WHEN` clause in the YAML frontmatter of [`SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILL.md):

```yaml
---
name: RecipeManager
description: Manage personal recipes. USE WHEN user asks to add, list, or modify a recipe.
---

```

This clause is parsed by Claude Code at start-up, guaranteeing deterministic activation based on literal string matching rather than probabilistic inference.

### 4. Create the Workflow Routing Table

Add a `## Workflow Routing` table inside [`SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILL.md) to map intent phrases to specific workflow files:

```markdown

## Workflow Routing

| Workflow | Trigger | File |
|----------|---------|------|
| **Add**  | "add a recipe", "new recipe" | `Workflows/Add.md` |
| **List** | "list my recipes", "show recipes" | `Workflows/List.md` |
| **Edit** | "edit recipe", "update recipe" | `Workflows/Edit.md` |

```

### 5. Implement Deterministic CLI Tools

Create TypeScript tools in `Tools/` that expose explicit flags and avoid hidden state. Every tool must:

- Be a TypeScript file ([`ToolName.ts`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/ToolName.ts)) with a shebang `#!/usr/bin/env bun`
- Expose explicit flags (`--name`, `--ingredients`, `--json`, `--dry-run`)
- Have a help file ([`ToolName.help.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/ToolName.help.md))
- Avoid random number generation unless a seed is provided

### 6. Reference Tools from Workflows

In each workflow file (e.g., [`Workflows/Add.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/Workflows/Add.md)), reference the deterministic tool with explicit arguments:

```markdown

## Add

1. **Voice notification** – (automatically inserted by the system).
2. **Parse user request** – extract `name` and `ingredients`.
3. **Run the deterministic tool**:
   ```bash
   bun Tools/SaveRecipe.ts --name "{{name}}" --ingredients "{{ingredients}}"
   ```

4. **Confirm success** – output a fixed confirmation message.

```

### 7. Add Required Examples Section

Include an `## Examples` section in [`SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILL.md) with two-to-three concrete prompts. This helps Claude Code match the intent and keeps the skill's behavior stable:

```markdown

## Examples

**Example 1 – Add a recipe**  

```

User: "Add a new recipe for chocolate chip cookies with flour, sugar, butter, chocolate chips"
→ Invokes Add workflow
→ Saves JSON entry
→ Responds "✅ Saved recipe "Chocolate Chip Cookies""

```

```

### 8. Validate the Skill

Run the `ValidateSkill` workflow to ensure deterministic compliance:

```bash
bun ~/.claude/skills/CreateSkill/Workflows/ValidateSkill.md \
    --skill RecipeManager

```

This checks TitleCase naming, presence of `USE WHEN`, flat folder depth ≤ 2 levels, and absence of stray `Context/` or `Docs/` subfolders.

## Code Example: Building a Deterministic Recipe Manager Skill

Here is a complete, runnable example demonstrating how to create custom PAI skills with predictable, deterministic results.

### The SKILL.md Configuration

```markdown
---
name: RecipeManager
description: Manage personal recipes. USE WHEN user asks to add, list, or modify a recipe.
---

# RecipeManager

## Workflow Routing

| Workflow | Trigger | File |
|----------|---------|------|
| **Add**  | "add a recipe", "new recipe" | `Workflows/Add.md` |
| **List** | "list my recipes", "show recipes" | `Workflows/List.md` |

## Examples

**Example 1 – Add a recipe**  

```

User: "Add a new recipe for banana bread with flour, bananas, sugar"
→ Invokes Add workflow → Saves JSON entry → Responds "✅ Saved recipe "Banana Bread""

```

```

### The Deterministic CLI Tool

Create [`Tools/SaveRecipe.ts`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/Tools/SaveRecipe.ts):

```typescript
#!/usr/bin/env bun
import { readFileSync, writeFileSync } from "fs";
import { resolve } from "path";

const args = process.argv.slice(2);
const nameIdx = args.indexOf("--name");
const ingIdx = args.indexOf("--ingredients");
if (nameIdx === -1 || ingIdx === -1) {
  console.error("Usage: SaveRecipe.ts --name <title> --ingredients <comma‑list>");
  process.exit(1);
}
const name = args[nameIdx + 1];
const ingredients = args[ingIdx + 1].split(",");

const dbPath = resolve(process.env.HOME, ".claude/skills/RecipeManager/recipes.json");
let db: any[] = [];
try { db = JSON.parse(readFileSync(dbPath, "utf-8")); } catch (_) {}

db.push({ name, ingredients });
writeFileSync(dbPath, JSON.stringify(db, null, 2));
console.log(`✅ Saved recipe "${name}"`);

```

### The Workflow Implementation

Create [`Workflows/Add.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/Workflows/Add.md):

```markdown

## Add

1. **Voice notification** – (automatically inserted by the system).  
2. **Parse user request** – extract `name` and `ingredients`.  
3. **Run the deterministic tool**:  

   ```bash
   bun Tools/SaveRecipe.ts --name "{{name}}" --ingredients "{{ingredients}}"
   ```

4. **Confirm success** – the tool itself prints `✅ Saved recipe "<name>"`.

```

## Summary

To create custom PAI skills with predictable, deterministic results, follow these core principles:

- **Scaffold with CreateSkill**: Use `~/.claude/skills/CreateSkill/Workflows/CreateSkill.md` to generate a canonical, flat directory structure that enforces TitleCase naming.
- **Declare Intent Explicitly**: Include a single-line `USE WHEN` clause in the YAML frontmatter of [`SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILL.md) to enable literal string matching for routing.
- **Route Deterministically**: Define a `## Workflow Routing` table that maps specific trigger phrases to explicit workflow files.

- **Build CLI-First Tools**: Implement all business logic in TypeScript CLI tools with explicit flags, pure functions, and no hidden state, stored in `Tools/`.
- **Validate Before Deploying**: Run `ValidateSkill` to check compliance with [`SKILLSYSTEM.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILLSYSTEM.md) rules, ensuring flat hierarchy and required sections.

## Frequently Asked Questions

### What makes a PAI skill deterministic rather than probabilistic?

A PAI skill is deterministic when it uses literal string matching via the `USE WHEN` clause for intent routing, executes pure CLI tools with explicit flags rather than AI-generated code, and stores state in version-controlled files rather than model context. According to the [`CLIFIRSTARCHITECTURE.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/CLIFIRSTARCHITECTURE.md) specification, deterministic skills avoid hidden randomness by delegating all operations to small, reusable command-line tools written in TypeScript or Bash.

### Why must skill names and files use TitleCase?

TitleCase naming is enforced by [`SKILLSYSTEM.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILLSYSTEM.md) to ensure deterministic file-system lookups and prevent routing ambiguity. The flat directory structure requires exactly one predictable path pattern (`~/.claude/skills/SkillName/`), and TitleCase eliminates collisions that could occur with lowercase or kebab-case variants. This convention allows the `CreateSkill` validator to confirm skill integrity with a single file-system scan.

### How does the `USE WHEN` clause ensure predictable activation?

The `USE WHEN` clause in the YAML frontmatter of [`SKILL.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILL.md) provides a literal string pattern that Claude Code parses at startup. When a user query contains the exact phrases defined in `USE WHEN`, the skill activates deterministically without requiring probabilistic model inference. This mechanism, documented in [`SKILLSYSTEM.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILLSYSTEM.md), guarantees that the same user prompt will always trigger the same skill workflow, eliminating non-deterministic routing variations.

### What validation steps confirm a skill will produce deterministic results?

The `ValidateSkill` workflow performs five critical checks defined in [`SKILLSYSTEM.md`](https://github.com/danielmiessler/Personal_AI_Infrastructure/blob/main/SKILLSYSTEM.md): it verifies TitleCase naming for all files and directories, confirms the presence of a single-line `USE WHEN` clause in the frontmatter, ensures folder depth never exceeds two levels, checks for prohibited subdirectories like `Context/` or `Docs/`, and validates that all workflow files are referenced in the `## Workflow Routing` table. Passing these checks ensures the skill adheres to the deterministic CLI-first architecture.