Plugs guide
Plugs provide template-based customization for rules that need different values across projects, stacks, or teams. Instead of forking rules to change test commands or file paths, you declare slots and fill them with project-specific values.
Quick example
Rule with plug:
rules:
- id: testing.run-tests
summary: Run tests before committing
guidance: |
Run tests with: [[plug:test.cmd]]
applies_to: ["**/*"]
plugs:
slots:
test.cmd:
description: "Command to run the project's tests"
format: command
required: true
example: "pytest -q"Fill the slot:
aligntrue plugs set test.cmd "pnpm test"Result after sync:
Run tests with: pnpm testWhen to use plugs
Good use cases
- Test commands -
pytest,pnpm test,cargo test, etc. - File paths - Config files, documentation URLs, build outputs
- Project metadata - Author names, organization names, repository URLs
- Stack-specific values - Package managers, build tools, deployment targets
Not suitable for
- Check logic - Use overlays to adjust severity/inputs, or fork for logic changes
- Multi-line content - Plugs are single-line only
- Secret values - Don’t put secrets in fills (use environment variables at runtime)
- Computed values - Plugs are static strings, not expressions
Declaring slots
Slots define the template variables in your rules.
Slot structure
plugs:
slots:
<key>:
description: "One-line description"
format: command | text | file | url
required: true | false
example: "example value" # Recommended for required slotsFormat types
command
- Single-line shell command
- No environment variable interpolation (except
CI=true) - Examples:
pnpm test,cargo build --release
text
- Any single-line UTF-8 string
- Examples:
John Doe,Acme Corp,v1.0.0
file
- Repo-relative POSIX path
- No
..segments (parent directory traversal blocked) - No absolute paths
- Examples:
config/settings.json,docs/README.md
url
- Must start with
http://orhttps:// - Examples:
https://docs.example.com,https://github.com/org/repo
Key naming rules
- Lowercase letters, numbers, dots, hyphens, underscores:
^[a-z0-9._-]+$ - Cannot start with
stack.orsys.(reserved) - Use dots for namespacing:
test.cmd,docs.url,author.name
Example declarations
plugs:
slots:
# Required command
test.cmd:
description: "Command to run tests"
format: command
required: true
example: "pytest -q"
# Optional URL
docs.url:
description: "Documentation website URL"
format: url
required: false
example: "https://example.com/docs"
# Required file path
config.file:
description: "Path to configuration file"
format: file
required: true
example: "config/settings.json"
# Optional text
author.name:
description: "Primary author name"
format: text
required: falseProviding fills
Fills provide the actual values for slots.
Fill sources (merge order)
Fills merge in this order (last writer wins):
- Base pack - Default fills from upstream
- Stack pack(s) - Stack-specific defaults (e.g.,
nextjs-packprovidestest.cmd: "pnpm test") - Repo-local - Your project’s fills (highest priority)
Setting fills
CLI command:
aligntrue plugs set <key> <value>Examples:
# Set test command
aligntrue plugs set test.cmd "pnpm test"
# Set author name
aligntrue plugs set author.name "Jane Smith"
# Set documentation URL
aligntrue plugs set docs.url "https://docs.example.com"
# Set config file path
aligntrue plugs set config.file "config/production.json"Direct YAML editing:
plugs:
fills:
test.cmd: "pnpm test"
author.name: "Jane Smith"
docs.url: "https://docs.example.com"
config.file: "config/production.json"Fill validation
AlignTrue validates fills against slot formats:
# Valid
aligntrue plugs set test.cmd "pnpm test" # ✓ Single-line command
# Invalid
aligntrue plugs set test.cmd "pnpm test && echo done" # ✗ Complex command with &&
aligntrue plugs set config.file "../secrets.json" # ✗ Parent directory traversal
aligntrue plugs set docs.url "example.com" # ✗ Missing http:// or https://Resolution algorithm
Plugs resolve during aligntrue sync before exporting to agents.
Resolution steps
- Normalize line endings - Convert CRLF/CR to LF
- Protect escapes - Temporarily replace
[[\plug:with sentinel - Resolve each plug:
- If fill exists → replace
[[plug:key]]with fill value - If required and no fill → insert TODO block
- If optional and no fill → replace with empty string
- If fill exists → replace
- Unescape literals - Restore
[[\plug:to[[plug: - Normalize output - Ensure single trailing LF
Resolution examples
Filled plug:
Input: Run tests with: [[plug:test.cmd]]
Fill: test.cmd: "pnpm test"
Output: Run tests with: pnpm testUnresolved required plug (with example):
Input: Run tests with: [[plug:test.cmd]]
Slot: required: true, example: "pytest -q"
Fill: (none)
Output: Run tests with: TODO(plug:test.cmd): Provide a value for this plug.
Examples: pytest -qUnresolved optional plug:
Input: Documentation: [[plug:docs.url]]
Slot: required: false
Fill: (none)
Output: Documentation:Escaped literal:
Input: Use [[\plug:key]] syntax for plugs
Output: Use [[plug:key]] syntax for plugsCLI commands
audit - List slots and fills
aligntrue plugs auditShows:
- All declared slots with descriptions and formats
- Current fill values
- Resolution status (filled, required, optional)
- Orphan fills (fills without slots)
- Summary statistics
Example output:
📌 Plugs Audit
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Slots declared:
test.cmd
Description: Command to run the project's tests
Format: command
Required: true
Example: pytest -q
Status: ✓ filled
Fill: pnpm test
docs.url
Description: Documentation website URL
Format: url
Required: false
Status: ○ optional
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Summary:
Total slots: 2
Required slots: 1
Filled required: 1resolve - Preview resolution
aligntrue plugs resolve [--dry-run]Previews plug resolution without writing changes. Shows resolved text and lists unresolved required plugs.
Example output:
✓ Resolved 2 plugs
Resolved text preview:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Run tests with: pnpm test
Documentation: https://docs.example.com
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Unresolved required plugs: 0set - Set fill value
aligntrue plugs set <key> <value>Sets a repo-local fill with format validation.
Example:
aligntrue plugs set test.cmd "pnpm test"Output:
✓ Set plug fill: test.cmd = "pnpm test"
Updated: .aligntrue/.rules.yaml
Next step:
Run: aligntrue syncSee CLI Reference for complete command documentation.
Scenario-based examples
Scenario 1: Solo developer with custom test command
Goal: Use shared TypeScript rules but customize test command for your project.
Setup:
# Pull upstream TypeScript pack
sources:
- git: https://github.com/org/typescript-standards
ref: v1.0.0Upstream pack includes:
rules:
- id: testing.run-before-commit
guidance: |
Run tests before committing: [[plug:test.cmd]]
plugs:
slots:
test.cmd:
description: "Command to run tests"
format: command
required: true
example: "pytest -q"Your customization:
# Set your project's test command
aligntrue plugs set test.cmd "pnpm test"
# Sync to agents
aligntrue syncResult: Rules use pnpm test instead of upstream’s pytest -q example.
Scenario 2: Team sharing stack-specific configs
Goal: Team uses shared base rules with stack-specific test commands.
Base pack (shared):
# base-rules.yaml
rules:
- id: testing.run-tests
guidance: |
Run tests: [[plug:test.cmd]]
plugs:
slots:
test.cmd:
description: "Command to run tests"
format: command
required: trueStack pack (Next.js team):
# nextjs-pack.yaml
plugs:
fills:
test.cmd: "pnpm test" # Default for Next.js projectsStack pack (Python team):
# python-pack.yaml
plugs:
fills:
test.cmd: "pytest -q" # Default for Python projectsProject overrides (if needed):
# Override stack default for specific project
aligntrue plugs set test.cmd "pnpm test:ci"Merge order:
- Base pack: declares slot
- Stack pack: provides stack default
- Repo-local: overrides if needed
Scenario 3: Multi-stack monorepo
Goal: Different test commands per scope in monorepo.
Config:
scopes:
- path: "apps/web"
rulesets: ["base-rules", "nextjs-rules"]
- path: "services/api"
rulesets: ["base-rules", "python-rules"]
plugs:
fills:
# Global fills (used if scope doesn't override)
test.cmd: "pnpm test"Scope-specific fills:
# apps/web/.aligntrue/.rules.yaml
plugs:
fills:
test.cmd: "pnpm test:web"
# services/api/.aligntrue/.rules.yaml
plugs:
fills:
test.cmd: "pytest -q"Result: Each scope uses its own test command.
Scenario 4: Documentation URLs per project
Goal: Shared rules reference project-specific documentation.
Shared rule:
rules:
- id: docs.link-in-readme
summary: Link to documentation in README
guidance: |
Add documentation link to README: [[plug:docs.url]]
applies_to: ["README.md"]
plugs:
slots:
docs.url:
description: "Project documentation URL"
format: url
required: false # Optional - not all projects have docs
example: "https://docs.example.com"Project A:
aligntrue plugs set docs.url "https://docs.projecta.com"Project B (no docs yet):
# Don't set fill - optional plug resolves to empty stringResult:
- Project A: Guidance includes docs URL
- Project B: Guidance omits docs URL (empty string)
Troubleshooting
Unresolved required plugs
Problem: Sync fails with “Unresolved required plugs”
Solution:
# 1. Audit to see which plugs need fills
aligntrue plugs audit
# 2. Set missing fills
aligntrue plugs set <key> <value>
# 3. Sync again
aligntrue syncFormat validation errors
Problem: Format validation failed: file
Solution: Check format requirements:
# Bad: Parent directory traversal
aligntrue plugs set config.file "../secrets.json" # ✗
# Good: Repo-relative path
aligntrue plugs set config.file "config/settings.json" # ✓
# Bad: Absolute path
aligntrue plugs set config.file "/etc/config.json" # ✗
# Good: Relative to repo root
aligntrue plugs set config.file "config/production.json" # ✓Orphan fills
Problem: Audit shows “Fills without declared slots”
Cause: Fill exists but no slot declared (typo or removed slot)
Solution:
# Option 1: Fix typo in fill key
aligntrue plugs set correct.key "value"
# Option 2: Remove orphan fill
# Edit .aligntrue/.rules.yaml and remove the fillMulti-line values
Problem: Need multi-line guidance with plug
Solution: Plugs are single-line only. Use multiple plugs or overlays:
# Bad: Multi-line plug (not supported)
guidance: |
[[plug:multi.line]]
# Good: Multiple single-line plugs
guidance: |
Step 1: [[plug:step.one]]
Step 2: [[plug:step.two]]
# Alternative: Use overlay to replace entire guidance
overlays:
overrides:
- selector: "rule[id=my-rule]"
set:
guidance: |
Custom multi-line
guidance hereEscaping plug syntax
Problem: Need to show [[plug:key]] literally in guidance
Solution: Use double backslash escape:
guidance: |
Use [[\plug:key]] syntax for plugsResult after resolution:
Use [[plug:key]] syntax for plugsDeterminism and hashing
Lock hash (pre-resolution)
Computed over canonicalized YAML before plug resolution:
# This YAML is hashed (with plugs unresolved)
rules:
- id: test
guidance: "Run: [[plug:test.cmd]]"
plugs:
slots:
test.cmd: { ... }
fills:
test.cmd: "pnpm test"Purpose: Detect changes to rule structure and plug declarations.
Export hash (post-resolution)
Computed over resolved text after plug resolution:
# This text is hashed (with plugs resolved)
Run: pnpm testPurpose: Detect changes to exported agent files.
Volatile fields
Fills are not volatile - they affect export hash. If you change a fill, the export hash changes.
Best practices
For rule authors
- Provide examples - Always include examples for required plugs
- Clear descriptions - One-line descriptions that explain the purpose
- Appropriate formats - Use the most restrictive format (command > file > text)
- Optional by default - Only mark as required if truly necessary
- Namespace keys - Use dots for organization:
test.cmd,docs.url,build.output
For solo developers
- Set fills early - Run
aligntrue plugs auditafter init - Use stack packs - Let stack packs provide sensible defaults
- Override selectively - Only set fills when defaults don’t work
- Document decisions - Add comments in .aligntrue/.rules.yaml explaining custom fills
For teams
- Share stack packs - Create org-specific stack packs with common fills
- Document required plugs - List required plugs in team onboarding docs
- Validate in CI - Run
aligntrue plugs auditin CI to catch missing fills - Review fill changes - Treat fill changes like code changes (PR review)
- Avoid secrets - Never put secrets in fills (use env vars at runtime)
Related documentation
- Customization Overview - When to use plugs vs overlays vs scopes
- Overlays Guide - Modify rule properties without forking
- Scopes Guide - Apply different rules per directory
- CLI Reference - Complete command docs
- Solo Developer Guide - Solo workflow with plugs
- Team Guide - Team collaboration with plugs