Configuration
Complete reference for promptscript.yaml.
File Location
The CLI looks for configuration in this order:
--configcommand line optionPROMPTSCRIPT_CONFIGenvironment variablepromptscript.yamlin current directorypromptscript.ymlin current directory.promptscriptrc.yamlin current directory.promptscriptrc.ymlin current directory
Full Configuration
id: full-examplesyntax: '1.4.0'
# Anonymous aggregate usage telemetrytelemetry: true
# ===================# Input Configuration# ===================input: # Entry point file (required) entry: .promptscript/project.prs
# Additional files to include include: - '.promptscript/**/*.prs'
# Files to exclude exclude: - '**/node_modules/**' - '**/*.test.prs'
# ======================# Registry Configuration# ======================registry: # Local registry path path: ./registry
# Or remote HTTP registry URL # url: https://registry.example.com/promptscript
# Or Git repository (recommended for teams) # git: # url: https://github.com/org/promptscript-registry.git # fallbackUrl: [email protected]:org/promptscript-registry.git # SSH fallback # ref: main # branch, tag, or commit # path: registry/ # subdirectory in repo # auth: # type: token # or "ssh" # tokenEnvVar: GITHUB_TOKEN # env var with PAT
# Authentication for HTTP registries # auth: # type: bearer # tokenEnvVar: REGISTRY_TOKEN
# Cache settings cache: enabled: true ttl: 3600000 # milliseconds (1 hour)
# =====================# Target Configuration# =====================targets: # List format (matches prs init output) - github - claude - cursor - factory: version: multifile rulesMode: split
# =============================# Named Build Profiles# =============================builds: plugin-factory: # Optional entry override for this build only entry: .promptscript/project.prs
# Optional output directory for this build only output: plugins/logstrip
# Optional target list for this build only targets: - factory: version: multifile skillBaseDir: skills includeSkills: - logstrip
# =========================# Validation Configuration# =========================validation: # Require named guards to be present requiredGuards: - security
# Maximum recursion depth for guard dependencies guardRequiresDepth: 3
# Custom rules rules: empty-block: warning
# Scan imported (registry cache / vendored) content with # heuristic rules. Off by default. scanExternalContent: false
# Per-import rule exclusions bound to the lockfile commit. # excludes: # - import: github.com/org/repo # commit: <sha from promptscript.lock> # rules: [blocked-patterns, authority-injection]
# Pattern sources exempt from blocked-patterns detection. # allowedPatterns: # - 'bypass\s+(your\s+)?(rules|restrictions)'
# ===================# Model Configuration# ===================models: # Models the instructions are written and tested for (PS041) supported: - opus - gpt-5.3-codex
# Custom model profiles, or overrides of built-in profiles # profiles: # claude-opus-9: # provider: anthropic # family: claude-opus # version: '9' # displayName: Claude Opus 9
# ====================# Watch Configuration# ====================watch: # Files to watch include: - '.promptscript/**/*.prs' - 'registry/**/*.prs'
# Files to ignore exclude: - '**/node_modules/**' - '**/.git/**'
# Debounce delay (ms) debounce: 300
# Clear console on rebuild clearScreen: true
# =====================# Output Configuration# =====================output: # Base directory for all outputs baseDir: '.'
# File header comment header: | # Auto-generated by PromptScript # Do not edit manually
# Overwrite existing files overwrite: true
# =========================# Formatting Configuration# =========================formatting: # Auto-detect .prettierrc in project prettier: true
# Or specify explicit path to .prettierrc # prettier: "./config/.prettierrc"
# Or specify options directly # proseWrap: always # 'always' | 'never' | 'preserve' # tabWidth: 4 # Number of spaces per indent # printWidth: 100 # Max line width for prose wrapping
# =============================# Universal Directory & Skills# =============================
# Universal directory for auto-discovering skills and commands.# - true or omitted: Use default '.agents/' directory# - false: Disable universal directory discovery# - string: Custom path (relative to project root)universalDir: true # default: '.agents'
# Include the bundled PromptScript language skill in compilation output.# When enabled, a SKILL.md that teaches AI agents how to work with .prs# files is added when the formatter exposes a bundled-skill output path.includePromptScriptSkill: true # default: trueConfiguration Sections
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Project identifier |
syntax | string | Yes | PromptScript syntax version |
targets | TargetEntry[] | Yes* | Output targets and target-specific options |
description | string | No | Project description |
telemetry | boolean | No | Enable anonymous aggregate usage telemetry |
extends | string | No | Base configuration file to merge |
inherit | string | No | Registry configuration inherited by the project |
input | object | No | Entry point and source file globs |
registry | object | No | Default local, HTTP, or Git registry |
registries | object | No | Named Git registry aliases |
watch | object | No | Watch mode behavior |
output | object | No | Global output directory, header, and overwrite |
builds | object | No | Named build profiles |
skillTargets | Record<string,string> | No | Per-source skill output directories |
formatting | object | No | Markdown formatting settings |
customConventions | object | No | User-defined output conventions |
universalDir | string or boolean | No | Universal skills and commands directory |
includePromptScriptSkill | boolean | No | Include the bundled language skill |
validation | object | No | Guard and validation rule settings |
models | object | No | Supported model set and model profiles |
policies | array | No | Policies for skill extensions and prompts |
releases | object | No | Release environments for prompt bundles |
eval | object | No | Providers and limits of prs eval |
governance | object | No | Admins, approval roles and CODEOWNERS settings |
id and syntax are required even when input.entry uses its default.
* targets is required unless every target is declared inside a named build
profile. Such builds-only projects compile with prs compile --build <name> or
prs compile --all-builds; a bare prs compile fails with the list of available profiles because
there is no default target list to use.
See the Policy Engine guide for policies syntax.
telemetry
Anonymous aggregate usage telemetry is enabled by default. Set telemetry: false to disable every telemetry network request for this project:
telemetry: falseProject and user opt-outs are hard vetoes. Environment opt-in cannot override them. See Anonymous Usage Telemetry for collected fields, delivery behavior, and all opt-out controls.
input
Configures source file handling.
input: entry: .promptscript/project.prs include: - '.promptscript/**/*.prs' exclude: - '**/*.test.prs'| Field | Type | Default | Description |
|---|---|---|---|
entry | string | Required | Main entry point |
include | string[] | ["**/*.prs"] | Glob patterns to include |
exclude | string[] | [] | Glob patterns to exclude |
registry
Configures the inheritance registry. PromptScript supports three registry types:
- Local filesystem - for development or monorepos
- HTTP/HTTPS - for simple remote registries
- Git repository - recommended for teams (supports versioning via tags)
Local Registry
registry: path: ./registryHTTP Registry
registry: url: https://registry.example.com/promptscript auth: type: bearer tokenEnvVar: REGISTRY_TOKENGit Registry
registry: git: url: https://github.com/org/promptscript-registry.git ref: main path: registry/ auth: type: token tokenEnvVar: GITHUB_TOKEN cache: enabled: true ttl: 3600000Registry Fields:
| Field | Type | Default | Description |
|---|---|---|---|
path | string | - | Local registry path |
url | string | - | HTTP registry URL |
git.url | string | - | Git repository URL |
git.fallbackUrl | string | - | Fallback URL (tried on auth failure) |
git.ref | string | main | Branch, tag, or commit |
git.path | string | - | Subdirectory within the repo |
git.timeout | number | 60000 | Git operation timeout (ms) |
git.auth.type | string | - | Auth type: token or ssh |
git.auth.token | string | - | Personal access token (direct) |
git.auth.tokenEnvVar | string | - | Env var containing the token |
git.auth.sshKeyPath | string | - | Path to SSH key (for SSH auth) |
cache.enabled | boolean | true | Enable caching |
cache.ttl | number | 3600000 | Cache TTL in milliseconds |
Version-tagged imports
With Git registry, you can pin imports to specific versions using Git tags:
```@inherit @company/[email protected]@use @company/[email protected] as sec```
This checkouts the specified tag before fetching the file.registries
Defines short aliases for Git repository URLs. Aliases are used as scope prefixes in @use and @inherit paths, resolving to their full Git URL at compile time.
Simple Form
registries: '@company': github.com/acme/promptscript-base '@team': github.com/acme/team-frontend '@shared': gitlab.com/acme/shared-libsExtended Form
registries: '@company': url: github.com/acme/promptscript-base '@internal': root: packages/promptscriptExtended Form (with fallback URL)
When registry files reference HTTPS URLs but you authenticate via SSH (or vice
versa), set fallbackUrl so the clone is retried with the alternative URL
on auth failures:
registries: '@acme': url: https://github.com/acme/standards.git '@internal': url: https://gitlab.internal.com/team/monorepo.git root: packages/promptscriptAlias Fields:
| Field | Type | Description |
|---|---|---|
| (simple string) | string | Bare Git host path, e.g. github.com/org/repo |
url | string | Bare Git host path (extended form) |
fallbackUrl | string | Fallback Git URL (tried on auth failure) |
root | string | Base path within the repository |
timeout | number | Git operation timeout in ms (default 60000) |
Three-Level Merge
The registries field is resolved by merging three sources in priority order:
| Priority | Source | Scope |
|---|---|---|
| Highest | promptscript.yaml in project | Project-level |
| Middle | ~/.promptscript/config.yaml | User-level |
| Lowest | /etc/promptscript/config.yaml | System-level |
Project aliases override user aliases, which override system aliases. This allows IT to provision company-wide aliases (system level) while teams or projects can add or override specific aliases. On Windows the system file is %ProgramData%\promptscript\config.yaml.
User-Level Config (~/.promptscript/config.yaml)
version: '1'
registries: '@company': github.com/acme/promptscript-base '@shared': github.com/acme/shared-libs
registry: git: url: https://github.com/acme/promptscript-base.git auth: type: token tokenEnvVar: GITHUB_TOKENSetting aliases in user config makes them available in every project on the machine without adding
them to individual promptscript.yaml files. Alias entries do not contain credentials. Use
registry.git.auth, SSH configuration, or the Git credential helper for authentication.
Usage in .prs Files
Once aliases are configured, use them in any import path:
# Resolves @company to github.com/acme/promptscript-base@inherit @company/@org/base
# Versioned alias import@use @company/@stacks/react@^1.0.0targets
Configures output targets. Targets can be specified as a simple list of names or with detailed configuration.
List format (recommended, matches prs init output):
targets: - github - claude - cursorObject format (advanced, for custom options):
targets: - github: convention: xml output: custom/path/instructions.md - claude: convention: markdown - cursor: version: legacyAvailable Targets:
PromptScript ships 50 coding agent targets and two prompt targets. See Target Platforms for platform families and Supported Formatters for the full capability matrix.
| Target | Default Output | Default Convention | Supported Versions |
|---|---|---|---|
github | .github/copilot-instructions.md | markdown | simple / multifile / full |
claude | CLAUDE.md | markdown | simple / multifile / full |
cursor | .cursor/rules/project.mdc | markdown | modern / multifile / legacy / agents-md / full |
antigravity | .agent/rules/project.md | markdown | simple / frontmatter / agents-md |
factory | AGENTS.md | markdown | simple / multifile / full |
opencode | OPENCODE.md | markdown | simple / multifile / full |
gemini | GEMINI.md | markdown | simple / multifile / full |
codex | AGENTS.md | markdown | simple / multifile / full |
grok | AGENTS.md | markdown | simple / multifile / full |
windsurf | .windsurf/rules/project.md | markdown | simple / multifile / full |
cline | .clinerules | markdown | simple / multifile / full |
roo | .roorules | markdown | simple / multifile / full |
continue | .continue/rules/project.md | markdown | simple / multifile / full |
amp | AGENTS.md | markdown | simple / multifile / full |
augment | .augment/rules/project.md | markdown | simple / multifile / full |
goose | .goosehints | markdown | simple / multifile / full |
kilo | .kilocode/rules/project.md | markdown | simple / multifile / full |
trae | .trae/rules/project_rules.md | markdown | simple / multifile / full |
junie | .junie/guidelines.md | markdown | simple / multifile / full |
kiro | .kiro/steering/project.md | markdown | simple / multifile / full |
cortex | .cortex/rules/project.md | markdown | simple / multifile / full |
crush | AGENTS.md | markdown | simple / multifile / full |
command-code | .commandcode/rules/project.md | markdown | simple / multifile / full |
kode | .kode/rules/project.md | markdown | simple / multifile / full |
mcpjam | .mcpjam/rules/project.md | markdown | simple / multifile / full |
mistral-vibe | .vibe/rules/project.md | markdown | simple / multifile / full |
mux | .mux/rules/project.md | markdown | simple / multifile / full |
openhands | .openhands/rules/project.md | markdown | simple / multifile / full |
pi | .pi/rules/project.md | markdown | simple / multifile / full |
qoder | .qoder/rules/project.md | markdown | simple / multifile / full |
qwen-code | .qwen/rules/project.md | markdown | simple / multifile / full |
zencoder | .zencoder/rules/project.md | markdown | simple / multifile / full |
neovate | .neovate/rules/project.md | markdown | simple / multifile / full |
pochi | .pochi/rules/project.md | markdown | simple / multifile / full |
adal | .adal/rules/project.md | markdown | simple / multifile / full |
iflow | .iflow/rules/project.md | markdown | simple / multifile / full |
openclaw | INSTRUCTIONS.md | markdown | simple / multifile / full |
codebuddy | .codebuddy/rules/project.md | markdown | simple / multifile / full |
gitlab-duo | AGENTS.md | markdown | simple / multifile / full |
aider | AGENTS.md | markdown | simple / multifile / full |
amazon-q | AGENTS.md | markdown | simple / multifile / full |
warp | AGENTS.md | markdown | simple / multifile / full |
zed | AGENTS.md | markdown | simple / multifile / full |
jules | AGENTS.md | markdown | simple / multifile / full |
devin | AGENTS.md | markdown | simple / multifile / full |
kimi | AGENTS.md | markdown | simple / multifile / full |
mimo | AGENTS.md | markdown | simple / multifile / full |
deep-agents | AGENTS.md | markdown | simple / multifile / full |
forgecode | AGENTS.md | markdown | simple / multifile / full |
hermes | AGENTS.md | markdown | simple / multifile / full |
bundle | prompts/index.json | - | v1 |
prompt-text | prompts/README.md | - | v1 |
bundle and prompt-text compile @prompts entries for applications, not instructions for a
coding agent. They are opt-in: no default selection includes them, so name them in targets. A
target output moves the primary file, and the other files sit next to it. The target owns that
directory, so output must name one. They write nothing for a program without prompts and need
syntax 1.6.0. See Application Prompts.
MCP, Hooks, and Plugins Support
The @mcpServers, @hooks, and @plugins blocks (syntax 1.4.0+) are emitted to target-native config files. Not all targets support all features.
| Target | MCP Config File | Hooks Config | Plugins Config |
|---|---|---|---|
claude | .mcp.json | .claude/settings.json | - |
cursor | .cursor/mcp.json | .cursor/hooks.json | .cursor/plugins.json |
factory | .factory/mcp.json | .factory/hooks.json | .factory/plugins.json |
codex | .codex/mcp.json | .codex/hooks.json | .codex/plugins.json |
grok | .mcp.json (via Claude) | .grok/hooks/promptscript.json | .grok/plugins.json |
github | .vscode/mcp.json | .github/hooks/promptscript.json | - |
antigravity | .agents/mcp_config.json | - | - |
gemini | .gemini/mcp_config.json | .gemini/settings.json | - |
windsurf | .windsurf/mcp_config.json | .windsurf/hooks.json | - |
cline | .cline/cline_mcp_settings.json | - | - |
roo | .roo/mcp_settings.json | - | - |
continue | .continue/config.json | - | - |
goose | .goose/mcp_config.json | - | - |
kilo | .kilocode/mcp_settings.json | - | - |
openhands | .openhands/mcp_config.toml | - | - |
qwen-code | .qwen/mcp.json | - | - |
zed | .zed/settings.json | - | - |
crush | .crush/mcp.json | - | - |
Hook files are emitted in multifile and full target modes. simple keeps
its single-file contract and reports a compatibility warning when @hooks is
present.
MCP and plugin files depend on the mode too. github, claude, cursor, and
grok write MCP config only in full mode, antigravity in every mode, and the
other MCP targets in multifile and full. cursor and grok write plugin
config only in full mode, factory and codex in multifile and full. A
target or mode that cannot write @skills, @mcpServers, or @plugins reports
PS4002 instead of dropping the block silently.
Cursor Versions:
| Version | Output Files |
|---|---|
modern | .cursor/rules/project.mdc + .cursor/commands/*.md for multi-line shortcuts |
multifile | Main + .cursor/rules/*.mdc (glob-based) + .cursor/rules/shortcuts.mdc + .cursor/commands/*.md |
legacy | .cursorrules (deprecated, no slash commands) |
agents-md | AGENTS.md (Cursor 2.4+, no frontmatter required) |
full | Multifile + .agents/skills/<name>/SKILL.md + .cursor/agents/<name>.md (Cursor 2.5+) |
Cursor Slash Commands
Multi-line @shortcuts are automatically converted to executable slash commands in .cursor/commands/.
Type / in Cursor chat (1.6+) to invoke them. See Language Reference.
Cursor Identity Handling
The Cursor formatter handles @identity blocks intelligently:
- If the identity starts with "You are...", the **full content** is used as the intro- Otherwise, a generated intro like "You are working on {project}" is created- Multiline strings are automatically dedented to remove source indentation
This means your `@identity` content appears exactly as written (without extra indentation).Target Configuration:
Targets can be specified as simple names (list format) or with configuration (object format).
The list format is recommended for most projects and matches prs init output:
targets: # List format (recommended) - github - claude - cursor - antigravity
# Object format (for custom options) - github: convention: xml output: custom/path/instructions.md - claude: convention: markdown
# With version for format variants - cursor: version: legacy # Use .cursorrules for Cursor < 0.45 - antigravity: version: frontmatter # Use YAML frontmatter with activation types
# GitHub Copilot versions - github: version: simple # Single file - github: version: multifile # Main + path-specific instructions + prompts - github: version: full # Multifile + skills + AGENTS.md (default)
# Claude Code versions - claude: version: simple # Single CLAUDE.md - claude: version: multifile # Main + modular rules in .claude/rules/ - claude: version: full # Multifile + skills + CLAUDE.local.md (default)
# Factory AI versions and split always-on rules - factory: version: multifile rulesMode: split
# OpenCode versions - opencode: version: simple # Single OPENCODE.md - opencode: version: multifile # Main + commands - opencode: version: full # Multifile + skills + agents
# Gemini CLI versions - gemini: version: simple # Single GEMINI.md - gemini: version: multifile # Main + commands + skills - gemini: version: full # Same as multifile (no agent concept)GitHub Copilot Versions:
| Version | Output Files |
|---|---|
simple | .github/copilot-instructions.md (single file) |
multifile | Main + .github/instructions/*.instructions.md + .github/prompts/*.prompt.md |
full | Multifile + .github/skills/<name>/SKILL.md + AGENTS.md |
Claude Code Versions:
| Version | Output Files |
|---|---|
simple | CLAUDE.md (single file) |
multifile | Main + .claude/rules/*.md with path-specific rules (from @guards.globs) |
full | Multifile + .claude/skills/<name>/SKILL.md (from @skills) + CLAUDE.local.md (from @local) |
Factory AI Versions:
| Version | Output Files |
|---|---|
simple | AGENTS.md only |
multifile | AGENTS.md + commands + .factory/skills/<name>/SKILL.md |
full | Multifile output + .factory/droids/<name>.md |
Factory defaults to rulesMode: monolith, which preserves the existing
single-file rules content in AGENTS.md. Set rulesMode: split with
multifile or full to emit always-on files under .factory/rules/ and a
discoverability index in AGENTS.md. rulesMode: split with simple is an
error.
OpenCode Versions:
| Version | Output Files |
|---|---|
simple | OPENCODE.md (single file) |
multifile | Main + .opencode/commands/<name>.md |
full | Multifile + .opencode/skills/<name>/SKILL.md + .opencode/agents/<name>.md |
Gemini CLI Versions:
| Version | Output Files |
|---|---|
simple | GEMINI.md (single file) |
multifile | Main + .gemini/commands/<name>.toml + .agents/skills/<name>/skill.md |
full | Same as multifile (Gemini CLI has no agent concept) |
Target Options:
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Whether target is enabled |
output | string | (see above) | Custom output path, relative to the output directory |
convention | string | markdown | Output convention (xml or markdown) |
version | string | full | Format version (varies by target, see below) |
rulesMode | monolith or split | monolith | Factory always-on rule layout |
skillBaseDir | string | target-specific | Custom base directory for generated skill files |
includeSkills | boolean or string array | true | Emit all skills, no skills, or only listed skill names |
Output paths stay inside the output directory
A target output that resolves outside the output directory (../, or an
absolute path pointing elsewhere, including through a symlink) aborts the
compile before any file is written. Use --output or output.baseDir to
change where the whole build lands; a base directory outside the project is
allowed and reported as a warning.
Disabling Targets
Setting enabled: false skips the target during compilation.
This is equivalent to removing the target from the list.
```yamltargets: - github # Will compile - claude: enabled: false # Will NOT compile (skipped) - cursor # Will compile```See Formatters API for more details.
Building skills into plugin or library folders
Use skillBaseDir when you want a target to place generated skills outside
its default directory. For example, this writes Factory skills under
plugins/logstrip/skills when combined with a build profile output:
```yamlbuilds: logstrip-factory: output: plugins/logstrip targets: - factory: version: multifile skillBaseDir: skills includeSkills: - logstrip```
Run it with:
```bashprs compile --build logstrip-factory# orprs build logstrip-factory```Built-in Conventions:
| Convention | Section Format | Description |
|---|---|---|
markdown | ## Section Name | Markdown headers |
xml | <section-name>content</section-name> | XML tags wrapping content |
Target-Specific Options:
| Option | Targets | Type | Description |
|---|---|---|---|
maxThreads | codex | number | Max parallel agent threads (positive integer, maps to .codex/config.toml) |
maxDepth | codex | number | Max nesting depth for agent delegation (positive integer) |
agentsFile | codex | string | Override agents file name (default: AGENTS.md, scoped builds: AGENTS.override.md) |
agentsFrontmatter | AGENTS.md targets | string | experimental - emit AGENTS.md v1.1 YAML frontmatter (description, tags from @meta) |
autoMode | claude | string | Claude auto mode: acceptEdits, plan, bypassPermissions (maps to .claude/settings.json) |
Codex Native Output:
The codex target emits native Codex agent TOML files in addition to AGENTS.md:
AGENTS.md # Root instructions.codex/agents/<name>.toml # Agent definitions (TOML).codex/config.toml # Project config (maxThreads, maxDepth, agentsFile).codex/hooks.json # Project hooks.agents/skills/<name>/SKILL.md # Skills (interoperable path)Agent field mapping (PRS -> Codex TOML):
| PRS Field | Codex TOML Field |
|---|---|
content | developer_instructions |
reasoningEffort | model_reasoning_effort |
sandboxMode | sandbox_mode |
nicknameCandidates | nickname_candidates |
mcpServers | mcp_servers |
skills | skills.config |
customConventions
Define custom output conventions for specialized formatting needs.
id: custom-convention-examplesyntax: '1.4.0'
customConventions: my-format: name: my-format description: Custom Markdown headings and fenced code section: start: '### {{name}}' end: '' nameTransform: none indent: '' subsection: start: '#### {{name}}' end: '' nameTransform: none indent: '' listStyle: bullet codeBlockDelimiter: '~~~'
# Use custom convention in targettargets: - github: convention: my-formatCustom Convention Structure:
| Field | Type | Description |
|---|---|---|
name | string | Convention identifier |
description | string | Human-readable purpose |
section.start | string | Section opening template, supports {{name}} |
section.end | string | Optional section closing template |
section.nameTransform | string | kebab-case, camelCase, PascalCase, or none |
section.indent | string | Indentation per nesting level |
subsection | object | Optional subsection renderer |
listStyle | string | dash, asterisk, bullet, or numbered |
codeBlockDelimiter | string | Code fence delimiter |
rootWrapper | object | Optional start and end templates |
builds
Defines named build profiles for compiling a specific entry point to a specific set of targets and output directories. Build profiles are useful when one repository needs to generate extra artifacts for subpackages, plugins, or tool-specific distribution folders without changing the default project build.
builds: logstrip-factory: entry: .promptscript/project.prs output: plugins/logstrip targets: - factory: version: multifile skillBaseDir: skills includeSkills: - logstripRun a profile with either command:
prs compile --build logstrip-factoryprs build logstrip-factory
# Compile all named build profiles in deterministic orderprs compile --all-buildsA profile without its own targets key falls back to the top-level targets list. When a project
keeps every target inside profiles and omits top-level targets, a bare prs compile fails and
lists the available profiles instead of compiling nothing. Inspect profile output with
prs diff --build <name>.
Nested AGENTS.md via Build Profiles:
Build profiles with output directories produce scoped AGENTS.md files. This enables nested instruction files for monorepo packages:
builds: api: entry: .promptscript/packages/api.prs output: packages/api targets: - factory codex-api-override: entry: .promptscript/packages/api-override.prs output: packages/api targets: - codex: agentsFile: AGENTS.override.mdOutput paths are validated against project root - path traversal (..) is rejected. Codex-only AGENTS.override.md is supported via the agentsFile option.
Build Profile Fields:
| Field | Type | Default | Description |
|---|---|---|---|
entry | string | input.entry | Entry file to compile for this profile |
output | string | output.baseDir | Base output directory for this profile |
targets | TargetEntry[] | targets | Target list to compile for this profile |
CLI flags still take precedence: --target/--format override the profile’s
target list, and --output overrides the profile’s output.
validation
Configures validation behavior.
validation: requiredGuards: - security guardRequiresDepth: 3 rules: empty-block: warning scanExternalContent: false excludes: - import: github.com/cloudflare/skills commit: 1a2b3c4d5e6f7890abcdef1234567890abcdef12 rules: [blocked-patterns, authority-injection] allowedPatterns: - 'bypass\s+(your\s+)?(rules|restrictions)'| Field | Type | Default | Description |
|---|---|---|---|
requiredGuards | string[] | [] | Guards every resolved project must define |
rules | object | {} | Rule severity overrides |
guardRequiresDepth | number | 3 | Maximum guard dependency recursion depth |
scanExternalContent | boolean | false | Scan imported (registry cache / vendored) content with heuristic rules. Heuristic findings in third-party skills are skipped by default because the importing project cannot fix them; concrete security findings (decoded payloads, suspicious URLs) always scan. |
excludes | array | [] | Per-import rule exclusions bound to the lockfile. Each entry needs import (the import source, optionally with a sub-path), commit (the SHA pinned in promptscript.lock when the content was reviewed), and rules (rule names or IDs to skip). Excludes apply only to imported content, never to local project files, and overlapping or repeated entries union their rules. When the lockfile pins a different commit, the entry stops suppressing (the original findings reappear) and PS040 fails the build so the consumer re-reviews the new content. |
allowedPatterns | string[] | [] | Pattern sources exempt from blocked-patterns detection. A blocked pattern is subtracted from the active set when its source text matches an entry exactly; other patterns keep scanning. |
Consumed by blocked-patterns (PS005) and authority-injection (PS011), the
two heuristic text rules that always scan imported content. Excludes are
declared by the consumer, never by the scanned file: a disable comment inside
an imported skill cannot mute its own scan.
models
Configures the model catalog. PromptScript uses it to write the native model
name each target expects in agent and skill model fields, and to check model
references (PS041).
models: supported: - opus - claude-sonnet-5 - gpt-5.3-codex profiles: claude-opus-9: provider: anthropic family: claude-opus version: '9' displayName: Claude Opus 9 apiId: claude-opus-9 releaseDate: '2027-01-15' targets: github: Claude Opus 9 (Preview)| Field | Type | Default | Description |
|---|---|---|---|
supported | string[] | - | Model set the instructions are written and tested for. Entries are profile ids, aliases, API ids, display names, or floating aliases. When set, PS041 reports model references outside the set |
profiles | object | {} | Custom model profiles, or overrides of built-in profiles, keyed by profile id |
Model references
PromptScript ships a built-in catalog of Anthropic, OpenAI, Google, and xAI models. Each profile records the provider, family, version, display name, API id, lifecycle status, successor, and release and retirement dates. The Model Catalog lists every built-in profile.
A model or specModel value in @agents, and model in @skills, matches
a profile by id, alias, API id, or display name, ignoring case. Two kinds of
values are special:
inheritkeeps the model already selected in the tool.opus,sonnet,haiku, andfableare floating aliases. Each one points at the newest release of its Claude family that is not retired, listed in Floating Aliases.
Names that are not in the catalog, such as gateway model ids, BYOK model ids,
or Claude Code’s opusplan, are written unchanged on every target. The
exception is a value the target spells its own way: GitHub Copilot writes
auto as Auto.
Target model names
| Target | Written value | inherit | Providers |
|---|---|---|---|
| Claude Code, Grok Build | Floating aliases as written, other models as API id | Written | Anthropic |
| GitHub Copilot | Display name, such as Claude Sonnet 5 or GPT-5.3-Codex; auto is Auto | Omitted | All |
| Factory AI | API id | Written | All |
| Codex | API id | Omitted | OpenAI |
| Cursor | Profile id, which has no snapshot date, such as claude-sonnet-4-5 | Written | All |
The Model Catalog shows what each target writes for common values.
For older releases the API id is a dated snapshot, such as
claude-sonnet-4-5-20250929. GitHub Copilot and Factory AI map specModel
the same way, and Claude Code and Grok Build also map the model field of
skills. A model from a provider the target cannot run is omitted from that
target’s output and reported with a PS4004 warning during compilation. So is
a name with a line break or control character, whether it comes from the
source or from a profile. A per-target name in profiles.<id>.targets always wins, including for
providers the target would otherwise omit. Its keys are the target names from
the table (claude, grok, github, factory, codex, cursor), matched
without regard to case.
Model profiles
A profiles key that matches a built-in profile id changes only the fields it
sets. Its targets entries merge with the built-in ones, and every other field
it sets, including aliases, replaces the built-in value. Any other key adds a
custom profile, so a team can use a model before PromptScript ships it. Unset
fields of a custom profile default to the key (family, displayName, and
apiId), provider: custom, and status: current.
| Field | Description |
|---|---|
provider | Model provider, such as anthropic, openai, google, or xai |
family | Model line that groups versions, such as claude-opus |
version | Version inside the family, such as 5.5 |
displayName | Human-readable name, also the GitHub Copilot model name |
apiId | Provider API model id |
aliases | Additional names that resolve to the profile |
status | current, legacy (superseded but still served), deprecated (retirement announced), or retired |
successor | Profile id of the recommended replacement |
releaseDate | Release date in YYYY-MM-DD format |
retirementDate | Date the provider stops serving the model, in YYYY-MM-DD format |
targets | Native model name per target, such as github: Claude Opus 9 |
A custom profile that joins a Claude family with a higher version also moves
the floating alias. With the example above, opus resolves to Claude Opus 9,
so GitHub Copilot agents that use opus get Claude Opus 9 (Preview).
Model validation
PS041 (valid-model-reference) is a warning. It reports:
- references to
deprecatedorretiredmodels, with the replacement found through the successor chain - when
supportedis set: references outside the set, references that are not in the catalog, andsupportedentries that are not in the catalog - problems in
profiles: a name used by two profiles, a profile or alias named after a floating alias orinherit, a successor that is unknown or loops back, a date not inYYYY-MM-DDformat, and atargetskey for a target that does not write model names
legacy models are still served, so they pass. Without supported, names
that are not in the catalog are not reported, because tools accept many names
no catalog can list.
watch
Configures watch mode.
watch: include: - '.promptscript/**/*.prs' debounce: 300 clearScreen: true| Field | Type | Default | Description |
|---|---|---|---|
include | string[] | See default patterns below | Patterns to watch |
exclude | string[] | [] | Patterns to ignore |
debounce | number | 300 | Debounce delay (ms) |
clearScreen | boolean | true | Clear on rebuild |
Default include patterns:
**/*.prs.promptscript/**/*.agents/**/*registry/**/*promptscript.yamlpromptscript.yml.promptscriptrc.yaml.promptscriptrc.ymlpromptscript.lock
output
Configures global output behavior.
output: baseDir: '.' header: Managed by the platform team. overwrite: false resources: - agents - skills| Field | Type | Default | Description |
|---|---|---|---|
baseDir | string | . | Base directory for generated output |
header | string | - | Header added to Markdown after PromptScript metadata and frontmatter |
overwrite | boolean | false | Overwrite conflicting user files without prompting, like --force |
resources | string[] | - | Compile only these resource kinds (agents, skills, commands, mcp, hooks, plugins, main); prs compile --resources wins |
resources selects what a compile emits. A selection without main omits
root instruction files, so baseDir: '${HOME}' with resources: [agents, skills] installs only generated agent and skill directories into the global
root. Protected personal files such as ~/.factory/AGENTS.md are never
written, and resource-only runs skip managed cleanup.
formatting
Configures output formatting to match your project’s Prettier configuration.
formatting: # Option 1: Auto-detect .prettierrc in project prettier: true
# Option 2: Explicit path to Prettier config prettier: './config/.prettierrc'
# Option 3: Inline options (overrides .prettierrc) proseWrap: always tabWidth: 4 printWidth: 100Prettier Detection:
When prettier: true, PromptScript searches for Prettier configuration files in this order:
.prettierrc.prettierrc.json.prettierrc.yaml.prettierrc.yml
Configuration Fields:
| Field | Type | Default | Description |
|---|---|---|---|
prettier | boolean | string | object | - | Enable auto-detect, path, or options |
proseWrap | 'always' | 'never' | 'preserve' | 'preserve' | How to wrap prose in markdown |
tabWidth | number | 2 | Number of spaces per indentation |
printWidth | number | 80 | Maximum line width for wrapping |
ProseWrap Options:
| Value | Description |
|---|---|
'always' | Wrap prose at printWidth |
'never' | Do not wrap prose (single long lines) |
'preserve' | Preserve original line wrapping from source |
Option Priority
Explicit options (proseWrap, tabWidth, printWidth) override values from .prettierrc.
This allows you to use your project’s Prettier config as a base while customizing specific options.
Example: Match Project Prettier Config
If your project already has a .prettierrc:
formatting: prettier: trueExample: Custom Formatting Without Prettier File
formatting: tabWidth: 4 proseWrap: always printWidth: 100universalDir
Configures the universal directory for auto-discovering skills and commands. Skills are discovered from <universalDir>/skills/ and commands from <universalDir>/commands/.
# Use default .agents/ directoryuniversalDir: true
# Custom directory pathuniversalDir: '.my-agents'
# Disable universal directory discoveryuniversalDir: false| Value | Type | Default | Description |
|---|---|---|---|
true | boolean | true | Use default .agents/ directory |
false | boolean | - | Disable universal directory |
| (string) | string | '.agents' | Custom path relative to project root |
releases
Opts in to prs release. Lists the release environments in promotion order, first to last.
releases: environments: [staging, prod]| Field | Type | Required | Description |
|---|---|---|---|
environments | string[] | Yes | Environment names, first to last, 1 to 16 |
Each name matches ^[a-z][a-z0-9-]{0,31}$ and appears once. The names index and manifest, and
the Windows device names con, prn, aux, nul, com1 to com9 and lpt1 to lpt9, are
refused because each environment is a file named <name>.json. Without releases every
prs release command fails with PS5001. See the releases guide.
eval
Settings of prs eval. They name the providers and set limits. They never
turn on a live run: the cache mode, the budget and extra hosts come from command-line flags only.
eval: providers: anthropic: { kind: anthropic, apiKeyEnvVar: ANTHROPIC_API_KEY } gateway: { kind: openai-compatible, baseUrl: 'https://llm.corp.example/v1', apiKeyEnvVar: GATEWAY_KEY } timeoutMs: 60000 maxOutputTokens: 1024 maxCases: 1000 reportDir: .promptscript/eval-reports| Field | Type | Required | Description |
|---|---|---|---|
providers | object | No | Providers by name, matching the provider of a model profile |
timeoutMs | integer | No | Time limit of one model call, response body included. Default 60000 |
maxOutputTokens | integer | No | Output token cap when a prompt sets no maxTokens. Default 1024 |
maxCases | integer | No | Largest number of dataset rows a suite runs. Default 1000. --max-cases wins |
reportDir | string | No | Directory for reports, relative to the project root. --report-dir wins |
A provider entry has kind (anthropic or openai-compatible), baseUrl and apiKeyEnvVar, the
name of the environment variable that holds the key. anthropic and openai have built-in URLs
and key variables, so they need no entry. Any other provider needs one. The config never holds a
key: a run stops with PS6307 when the value of a key variable, or of a variable named like a
secret, appears anywhere in eval or in a model profile. A provider key goes only to
api.anthropic.com, api.openai.com and the hosts you pass with --allow-host, so review a change
to apiKeyEnvVar like code.
governance
Who owns the setup and which teams review each approval role. prs governance codeowners turns it
into CODEOWNERS lines, and PS047 checks prompt owners and data classes against it.
governance: admins: ['@acme/prompt-platform'] roles: legal: ['@acme/legal'] dataClasses: [pii, phi, financial, credentials, internal, public] codeowners: output: .github/CODEOWNERS protect: [.github/workflows] prompts: true| Field | Type | Required | Description |
|---|---|---|---|
admins | string[] | No | Owners of the config, the approvals root, the releases and the CODEOWNERS files |
roles | object | No | Approval roles, each with a non-empty list of owners. At most 32 roles |
dataClasses | string[] | No | Data class names the project uses (PS047, and the data classes of policies) |
codeowners.output | string | No | .github/CODEOWNERS (default), CODEOWNERS, docs/CODEOWNERS, .gitlab/CODEOWNERS |
codeowners.protect | string[] | No | More paths the admins own, relative to the repository root |
codeowners.prompts | boolean | No | Write CODEOWNERS lines for the .prs files that define prompts. Default true |
Owners are a user (@jane; ., _ and - allowed between letters or digits, like @jane.doe), a team (@acme/legal) or an email address of at most 254 characters.
Role names match ^[a-z][a-z0-9-]{0,31}$ and are not a Windows device name, because a role names a
directory. Unknown keys are refused with the closest key. prs governance codeowners needs
admins; a problem in this section is PS5101. See
CODEOWNERS from Governance.
includePromptScriptSkill
Controls whether the bundled PromptScript language skill is included in compilation output. When enabled, the compiler adds it only when the formatter exposes a bundled-skill output path.
# Include the PromptScript skill (default)includePromptScriptSkill: true
# Disable the PromptScript skillincludePromptScriptSkill: false| Field | Type | Default | Description |
|---|---|---|---|
includePromptScriptSkill | boolean | true | Include bundled PromptScript language skill |
Environment Variables
Configuration values can reference environment variables:
id: environment-examplesyntax: '1.4.0'
registry: auth: type: bearer token: ${REGISTRY_TOKEN}
targets: - github: output: ${OUTPUT_DIR:-.github}/copilot-instructions.md| Syntax | Description |
|---|---|
${VAR} | Required variable |
${VAR:-default} | Variable with default |
Minimal Configuration
The simplest valid configuration:
id: minimal-projectsyntax: '1.4.0'
input: entry: .promptscript/project.prs
targets: - githubExtending Configuration
You can extend another configuration file, for example one shared by every project in a monorepo:
syntax: '1.4.0'registries: '@company': github.com/acme/promptscript-basetargets: - claudeid: extended-projectextends: ../shared/base.config.yaml
targets: - github: output: custom/path.mdHow the merge works:
- The
extendspath is relative to the file that declares it. A base file can extend another file. A circular chain is an error. - Objects merge deeply and the extending file wins. Arrays such as
targetsare replaced, not joined, so the example above compiles onlygithub. - A
__proto__,constructororprototypekey in an object that both files set is a config error (PS3002) that names the key. The merge reads and writes own keys only, so no value goes through a prototype. policiesis joined: the base policies come first and the extending file’s policies are appended. A base policy cannot be removed or redefined, so a policy with the samenameas a base policy is a config error, and so is apoliciesvalue that is not a list, such aspolicies: null(a barepolicies:key is accepted only when the base has no policies). Settingvalidation.rules.policy-compliancetooffstill turns PS030 off, including from an extending file.governance.adminsand each owner list undergovernance.rolesare joined the same way: base owners come first, the extending file’s new owners are appended and duplicates are dropped. The extending file can add roles and owners, but cannot remove one.governance.codeowners.protectis joined the same way, so a protected path set in a base file stays protected. A value of the wrong type forgovernance,governance.admins,governance.roles, one role,governance.codeownersorgovernance.codeowners.protectis a config error, and so isnullwhen the base sets entries there (a bare key is accepted only when the base has none). A__proto__key undergovernance,governance.rolesorgovernance.codeownersis refused. Other keys undergovernancemerge like the rest of the file.registrymerges like the other config levels: if the extending file picks another backend (for exampleregistry.pathover a baseregistry.git), the base backend is dropped.- Paths inside a base file, like
input.entryorregistry.path, stay relative to the project, not to the base file. prs migrateandprs serveread only the project file.
Schema Validation
The configuration file is validated against a JSON schema. Enable editor support by adding the schema reference at the top of your promptscript.yaml:
# yaml-language-server: $schema=https://getpromptscript.dev/schema/config.json
id: schema-examplesyntax: '1.4.0'input: entry: .promptscript/project.prstargets: - githubThis provides:
- Autocomplete - suggestions for all configuration options
- Validation - errors for invalid fields or values
- Documentation - hover tooltips with field descriptions
Schema is the source of truth
The JSON schema is automatically generated from TypeScript types in @promptscript/core.
When in doubt about configuration options, the schema reflects the current implementation.
Schema URL: [`schema/config.json`](https://getpromptscript.dev/schema/config.json)Examples
Minimal Project
id: minimal-projectsyntax: '1.4.0'
input: entry: .promptscript/project.prs
targets: - githubMulti-Team Setup
id: multi-team-projectsyntax: '1.4.0'
input: entry: .promptscript/${TEAM}/project.prs
registry: path: ./shared-registry
targets: - github: output: .github/copilot-instructions.md - claude: output: CLAUDE.mdCI/CD Configuration
id: ci-projectsyntax: '1.4.0'
input: entry: .promptscript/project.prs
registry: git: url: https://github.com/org/promptscript-registry.git ref: main auth: type: token tokenEnvVar: GITHUB_TOKEN cache: enabled: true ttl: 3600000
targets: - github - claude - cursor - antigravity - opencode - geminiPrivate Git Registry with SSH
registry: git: ref: v1.0.0 # Pin to specific version auth: type: ssh sshKeyPath: *****************HTTPS Registry with SSH Fallback
When registry references use HTTPS URLs but you authenticate via SSH keys,
configure a fallbackUrl so PromptScript automatically retries the clone
with SSH on auth failure:
registry: git: url: https://github.com/org/registry.git ref: mainThe same pattern works for registry aliases:
registries: '@acme': url: https://github.com/acme/standards.git