Skip to content

Configuration

Complete reference for promptscript.yaml.

File Location

The CLI looks for configuration in this order:

  1. --config command line option
  2. PROMPTSCRIPT_CONFIG environment variable
  3. promptscript.yaml in current directory
  4. promptscript.yml in current directory
  5. .promptscriptrc.yaml in current directory
  6. .promptscriptrc.yml in current directory

Full Configuration

id: full-example
syntax: '1.4.0'
# Anonymous aggregate usage telemetry
telemetry: 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: true

Configuration Sections

Top-level fields

FieldTypeRequiredDescription
idstringYesProject identifier
syntaxstringYesPromptScript syntax version
targetsTargetEntry[]Yes*Output targets and target-specific options
descriptionstringNoProject description
telemetrybooleanNoEnable anonymous aggregate usage telemetry
extendsstringNoBase configuration file to merge
inheritstringNoRegistry configuration inherited by the project
inputobjectNoEntry point and source file globs
registryobjectNoDefault local, HTTP, or Git registry
registriesobjectNoNamed Git registry aliases
watchobjectNoWatch mode behavior
outputobjectNoGlobal output directory, header, and overwrite
buildsobjectNoNamed build profiles
skillTargetsRecord<string,string>NoPer-source skill output directories
formattingobjectNoMarkdown formatting settings
customConventionsobjectNoUser-defined output conventions
universalDirstring or booleanNoUniversal skills and commands directory
includePromptScriptSkillbooleanNoInclude the bundled language skill
validationobjectNoGuard and validation rule settings
modelsobjectNoSupported model set and model profiles
policiesarrayNoPolicies for skill extensions and prompts
releasesobjectNoRelease environments for prompt bundles
evalobjectNoProviders and limits of prs eval
governanceobjectNoAdmins, 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: false

Project 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'
FieldTypeDefaultDescription
entrystringRequiredMain entry point
includestring[]["**/*.prs"]Glob patterns to include
excludestring[][]Glob patterns to exclude

registry

Configures the inheritance registry. PromptScript supports three registry types:

  1. Local filesystem - for development or monorepos
  2. HTTP/HTTPS - for simple remote registries
  3. Git repository - recommended for teams (supports versioning via tags)

Local Registry

registry:
path: ./registry

HTTP Registry

registry:
url: https://registry.example.com/promptscript
auth:
type: bearer
tokenEnvVar: REGISTRY_TOKEN

Git 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: 3600000

Registry Fields:

FieldTypeDefaultDescription
pathstring-Local registry path
urlstring-HTTP registry URL
git.urlstring-Git repository URL
git.fallbackUrlstring-Fallback URL (tried on auth failure)
git.refstringmainBranch, tag, or commit
git.pathstring-Subdirectory within the repo
git.timeoutnumber60000Git operation timeout (ms)
git.auth.typestring-Auth type: token or ssh
git.auth.tokenstring-Personal access token (direct)
git.auth.tokenEnvVarstring-Env var containing the token
git.auth.sshKeyPathstring-Path to SSH key (for SSH auth)
cache.enabledbooleantrueEnable caching
cache.ttlnumber3600000Cache 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-libs

Extended Form

registries:
'@company':
url: github.com/acme/promptscript-base
'@internal':
url: [email protected]:platform/prs-registry
root: packages/promptscript

Extended 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
fallbackUrl: [email protected]:acme/standards.git
'@internal':
url: https://gitlab.internal.com/team/monorepo.git
fallbackUrl: [email protected]:team/monorepo.git
root: packages/promptscript

Alias Fields:

FieldTypeDescription
(simple string)stringBare Git host path, e.g. github.com/org/repo
urlstringBare Git host path (extended form)
fallbackUrlstringFallback Git URL (tried on auth failure)
rootstringBase path within the repository
timeoutnumberGit operation timeout in ms (default 60000)

Three-Level Merge

The registries field is resolved by merging three sources in priority order:

PrioritySourceScope
Highestpromptscript.yaml in projectProject-level
Middle~/.promptscript/config.yamlUser-level
Lowest/etc/promptscript/config.yamlSystem-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)

~/.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_TOKEN

Setting 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.0
Try in Playground

targets

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
- cursor

Object format (advanced, for custom options):

targets:
- github:
convention: xml
output: custom/path/instructions.md
- claude:
convention: markdown
- cursor:
version: legacy

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

TargetDefault OutputDefault ConventionSupported Versions
github.github/copilot-instructions.mdmarkdownsimple / multifile / full
claudeCLAUDE.mdmarkdownsimple / multifile / full
cursor.cursor/rules/project.mdcmarkdownmodern / multifile / legacy / agents-md / full
antigravity.agent/rules/project.mdmarkdownsimple / frontmatter / agents-md
factoryAGENTS.mdmarkdownsimple / multifile / full
opencodeOPENCODE.mdmarkdownsimple / multifile / full
geminiGEMINI.mdmarkdownsimple / multifile / full
codexAGENTS.mdmarkdownsimple / multifile / full
grokAGENTS.mdmarkdownsimple / multifile / full
windsurf.windsurf/rules/project.mdmarkdownsimple / multifile / full
cline.clinerulesmarkdownsimple / multifile / full
roo.roorulesmarkdownsimple / multifile / full
continue.continue/rules/project.mdmarkdownsimple / multifile / full
ampAGENTS.mdmarkdownsimple / multifile / full
augment.augment/rules/project.mdmarkdownsimple / multifile / full
goose.goosehintsmarkdownsimple / multifile / full
kilo.kilocode/rules/project.mdmarkdownsimple / multifile / full
trae.trae/rules/project_rules.mdmarkdownsimple / multifile / full
junie.junie/guidelines.mdmarkdownsimple / multifile / full
kiro.kiro/steering/project.mdmarkdownsimple / multifile / full
cortex.cortex/rules/project.mdmarkdownsimple / multifile / full
crushAGENTS.mdmarkdownsimple / multifile / full
command-code.commandcode/rules/project.mdmarkdownsimple / multifile / full
kode.kode/rules/project.mdmarkdownsimple / multifile / full
mcpjam.mcpjam/rules/project.mdmarkdownsimple / multifile / full
mistral-vibe.vibe/rules/project.mdmarkdownsimple / multifile / full
mux.mux/rules/project.mdmarkdownsimple / multifile / full
openhands.openhands/rules/project.mdmarkdownsimple / multifile / full
pi.pi/rules/project.mdmarkdownsimple / multifile / full
qoder.qoder/rules/project.mdmarkdownsimple / multifile / full
qwen-code.qwen/rules/project.mdmarkdownsimple / multifile / full
zencoder.zencoder/rules/project.mdmarkdownsimple / multifile / full
neovate.neovate/rules/project.mdmarkdownsimple / multifile / full
pochi.pochi/rules/project.mdmarkdownsimple / multifile / full
adal.adal/rules/project.mdmarkdownsimple / multifile / full
iflow.iflow/rules/project.mdmarkdownsimple / multifile / full
openclawINSTRUCTIONS.mdmarkdownsimple / multifile / full
codebuddy.codebuddy/rules/project.mdmarkdownsimple / multifile / full
gitlab-duoAGENTS.mdmarkdownsimple / multifile / full
aiderAGENTS.mdmarkdownsimple / multifile / full
amazon-qAGENTS.mdmarkdownsimple / multifile / full
warpAGENTS.mdmarkdownsimple / multifile / full
zedAGENTS.mdmarkdownsimple / multifile / full
julesAGENTS.mdmarkdownsimple / multifile / full
devinAGENTS.mdmarkdownsimple / multifile / full
kimiAGENTS.mdmarkdownsimple / multifile / full
mimoAGENTS.mdmarkdownsimple / multifile / full
deep-agentsAGENTS.mdmarkdownsimple / multifile / full
forgecodeAGENTS.mdmarkdownsimple / multifile / full
hermesAGENTS.mdmarkdownsimple / multifile / full
bundleprompts/index.json-v1
prompt-textprompts/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.

TargetMCP Config FileHooks ConfigPlugins 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:

VersionOutput Files
modern.cursor/rules/project.mdc + .cursor/commands/*.md for multi-line shortcuts
multifileMain + .cursor/rules/*.mdc (glob-based) + .cursor/rules/shortcuts.mdc + .cursor/commands/*.md
legacy.cursorrules (deprecated, no slash commands)
agents-mdAGENTS.md (Cursor 2.4+, no frontmatter required)
fullMultifile + .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:

VersionOutput Files
simple.github/copilot-instructions.md (single file)
multifileMain + .github/instructions/*.instructions.md + .github/prompts/*.prompt.md
fullMultifile + .github/skills/<name>/SKILL.md + AGENTS.md

Claude Code Versions:

VersionOutput Files
simpleCLAUDE.md (single file)
multifileMain + .claude/rules/*.md with path-specific rules (from @guards.globs)
fullMultifile + .claude/skills/<name>/SKILL.md (from @skills) + CLAUDE.local.md (from @local)

Factory AI Versions:

VersionOutput Files
simpleAGENTS.md only
multifileAGENTS.md + commands + .factory/skills/<name>/SKILL.md
fullMultifile 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:

VersionOutput Files
simpleOPENCODE.md (single file)
multifileMain + .opencode/commands/<name>.md
fullMultifile + .opencode/skills/<name>/SKILL.md + .opencode/agents/<name>.md

Gemini CLI Versions:

VersionOutput Files
simpleGEMINI.md (single file)
multifileMain + .gemini/commands/<name>.toml + .agents/skills/<name>/skill.md
fullSame as multifile (Gemini CLI has no agent concept)

Target Options:

FieldTypeDefaultDescription
enabledbooleantrueWhether target is enabled
outputstring(see above)Custom output path, relative to the output directory
conventionstringmarkdownOutput convention (xml or markdown)
versionstringfullFormat version (varies by target, see below)
rulesModemonolith or splitmonolithFactory always-on rule layout
skillBaseDirstringtarget-specificCustom base directory for generated skill files
includeSkillsboolean or string arraytrueEmit 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.

```yaml
targets:
- 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:

```yaml
builds:
logstrip-factory:
output: plugins/logstrip
targets:
- factory:
version: multifile
skillBaseDir: skills
includeSkills:
- logstrip
```
Run it with:
```bash
prs compile --build logstrip-factory
# or
prs build logstrip-factory
```

Built-in Conventions:

ConventionSection FormatDescription
markdown## Section NameMarkdown headers
xml<section-name>content</section-name>XML tags wrapping content

Target-Specific Options:

OptionTargetsTypeDescription
maxThreadscodexnumberMax parallel agent threads (positive integer, maps to .codex/config.toml)
maxDepthcodexnumberMax nesting depth for agent delegation (positive integer)
agentsFilecodexstringOverride agents file name (default: AGENTS.md, scoped builds: AGENTS.override.md)
agentsFrontmatterAGENTS.md targetsstringexperimental - emit AGENTS.md v1.1 YAML frontmatter (description, tags from @meta)
autoModeclaudestringClaude 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 FieldCodex TOML Field
contentdeveloper_instructions
reasoningEffortmodel_reasoning_effort
sandboxModesandbox_mode
nicknameCandidatesnickname_candidates
mcpServersmcp_servers
skillsskills.config

customConventions

Define custom output conventions for specialized formatting needs.

id: custom-convention-example
syntax: '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 target
targets:
- github:
convention: my-format

Custom Convention Structure:

FieldTypeDescription
namestringConvention identifier
descriptionstringHuman-readable purpose
section.startstringSection opening template, supports {{name}}
section.endstringOptional section closing template
section.nameTransformstringkebab-case, camelCase, PascalCase, or none
section.indentstringIndentation per nesting level
subsectionobjectOptional subsection renderer
listStylestringdash, asterisk, bullet, or numbered
codeBlockDelimiterstringCode fence delimiter
rootWrapperobjectOptional 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:
- logstrip

Run a profile with either command:

Terminal window
prs compile --build logstrip-factory
prs build logstrip-factory
# Compile all named build profiles in deterministic order
prs compile --all-builds

A 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.md

Output paths are validated against project root - path traversal (..) is rejected. Codex-only AGENTS.override.md is supported via the agentsFile option.

Build Profile Fields:

FieldTypeDefaultDescription
entrystringinput.entryEntry file to compile for this profile
outputstringoutput.baseDirBase output directory for this profile
targetsTargetEntry[]targetsTarget 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)'
FieldTypeDefaultDescription
requiredGuardsstring[][]Guards every resolved project must define
rulesobject{}Rule severity overrides
guardRequiresDepthnumber3Maximum guard dependency recursion depth
scanExternalContentbooleanfalseScan 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.
excludesarray[]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.
allowedPatternsstring[][]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)
FieldTypeDefaultDescription
supportedstring[]-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
profilesobject{}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:

  • inherit keeps the model already selected in the tool.
  • opus, sonnet, haiku, and fable are 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

TargetWritten valueinheritProviders
Claude Code, Grok BuildFloating aliases as written, other models as API idWrittenAnthropic
GitHub CopilotDisplay name, such as Claude Sonnet 5 or GPT-5.3-Codex; auto is AutoOmittedAll
Factory AIAPI idWrittenAll
CodexAPI idOmittedOpenAI
CursorProfile id, which has no snapshot date, such as claude-sonnet-4-5WrittenAll

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.

FieldDescription
providerModel provider, such as anthropic, openai, google, or xai
familyModel line that groups versions, such as claude-opus
versionVersion inside the family, such as 5.5
displayNameHuman-readable name, also the GitHub Copilot model name
apiIdProvider API model id
aliasesAdditional names that resolve to the profile
statuscurrent, legacy (superseded but still served), deprecated (retirement announced), or retired
successorProfile id of the recommended replacement
releaseDateRelease date in YYYY-MM-DD format
retirementDateDate the provider stops serving the model, in YYYY-MM-DD format
targetsNative 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 deprecated or retired models, with the replacement found through the successor chain
  • when supported is set: references outside the set, references that are not in the catalog, and supported entries that are not in the catalog
  • problems in profiles: a name used by two profiles, a profile or alias named after a floating alias or inherit, a successor that is unknown or loops back, a date not in YYYY-MM-DD format, and a targets key 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
FieldTypeDefaultDescription
includestring[]See default patterns belowPatterns to watch
excludestring[][]Patterns to ignore
debouncenumber300Debounce delay (ms)
clearScreenbooleantrueClear on rebuild

Default include patterns:

  • **/*.prs
  • .promptscript/**/*
  • .agents/**/*
  • registry/**/*
  • promptscript.yaml
  • promptscript.yml
  • .promptscriptrc.yaml
  • .promptscriptrc.yml
  • promptscript.lock

output

Configures global output behavior.

output:
baseDir: '.'
header: Managed by the platform team.
overwrite: false
resources:
- agents
- skills
FieldTypeDefaultDescription
baseDirstring.Base directory for generated output
headerstring-Header added to Markdown after PromptScript metadata and frontmatter
overwritebooleanfalseOverwrite conflicting user files without prompting, like --force
resourcesstring[]-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: 100

Prettier Detection:

When prettier: true, PromptScript searches for Prettier configuration files in this order:

  1. .prettierrc
  2. .prettierrc.json
  3. .prettierrc.yaml
  4. .prettierrc.yml

Configuration Fields:

FieldTypeDefaultDescription
prettierboolean | string | object-Enable auto-detect, path, or options
proseWrap'always' | 'never' | 'preserve''preserve'How to wrap prose in markdown
tabWidthnumber2Number of spaces per indentation
printWidthnumber80Maximum line width for wrapping

ProseWrap Options:

ValueDescription
'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: true

Example: Custom Formatting Without Prettier File

formatting:
tabWidth: 4
proseWrap: always
printWidth: 100

universalDir

Configures the universal directory for auto-discovering skills and commands. Skills are discovered from <universalDir>/skills/ and commands from <universalDir>/commands/.

# Use default .agents/ directory
universalDir: true
# Custom directory path
universalDir: '.my-agents'
# Disable universal directory discovery
universalDir: false
ValueTypeDefaultDescription
truebooleantrueUse default .agents/ directory
falseboolean-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]
FieldTypeRequiredDescription
environmentsstring[]YesEnvironment 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
FieldTypeRequiredDescription
providersobjectNoProviders by name, matching the provider of a model profile
timeoutMsintegerNoTime limit of one model call, response body included. Default 60000
maxOutputTokensintegerNoOutput token cap when a prompt sets no maxTokens. Default 1024
maxCasesintegerNoLargest number of dataset rows a suite runs. Default 1000. --max-cases wins
reportDirstringNoDirectory 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
FieldTypeRequiredDescription
adminsstring[]NoOwners of the config, the approvals root, the releases and the CODEOWNERS files
rolesobjectNoApproval roles, each with a non-empty list of owners. At most 32 roles
dataClassesstring[]NoData class names the project uses (PS047, and the data classes of policies)
codeowners.outputstringNo.github/CODEOWNERS (default), CODEOWNERS, docs/CODEOWNERS, .gitlab/CODEOWNERS
codeowners.protectstring[]NoMore paths the admins own, relative to the repository root
codeowners.promptsbooleanNoWrite 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 skill
includePromptScriptSkill: false
FieldTypeDefaultDescription
includePromptScriptSkillbooleantrueInclude bundled PromptScript language skill

Environment Variables

Configuration values can reference environment variables:

id: environment-example
syntax: '1.4.0'
registry:
auth:
type: bearer
token: ${REGISTRY_TOKEN}
targets:
- github:
output: ${OUTPUT_DIR:-.github}/copilot-instructions.md
SyntaxDescription
${VAR}Required variable
${VAR:-default}Variable with default

Minimal Configuration

The simplest valid configuration:

id: minimal-project
syntax: '1.4.0'
input:
entry: .promptscript/project.prs
targets:
- github

Extending Configuration

You can extend another configuration file, for example one shared by every project in a monorepo:

shared/base.config.yaml
syntax: '1.4.0'
registries:
'@company': github.com/acme/promptscript-base
targets:
- claude
app/promptscript.yaml
id: extended-project
extends: ../shared/base.config.yaml
targets:
- github:
output: custom/path.md

How the merge works:

  • The extends path 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 targets are replaced, not joined, so the example above compiles only github.
  • A __proto__, constructor or prototype key 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.
  • policies is 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 same name as a base policy is a config error, and so is a policies value that is not a list, such as policies: null (a bare policies: key is accepted only when the base has no policies). Setting validation.rules.policy-compliance to off still turns PS030 off, including from an extending file.
  • governance.admins and each owner list under governance.roles are 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.protect is joined the same way, so a protected path set in a base file stays protected. A value of the wrong type for governance, governance.admins, governance.roles, one role, governance.codeowners or governance.codeowners.protect is a config error, and so is null when the base sets entries there (a bare key is accepted only when the base has none). A __proto__ key under governance, governance.roles or governance.codeowners is refused. Other keys under governance merge like the rest of the file.
  • registry merges like the other config levels: if the extending file picks another backend (for example registry.path over a base registry.git), the base backend is dropped.
  • Paths inside a base file, like input.entry or registry.path, stay relative to the project, not to the base file.
  • prs migrate and prs serve read 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-example
syntax: '1.4.0'
input:
entry: .promptscript/project.prs
targets:
- github

This 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-project
syntax: '1.4.0'
input:
entry: .promptscript/project.prs
targets:
- github

Multi-Team Setup

id: multi-team-project
syntax: '1.4.0'
input:
entry: .promptscript/${TEAM}/project.prs
registry:
path: ./shared-registry
targets:
- github:
output: .github/copilot-instructions.md
- claude:
output: CLAUDE.md

CI/CD Configuration

id: ci-project
syntax: '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
- gemini

Private Git Registry with SSH

registry:
git:
url: [email protected]:org/private-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
fallbackUrl: [email protected]:org/registry.git
ref: main

The same pattern works for registry aliases:

registries:
'@acme':
url: https://github.com/acme/standards.git
fallbackUrl: [email protected]:acme/standards.git