Enterprise pack guide
This guide covers how an organisation creates, packages, verifies, distributes, deploys, and connects its own vsuite packs. It builds on three reference pages and does not repeat them:
- Pack author guide: layout, front matter, filters, partials, auto-append, error codes, limits, trust model.
- Template context reference: every variable a template can read.
- Example pack: acme: a small annotated pack.
The worked example here is the contoso pack in tests/fixtures/packs/contoso/. Its file listings below are checked against the fixture by tests/docs-snippets.test.ts, and the command output was captured from the built CLI (node packages/cli/dist/main.js) at vsuite 0.4.0.
1. Overview and concepts
A pack is a directory of Liquid templates plus a vsuite-pack.yaml manifest. A project lists packs in vsuite.json, picks which agents and skills come from them, and vsuite generate renders them for every configured target (OpenCode, Claude Code, GitHub Copilot) with the same engine as the built-in catalog.
| A pack can | A pack cannot |
|---|---|
Add new agents (agents/<id>.md.liquid) and skills (skills/<id>/SKILL.md.liquid). |
Override individual built-in fragments; it replaces a whole agent or skill body. |
| Override a built-in agent or skill by using its id; omitted front matter is inherited. | Run code: there are no hooks, scripts, or custom filters. |
Share text through pack:<name> partials (partials/<name>.md.liquid). |
Include arbitrary files: include, layout, and block are disabled; render accepts only vsuite: and pack: names. |
Place the built-in vsuite:* sections (skills, stack, metrics, memory, telemetry, roster, …) where it wants; required ones it skips are auto-appended. |
Produce non-deterministic output: the date filters and sample are disabled. |
| Read project data: stack, preferences, capabilities, roster, target. | Read variables outside the context (TPL_UNKNOWN_VAR). |
The built-in catalog is always available. A pack only affects entries a project explicitly points at it ("source": "pack:<name>"), plus new pack-only ids the project adds.
How a pack flows into generated files:
flowchart LR
A[vsuite.json<br/>packs + sources] --> B[Resolve source<br/>path / npm / git]
B --> C[Read and validate<br/>manifest, layout, front matter]
C --> D{Integrity matches<br/>vsuite.lock.json?}
D -- "no, npm/git" --> X[Stop: PACK_INTEGRITY]
D -- "no, path" --> W[Warn and relock]
D -- yes --> E[Merge with catalog<br/>by id]
W --> E
E --> F[Render Liquid<br/>per agent, skill, target]
F --> G[Auto-append missing<br/>required sections]
G --> H[Lint Markdown<br/>MD_LINT]
H --> I[Write target files<br/>.opencode, .claude, .github]
2. Planning an enterprise pack
One organisation pack or several
| Model | When it fits | Watch out for |
|---|---|---|
One org pack (@contoso/vsuite-pack) |
Shared policy, one platform team owns agent definitions. | Every team gets every change; release cadence is shared. |
| Org pack + team packs | Teams add domain agents on top of org policy. | Two packs defining the same id fail with PACK_CONFLICT; the project must choose one with source: "pack:<name>". Agree id prefixes per pack. |
Repo-local pack (path:./.vsuite/packs/team) |
Experiments, single-repo agents. | No version; changes relock silently with a warning. |
Partials are private to their pack: pack:<name> resolves only inside the same pack, so a team pack cannot render the org pack’s partials. Shared wording must be copied or kept in one pack.
Naming and versioning
- Pack id (
idin the manifest):[a-z0-9-]+, for examplecontoso. Projects can rename it locally withpack add --name. - New ids: prefix agents and skills that are new to the catalog with the org name (
contoso-secure-coding) so they never collide with future built-ins or other packs. Use a bare built-in id (code-reviewer) only when you intend to override it. description(manifest): optional one-line summary of the pack, shown in the UI and sent to the AI assistant.version: semver. Bump it on every release; major for removed or renamed ids or changedrequiredSkills, minor for new ids, patch for wording.contextVersion:1or2(current:2) in this release. A breaking context change in vsuite gets a new version.vsuite: the range of vsuite releases you test against, for example">=0.4". A release outside the range fails withPACK_MANIFEST.
Override or new agent
flowchart TD
S[Need different agent behaviour] --> Q1{Same job as a<br/>built-in agent?}
Q1 -- no --> N[New agent with a prefixed id<br/>description required]
Q1 -- yes --> Q2{Should every project using<br/>the pack get the change<br/>when it selects the pack?}
Q2 -- yes --> O[Override the built-in id<br/>projects opt in per agent]
Q2 -- "no, only extra rules" --> K[Keep the built-in agent and<br/>add a pack skill it can be given]
Overrides replace the whole body, so you own its upkeep when the built-in improves. Prefer a new skill when you only need to add rules.
3. Tutorial: the Contoso pack
The pack adds a compliance-reviewer agent and a contoso-secure-coding skill, overrides code-reviewer, and shares one contoso-policy partial.
contoso-pack/
├── vsuite-pack.yaml
├── agents/
│ ├── code-reviewer.md.liquid
│ └── compliance-reviewer.md.liquid
├── partials/
│ └── contoso-policy.md.liquid
└── skills/
└── contoso-secure-coding/
└── SKILL.md.liquidOther files (README, package.json, CI config) are ignored by vsuite and are not part of the integrity hash.
Manifest
id: contoso
name: Contoso Engineering Pack
version: 1.0.0
contextVersion: 2
vsuite: ">=0.4"Shared partial
Uses pack.id, pack.version, and capabilities.agentMetrics. The {%- trims keep the output free of blank lines when the condition is false.
## Contoso Engineering Policy
- Policy source: {{ pack.id }} pack {{ pack.version }}.
- Every change references a work item in the commit body (`Work-Item: CTS-1234`).
- Secrets come from the Contoso key vault; never commit credentials, tokens, or `.env` files.
- Personal data follows the Contoso data classification: `public`, `internal`, `confidential`, `restricted`.
- Findings use the Contoso severity scale: `SEV1` blocks release, `SEV2` blocks merge, `SEV3` is tracked.
{%- if capabilities.agentMetrics %}
- Record compliance findings in the job-metrics log so audits can trace them.
{%- endif %}New agent: compliance-reviewer
New id, so description is required. It requires the pack skill, loops over project.stack, renders the pack partial, and places vsuite:skills; telemetry, stack, metrics, and memory are auto-appended (each renders nothing when its condition is off). Agent and skill front matter may also set whenToUse, decision-oriented prose for the AI assistant that falls back to description when omitted.
---
description: Reviews diffs for Contoso compliance, data-handling, and secure-coding policy violations.
tools: [read, search, todo]
requiredSkills: [contoso-secure-coding]
role: specialist
---
## Identity
- Role: Compliance reviewer for Contoso services.
- Personality: Methodical, policy-literate, evidence-driven.
- Experience: Knows that audit findings start as small, unreviewed shortcuts.
## Core Mission
Find compliance and data-handling violations in a supplied diff before it merges.
1. Classify every data field the change touches.
2. Check the change against the Contoso policy and the secure-coding skill.
3. Report each finding with file, line, Contoso severity, and the policy clause.
{%- if project.stack.size > 0 %}
## Stack Focus
{% for entry in project.stack %}
- `{{ entry.category }}`: check {{ entry.labels | join_human }} against the secure-coding rules for that technology.
{%- endfor %}
{%- endif %}
{% render "pack:contoso-policy" %}
{% render "vsuite:skills" %}
## Review Contract
- Reply `APPROVE`, `CHANGE: <finding>`, or `BLOCK: <SEV1 finding>`.
- Review read-only; do not edit files.project.stack holds only the stack categories the agent is configured for (the stack array on the agent entry in vsuite.json). With "stack": ["backend", "orm", "database"] on a NestJS + Prisma + PostgreSQL project, the generated section is:
## Stack Focus
- `backend`: check NestJS against the secure-coding rules for that technology.
- `orm`: check Prisma against the secure-coding rules for that technology.
- `database`: check PostgreSQL against the secure-coding rules for that technology.Override: code-reviewer
code-reviewer exists in the catalog, so the template inherits description, tools, and the rest. requiredSkills adds the Contoso skill to the skills the project configures (the generated agent lists both review-priority-tiers and contoso-secure-coding).
---
requiredSkills: [contoso-secure-coding]
---
## Identity
- Role: Code reviewer for Contoso repositories.
- Personality: Constructive, specific, evidence-driven.
- Experience: Knows that the best reviews teach, not just criticize.
## Core Mission
Review verified diffs against Contoso standards in one pass.
1. Classify every finding as `BLOCK`, `CHANGE`, or `NOTE`.
2. Name the file, line, and correction for each finding.
3. Explain why each finding matters.
{% render "vsuite:efficiency" %}
{% render "vsuite:evidence" %}
{% render "vsuite:review-contract" %}
{% render "pack:contoso-policy" %}Skill: contoso-secure-coding
Skills have no required sections. roster.specialists is guarded so the line appears only when there are specialists to name.
---
description: Applies the Contoso secure-coding checklist to a change. Use when code handles input, secrets, authentication, or personal data.
---
# Contoso Secure Coding
Checklist from the {{ pack.id }} pack, version {{ pack.version }}.
1. Validate every external input at the trust boundary; reject, do not sanitize silently.
2. Load secrets from the Contoso key vault at runtime; never log them.
3. Require authentication and authorization on every non-public endpoint.
4. Mask `confidential` and `restricted` fields in logs, errors, and analytics.
5. Pin dependencies and keep the lockfile in the same change as the manifest.
{%- if roster.specialists.size > 0 %}
Escalate to a specialist when a finding is outside your role: {{ roster.specialists | map: "id" | join_human }}.
{%- endif %}Validate and generate
$ vsuite pack validate ../contoso-pack --strict
Pack ../contoso-pack is valid
[exit 0]Connecting it to a project (pack served from a git mirror; <tmp> stands for the local directory):
$ vsuite pack add git:file://<tmp>/contoso-pack#v1.0.0 --name contoso
Added pack contoso: Contoso Engineering Pack 1.0.0
agents added: compliance-reviewer
agents overriding the catalog: code-reviewer
skills added: contoso-secure-coding
skills overriding the catalog: -
instructions added: -
Select entries with `vsuite agent use <id> --from contoso`, then run `vsuite generate`.
[exit 0]
$ vsuite agent use code-reviewer --from contoso
agent code-reviewer now uses pack:contoso
Run `vsuite generate` to update generated files.
[exit 0]
$ vsuite agent use compliance-reviewer --from contoso
agent compliance-reviewer now uses pack:contoso
added agent compliance-reviewer as a specialist
Run `vsuite generate` to update generated files.
[exit 0]
$ vsuite generate --strict
warning [claude-code] skills-not-enforced: code-reviewer: claude-code preloads the listed skills but cannot deny unlisted ones
warning [claude-code] skills-not-enforced: compliance-reviewer: claude-code preloads the listed skills but cannot deny unlisted ones
warning [claude-code] coordinator-main-thread: orchestrator: Claude Code enforces canCall only when the coordinator runs as the main thread; start it with "claude --agent orchestrator"
.opencode/agents/code-reviewer.md
.claude/agents/code-reviewer.md
.opencode/agents/compliance-reviewer.md
.claude/agents/compliance-reviewer.md
.opencode/agents/orchestrator.md
.claude/agents/orchestrator.md
.opencode/skills/agent-efficiency-protocol/SKILL.md
.claude/skills/agent-efficiency-protocol/SKILL.md
.opencode/skills/contoso-secure-coding/SKILL.md
.claude/skills/contoso-secure-coding/SKILL.md
.opencode/skills/review-priority-tiers/SKILL.md
.claude/skills/review-priority-tiers/SKILL.md
.opencode/opencode.json
[exit 0]
$ vsuite pack list
contoso git:file://<tmp>/contoso-pack#v1.0.0 1.0.0 locked: a3c0479526230b7337761631e7c8bc49aab0f474 sha256-1Dv4A/5XhtDH integrity: ok
agents added: compliance-reviewer
agents overriding the catalog: code-reviewer
skills added: contoso-secure-coding
skills overriding the catalog: -
instructions added: -
[exit 0]The [claude-code] warnings are target capability notes, not pack problems; --strict fails only on MD_LINT. agent use … --from contoso on a new id adds the agent as a specialist and to the coordinator’s canCall. The pack skill is generated because an agent requires it; use vsuite skill use <id> --from contoso when the pack overrides a catalog skill.
4. Local development loop
-
Keep the pack in its own repository (or a folder of a monorepo) and point a test project at it with
path::vsuite pack add path:../contoso-pack --name contoso -
Edit templates, then run
vsuite pack validate ../contoso-pack --strict. It needs no project and test-renders every template against built-in fixture contexts (empty and full stack, each target, metrics and memory on and off), so it catchesifbranches your test project never hits. -
Run
vsuite generatein the test project. A changedpath:pack is relocked with a warning:warning [pack:contoso] vsuite.lock.json PACK_INTEGRITY: [contoso] local pack changed since vsuite.lock.json was written (sha256-7TCm1ruHLs/rbIMndiao/lTwkVY9iUoH9gkqu5orYgI= → sha256-IBQUUtPF+iCe23C1icWn7QA0AY09gT7T9bqLx+SIuz4=); lock entry rewritten -
Or use the desktop app’s Preview tab: it shows the exact generated Markdown for the selected agent or skill and target, marks auto-appended required sections, and lists diagnostics with file and line. It refreshes when files change under a
path:pack folder (folders outside the project must have been chosen with the Packs tab folder picker to be watched).
Use --json in scripts; each entry has code, pack, file, line, column, hint, and issues.
Reading errors
A pack with a typo in skill front matter and an unknown variable in a new agent:
$ vsuite pack validate broken
skills/contoso-secure-coding/SKILL.md.liquid:2:13 PACK_FRONTMATTER [contoso] 2 issue(s)
skills/contoso-secure-coding/SKILL.md.liquid:2:13: descriptio: unknown key
skills/contoso-secure-coding/SKILL.md.liquid:2:1: description: required for ids that do not override a built-in (Fix the template front matter; every issue is listed.)
skills/contoso-secure-coding/SKILL.md.liquid:2:13 descriptio: unknown key
skills/contoso-secure-coding/SKILL.md.liquid:2:1 description: required for ids that do not override a built-in
agents/release-notes.md.liquid:6:11 TPL_UNKNOWN_VAR [contoso] undefined variable: project.stacks (Use only variables defined by the TemplateContext schema.)
Pack broken has 2 error(s)
[exit 1]Format: file:line:column CODE [pack] message (hint), then one line per issue.
| Code | Typical cause in an org pack | Fix |
|---|---|---|
PACK_FETCH |
Wrong path, registry auth, unreachable git host, tag not found. | Check the source string and credentials; run the npm/git command by hand. |
PACK_INTEGRITY |
npm/git content changed under the same source (republished tag, new version in range). | Review the change, then vsuite pack update <name> or generate --update-packs. |
PACK_MANIFEST |
Bad manifest field, or the running vsuite is outside the vsuite range. |
Fix the manifest or upgrade vsuite. |
PACK_FRONTMATTER |
Typo in a key, missing description on a new id. |
Fix front matter; every issue is listed. |
PACK_LAYOUT |
Unexpected file name, id with capitals or _, file over 256 KB, symlink leaving the pack. |
Rename or move the file. |
PACK_CONTEXT_VERSION |
contextVersion not supported by this vsuite. |
Set contextVersion: 1 or 2, or release a pack for the newer context. |
PACK_CONFLICT |
Org and team pack define the same id. | Set source: "pack:<name>" for that entry, or rename one id. |
PACK_MISSING_ENTRY |
The project selects an id the pack no longer ships. | Restore the id or move the project to --from catalog. |
TPL_UNKNOWN_VAR |
Misspelt variable, or one not in the context. | Check the context reference. |
TPL_UNKNOWN_FILTER |
A filter from another Liquid flavour. | Use Liquid built-ins or md_escape, code, join_human. |
TPL_UNKNOWN_TAG |
include, layout, block. |
Use {% render "pack:<name>" %}. |
TPL_BAD_PARTIAL |
render of a missing partial or a path. |
Add partials/<name>.md.liquid or fix the name. |
TPL_LIMIT |
Runaway loop, huge output, NUL character. | Simplify the template. |
MD_LINT |
Rendered Markdown issue (often blank-line handling around if). |
Use {%-/-%} trims; the report gives outputLine and templateLine. |
5. Packaging and distribution
The pack root (the directory with vsuite-pack.yaml) must be the package root for npm and the repository root for git. There is no subdirectory option for npm: or git: sources.
| Channel | Source string | Lock resolved |
Best for | Notes |
|---|---|---|---|---|
| npm (private registry) | npm:@contoso/vsuite-pack@1.0.0 |
exact version | Org-wide releases, existing npm tooling. | Range specs (@^1.0.0) resolve to the newest matching version on every fetch; see Verification. |
| git | git:https://git.contoso.com/platform/vsuite-pack.git#v1.0.0 or #<commit sha> |
40-hex commit SHA | Teams without a registry, signed tags. | URLs must be https://, ssh://, git@host:path, or file://; transport helpers (ext::) are rejected. Refs are tags, branches, or 7–40 hex SHAs. |
| path | path:./.vsuite/packs/team or path:../contoso-pack |
project-relative path | Monorepos, local development. | Content changes relock with a warning; no version pinning. |
Fetched npm and git packs are cached under node_modules/.cache/vsuite/packs in the consuming project.
npm
package.json in the pack repository:
{
"name": "@contoso/vsuite-pack",
"version": "1.0.0",
"description": "Contoso agents and skills for vsuite",
"files": ["vsuite-pack.yaml", "agents", "skills", "partials"],
"publishConfig": { "registry": "https://npm.contoso.com/" }
}Keep version equal to the manifest version. Publish with npm publish.
vsuite runs npm view <spec> version in the project directory and npm pack <name>@<version> in a temporary directory. Configure the scope registry and token where both see it: user ~/.npmrc or NPM_CONFIG_* environment variables in CI. A project-level .npmrc applies only to npm view.
@contoso:registry=https://npm.contoso.com/
//npm.contoso.com/:_authToken=${NPM_TOKEN}git
Tag each release with the manifest version and reference the tag or the commit:
git tag -s v1.0.0 -m "contoso pack 1.0.0"
git push origin v1.0.0vsuite resolves tags and branches with git ls-remote, fetches a shallow clone, and locks the commit SHA. Authentication is whatever your git uses (SSH agent, credential helper).
Release sequence
sequenceDiagram participant A as Pack author participant R as Pack repo CI participant G as Registry / git host participant P as Consumer repo participant C as Consumer CI A->>R: PR with template changes R->>R: vsuite pack validate . --strict R->>R: generate --strict in a sample project A->>G: npm publish or signed tag v1.1.0 P->>P: change source to 1.1.0, vsuite pack update P->>P: vsuite generate, commit vsuite.json, vsuite.lock.json, outputs P->>C: PR C->>C: verify tag or npm signatures (external) C->>C: vsuite generate --strict, git diff --exit-code
6. Verification and supply-chain integrity
What vsuite verifies
vsuite does not implement pack signatures or signature verification. It pins packs:
vsuite.lock.jsonrecords each pack’ssource,resolved(exact npm version, git commit SHA, or project-relative path), andintegrity:sha256-plus base64 of a SHA-256 over the sorted list of pack files with their per-file SHA-256 (CRLF normalised to LF). Only the files vsuite reads count: the manifest, agents, skills, and partials.npm:andgit:: if fetched content does not match the locked integrity,generateand the UI preview stop withPACK_INTEGRITY. Nothing is written until you accept the change withvsuite pack update [name]orvsuite generate --update-packs.path:: a mismatch warns and relocks.
Lockfile after the tutorial:
{
"lockfileVersion": 2,
"packs": {
"contoso": {
"source": "git:file://<tmp>/contoso-pack#v1.0.0",
"resolved": "a3c0479526230b7337761631e7c8bc49aab0f474",
"integrity": "sha256-1Dv4A/5XhtDHi7nu2u0zbs/jYHzNx6XSrQ3Cs3V0Izc=",
"contextVersion": 2,
"generatedSkills": [
"contoso-secure-coding"
],
"generatedAgents": [
"code-reviewer",
"compliance-reviewer"
]
}
}
}What triggers PACK_INTEGRITY
Any change in the fetched files under the same source: a moved git tag or branch, a new npm version matching a range, or a republished package. Here the v1.0.0 tag was moved to a new commit:
$ vsuite generate
vsuite.lock.json:0:0 PACK_INTEGRITY [contoso] integrity mismatch: locked sha256-1Dv4A/5XhtDHi7nu2u0zbs/jYHzNx6XSrQ3Cs3V0Izc=, fetched sha256-kHIt52Gx+C/GGu4CcBFGVBrqK/o9DTnWvJAm2QmWkEE= (The pack changed since vsuite.lock.json was written; review it, then re-run with updatePacks.)
[exit 1]
$ vsuite pack update contoso
contoso: updated 1.0.0 (sha256-1Dv4A/5XhtDH -> sha256-kHIt52Gx+C/G)
[exit 0]- "resolved": "a3c0479526230b7337761631e7c8bc49aab0f474",
- "integrity": "sha256-1Dv4A/5XhtDHi7nu2u0zbs/jYHzNx6XSrQ3Cs3V0Izc=",
+ "resolved": "f27401d6287d2e26d4c39af2fdd6529dd7ca7aaf",
+ "integrity": "sha256-kHIt52Gx+C/GGu4CcBFGVBrqK/o9DTnWvJAm2QmWkEE=",pack update only relocks; run vsuite generate afterwards to regenerate files. A lock diff where resolved changes while the version in source does not is a red flag: review what changed before accepting it.
For reproducible builds, use exact npm versions (@1.0.0) or commit SHAs rather than ranges or moving branches.
Organisational practices outside vsuite
These are external practices that compose with lockfile pinning. vsuite does not perform or check any of them; signature verification inside vsuite is future work (the lockfile format leaves room for signature fields).
| Practice | Where | What it adds |
|---|---|---|
Signed release tags; CI runs git verify-tag v1.1.0 (or git verify-commit <sha>) on a clone of the pack repo before anyone runs vsuite pack update |
Pack repo, consumer CI | Proves who released the content vsuite will lock. |
npm provenance on publish (npm publish --provenance from CI) and npm audit signatures in consumer CI, where your private registry supports them |
Registry, consumer CI | Registry signatures and build provenance for the package. |
CODEOWNERS on vsuite.json and vsuite.lock.json (and generated agent folders) |
Consumer repos | Pack source and lock changes need platform-team approval. |
CI runs vsuite pack validate . --strict on every pack PR |
Pack repo | No broken template reaches the registry. |
CI runs vsuite generate --strict and fails on a diff |
Consumer repos | Committed outputs always match the locked pack. |
| Protected tags and immutable registry versions | Git host, registry | Prevents silent republish; vsuite would catch it as PACK_INTEGRITY, this prevents it. |
flowchart LR
subgraph External["Organisation controls (outside vsuite)"]
S1[Signed tag / npm provenance]
S2[CI: git verify-tag,<br/>npm audit signatures]
S3[CODEOWNERS review of<br/>vsuite.json + lock]
end
subgraph Vsuite["vsuite"]
V1[Fetch by version / SHA]
V2[sha256 integrity<br/>vs vsuite.lock.json]
V3[Validate, render, lint]
end
S1 --> S2 --> V1 --> V2 --> V3
S3 --> V2
V3 --> O[Committed agent files]
7. Deployment and rollout
Connecting a project
CLI:
vsuite pack add npm:@contoso/vsuite-pack@1.0.0 --name contoso
vsuite agent use code-reviewer --from contoso
vsuite agent use compliance-reviewer --from contoso
vsuite skill use <skill-id> --from contoso # only for skills the pack overrides or the project selects
vsuite generate --strict
git add vsuite.json vsuite.lock.json .opencode .claudeDesktop app: Packs tab → add (folder picker, npm, or git); then in the agents or skills view pick the pack in the Definition select for overridden built-ins, or add pack-only entries from the From packs group; check the Preview tab; save and generate. Pack add, remove, and update are disabled while the config draft has unsaved changes.
Commit vsuite.json, vsuite.lock.json, and the generated target folders together.
CI
Availability: pack support requires vsuite 0.4.0 or later, which is not yet published to npm (the latest published version is 0.3.1). Until it is, the
npx @krizic/vsuite@0.4.0steps below will fail; run vsuite from a repository build instead (pnpm build, thennode packages/cli/dist/main.js) or install a private build from your internal registry.
Pack repository (GitHub Actions; Gitea Actions accepts the same syntax):
name: pack
on: [pull_request, push]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npx @krizic/vsuite@0.4.0 pack validate . --strictConsumer repository:
name: agents
on: [pull_request]
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://npm.contoso.com/
scope: "@contoso"
- run: npx @krizic/vsuite@0.4.0 generate --strict
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- run: git diff --exit-codegenerate fails on PACK_INTEGRITY, so CI never accepts unreviewed pack content; never pass --update-packs in CI. Pin the vsuite version you run in CI to one inside the pack’s vsuite range. Insert your external verification step (for example git verify-tag against a clone of the pack repo) before generate.
Upgrading
- Change the source to the new version (
npm:@contoso/vsuite-pack@1.1.0or#v1.1.0) invsuite.json. vsuite pack update contoso, thenvsuite generate --strict.- Open a PR with the
vsuite.json, lock, and generated-file diffs; reviewers read the generated Markdown diff, not just the version bump.
Rollback
| Goal | Action |
|---|---|
| Previous pack release | Revert the PR, or set the previous version or SHA as the source, then vsuite pack update contoso and vsuite generate. |
| One agent back to built-in | vsuite agent use code-reviewer --from catalog, then vsuite generate. |
| Drop the pack | vsuite pack remove contoso --reset-to-catalog, then vsuite generate. |
Removal and cleanup
vsuite pack remove <name> fails with PACK_REFERENCED while entries still use the pack and lists them. --reset-to-catalog resets overrides to the catalog and removes pack-only agents and skills from vsuite.json. Their generated ids move to pendingRemovalAgents / pendingRemovalSkills in the lock, and the next vsuite generate deletes those files. Commit after that generate so the deletions land with the config change.
8. Governance and security
Trust model
Packs are trusted, code-adjacent content: they become instructions your agents follow and set agent tools. vsuite pins and hashes them and limits what templates can do, but there is no sandbox and no signature check. Treat a pack release like a dependency release. See Trust model.
Limits
| Limit | Value | Error |
|---|---|---|
| Files per pack | 500 | PACK_LAYOUT |
| File size | 256 KB | PACK_LAYOUT |
| Ids | [a-z0-9-]+ |
PACK_LAYOUT |
| Symlinks | must resolve inside the pack | PACK_LAYOUT |
| File content | regular, UTF-8, no NUL | PACK_LAYOUT |
| Template parse | 1 Mi characters | TPL_LIMIT |
| Render time | 2000 ms | TPL_LIMIT |
| Render memory | 16 Mi units | TPL_LIMIT |
Pack PR review checklist
-
vsuite pack validate . --strictpasses in CI. -
versionbumped (semver) and matchespackage.json/ the tag. -
vsuiterange still covers the vsuite versions consumers run. - New ids are org-prefixed; overrides of built-in ids are intentional and noted in the changelog.
-
toolsin front matter grant no more than the agent needs (for example, reviewers withouteditorexecute). -
requiredSkillschanges are listed in the changelog (consumers get them automatically). - No secrets, internal hostnames, or personal data in templates; everything in a pack ends up in every consumer repo.
- Instructions do not tell agents to fetch and run remote content or bypass review.
- Rendered output reviewed in a sample project (Preview tab or
generate).
Ownership
| Asset | Owner |
|---|---|
| Pack repository and releases | Platform or developer-experience team. |
| Signing keys, registry tokens | Same team, managed by your secrets process. |
vsuite.json, vsuite.lock.json in consumers |
Consumer team, with platform team as CODEOWNER. |
| Team packs | The team, under the same checklist. |
9. Troubleshooting
generate stops with PACK_INTEGRITY in CI but works locally. Someone ran pack update locally without committing the lock, or the source is a range or branch that moved. Commit the lock; pin exact versions or SHAs.
PACK_FETCH for an npm pack in CI. The registry or token is not visible to npm pack, which runs in a temporary directory. Configure it in user ~/.npmrc or environment variables, not only the project .npmrc.
PACK_FETCH: unsupported git url. Use https://, ssh://, git@host:path, or file://.
PACK_MANIFEST after upgrading vsuite. The new release is outside the pack’s vsuite range. Release a pack with a wider range after testing.
PACK_CONFLICT after adding a team pack. Both packs define an id. Set that entry’s source to the pack you want.
My override lost a built-in section. Required sections are auto-appended, but optional ones (vsuite:efficiency, vsuite:evidence, vsuite:review-contract, …) appear only where you render them.
Extra blank lines in output, or MD_LINT with --strict. Trim around tags: {%- if … %} / {%- endif %}. The report gives templateLine.
A pack-only agent’s files remain after removal. Run vsuite generate after pack remove; deletions are applied from the lock’s pending removals.
Is the pack signed? No; see Organisational practices outside vsuite.
References
- Pack author guide · Template context reference · Example pack
- Architecture · CLI README · UI README
- Historical records (dated, not maintained): the design spec
docs/superpowers/specs/2026-10-02-enterprise-agent-packs-design.mdand the security reviews indocs/superpowers/reviews/. Where they differ from this guide or the code, the guide and the code are current.