Pack author guide
A pack is a directory of Liquid templates that adds agents, skills, and instructions to vsuite or overrides built-in agents and skills by id. The built-in catalog stays available; packs are optional. A project selects pack agents and skills in vsuite.json, and vsuite generate renders them with the same engine and context as the catalog. See the example pack for a complete walkthrough, the boilerplate pack for a copyable starter pack, and the template context reference for every variable. Organisations packaging, distributing, and rolling out their own packs should read the enterprise pack guide.
Layout
my-pack/
├── vsuite-pack.yaml
├── agents/<id>.md.liquid
├── skills/<id>/SKILL.md.liquid
├── instructions/<id>.md.liquid
└── partials/<name>.md.liquidvsuite-pack.yaml fields:
| Field | Meaning |
|---|---|
id |
Pack id, [a-z0-9-]+. |
name |
Display name. |
description |
Optional one-line summary of the pack, shown in UI and sent to the AI assistant. |
version |
Pack version (semver). |
contextVersion |
Template context contract version. 1 or 2 (current: 2). |
vsuite |
Semver range of vsuite releases the pack supports, for example ">=0.4". Enforced: a vsuite release outside the range fails with PACK_MANIFEST. |
The config key a project gives the pack (acme in "packs": { "acme": … }, or --name on pack add) is its name in pack:<name> sources, pack:<name> partials, and error messages; it defaults to the manifest id.
Limits
- At most 500 files, each at most 256 KB.
- Agent, skill, and partial ids match
[a-z0-9-]+. - Symbolic links must resolve inside the pack directory.
- Every file must be a regular, valid UTF-8 text file without NUL bytes.
These limits are cooperative safeguards against mistakes, not a sandbox; see Trust model.
Front matter
Agent and skill templates start with YAML front matter:
---
description: Reviews diffs for security defects against the Acme standards and threat model.
tools: [read, search, execute, todo]
requiredSkills: [acme-threat-model]
---| Field | Applies to | Meaning |
|---|---|---|
description |
agents, skills | Required for ids that are new to the catalog. Overrides inherit the built-in description when omitted. |
whenToUse |
agents, skills | Decision-oriented prose for the AI assistant; falls back to description when omitted. |
tools |
agents | Neutral tool names. The agent gets the union of the template’s tools and any tools configured in vsuite.json. |
requiredSkills |
agents | Skills the agent always gets. The agent’s skills are the union of configured skills and these. |
preferences |
agents | Preference groups the agent declares (for example tracking), which makes the matching vsuite.json preferences valid. |
role |
agents | coordinator or specialist. |
Overrides inherit every field they omit from the built-in definition.
Templates
Templates use LiquidJS 10.x (exact version pinned in packages/templates/package.json) with a restricted configuration:
strictVariables: an unknown variable is an error (TPL_UNKNOWN_VAR). Only paths in the context reference exist.lenientIf:{% if optional.field %}works for optional fields that may be absent.strictFilters: an unknown filter is an error (TPL_UNKNOWN_FILTER).ownPropertyOnly: templates see only the context’s own data.include,layout, andblockare disabled (TPL_UNKNOWN_TAG). Use{% render %}.- The
datefamily of filters andsampleare disabled so output is deterministic. - Parse limit 1 Mi characters, render limit 2000 ms, memory limit 16 Mi units (
TPL_LIMIT).
Filters
All Liquid built-in filters except those above, plus:
| Filter | Result |
|---|---|
md_escape |
Backslash-escapes \ * _ ` [ ] < > #. |
code |
A CommonMark inline code span whose fence is one backtick longer than the longest backtick run in the value. |
join_human |
Joins an array as "", a, a and b, or a, b and c. |
Partials
{% render %} accepts only two kinds of names:
vsuite:<name>: a built-in partial (list below).pack:<name>:partials/<name>.md.liquidin the same pack.
Any other name, path, or .. fails with TPL_BAD_PARTIAL. Partials see the whole template context.
Built-in partials:
| Partial | Renders |
|---|---|
vsuite:collaboration |
Collaboration section. |
vsuite:context7 |
Current documentation (Context7) section. |
vsuite:documentation-preference |
Documentation preference line. |
vsuite:efficiency |
Working efficiently section. |
vsuite:evidence |
Evidence standards section. |
vsuite:frontend-preference |
Frontend framework and design library lines. |
vsuite:memory |
Persistent memory section; empty unless capabilities.agentMemory. Required. |
vsuite:metrics |
Job metrics rules; empty unless capabilities.agentMetrics. Required. |
vsuite:metrics-delegation |
Metrics records for read-only specialists; empty unless metrics are on and there are read-only specialists. |
vsuite:review-contract |
Review contract section. |
vsuite:roster |
Specialist roster; empty when there are no specialists. |
vsuite:skills |
Required skills section; empty when the agent has no skills. Required. |
vsuite:stack |
Project stack section; empty when the stack is empty. Required. |
vsuite:telemetry |
Target-specific telemetry instructions; empty unless the agent is agent-optimizer and metrics are on. Required. |
vsuite:tracking-preference |
Tracking provider line. |
Required sections and auto-append
Agent templates must include five sections: telemetry, stack, skills, metrics, and memory. Place them with {% render "vsuite:<name>" %} where you want them. Any you do not place are appended to the end of the agent body in that order. Skill templates have no required sections.
- A partial placed inside an
{% if %}branch that does not render does not count as placed, so it is appended. - A required partial placed twice produces an
MD_LINTwarning. - Required partials guard themselves: they render nothing when their condition is false, so you can place them unconditionally.
The UI preview marks which sections were auto-appended.
Instructions
An instructions/<id>.md.liquid file is a pack-only instruction template. It has no front matter and no selection: every loaded pack’s instructions are rendered for every configured target. Instructions see the standard template context but have no agent context (like skills).
Each rendered instruction is written to the target’s native location and auto-wired:
| Target | Output | Wiring |
|---|---|---|
| OpenCode | .opencode/instructions/<pack>-<id>.md |
The path is appended to the instructions array in .opencode/opencode.json. |
| Claude Code | .claude/rules/<pack>-<id>.md |
Everything under .claude/rules/ is auto-loaded. |
| GitHub Copilot | .github/instructions/<pack>-<id>.instructions.md |
The file starts with applyTo: "**" so it applies to the whole repository. |
The <pack> part is the pack’s config name, so a pack renamed with pack add --name changes the file stem.
Errors
Every failure has a code, the pack name (catalog for built-in templates), and, where known, file, line, column, and a hint.
| Code | Meaning |
|---|---|
PACK_FETCH |
The source could not be fetched (missing path, missing or unreadable vsuite-pack.yaml, npm or git failure). |
PACK_INTEGRITY |
Pack content does not match the lockfile integrity. |
PACK_MANIFEST |
vsuite-pack.yaml is invalid (schema, or the vsuite range excludes this release). |
PACK_FRONTMATTER |
Template front matter is invalid (for example, a new id without description). |
PACK_LAYOUT |
Unexpected files, bad ids, or limit violations (file size, file count, symlinks escaping the pack, non-regular, non-UTF-8, or NUL-containing files). |
PACK_CONTEXT_VERSION |
The pack’s contextVersion does not match this vsuite’s template context version. |
PACK_CONFLICT |
Two packs define the same id; select one with source: "pack:<name>". |
PACK_MISSING_ENTRY |
The selected pack does not provide the id named in vsuite.json. |
TPL_UNKNOWN_VAR |
A variable is not in the context. |
TPL_UNKNOWN_FILTER |
A filter is not a Liquid built-in or md_escape, code, join_human. |
TPL_UNKNOWN_TAG |
A disabled or unknown tag (include, layout, block). |
TPL_BAD_PARTIAL |
render names something other than an existing vsuite:<name> or pack:<name> partial. |
TPL_LIMIT |
A parse, render-time, or memory limit was exceeded, or the output contains a NUL character. |
MD_LINT |
The rendered Markdown has a lint issue. Reports outputLine (line in the generated file) and templateLine (line in the template). A warning, or an error with --strict. |
Using a pack in a project
vsuite.json:
"packs": {
"acme": { "source": "npm:@acme/vsuite-pack@^1.2.0" },
"local": { "source": "path:./.vsuite/packs/team" },
"infra": { "source": "git:https://git.example.com/infra/pack.git#v2.0.0" }
},
"agents": {
"code-reviewer": { "source": "pack:acme" },
"secure-reviewer": { "source": "pack:acme" }
},
"skillSources": {
"acme-threat-model": { "source": "pack:acme" }
}Sources are path:<dir>, npm:<spec>, and git:<url>#<ref>. Entries default to source: "catalog"; set it back to catalog to revert an override. Use vsuite agent use and vsuite skill use rather than editing by hand (see the CLI README).
Lockfile
vsuite.lock.json (lockfileVersion: 2; version 1 files are read and rewritten) records per pack the source, the resolved version or commit, integrity (an SRI string, sha256- plus base64, over the sorted file list and contents), contextVersion, and generatedSkills / generatedAgents / generatedInstructions (ids last generated, so stale outputs are removed). pendingRemovalSkills / pendingRemovalAgents / pendingRemovalInstructions record outputs of removed packs that the next generate deletes. Commit the lockfile.
When pack content no longer matches the lock:
path:packs:generatewarns and relocks.npm:andgit:packs:generateand the UI preview stop withPACK_INTEGRITYunless you pass--update-packs(or runvsuite pack update).
Validating
vsuite pack validate <dir> [--json] [--strict] needs no project. It checks the manifest, front matter, and layout, test-renders every template against built-in fixture contexts (empty and full stack, each target, metrics and memory on and off), and lints the Markdown. It exits non-zero on failure; --strict also fails on MD_LINT warnings.
Trust model
Packs are trusted code-adjacent content: install them only from sources you trust, pinned by version, commit, or path and verified by lockfile integrity. The size, count, and render limits are cooperative safeguards, not isolation. There is no signing or sandbox yet; the lockfile format leaves room for signature fields. The original security reviews are kept as historical records in docs/superpowers/reviews/ (dated 2026-10-02); this guide describes current behavior.
Versioning
contextVersionversions the template context. This release supports1and2(current:2); a breaking context change gets a new version and a new reference.vsuitein the manifest declares which vsuite releases the pack supports. Enforced: a vsuite release outside the range fails withPACK_MANIFEST.- Bump the pack
versionon every release; consumers relock withvsuite pack update.