# 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 49 built-in compilation targets, including GitHub Copilot, Claude Code, Cursor, Antigravity, Factory AI, and AGENTS.md-based platforms.

- Skill: `mrwogu/promptscript` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mrwogu/promptscript`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mrwogu/promptscript/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-10
- Page: https://skillmd.com/skills/mrwogu/promptscript

---


# 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.

Imported SKILL.md frontmatter is bounded: 256 KiB per document, 10,000 YAML nodes, 32 nesting
levels, 2,000 entries per mapping or sequence, and 64 KiB per string value. Documents over any
limit are rejected before their YAML values are converted.

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)
  }
}
```

Imported agent definitions are qualified by an aliased `@use`:

```
@use ./frontend-team as frontend
@use ./backend-team as backend
```

If both imports define `reviewer`, the resolved names are `frontend.reviewer` and
`backend.reviewer`. Unique unaliased imports keep their original names. Conflicting unaliased
definitions stop compilation with source and import diagnostics instead of silently overwriting
one another. Native targets map dots to hyphens, so `frontend.reviewer` becomes
`frontend-reviewer`.

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.
- **PS039 (`agent-namespaces`)**: validates qualified agent name segments and checks them against recorded import provenance.
- **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 explain <path>          # Explain source and composition provenance
prs explain <path> --format json # Machine-readable provenance history
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 diff --all --format json # Machine-readable diff report for CI
prs diff --format json --include-content # Include generated content in the report
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

49 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/\*/SKI

…(truncated)
