# Promptscript

> PromptScript language expert for reading, writing, modifying, and troubleshooting .prs files. Use when working with PromptScript syntax, creating or editing .prs files, adding blocks like @identity, @standards, @restrictions, @shortcuts, @skills, or @agents, configuring promptscript.yaml, resolving compilation errors, understanding inheritance (@inherit), composition (@use, @extend, @override), contextual @header metadata, or migrating AI instructions to PromptScript. Also use when asked about the 48 built-in compilation targets, including GitHub Copilot, Claude Code, Cursor, Antigravity, Factory AI, and AGENTS.md-based platforms.

- Skill: `mrwogu/promptscript-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mrwogu/promptscript-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mrwogu/promptscript-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: mrwogu (https://skillmd.com/u/mrwogu)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mrwogu/promptscript-2

---


# PromptScript Language Guide

PromptScript is a domain-specific language that compiles `.prs` files into native instruction formats for AI coding assistants (GitHub Copilot, Claude Code, Cursor, Antigravity, Factory AI, OpenCode, Gemini CLI). One source of truth, multiple outputs.

## File Structure

A `.prs` file contains ordered declarations. Syntax `1.5.0` applies `@inherit`,
`@use`, local blocks, `@extend`, and `@override` in source order. Put `@meta`
first.

```
# Comments start with #

@meta { ... }           # Required metadata
@inherit @path          # Single inheritance (optional)
@use @path [as alias]   # Imports/mixins (optional, multiple)

@identity { ... }       # AI persona
@context { ... }        # Project context
@standards { ... }      # Coding conventions
@restrictions { ... }   # Hard rules
@shortcuts { ... }      # Command aliases
@knowledge { ... }      # Reference documentation
@skills { ... }         # Reusable skill definitions
@agents { ... }         # Subagent definitions
@workflows { ... }      # Repeatable agent procedures
@examples { ... }       # Few-shot input/output examples (syntax 1.2.0+)
@params { ... }         # Template parameters
@guards { ... }         # File globs and priorities
@hooks { ... }          # Portable lifecycle hooks (syntax 1.4.0+)
@mcpServers { ... }     # MCP server configurations (syntax 1.4.0+)
@plugins { ... }        # Capability bundles (syntax 1.4.0+)
@local { ... }          # Private config (not committed)
@extend path { ... }    # Modify imported blocks
@override path { ... }  # Replace one complete existing target (syntax 1.5.0+)
@custom-name { ... }    # Arbitrary named blocks
```

Contextual `@header` entries appear inside supported owner blocks, not at the
top level.

## Content Types

PromptScript has four canonical content shapes inside blocks:

### Text Content

Use triple quotes (three double-quote characters) to wrap multiline text.
Text is automatically dedented - leading whitespace from source indentation is stripped.
Use for prose, markdown, or freeform content.

Example: `@identity` with a text block describing an AI persona starting with "You are..."

### Object Content (key-value pairs)

```
@context {
  project: "My App"
  team: "Frontend"
  monorepo: {
    tool: "Nx"
    packageManager: "pnpm"
  }
}
```

Values can be strings (quoted or unquoted), numbers, booleans, nested objects, or arrays.

### Array Content

```
@standards {
  code: [
    "Use strict TypeScript",
    "Named exports only"
  ]
}

@restrictions {
  - "Never use any type"
  - "Never commit secrets"
}
```

### Mixed Content

Blocks can contain both object properties and text in the same block.
Place the triple-quoted text block alongside key-value pairs.

## Block Reference

### @meta (required)

```
@meta {
  id: "project-id"        # Required: unique identifier
  syntax: "1.0.0"         # Required: syntax version (semver)
  org: "Company Name"     # Optional
  team: "Frontend"        # Optional
  tags: [react, ts]       # Optional
  params: {               # Optional: template parameters
    projectName: string
    port: number = 3000
    debug?: boolean
    framework: enum("react", "vue") = "react"
  }
}
```

### @identity

Defines AI persona. Start with "You are..." for consistent output across all formatters.
Contains a triple-quoted text block with the persona description.

### @context

Project context with structured properties (project, team, languages, runtime)
plus optional triple-quoted text for architecture details, diagrams, etc.

### @standards

Category-based conventions. Any category name is valid:

```
@standards {
  typescript: ["Strict mode", "No any type"]
  naming: ["Files: kebab-case.ts", "Classes: PascalCase"]
  git: {
    format: "Conventional Commits"
    types: [feat, fix, docs, refactor, test, chore]
  }
}
```

Category names are arbitrary. `@standards` can also contain free-form text:

```
@standards {
  """
  ## Formatting
  Preserve heading structure and use four-space indentation.

  ## Testing
  Add regression coverage for every behavior change.
  """
  typescript: ["Strict mode", "Named exports only"]
  git: {
    format: "Conventional Commits"
  }
}
```

Free-form text is dedented and rendered with its Markdown heading structure. Factory
monolith output nests it under `Conventions & Patterns`; split Factory rules adjust
heading levels relative to the generated section. Custom structured categories remain
available to formatters that support them.

### @restrictions

Hard rules as a list of dash-prefixed strings:

```
@restrictions {
  - "Never expose API keys"
  - "Never commit secrets to version control"
  - "Always validate user input"
}
```

### @shortcuts

Simple strings appear as documentation. Objects with `prompt: true` generate
executable prompt/command files for GitHub Copilot and Cursor:

```
@shortcuts {
  "/review": "Review code for quality"
  "/test": {
    prompt: true
    description: "Write unit tests"
    content: (triple-quoted text with instructions)
  }
}
```

> `@commands` is a backwards-compatible alias for `@shortcuts` — prefer `@shortcuts` in new files.

### @skills

Reusable skill definitions with metadata:

```
@skills {
  commit: {
    description: "Create git commits"
    trigger: "commit, git commit"
    disableModelInvocation: true
    userInvocable: true
    allowedTools: ["Bash", "Read"]
    content: (triple-quoted text with skill instructions)
  }
}
```

Properties: description (required), content (required), trigger, disableModelInvocation,
userInvocable, allowedTools, context ("fork" or "inherit"), agent, requires, references, inputs, outputs.

The `references` property attaches external files to the skill's context:

```
@skills {
  architecture-review: {
    description: "Review architecture decisions"
    references: [
      ./references/architecture.md
      ./references/modules.md
    ]
    content: (triple-quoted text)
  }
}
```

Allowed file types: `.md`, `.json`, `.yaml`, `.yml`, `.txt`, `.csv`. Paths are resolved relative
to the `.prs` file. Formatters emit referenced files alongside SKILL.md in the output directory.

### Parameterized Skills

Skills in `.promptscript/skills/<name>/SKILL.md` support template parameters via
YAML frontmatter. Define `params` in frontmatter and use `{{variable}}` in content:

```yaml
---
name: review
description: 'Review {{language}} code for {{standard}}'
params:
  language:
    type: string
  standard:
    type: string
    default: 'best practices'
references:
  - references/architecture.md
---
Review the code using {{language}} conventions following {{standard}}.
```

The `references` field in SKILL.md frontmatter lists files to attach to the skill's context.
Paths are relative to the SKILL.md file.

Pass values in `@skills` block:

```
@skills {
  review: {
    description: "Review code"
    language: "typescript"
    standard: "strict mode"
  }
}
```

Non-reserved properties (anything other than description, content, trigger,
userInvocable, allowedTools, disableModelInvocation, context, agent, requires,
inputs, outputs) are treated as skill parameter arguments.

### Skill Dependencies

Skills can declare dependencies on other skills via `requires`:

```
@skills {
  deploy: {
    description: "Deploy service"
    requires: ["lint-check", "test-suite"]
    content: (triple-quoted text)
  }
}
```

The validator (PS016) checks that required skills exist, detects self-references,
and catches circular dependency chains.

### Skill Contracts (Inputs/Outputs)

Skills can declare typed inputs and outputs in SKILL.md frontmatter:

```yaml
---
name: security-scan
description: 'Scan for vulnerabilities'
inputs:
  files:
    description: 'Files to scan'
    type: string
  severity:
    description: 'Minimum severity'
    type: enum
    options: [low, medium, high]
    default: medium
outputs:
  report:
    description: 'Scan report'
    type: string
  passed:
    description: 'Whether scan passed'
    type: boolean
---
```

Field types: `string`, `number`, `boolean`, `enum` (with `options` list).
The validator (PS017) checks field types, ensures enum fields have options,
and warns if param names collide with input names.

### Shared Resources

Skills in a folder can share common resources via `.promptscript/shared/`:

```
.promptscript/
  shared/
    templates.md         # Shared across all skills
    style-guide.md
  skills/
    review/
      SKILL.md           # Gets @shared/templates.md, @shared/style-guide.md
    deploy/
      SKILL.md           # Also gets shared resources
```

Files in `shared/` are automatically included in every skill with `@shared/` prefix.

### @agents

Custom subagent definitions. Compiles to `.claude/agents/` for Claude Code,
`.github/agents/` for GitHub Copilot, `.factory/droids/` for Factory AI, etc.

```
@agents {
  code-reviewer: {
    description: "Reviews code quality"
    tools: ["Read", "Grep", "Glob", "Bash"]
    model: "sonnet"
    permissionMode: "default"
    content: (triple-quoted text with agent instructions)
  }
}
```

Supports mixed models per agent: `specModel` sets a different model for
Specification/planning mode (GitHub, Factory), `specReasoningEffort` sets reasoning
effort for the spec model (Factory only, values: "low", "medium", "high").

Factory AI droids support additional properties: `model` (any model ID or "inherit"),
`reasoningEffort` ("low", "medium", "high"), and `tools` (category name like "read-only"
or array of tool IDs).

### @workflows

Repeatable multi-step agent procedures. Requires syntax `1.1.0`.

```
@workflows {
  release: {
    description: "Prepare a validated release"
    content: """
      1. Run formatting, linting, type checks, and tests.
      2. Validate compiled output.
      3. Stop before publishing and request approval.
    """
  }
}
```

Targets with native workflow discovery emit dedicated workflow files. Other targets
retain workflow instructions in their main output when supported.

### @examples

Structured few-shot examples for AI assistants (requires syntax `1.2.0`):

```
@meta {
  id: "commit-style"
  syntax: "1.2.0"
}

@examples {
  feat-commit: {
    description: "Feature commit with scope"
    input: "Added user authentication with JWT tokens"
    output: "feat(auth): add JWT-based user authentication"
  }
}
```

Each entry is a named example with `input` and `output` (both required),
plus optional `description`. Multi-line content uses triple-quoted strings.

Examples can also be attached to skills via the `examples` property:

```
@skills {
  commit: {
    description: "Create conventional commits"
    examples: {
      basic: {
        input: "Added dark mode toggle"
        output: "feat(settings): add dark mode toggle"
      }
    }
    content: (triple-quoted text)
  }
}
```

### @knowledge

Reference documentation as triple-quoted text. Used for command references,
API docs, and other material that should appear in the output.

### @params

Template parameter definitions with types: string, number, boolean, enum("a", "b").
Optional parameters use `?` suffix. Defaults use `= value`.

### @guards

File glob patterns and priority rules for path-specific instructions.

### @hooks

Portable lifecycle hooks. Requires syntax `1.4.0`. Each hook needs exactly one of
`command` or `script`.

```
@hooks {
  validate-types: {
    event: "post-tool-use"
    matcher: "Edit|Write"
    script: {
      path: ".promptscript/scripts/validate.py"
      interpreter: "python3"
      args: ["--strict"]
    }
    cwd: "project"
    timeoutMs: 120000
    statusMessage: "Checking TypeScript"
    continueOnFailure: false
    enabled: true
    targets: {
      factory: { matcher: "Execute" }
      vscode: { matcher: "run_in_terminal" }
      github: { enabled: false }
    }
  }
}
```

Portable events:

| Event                  | Meaning                   |
| ---------------------- | ------------------------- |
| `pre-terminal-command` | Before a terminal command |
| `pre-tool-use`         | Before a tool invocation  |
| `post-tool-use`        | After a tool invocation   |
| `session-start`        | Agent session start       |
| `setup`                | Session setup             |
| `subagent-start`       | Subagent start            |
| `notification`         | Agent notification        |
| `stop`                 | Agent stop                |

`command` is a non-empty string array. Shell interpolation (`$()`, backticks,
`${...}`) is forbidden. `script` requires:

- `path` under `.promptscript/scripts/`, using forward slashes.
- Existing regular file at compile time.
- No traversal, absolute path, invalid segment, or symlink escape.
- Explicit interpreter: `python3`, `python`, `node`, `deno`, `bun`, `ruby`, `php`,
  `perl`, `bash`, `sh`, `zsh`, `pwsh`, or `powershell`.
- Optional `args` string array; each argument remains one argument.

`cwd: "project"` runs from project root. Other values are portable forward-slash
paths relative to project root. Hook config file location does not set command cwd.
Environment-root and Git-root wrappers exit before script or command execution when
the required root is unavailable. Native-cwd and workspace-cwd targets retain host
cwd fields and report `PS4002` when PromptScript cannot verify that cwd.
`timeoutMs` range is 100-600000. `matcher` uses target-native tool names, so a
matcher valid for one target may match nothing on another.

`pre-terminal-command` supplies native defaults: Factory `Execute`, Claude and
Codex `Bash`, Windsurf `pre_run_command`, Cursor `run_terminal_cmd`, Gemini
`run_shell_command`, and VS Code `run_in_terminal`. Override a native tool name
with `targets.<name>.matcher`. Cursor, Gemini, and VS Code report best-effort
`PS4002` warnings. GitHub and Grok omit the event with `PS4002`.

Target overrides may change `event`, `matcher`, `timeoutMs`, `statusMessage`,
`continueOnFailure`, `enabled`, or `cwd`. Native hook files are emitted only in
target modes that support additional files:

| Target         | Hook output                                                            | Mode                |
| -------------- | ---------------------------------------------------------------------- | ------------------- |
| Claude Code    | `.claude/settings.json`                                                | `full`              |
| Factory AI     | `.factory/hooks.json`                                                  | `multifile`, `full` |
| GitHub Copilot | `.github/hooks/promptscript.json`                                      | `multifile`, `full` |
| Cursor         | `.cursor/hooks.json`                                                   | `full`              |
| Codex          | `.codex/hooks.json`                                                    | `multifile`, `full` |
| Gemini CLI     | `.gemini/settings.json`                                                | `multifile`, `full` |
| Windsurf       | `.windsurf/hooks.json`                                                 | `multifile`, `full` |
| Grok Build     | `.grok/hooks/promptscript.json`                                        | `full`              |
| VS Code Agent  | `.github/hooks/promptscript-vscode.json` when `vscode` override exists | target-specific     |

Simple mode and targets without native project hooks report `PS4002` instead of
silently dropping hooks. Use `prs compile --watch` as fallback. Plugin-only and
agent-scoped integrations are not emitted as universal project hooks.

Each generated command carries a PromptScript ownership marker. CLI cleanup removes
only marked entries and preserves user hooks/settings. Removing `@hooks` removes a
fully owned generated hook file and prunes directories left empty. `prs hooks install factory`
migrates unambiguous legacy hooks from `.factory/settings.json`; ambiguous
entries remain for manual review.

Factory compilation performs the same migration when `.factory/hooks.json` is
absent. Use `prs compile --dry-run` to preview the changes or
`--no-migrate-factory-hooks` to keep warning-only behavior. Unknown events,
malformed entries, and mixed ownership abort without a partial migration.

`@hooks` compilation is separate from `prs hooks install`. The latter installs
auto-compilation and generated-output protection for supported AI tools. Copilot VS
Code Agent hooks use `promptscript-vscode.json`; GitHub Copilot repository hooks use
`promptscript.json`.

### @mcpServers

Project-local Model Context Protocol servers. Requires syntax `1.4.0`.

```
@mcpServers {
  issue-tracker: {
    transport: "stdio"
    command: ["node", "./tools/issues.mjs"]
    env: { LOG_LEVEL: "info" }
  }
}
```

Use `stdio` with `command`, or `http`/`sse` with `url`. Keep credentials out of
`.prs` files and provide them through target-native secret management.

### @plugins

Portable capability bundles. Requires syntax `1.4.0`.

```
@plugins {
  security-suite: {
    description: "Security review tooling"
    version: "1.0.0"
    skills: ["security-review"]
    hooks: ["validate-types"]
    mcpServers: ["issue-tracker"]
  }
}
```

### @local

Private local configuration. Not included in compiled output or committed to git.

## Inheritance and Composition

### @inherit (single, linear)

One per file. Child blocks merge on top of parent:

```
@inherit @company/frontend-team
@inherit ./parent
@inherit @stacks/react-app(projectName: "my-app", port: 3000)
```

### @use (multiple, mixins)

Import and merge fragments:

```
@use @core/security
@use @core/quality
@use ./local-config
@use @core/typescript as ts   # alias enables @extend access
```

#### URL imports (Go-module style)

Import directly from any Git repository by host path - no alias required:

```
@use github.com/acme/shared-standards/@fragments/security
@use gitlab.com/myorg/prompts/@stacks/python
```

Version pinning with `@`:

```
@use github.com/acme/shared-standards/@org/base@1.2.0    # exact version
@use github.com/acme/shared-standards/@org/base@^1.0.0   # semver range
@use github.com/acme/shared-standards/@org/base@main     # branch
```

#### Registry aliases

Short names for Git repository URLs, configured in `promptscript.yaml`:

```yaml
registries:
  company:
    url: github.com/acme/promptscript-registry
```

Then use the alias as scope prefix:

```
@use @company/security
@inherit @company/base-config
```

Merge rules:

- Text: concatenated with deduplication
- Objects: deep merged (imported source wins same-shape conflicts)
- Arrays: unique concatenation
- Shape mismatch: existing target body wins

Under syntax `1.5.0`, later local blocks, `@extend`, and `@override`
operations apply to the accumulated import result in declaration order.

### Block Filtering

Control which blocks are imported using the reserved `only` and `exclude` parameters:

```
@use ./shared-config(only: ["skills", "context"])
@use ./shared-config(exclude: ["knowledge"])
@use ./shared-config(exclude: ["knowledge"], mode: "strict")
```

Rules:

- `only` and `exclude` are mutually exclusive — using both is a validation error (PS021)
- Values are block type names: `identity`, `context`, `standards`, `knowledge`, `skills`, `shortcuts`, `agents`, etc.
- Block filtering does not apply to `@inherit` directives

### Markdown Imports

Import skills directly from `.md` files (v1.8+). No external tools needed:

```
@use ./skills/frontend-design.md
@use ./shared/commit.md as commit
@use github.com/anthropics/skills/commit@1.0.0
@use github.com/repo/skills/gitnexus         # directory → SKILL.md
```

Content detection: PromptScript blocks in `.md` are parsed as a `.prs` fragment;
YAML frontmatter with `name`/`description` is loaded as a skill definition;
otherwise content is treated as free-form knowledge.

CLI management:

```
prs skills add github.com/anthropics/skills/commit@1.0.0
prs skills remove commit
prs skills list
prs skills update
```

### @extend (modify existing or imported blocks)

Use a direct path for inherited or local blocks:

```
@extend standards.testing {
  coverage: 95
}
```

Use an alias when targeting a specific imported block:

```
@use @core/typescript as ts

@extend ts.standards {
  testing: { coverage: 95 }
}
```

#### Replacing regular block fields

Syntax `1.3.0` supports explicit replacement of complete regular block field values:

```
@meta { id: "project" syntax: "1.3.0" }

@inherit ./company-base

@extend standards {
  testing!: ["Use Vitest"]
  linting: ["Use ESLint"]
}
```

`testing!` replaces the inherited value. Fields without `!` keep normal merge behavior.
Replacement works after `@inherit` and `@use`, including aliases and nested target paths.
A missing field is set. The modifier is rejected for `@skills`, which retain their dedicated
merge and sealing semantics.

#### Replacing complete targets with @override

Syntax `1.5.0` adds atomic replacement for an existing block or nested value:

```
@meta { id: "project" syntax: "1.5.0" }

@standards {
  testing: ["Use Jest", "Use Mocha"]
}

@override standards.testing {
  ["Use Vitest"]
}
```

`@override` requires the complete target path to exist, applies in declaration
order, and cannot bypass sealed skill properties. Later `@extend` declarations
merge into the replacement. Use `@extend` for additive changes, `field!` for
compatibility replacement of one direct regular field, and `@override` for
intentional complete replacement.

#### Skill-aware @extend semantics

When extending a skill definition via `@extend`, individual skill properties follow specific merge
strategies rather than the generic block merge rules:

| Strategy          | Properties                                                                                                  |
| ----------------- | ----------------------------------------------------------------------------------------------------------- |
| **Replace**       | content, description, trigger, userInvocable, allowedTools, disableModelInvocation, context, agent, license |
| **Append**        | references, examples, requires                                                                              |
| **Shallow merge** | params, inputs, outputs                                                                                     |

Example — extending a base skill to add references and override content:

```
@use @company/skills as skills

@extend skills.code-review {
  content: (triple-quoted text with overridden instructions)
  references: [
    ./extra-context.md
  ]
}
```

The `references` array from the base skill and the overlay are combined (append). The `content`
field from the overlay replaces the base (replace).

#### Reference negation

Use `!` prefix in `@extend` to remove entries from a lower layer's append-strategy arrays:

```
@extend skills.code-review {
  references: [
    "!references/deprecated.md"
    "references/replacement.md"
  ]
}
```

Path matching is normalized (`"!./foo.md"` matches `"foo.md"`). Only works in `@extend` blocks
on `references` and `requires`. Validator PS028 warns about `!` in base definitions.

#### Overlay consistency warnings

The resolver emits warnings during compile when an overlay drifts from its base. Always shown
(not gated by `--verbose`):

- **Orphaned extend** — `@extend target "X" not found — overlay will be ignored.` Triggered when
  the targeted block doesn't exist (base removed or renamed).
- **Stale skill target** — `@extend creates new skill "X" — base does not define it.` Triggered
  when an `@extend` inside `@skills` would create a new skill instead of extending an existing one.
- **Negation orphan** — `Negation "!path" did not match any base entry — it may be stale.`
  Triggered when a `!entry` in references/requires doesn't match anything in the base.

These come from the resolver, not the validator (PS0XX rules). They appear during `prs compile`,
not `prs validate`.

#### Sealed properties

Prevent `@extend` from overriding specified replace-strategy properties:

```
@skills {
  deploy: {
    content: (triple-quoted text with critical workflow)
    sealed: ["content", "description"]
  }
}
```

`sealed: true` seals all replace-strategy properties. Attempting to override a sealed
property is a hard compilation error. Only the base skill author can set `sealed` —
overlays cannot add or modify it. Append-strategy properties remain extendable.
Validator PS029 warns about invalid entries in `sealed`.

#### Skill composition (inline @use)

Import sub-skills within a `@skills` block to compose multi-phase workflows:

```
@skills {
  ops: {
    description: "Production triage"
    content: (triple-quoted text with orchestrator instructions)
  }
  @use ./phases/health-scan
  @use ./phases/triage
  @use ./phases/code-fix as autofix
}
```

Each `@use` resolves the referenced `.prs` file, extracts its skill definition and context
blocks, and flattens them as numbered phase sections into the parent skill's content. The
`as alias` form controls the phase display name. Validator PS027 checks composition validity.

### Parameterized Inheritance (Template Variables)

Use `{{variable}}` placeholders in a **parent/template** file, and pass values
from the **child** file via `@inherit` or `@use` with `(key: value)` syntax.

**IMPORTANT:** Variables are NOT set from `promptscript.yaml` or CLI. They are
passed from one `.prs` file to another through `@inherit` or `@use`.

**Step 1: Create the template** (parent file with `params` in `@meta`):

```
# base.prs - reusable template
@meta {
  id: "service-template"
  syntax: "1.0.0"
  params: {
    serviceName: string
    port?: number = 3000
  }
}

@identity {
  """
  You are working on {{serviceName}} running on port {{port}}.
  """
}
```

**Step 2: Inherit with values** (child file passes params):

```
# project.prs - concrete project
@meta { id: "user-api" syntax: "1.0.0" }

@inherit ./base(serviceName: "user-api", port: 8080)
```

After compilation, `{{serviceName}}` becomes `user-api` and `{{port}}` becomes `8080`.

The same works with `@use`:

```
@use ./base(serviceName: "auth-service") as auth
```

**Parameter types:** `string`, `number`, `boolean`, `enum("a", "b")`.
Optional params use `?` suffix. Defaults use `= value`.
Missing required params produce a compile error.

**Multi-service pattern** - reuse one template across many projects:

```
services/
  base.prs                          # template with params
  user-api/
    promptscript.yaml               # source: project.prs
    project.prs                     # @inherit ../base(serviceName: "user-api")
  auth-service/
    promptscript.yaml
    project.prs                     # @inherit ../base(serviceName: "auth-service")
```

## Configuration: promptscript.yaml

### Auto-injection

This skill is automatically included when compiling with `prs compile`. No manual copying needed.
To disable, set `includePromptScriptSkill: false` in your `promptscript.yaml`.

```
id: my-project
syntax: "1.1.0"
description: "My project description"
input:
  entry: .promptscript/project.prs
  include: ['.promptscript/**/*.prs']
targets:
  github:
    version: full      # simple | multifile | full
  claude:
    version: full
  cursor:
    version: standard
  antigravity:
    version: frontmatter
  factory:
    version: full
  windsurf:             # 41 additional targets supported
    version: simple
  cline:
    version: simple
registry:
  git: https://github.com/org/registry.git
  ref: main
registries:
  company:
    url: github.com/acme/promptscript-registry
  oss:
    url: github.com/prscrpt/community-registry
    ref: v2
policies:
  - name: adjacent-layers-only
    kind: layer-boundary
    severity: error
    layers: ['@core', '@team', '@project']
    maxDistance: 1
```

### Lockfile: `promptscript.lock`

When remote imports are used, run `prs lock` to generate or update the lockfile
before compilation. It records the exact resolved commit for each dependency.
Integrity hashes (SHA-256) are included for registry references to detect
tampering or drift. This enables reproducible builds across machines and CI.
Commit `promptscript.lock` to version control.

Use `--ignore-hashes` on `prs compile` or `prs validate` to skip integrity
hash verification when needed.

### Policy Engine

Define organizational policies in `promptscript.yaml` to validate skill extensions:

```yaml
policies:
  - name: adjacent-layers-only
    kind: layer-boundary
    description: 'Only adjacent layers can extend each other'
    severity: error
    layers: ['@core', '@team', '@project']
    maxDistance: 1

  - name: protect-content
    kind: property-protection
    description: 'Content override requires explicit approval'
    severity: warning
    properties: ['content', 'description']

  - name: approved-registries
    kind: registry-allowlist
    description: 'Extensions must come from approved registries'
    severity: error
    allowed: ['@core', '@team']
```

Policy kinds: `layer-boundary` (controls layer distance), `property-protection`
(prevents overriding specific properties), `registry-allowlist` (restricts extension sources).
Severity: `error` (fails validation) or `warning` (reported only).
Skip with `--skip-policies` during development (never in CI).

## Syntax Version Validation

The `syntax` field in `@meta` declares the PromptScript language version (semver).

### Known Versions

| Version | What it adds                                                                                                            |
| ------- | ----------------------------------------------------------------------------------------------------------------------- |
| `1.0.0` | Core blocks (identity, context, standards, restrictions, knowledge, shortcuts, commands, guards, params, skills, local) |
| `1.1.0` | Adds `@agents` and `@workflows`; reserves internal `@prompts`                                                           |
| `1.2.0` | Adds `@examples` (few-shot input/output pairs)                                                                          |
| `1.3.0` | Adds explicit regular block field replacement in `@extend`                                                              |
| `1.4.0` | Adds `@hooks`, `@mcpServers`, and `@plugins`                                                                            |
| `1.5.0` | Adds `@header` section titles, `@override` replacement, and unquoted `${VAR}` values                                    |

### Block Version Requirements

| Block         | Minimum Syntax Version |
| ------------- | ---------------------- |
| `@agents`     | `1.1.0`                |
| `@workflows`  | `1.1.0`                |
| `@examples`   | `1.2.0`                |
| `@hooks`      | `1.4.0`                |
| `@mcpServers` | `1.4.0`                |
| `@plugins`    | `1.4.0`                |

All other built-in blocks are available from `1.0.0`.
Regular block field replacement with `field!: value` requires syntax `1.3.0`.
Generated section title overrides with `@header` require syntax `1.5.0`.
Atomic replacement with `@override` requires syntax `1.5.0`.
Unquoted `${VAR}` references as values require syntax `1.5.0`.

### Generated Section Headers

Use `@header` inside a registered owner block to rename human-readable output
sections without changing filenames, frontmatter, XML tags, or structured keys:

```promptscript
@meta { id: "localized" syntax: "1.5.0" }

@standards {
  @header "Coding Rules"
  @header git-commits "Commit Rules"
  code: ["Use strict TypeScript"]
}
```

- `@header "Title"` targets the block's primary section.
- `@header <section-key> "Title"` targets an owned derived section.
- Titles must be non-empty, single-line strings.
- Source overrides take precedence over formatter configuration and target defaults.
- Child inheritance, imported source, and the latest root extension take precedence.
- An initial `## Heading` in a registered text-only primary owner is a syntax
  `1.5.0` compatibility fallback. Explicit `@header` metadata wins.
- Ordinary `header` and `headers` fields remain domain data.

### Validation Rules

- **PS018 (`syntax-version-compat`)**: warns when resolved blocks or syntax features require a higher version than declared. Requirements from inheritance, imports, and skill composition are included. Suggestion: run `prs validate --fix`.
- **PS019 (`unknown-block-name`)**: warns when a block name is not a known PromptScript type, with fuzzy-match suggestions for typos.
- **PS037 (`valid-section-headers`)**: rejects invalid titles, unknown or unowned section keys, duplicate overrides, and nested extension overrides.
- **PS038 (`valid-block-shape`)**: rejects unsupported built-in block shapes and warns about formatter-sensitive legacy shapes or multiline shortcut scalars.
- **PS021 (`use-block-filter`)**: errors when `only` and `exclude` are both specified in `@use` parameters.
- **PS025 (`valid-skill-references`)**: errors when a `references` entry points to a file with a disallowed extension or a path that cannot be resolved.
- **PS026 (`safe-reference-content`)**: warns when a referenced file contains potentially sensitive content (e.g., secrets, credentials).
- **PS027 (`valid-skill-composition`)**: warns about conflicting phase names or excessive phases in composed skills.
- **PS028 (`valid-append-negation`)**: warns when negation prefix `!` appears in base skill definitions (only effective in `@extend`).
- **PS029 (`valid-sealed-property`)**: warns when `sealed` contains non-replace-strategy property names.
- **PS030 (`policy-compliance`)**: validates skill extensions against organizational policies defined in `promptscript.yaml`.
- **PS034 (`valid-hooks`)**: validates portable hook events, commands/scripts, paths, interpreters, timeouts, cwd, and target overrides.

Target formatters report **PS4002** when a hook event or field has no native equivalent,
when a target cannot guarantee project-root execution, or when output mode cannot emit
the additional hook file.

### Fixing Syntax Versions

```
prs validate --fix          # Auto-fix syntax versions in .prs files
prs upgrade                 # Upgrade all .prs files to the latest version
```

`--fix` rewrites the `syntax: "..."` line in each file's `@meta` block to match the minimum version required by resolved blocks and syntax features. It follows inheritance, imports, and skill composition. It only upgrades, never downgrades.

`prs upgrade` upgrades all files to the latest known syntax version regardless of what blocks they use.

## CLI Commands

```
prs init                    # Initialize project (auto-detects existing files)
prs init --yes --targets claude factory
prs init --dry-run          # Preview initialization
prs init --auto-import      # Initialize + static import of existing files
prs migrate                 # Interactive migration flow
prs migrate --static        # Non-interactive static import
prs migrate --llm           # Generate AI-assisted migration prompt
prs migrate --static --dry-run
prs compile                 # Compile to all targets
prs compile --watch         # Watch mode
prs compile --ignore-hashes # Skip integrity hash verification
prs build <name>            # Compile a named build profile
prs validate --strict       # Validate syntax
prs validate --fix          # Auto-fix syntax version declarations
prs validate --skip-policies # Skip policy engine evaluation
prs upgrade                 # Upgrade all .prs files to latest syntax version
prs import CLAUDE.md        # Import existing AI instructions
prs import CLAUDE.md --dry-run # Preview import conversion
prs inspect <skill>         # Show skill composition provenance
prs inspect <skill> --layers # Show layer-level breakdown
prs hooks install           # Install auto-compilation hooks for AI tools
prs hooks install claude    # Install hooks for a specific tool
prs hooks uninstall         # Remove installed auto-compilation hooks
prs hooks uninstall claude  # Remove hooks for a specific tool
prs skills add <source>     # Add a remote skill (@use + lock update + SKILL.md validation)
prs skills add <source> --strict          # Treat validation warnings as errors
prs skills add <source> --skip-validation # Bypass Agent Skills spec checks (not recommended)
prs skills remove <name>    # Remove a skill (@use line + lock entry)
prs skills list             # List all imported skills
prs skills update           # Re-resolve markdown-imported skills (re-validates + re-hashes)
prs pull                    # Update registry
prs diff --target claude    # Show compilation diff
prs lock                    # Generate/update promptscript.lock
prs lock --dry-run          # Preview lockfile changes
prs update                  # Re-resolve all remote imports to latest
prs update <url>            # Update a specific registry
prs vendor sync             # Copy cached deps to .promptscript/vendor/
prs vendor check            # Verify vendor matches lockfile
prs resolve @alias/path     # Debug: show how an import resolves
prs registry list           # Show configured registries and aliases
prs registry add <alias> <url>  # Add a registry alias
```

`prs init --yes` requires explicit, detected, or user-configured targets. It does not invent
default tools. For existing projects, `prs migrate` preserves `promptscript.yaml`, isolates static
output under `.promptscript/migrated/`, leaves source instructions untouched, and performs no
writes when no candidates are detected.

## Output Targets

48 supported targets. Key examples:

| Target      | Main File                       | Skills                                             |
| ----------- | ------------------------------- | -------------------------------------------------- |
| GitHub      | .github/copilot-instructions.md | .github/skills/\*/SKILL.md                         |
| Claude      | CLAUDE.md                       | .claude/skills/\*/SKILL.md                         |
| Cursor      | .cursor/rules/project.mdc       | .agents/skills/\*/SKILL.md                         |
| Antigravity | .agent/rules/project.md         | -                                                  |
| Factory     | AGENTS.md                       | .factory/skills/\*/SKILL.md, .factory/droids/\*.md |
| OpenCode    | OPENCODE.md                     | .opencode/skills/\*/SKILL.md                       |
| Gemini      | GEMINI.md                       | .agents/skills/\*/skill.md                         |
| Windsurf    | .windsurf/rules/project.md      | .windsurf/skills/\*/SKILL.md                       |
| Cline       | .clinerules                     | -                                                  |
| Roo Code    | .roorules                       | -                                                  |
| Codex       | AGENTS.md                       | .agents/skills/\*/SKILL.md                         |
| Continue    | .continue/rules/project.md      | -                                                  |
| + 36 more   |                                 | See full list in documentation                     |

### Formatter Documentation

For detailed information about each formatter's output paths, supported features, quirks, and example outputs:

- **Full formatter reference:** `docs/reference/formatters/` (7 dedicated pages + index of all 48)
- **llms-full.txt:** Available at the docs site root - contains all documentation in a single file for LLM consumption
- **Dedicated pages exist for:** Claude Code, GitHub Copilot, Cursor, Antigravity, Factory AI, Gemini CLI, OpenCode
- **All 48 formatters indexed at:** `docs/reference/formatters/index.md` with output paths, tier, and feature flags

### Auto-Compilation Hooks

Instead of running `prs compile --watch` manually, install hooks so your AI tool
triggers compilation automatically when you edit `.prs` files:

```
prs hooks install          # Auto-detect and install for all detected tools
prs hooks install claude   # Install for a specific tool
```

Hooks also protect generated file

…(truncated)
