Build Your Registry¶
PromptScript supports registries - collections of reusable configurations that can be inherited across projects. Each organization creates and manages their own registry, giving full control over AI instruction standards.
Quick Start¶
1. Create a Registry¶
This scaffolds a complete registry with starter configurations. See Creating a Registry for details.
2. Configure Your Project¶
Add to your promptscript.yaml:
registry:
git:
url: https://github.com/your-org/your-registry.git
ref: main # Or pin to version: v1.0.0
2. Inherit Configurations¶
@meta {
id: "my-project"
syntax: "1.0.0"
}
@inherit @stacks/react
@use @fragments/testing
3. Compile¶
Note: When using a Git registry, the CLI automatically clones and caches the repository. You don't need to run prs pull separately - the compile and validate commands handle this automatically.
The registry is cached at ~/.promptscript/.cache/git/ with a default TTL of 1 hour. Use prs pull --refresh to force an update.
Using prs init¶
The prs init command can connect to your registry and suggest configurations:
It will:
- Detect your tech stack (React, Node, Python, etc.)
- Offer to connect to a Git or local registry
- Suggest relevant configurations from your registry's catalog
- Generate your
promptscript.yamland.promptscript/project.prs
You can also set a default registry via user-level config so prs init --yes automatically uses it.
How Overlay-Aware Suggestions Work¶
When your registry catalogs Layer 2 / Layer 3 skill overlays, prs init collapses overlay relationships before showing the picker so you don't see both the base skill and its overlay as separate choices.
Detection works two ways:
- Manifest
extendsfield — when a skill entry inregistry-manifest.yamldeclaresextends: <base-skill-id>, the suggestion engine treats it as an overlay of that base. - Inline
@extendscan — when no manifest hint exists, the engine scans the suggested skill's.prssource for@use … as <alias>plus@extend <alias>.skills.<name>and resolves the base skill via the alias map.
When an overlay is detected and both the overlay and its base were suggested, the base is removed from the choices. The overlay choice is annotated inline:
? Select skills to add: (Use space to select, enter to confirm)
◉ @stacks/react (use)
◉ @skills/code-review (extends @skills/code-review-base) (skill)
◉ @skills/security-review (skill)
The (extends …) annotation makes it explicit which base the overlay is layering on top of, so reviewers can audit the chain at a glance. If your registry doesn't yet declare extends, populate the field in registry-manifest.yaml to get the cleanest experience:
catalog:
- id: '@skills/code-review-base'
description: 'Generic code-review base skill'
- id: '@skills/code-review'
description: 'Org-specific code-review overlay (banking compliance)'
extends: '@skills/code-review-base'
See Skill Overlays for the overlay model itself, and the Registry Manifest section below for the full schema.
Usage Patterns¶
Pattern 1: Inherit a Tech Stack¶
@meta { id: "react-app" syntax: "1.0.0" }
@inherit @stacks/react
Pattern 2: Mix in Fragments¶
@meta { id: "secure-app" syntax: "1.0.0" }
@inherit @stacks/node
@use @fragments/testing
@use @fragments/security/owasp-security-review
Pattern 3: Use Prompts Directly¶
@meta { id: "terminal" syntax: "1.0.0" }
@inherit @prompts/coding/linux-terminal
How Git Registry Resolution Works¶
When you configure a Git registry, the CLI handles everything automatically:
- On first use: The registry is cloned to
~/.promptscript/.cache/git/<hash>/ - On subsequent uses: The cached version is used if not stale (default: 1 hour TTL)
- On cache expiry: The registry is updated with
git fetch
prs init --yes
↓
Creates config with registry.git.url
prs compile
↓
resolveRegistryPath() → checks cache validity
↓
If stale/missing: GitRegistry.fetch() → clone/update
↓
Compiler uses cached registry path
Cache Configuration¶
Control caching behavior in promptscript.yaml:
registry:
git:
url: https://github.com/your-org/your-registry.git
ref: main
cache:
enabled: true # Set to false to always fetch
ttl: 3600000 # Cache TTL in ms (default: 1 hour)
Force Refresh¶
Version Pinning¶
Pin to a specific version for stability:
Or in .prs files:
@inherit @stacks/react@1.0.0
Creating a Registry¶
Use the prs registry init command to scaffold a new registry:
This creates the full directory structure, manifest, and optional seed configurations.
Interactive Mode¶
Non-Interactive Mode¶
prs registry init my-registry --yes --name "My Company Registry" --namespaces @core @stacks @fragments
Skip Seed Configs¶
Registry Structure¶
my-registry/
├── registry-manifest.yaml # Catalog of all configurations
├── @core/
│ └── base.prs
├── @roles/
│ └── developer/
│ └── fullstack.prs
├── @stacks/
│ └── react.prs
└── @fragments/
└── testing.prs
Registry Manifest¶
The registry-manifest.yaml file catalogs all configurations and enables prs init suggestions:
version: '1'
meta:
name: 'My Company Registry'
description: 'Internal AI instruction configurations'
lastUpdated: '2025-01-28'
namespaces:
'@core':
description: 'Universal foundations'
priority: 100
'@roles':
description: 'AI personas'
priority: 90
'@stacks':
description: 'Tech stack configurations'
priority: 80
'@fragments':
description: 'Reusable mixins'
priority: 70
catalog:
- id: '@core/base'
path: '@core/base.prs'
name: 'Base Foundation'
description: 'Universal AI assistant foundation'
tags: [core, foundation]
targets: [github, claude, cursor]
dependencies: []
detectionHints:
always: true
- id: '@stacks/react'
path: '@stacks/react.prs'
name: 'React Stack'
description: 'React + TypeScript configuration'
tags: [react, typescript, frontend]
targets: [github, claude, cursor]
dependencies: ['@core/base']
detectionHints:
dependencies: ['react', 'react-dom']
frameworks: ['react', 'nextjs']
suggestionRules:
- condition: { always: true }
suggest: { inherit: '@core/base' }
- condition: { frameworks: ['react'] }
suggest: { inherit: '@stacks/react', use: ['@fragments/testing'] }
Manifest Fields¶
catalog Entry Fields¶
| Field | Required | Description |
|---|---|---|
id | Yes | Unique ID matching file path |
path | Yes | Path to the .prs file |
name | Yes | Human-readable name |
description | Yes | Brief description |
tags | Yes | Searchable tags |
targets | No | Supported targets (github, claude, etc.) |
dependencies | No | Required configurations |
detectionHints | No | Auto-suggestion hints (see below) |
detectionHints Fields¶
| Field | Description |
|---|---|
always | Always suggest this configuration |
files | Suggest if these files exist |
dependencies | Suggest if package.json has these dependencies |
languages | Suggest for these languages |
frameworks | Suggest for these frameworks |
Using Your Registry¶
Git Registry¶
Host on GitHub, GitLab, or any Git provider:
Local Registry¶
For development or air-gapped environments:
Validating a Registry¶
Use prs registry validate to check your registry structure:
Validation checks:
registry-manifest.yamlexists and parses correctly- Manifest schema is valid (version, meta, namespaces, catalog)
- All catalog entry
.prsfiles exist - Catalog IDs match declared namespaces
- No circular dependencies
- Warns about orphaned
.prsfiles not in catalog
Use --strict to treat warnings as errors:
Use --format json for machine-readable output:
Publishing a Registry¶
Use prs registry publish to commit and push registry updates:
This will:
- Validate the registry (use
--forceto skip) - Update
meta.lastUpdatedin the manifest - Stage, commit, and push changes
Options:
prs registry publish ./my-registry --dry-run # Preview without publishing
prs registry publish ./my-registry -m "Add React stack" # Custom commit message
prs registry publish ./my-registry --tag v1.0.0 # Tag the release
prs registry publish ./my-registry --force # Skip validation
CI/CD Integration¶
Add registry validation to your CI pipeline:
# .github/workflows/registry.yml
name: Registry CI
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g @promptscript/cli
- run: prs registry validate --strict
Next Steps¶
- Enterprise Setup - Scale PromptScript across your organization
- CI/CD Integration - Automate validation and compilation in your pipeline
Registry Aliases¶
Registry aliases let you define short names for Git repository URLs so that imports stay readable and organization-wide base URLs are configured in one place.
Configuring Aliases¶
Aliases are defined in the registries field of promptscript.yaml (project scope) or ~/.promptscript/config.yaml (user scope):
# promptscript.yaml
registries:
'@company': github.com/acme/promptscript-base
'@team': github.com/acme/team-frontend
Use any scoped name as the key. The value is a bare Git host path - no https:// prefix required.
Three-Level Merge¶
Aliases are merged from three sources in priority order (highest first):
- Project -
promptscript.yamlin the repo (team-specific overrides) - User -
~/.promptscript/config.yaml(developer preferences) - System -
/etc/promptscript/config.yaml(IT-provisioned defaults)
Project aliases win over user aliases, which win over system aliases. This lets IT provision company-wide aliases while still allowing projects to override specific ones.
Using Aliases in .prs Files¶
Once configured, use the alias as the scope prefix in any import:
@meta { id: "my-project" syntax: "1.0.0" }
# Resolves to github.com/acme/promptscript-base/@org/base.prs
@inherit @company/@org/base
# Resolves to github.com/acme/team-frontend/@stacks/react.prs
@use @team/@stacks/react
Go-Style URL Imports¶
Beyond registry aliases, PromptScript supports Go-module-style bare URL imports. You can reference any Git repository directly by its host path - no alias required.
Basic URL Import¶
@meta { id: "my-project" syntax: "1.0.0" }
# Import directly from a public GitHub repo
@use github.com/acme/shared-standards/@fragments/security
# Import from any Git host
@use gitlab.com/myorg/prompts/@stacks/python
Version Pinning in URL Imports¶
Append a version specifier with @:
# Pin to an exact tag
@use github.com/acme/shared-standards/@org/base@1.2.0
# Pin to a semver range (latest patch in 1.x)
@use github.com/acme/shared-standards/@org/base@^1.0.0
# Pin to a branch
@use github.com/acme/shared-standards/@org/base@main
| Specifier | Meaning |
|---|---|
@1.2.0 | Exact tag v1.2.0 or 1.2.0 |
@^1.0.0 | Latest tag matching ^1.0.0 (semver) |
@main | Tip of branch main |
| (none) | Default branch as configured |
Alias vs URL Import¶
| Style | Example | When to Use |
|---|---|---|
| Alias | @use @company/security | Frequently-used internal packages |
| Full URL | @use github.com/acme/security | One-off external imports |
| Versioned URL | @use github.com/acme/security@^1.0.0 | Reproducible external dependencies |
Auto-Discovery¶
When you import a repository that does not contain .prs files, PromptScript looks for native AI plugin files and converts them automatically. This means you can @use any GitHub repository that contains SKILL.md, agent definitions, or command files - even if it was not authored with PromptScript.
What Gets Auto-Discovered¶
| Source File Pattern | Imported As |
|---|---|
SKILL.md in root or skills/ directory | @skills block |
.claude/agents/*.md | @agents block |
.claude/commands/*.md | @shortcuts block |
.github/skills/*/SKILL.md | @skills block |
Example: Importing an Open-Source Skill Library¶
@meta { id: "my-project" syntax: "1.0.0" }
# This repo has a SKILL.md but no .prs files - auto-discovered
@use github.com/some-org/claude-skills/skills/tdd-workflow
PromptScript fetches the repository, detects the SKILL.md, and synthesizes a virtual .prs fragment that you can merge into your project just like any other import.
Zero Config Required
Auto-discovery works without any setup in the remote repo. The remote maintainer does not need to know about PromptScript.
Lockfile¶
PromptScript generates a promptscript.lock file to record the exact resolved commit for every remote import. This gives you reproducible builds - the same source always produces the same output, regardless of when you compile.
Generating the Lockfile¶
prs lock # Create or update promptscript.lock
prs lock --dry-run # Show what would change without writing
The lockfile is also written automatically during prs compile when remote imports are present.
Lockfile Format¶
# promptscript.lock
version: 1
packages:
github.com/acme/promptscript-base:
url: https://github.com/acme/promptscript-base.git
ref: main
commit: a3f8c2d91b4e6f7890123456789abcdef0123456
resolved: '2026-03-23T10:00:00Z'
references:
'@stacks/react.prs':
hash: sha256:a1b2c3d4e5f6...
'@fragments/testing.prs':
hash: sha256:f6e5d4c3b2a1...
github.com/some-org/claude-skills:
url: https://github.com/some-org/claude-skills.git
ref: v1.2.0
commit: deadbeef12345678901234567890abcdef012345
resolved: '2026-03-22T08:30:00Z'
references:
'skills/tdd-workflow/SKILL.md':
hash: sha256:1234abcd5678...
Integrity Hashes¶
Each lockfile entry includes SHA-256 hashes for the individual files resolved from that package. During compilation and validation, these hashes are verified against the actual file contents. If a file has been modified since it was locked, a reference integrity error is raised.
This protects against:
- Tampered dependencies - changes to registry files after locking
- Cache corruption - stale or corrupted cached copies
- Supply chain attacks - unauthorized modifications to shared skills
To skip hash verification (e.g., during local development), use:
Warning
Never use --ignore-hashes in CI pipelines. Hash verification is a critical security check for production builds.
Committing the Lockfile¶
Commit promptscript.lock to version control. This ensures:
- Reproducible builds - CI always compiles against the same commits
- Auditable deps - diffs show exactly when a dependency was updated
- Offline support - works with
prs vendor sync(see below)
Updating Dependencies¶
# Update a specific package to its latest allowed version
prs update github.com/acme/promptscript-base
# Update all packages
prs update
# Preview updates without writing
prs update --dry-run
Vendor Mode¶
Vendor mode copies all remote dependencies into a local .promptscript/vendor/ directory. This enables fully offline builds - useful in air-gapped CI environments or when you want to audit third-party content before it runs.
Syncing the Vendor Directory¶
# Download all lockfile-resolved packages to vendor/
prs vendor sync
# Check that vendor/ is in sync with the lockfile
prs vendor check
After running prs vendor sync, compilation never performs network requests. The vendor directory is used as-is.
Vendor Directory Structure¶
.promptscript/
└── vendor/
├── github.com/
│ ├── acme/
│ │ └── promptscript-base/
│ │ ├── @org/base.prs
│ │ └── @org/security.prs
│ └── some-org/
│ └── claude-skills/
│ └── skills/
│ └── tdd-workflow/
│ └── SKILL.md
└── .vendor-manifest.yaml
CI Pipeline with Vendor¶
# .github/workflows/promptscript.yml
- name: Sync vendor
run: prs vendor sync
- name: Validate
run: prs vendor check && prs validate --strict
- name: Compile
run: prs compile
Commit the vendor directory to your repository if you want fully self-contained, network-free builds. Otherwise, regenerate it in CI from the lockfile.
Private Repositories¶
SSH Authentication¶
PromptScript uses your existing SSH keys automatically for git@ URLs:
Or in URL imports:
@use git@github.com:acme/private-skills/@fragments/security
Ensure your SSH key is added to ssh-agent or configured in ~/.ssh/config.
Token Authentication (GITHUB_TOKEN)¶
For HTTPS URLs, configure a token in your registry entry:
# promptscript.yaml
registry:
git:
url: https://github.com/acme/promptscript-base.git
ref: main
auth:
type: token
tokenEnvVar: GITHUB_TOKEN
The tokenEnvVar field names the environment variable that holds the token - it is never stored in plain text.
User-Level Token Configuration¶
Set up credentials once in ~/.promptscript/config.yaml and they apply to all projects:
# ~/.promptscript/config.yaml
registries:
'@company': github.com/acme/promptscript-base
auth:
github.com:
type: token
tokenEnvVar: GITHUB_TOKEN
gitlab.com:
type: token
tokenEnvVar: GITLAB_TOKEN