Open Source · MIT License · v0.1.x

promptweave

YAML composer for assembling agent prompts, hooks, and MCP configs from reusable behaviors.

0 engine passes
0 output kinds
0 bundled demo behaviors
0% deterministic
$ promptweave build inspect --dry-run
resolve inspect [project-context, worktree-isolation, read-only-mode]
validate 3/3 ok · compose 1 rule applied (announce-readonly)
✅ assemble prompt.md + hooks/*.sh + .mcp.json | SKILL.md — deterministic, diffable

Why promptweave?

Make your agent prompts, hooks, and MCP configs maintainable, vendor-agnostic, and diffable.

YAML, not copy-paste

Define agent identity, capabilities, and constraints in version-controlled YAML. Diff your prompts in code review like any other change.

$ git diff behaviors/read-only-mode.yaml
--- a/behaviors/read-only-mode.yaml
+++ b/behaviors/read-only-mode.yaml
@@ section 090-safety-readonly @@
- You are in read-only mode.
+ You are in read-only mode. Analyze, communicate, report.
→ rerenders 12 presets across 4 vendors

Vendor-agnostic

The same behavior catalog renders prompts, hooks, and MCP configs for Claude Code, Cursor, Cline, Aider — anything that consumes prompt + hook + MCP-config triples.

Claude Code
prompt + hooks + .mcp.json
Cursor
.cursorrules + MCP
Cline / Aider
prompt + tools
Your CLI
custom writer plugin

Composition over duplication

Behaviors compose. A read-only-mode overlay rewrites the agent's instructions automatically when paired with announce-before-write, instead of duplicating prompt text across roles.

Composition rule fires

presetinspect
behaviors
project-context worktree-isolation read-only-mode
rule matchedannounce-readonly-adaptation
actionsection 020 rewritten · "before your analysis"
outcomeno copy-paste · no drift

Numbered sections, deterministic output

Every behavior contributes numbered sections. The assembler sorts them, dedups, and produces byte-identical output for identical inputs — perfect for CI.

000 project-context → identity
010 worktree-isolation → setup
020 announce-before-write → collab
055 worktree-isolation → teardown
090 read-only-mode → safety
5 sections  ·  3 behaviors  ·  byte-identical

Pair with a runtime

Generated agents pair with mcp-coordinator for runtime announce/conflict/quota; see essaim for an end-to-end example.

The prompt-engineering problem

Hand-written agent prompts don't scale. Once you have 5+ roles across 2+ vendors, the catalog becomes unmaintainable.

📋

Copy-pasted prompts

Every new agent role starts as a copy of an existing prompt. Drift sets in. The team's many agents say slightly different things about the same constraints.

📄

No version control discipline

Prompts live in scattered files, copy-paste blocks in chat windows, or commits from days ago that nobody can reconstruct. Reviewing a prompt change is harder than reviewing code.

🔗

Cross-vendor incompatibility

Switching from Claude Code to Cursor or Aider means rewriting prompts, hooks, and MCP configs by hand. The same behavior — say, "work in read-only mode" — gets rewritten three times.

From chaos to composition

Compose your behavior catalog once, ship hundreds of agent variants. Without copy-paste, without drift, without vendor lock-in.

N behaviors
×
M presets
×
K vendors
=
N×M×K prompts assembled

All assembled from N YAML files. Add a vendor target — every preset re-renders. Change a behavior — all M presets pick it up. Hand-edited prompts cannot do this.

🫠

Edit once, propagate everywhere

Change a single line in read-only-mode.yaml — every preset that includes it re-renders byte-deterministically. No find-and-replace across 50 prompt files. No drift between agents that should say the same thing.

Conditional logic without branches

Composition rules apply mutations declaratively when behaviors meet — "if A and B both present, rewrite section X". Replaces dozens of conditional if/else blocks copy-pasted across role-specific prompts.

🎯

One catalog, every vendor

The same N behaviors compose for Claude Code, Cursor, Cline, Aider — anything consuming prompt + hook + MCP-config triples. Add vendor #5 with one writer plugin; never rewrite a behavior.

🧬

Prompts as first-class code

Generated outputs are deterministic. Diff them in PRs. Catch behavior drift in CI before it ships. Onboarding a new agent role → copy a preset, change one parameter, ship.

See it on a real preset

Watch a complex 6-behavior preset assemble. Composition rules fire automatically. Three artifacts emerge — deterministic, vendor-portable, diffable.

PRESET audit-team-leader
project-context 000
worktree-isolation 010, 055
sequential-wait 012
announce-before-write 020
read-only-mode 090
activity-tracking 095
compose
RULES FIRED 3 of 4 matched
sequential-then-announce when both present
+ inject section 012 — "wait for predecessor → announce → code"
announce-readonly-adaptation when both present
~ rewrite section 020 — "before your analysis" instead of "before modifying"
tracking-overlay when activity-tracking
+ append section 095 hooks — log every tool call to .coordinator-events
emit
ARTIFACTS byte-deterministic
📄 prompt.md
000 project-context
010 worktree setup
012 wait → announce → code injected
020 before your analysis rewritten
055 worktree teardown
090 read-only mode
095 activity-tracking appended
⚡ hooks/*.sh
SessionStart.sh
PostToolUse.sh
Stop.sh
⚙ .mcp.json
2 MCP tools registered

Change one behavior YAML → every preset that includes it re-renders byte-identically. That's the leverage.

How the engine works

Five passes from a preset to ready-to-ship prompts, hooks, and MCP configs.

1
🔗

Resolve

A preset is resolved into a flat list of behaviors. Shared dependencies are deduplicated automatically.

2

Validate

Every behavior is checked: required parameters present, references resolve, schema valid. Errors point to the source YAML.

3
🧰

Compose

Composition rules apply: when behaviors A and B are both present, override section X, inject section Y, or strip behavior Z.

4
📦

Assemble

Sections sort numerically into a single prompt. Hooks consolidate per lifecycle. MCP tools merge into a single .mcp.json. Output is byte-deterministic.

Anatomy of a behavior

One YAML file. Every field, optional or required, in one place.

# behaviors/read-only-mode.yaml
name: read-only-mode # required — unique id, kebab-case
description: "Analyze without writing" # required — one-line summary
category: safety # optional — workspace | coordination | mission | safety | tone
 
# — Dependencies —
requires:
  behaviors: [project-context] # must compose with these
  infrastructure: [git] # tools that must be present
conflicts_with: [auto-commit] # cannot coexist
suggests: [announce-readonly] # soft hint, not enforced
 
# — Parameters —
params:
  scope:
    type: string # string | number | boolean | string[] | number[]
    default: "workspace"
    required: false
    description: "Where the read-only rule applies"
 
# — Prompt sections (required, sorted by NNN-key) —
sections:
  090-safety-readonly:
    prompt: "You are read-only. Analyze, communicate, report."
 
# — Lifecycle hooks —
hooks:
  pre-tool-use: # session-start | pre-tool-use | post-tool-use | session-stop
    script: hooks/block-writes.sh
    args: ["--strict"]
    blocking: true
    order: 10
 
# — MCP & phase —
mcp_tools: [filesystem, git] # servers this behavior expects
phase:
  name: inspect
  tools_mode: read_only # read_only | full | none
  loop: false
applies_when:
  phase_tools_mode: [read_only] # gate: only apply in matching modes
nameUnique kebab-case identifier used to compose
string
required
descriptionOne-line summary shown in catalogs and diffs
string
required
sectionsPrompt fragments keyed by NNN-name, deterministic order
map
required
categoryTaxonomy bucket: workspace, coordination, mission, safety, tone
enum
optional
requiresHard dependencies on other behaviors and infrastructure
object
optional
conflicts_withBehaviors that cannot be composed alongside this one
string[]
optional
suggestsSoft hints surfaced to the user, never enforced
string[]
optional
paramsTyped inputs with default, required flag, and description
map
optional
hooksLifecycle scripts (script, args, blocking, order) per phase
map
optional
mcp_toolsMCP servers this behavior declares as needed
string[]
optional
phaseDeclares phase name, tools_mode, and loop
object
optional
applies_whenConditional gate based on the active phase tools_mode
object
optional

Only name, description, and sections are strictly required. Everything else is opt-in — declare exactly what your behavior needs, nothing more.

Composition rules: declarative behavior adaptation

When two behaviors meet, rewrite or strip sections — without forcing every behavior to know about every other.

The when predicate

A rule fires only when the assembled behavior set matches its predicate. Combine all, any, none, and params_match to express « these two together, but not with that third one » without coupling behavior YAMLs to each other.

# compositions/announce-readonly-adaptation.yaml
name: announce-readonly-adaptation
priority: 10
when:
  all: [announce-before-write, read-only-mode]
  none: [worktree-isolation]
  params_match:
    read-only-mode: { strict: true }
# → matches preset `inspect`, skips `dev`

The four actions

Once a rule matches, its actions reshape the assembly. Override an existing section in place, inject a brand-new bridge section, force params on a behavior you don't own, or strip a behavior wholesale — all declaratively, no JS hooks.

actions: { ... }

override_sections[]rewrite 020 · "before your analysis"
inject_sections{}+ 012-bridge · new section
override_params[]force quiet: true on announce
disable_behaviors[]strip conflict-resolution
outcomeno behavior knows about the others

Priority & evaluation order

Rules are evaluated in ascending priority order (default 0), then by registration order. Lower priorities run first — so a high-priority « strip » rule sees the result of every override beneath it. Deterministic. Diffable.

$ promptweave build inspect --dry-run
 
priority 0  sequential-then-announce
    when: all=[sequential-pipeline, announce-before-write]
    + inject 012-bridge → "wait → announce → code"
 
priority 10 announce-readonly-adaptation
    when: all=[announce-before-write, read-only-mode]
    ~ rewrite 020-before-coding → "before your analysis"
 
priority 20 solo-mode-strip
    when: any=[solo-mode] · params_match failed
    × skipped — preset is multi-agent
 
2 of 3 rules applied · byte-deterministic

Rules live in compositions/*.yaml

One file per rule, version-controlled next to your behaviors. The engine auto-loads the directory, evaluates every rule against the resolved behavior set, and emits a compositionRulesApplied trace in the pipeline result — so you can audit which rules fired on every render.

Hook lifecycle

Bash scripts run at four lifecycle points. Behaviors compose them; the engine merges them per point in declared order.

Lifecycle point Fires Typical use Example
session-start Once, before agent's first turn Setup workspace, env, worktree worktree-isolation creates a branch
pre-tool-use Before every tool call Validate, log, gate Custom rules check before file edit
post-tool-use After every tool call Audit, sync, cleanup Activity tracking writes to log
session-stop Once, after agent's last turn Teardown, archive worktree-isolation cleans up branch

Declare a hook in a behavior

Add a hooks: block to any behavior YAML. The engine collects entries from every behavior in the preset and writes one merged script per lifecycle point.

hooks:
  session-start:
    script: hooks/setup_worktree.sh
    args: ["--branch", "agent-{{agent.id}}"]
    blocking: true
    order: 10

The engine merges hooks from multiple behaviors by lifecycle point, sorted by order. The Bundle target writes them as hooks/<lifecycle>.sh. The Skill target drops them with a warning.

Phases & profiles

Multi-stage workflows out of the box. Tools modes per phase, profiles for intent.

Phases — multi-stage agent workflows

A behavior can declare a phase; presets that include phased behaviors render as a multi-stage workflow, while presets without any phase produce a single one-shot prompt (backward-compat).

Phase Tools Loop Purpose
discover read_only no Scan code, list findings independently.
review none no Compare findings, dedup pool.
execute full yes Atomic claim → run → claim next.
no-phase configurable no One-shot mode (backward-compat).

A behavior can also declare applies_when.phase_tools_mode: ["read_only"] to scope itself to phases with a matching tools mode — included in some stages, filtered out of others.

Profiles — declare agent intent

A profile is a shorthand declared on a preset or an agent. It signals what the agent is for; composition rules and templates can read it.

codeur

profile: codeur

Agent that writes code. Defaults to full tool access. Pairs with worktree-isolation and mission behaviors.

communicant

profile: communicant

Agent that reports, reviews, communicates. Pairs with read-only-mode for analysis-only flows.

Inside the engine

A preset names the behaviors. The engine resolves, validates, composes, assembles, and emits prompt.md + hooks/*.sh + .mcp.json — deterministic, byte-for-byte.

Preset
your-preset.yaml
promptweave engine
resolve · validate · compose · assemble
prompt.md
hooks/*.sh
 
.mcp.json

Four behavioral layers, deterministic section order

Each behavior contributes numbered sections. Layers are a recommended convention so prompts stay readable as your catalog grows.

FoundationIdentity, project context
000–009
layer 1
PatternsHow the agent collaborates
010–029
layer 2
MissionWhat the agent actually does
030–049
layer 3
TransversalConstraints and style overlays
050–099
layer 4

Get started in 5 steps

From npm install to a shipped bundle — with full control over what lands on disk.

Step 1

Install

Grab the npm package. The CLI is self-contained — only Node.js 20+ required.

# Node 20+ required
npm install -g @swoofer/promptweave
promptweave --version
Step 2

Inspect bundled demos

4 demo behaviors and 2 demo presets ship bundled — just enough to feel the engine. Real catalogs live in your repo via --root.

# list the 4 demo behaviors
promptweave list behaviors
# list the 2 demo presets
promptweave list presets
Step 3

Preview a build

See exactly what would be assembled — resolved behaviors, composed sections, generated files — without touching disk.

# preview, no files written
promptweave build inspect --dry-run
Step 4

Ship it

Two render targets. Default writes a bundle (prompt.md + hooks + .mcp.json) into ./.claude/promptweave/. Pass --target skill for a Claude Code SKILL.md instead.

# bundle (default target)
promptweave build inspect
# or as a Claude Code skill
promptweave build inspect --target skill
Step 5

Use your own catalog

Point --root at your repo's catalog and override any templated parameter on the fly with --set k=v — repeatable, deterministic, scriptable.

# build from your catalog
promptweave build my-preset --root ./my-catalog
# override params at build time
promptweave build my-preset --root ./my-catalog --set language=rust

Your first catalog in 5 minutes

Build a custom behavior, compose a preset, render the bundle. Real shell commands you can copy.

1
📁

Scaffold the catalog

Three folders — one per concept. Point --root at this directory and promptweave will discover everything inside.

$ mkdir -p my-catalog/{behaviors,presets,compositions}
my-catalog/
├── behaviors/ # one YAML per reusable trait
├── presets/ # named lists of behaviors
└── compositions/ # rules that fire when behaviors meet
2
📝

Write a behavior

A behavior is one YAML. It contributes one or more numbered sections to the assembled prompt — here, section 070 in the tone layer.

# behaviors/concise-tone.yaml
name: concise-tone
description: Agent answers in short, declarative sentences
category: tone
sections:
  "070-tone":
    prompt: |
      Be brief. One claim per sentence. Skip pleasantries.
3
🧰

Compose a preset

A preset is a named list of behaviors. Mix bundled demos (project-context, read-only-mode) with your custom concise-tone.

# presets/quick-review.yaml
name: quick-review
description: Concise read-only code review
profile: communicant
behaviors:
  - project-context
  - read-only-mode
  - concise-tone
4
🔎

Preview with --dry-run

Resolve, validate, compose, assemble — nothing is written to disk. Catch missing references and section conflicts before they reach an agent.

$ promptweave build quick-review --root ./my-catalog --dry-run
resolve quick-review → [project-context, read-only-mode, concise-tone]
validate 3/3 ok · refs resolved · schema valid
compose 1 rule fired · announce-readonly-adaptation → section 020 rewritten
assemble sections [000, 020, 070, 090] · 4 unique · sorted
✅ preview ready — prompt.md (1.2 KB) · .mcp.json · hooks/ (0)
⚠ --dry-run: nothing written. Drop the flag to ship.
5
🚀

Ship it — bundle or skill

Same preset, two outputs. bundle writes .claude/promptweave/ for in-repo use; skill writes a publish-ready Claude Code SKILL.md.

# default target: bundle (prompt + hooks + .mcp.json)
$ promptweave build quick-review --root ./my-catalog
✅ wrote .claude/promptweave/quick-review/ · 3 files
# or, publish-ready Claude Code skill
$ promptweave build quick-review --root ./my-catalog --target skill
✅ wrote .claude/skills/quick-review/SKILL.md
# tweak params at build time, no YAML edit needed
$ promptweave build quick-review --root ./my-catalog --set language=python --output ./out

Need richer catalogs? See essaim — the reference orchestrator with 32+ behaviors, 20+ presets, and 12 pre-composed templates, all rendered by promptweave.

Bundle or Skill — pick your output

One catalog, two emit modes. Bundle for full runtime, Skill for catalog publishing.

Default target

Bundle

Full runtime profile. Prompt + hooks + MCP config + env vars, written to ./.claude/promptweave/<agent>/ with an atomic backup-swap.

./.claude/promptweave/<agent>/
prompt.md
hooks/*.sh
.mcp.json
.env
  • Full prompt assembly (numbered sections)
  • Hooks emitted as executable .sh files
  • MCP servers merged into project-root .mcp.json
  • Phases & env vars preserved
  • Atomic backup-swap on rebuild
promptweave build inspect
Catalog target

Skill

A single SKILL.md ready to publish, written to ./.claude/skills/<preset>/. Frontmatter + prompt body + auto-generated Parameters.

frontmatter
+
body
+
## Parameters
./.claude/skills/<preset>/
SKILL.md
  • Slug-validated name (^[a-z0-9-]+$) & YAML-escaped description
  • Auto-generated ## Parameters from preset params
  • Drops with warning: hooks · mcp_tools · phases · env vars
  • Output dir is rewritten on every build — don't hand-edit
promptweave build inspect --target skill

Which one fits?

Need hooks, MCP tools, phased workflows, or env vars? → Bundle
Publishing to a Claude Code skill catalog? → Skill
Just exploring? Default is fine. bundle (no flag needed)

What ships bundled

promptweave bundles 4 demo behaviors and 2 demo presets — just enough to show the engine working. Real-world catalogs (32+ behaviors, dozens of presets) live in your project via --root.

4 demo behaviors

One YAML per behavior. Each contributes one or more numbered sections to the assembled prompt.

project-context

category: coordination · section 000

Project identity. Templated parameters for language, test command, and module list. Renders the agent's "where am I?" briefing.

worktree-isolation

category: workspace · sections 010 + 055 · hooks: session-start, session-stop

Isolate the agent in a dedicated git worktree branch. Ships hook scripts that set up and tear down the worktree. Conflicts with shared-workspace.

shared-workspace

category: workspace · section 010

All agents work in the same directory. Typically paired with read-only-mode for analysis-only flows. Conflicts with worktree-isolation.

read-only-mode

category: safety · section 090

Agent cannot modify files. Analyzes, communicates, reports. Useful for code-review or audit roles.

2 demo presets

A preset is a named list of behaviors. The engine resolves, validates, composes, and assembles them into ready-to-ship outputs.

devSolo development session in an isolated worktree.
Composes: project-context + worktree-isolation
2 behaviors
inspectRead-only project inspection in an isolated worktree.
Composes: project-context + worktree-isolation + read-only-mode
3 behaviors

Looking for richer catalogs? The reference orchestrator essaim ships 32+ behaviors, 20+ presets, and 12 pre-composed templates (bug-hunt, parallel-tests, code-review, etc.) — all assembled by promptweave at runtime.

Use as a library

Programmatic API for CI pipelines, custom renderers, and migration tools.

Run the pipeline programmatically

The pipeline is a pure function: Registry → AgentSpec → PipelineResult. No filesystem side effects until you call writeOutput. Ideal for CI that re-renders every bundle on each commit, custom writers that target proprietary tools, or migration scripts that diff old vs. new behavior catalogs.

PipelineResult exposes agent, behaviors[], compositionRulesApplied[], output, warnings[], and sectionTrace[] — everything you need to assert on in tests.

import { Registry, runPipeline } from "@swoofer/promptweave";
 
// Load behaviors, presets, compositions from disk
const registry = Registry.load("./my-prompts");
 
// Pure: no writes, just resolve + assemble
const result = runPipeline(
  { name: "agent-x", preset: "inspect" },
  "./my-prompts",
  {},
);
 
console.log(result.output.prompt);
console.log(result.output.hooks);
console.log(result.output.mcpTools);

High-level

Two entry points cover 90% of integrations.

Registry.load(path) — loads behaviors, presets, and compositions from a directory.

runPipeline(agent, path, params) — orchestrates resolve → validate → compose → assemble and returns a full PipelineResult.

Low-level (granular)

Drop into any pipeline stage to build custom tooling.

resolveBehaviors, resolveParams — expand presets and merge parameters.

validateBehaviors — enforce conflicts, requires, and missing-param checks.

applyCompositionRules — apply pattern-matched rule overrides.

assemblePrompt, assembleHooks, assembleMcpTools — deterministic section sort and dedup.

bundleRenderer, skillRenderer — built-in writers for prompt+hooks+MCP and SKILL.md targets.

Types live in @swoofer/promptweave/types. The pipeline is deterministic — same inputs produce identical PipelineResult.

Roadmap

Where we're going next.

Done

v0.1 — Initial release

Engine + 4 demo behaviors + 2 demo presets. npm package, deterministic output, GH Pages landing.

In Progress

v0.2 — Stabilization

Better validation errors, machine-readable validate output, custom output writers, behavior schema versioning.

Planned

v0.3 — Plugin system

Third-party renderers (TOML hooks, INI configs, custom MCP-config dialects). Behaviors stay vendor-agnostic; targets are pluggable.

Future

v1.0 — Cross-catalog imports

Pull a behavior from another package as a dependency. Behavior versioning + lockfile-style resolution for shared catalogs across teams.

Future

Long-term — Declarative agent contracts

A behavior's effective contract — sections it owns, parameters it accepts, hooks it provides — published as a typed schema. Composition errors caught at validate-time, not at runtime.