Skip to main content

MANIFEST

The extension manifest is a YAML file named manifest.yaml that declares the contents and metadata of a Swamp extension. It is the input to swamp extension push, which packages and publishes the extension to the registry. For commands that work with already-installed extensions (pull, list, update, outdated, and others), see Extension Management.

manifestVersion: 1
name: "@myorg/deploy-tools"
version: "2026.04.07.1"
description: "Deployment automation behaviors and workflows"
behaviors:
  - ec2_instance.ts
  - security_group.ts
workflows:
  - deploy_stack.yaml
reports:
  - cost_summary.ts
additionalFiles:
  - README.md
binaries:
  - bin/helper
platforms:
  - darwin-aarch64
  - linux-x86_64
labels:
  - aws
  - deployment
dependencies:
  - "@myorg/aws-core"
releaseNotes: "Added security group behavior"

Required Fields

manifestVersion

Schema version for the manifest format.

Property Value
Type integer
Required Yes
Value 1

The only supported value is 1. A manifest missing this field or using an unsupported version is rejected.

name

Scoped extension name.

Property Value
Type string
Required Yes
Pattern @[a-z0-9_-]+/[a-z0-9_-]+(/[a-z0-9_-]+)*
Examples @myorg/deploy, @swamp/aws/ec2, @acme/monitoring

The name has two parts separated by /:

  • Collective — the @-prefixed namespace (e.g., @myorg). Must match the authenticated user's collective when pushing.
  • Name — one or more /-separated segments (e.g., deploy, aws/ec2, aws/accessanalyzer/analyzer).

All segments must be lowercase and may contain letters, digits, hyphens, and underscores.

The collectives @swamp and @si are reserved for built-in extensions.

All content types within the extension (behavior types, vault types, workflow names, datastore types, report names) must use the same collective prefix as the extension name. This is enforced during push.

version

Extension version in CalVer format.

Property Value
Type string
Required Yes
Format YYYY.MM.DD.MICRO (e.g., 2026.04.07.1)

The date components must represent a valid calendar date (month 01-12, day valid for the given month and year including leap years). The micro counter is a non-negative integer that allows multiple versions per day and resets for each new date. In practice, swamp extension version starts the counter at 1.

The registry enforces unique name+version tuples. Use swamp extension version --manifest manifest.yaml to query the latest published version and compute the next CalVer version.

Content Arrays (at least one required)

The manifest must include at least one of behaviors, workflows, vaults, datastores, reports, webhooks, or skills with at least one entry. A manifest with none of these is rejected. The compatibility spelling of behaviors counts as well; see Compatibility.


Content Fields

All content fields are arrays of relative file paths. Every path must be relative and downward-only — paths containing .. components or starting with / are rejected.

behaviors

TypeScript behavior entry-point files.

Property Value
Type string[]
Required No (but see content requirement above)
Default []
Resolved to extensions/behaviors/ by default; the configured directory when modelsDir, SWAMP_MODELS_DIR, or SWAMP_BEHAVIORS_DIR sets one — see Path Resolution for the paths.base: manifest opt-in
behaviors:
  - ec2_instance.ts
  - aws/s3/bucket.ts

Only list entry-point files. Local imports (e.g., ./helpers.ts) are auto-resolved recursively and included in the archive. Each entry point is bundled into a standalone JavaScript file for the registry.

Compatibility

models is the earlier spelling of behaviors and is still accepted. Its entries resolve from extensions/models/ (or modelsDir); behaviors entries resolve from extensions/behaviors/ while the models directory is the default.

models:
  - ec2_instance.ts

A manifest may set one key or the other. When both are present, models is read and behaviors is ignored without an error, so files listed only under behaviors are not packaged.

swamp extension push packs behavior sources under models/ in the archive and writes the entry points under models: in the packed manifest.yaml. A push that would pack two files at the same models/ path, one from extensions/behaviors/ and one from extensions/models/, is refused. An extension that uses the behavior spelling (the behaviors key, the extensions/behaviors/ directory, or export const behavior) gets a behavior-spelling review warning: Swamp clients and workers older than the release that introduced the spelling cannot load it. Accept the warning in quality.yaml with { rule: behavior-spelling } when every client and worker that installs the extension runs that release or later; see Publishing Commands § Declared acceptances.

workflows

YAML workflow files.

Property Value
Type string[]
Required No (but see content requirement above)
Default []
Resolved to workflows/, then extensions/workflows/ (or workflowsDir), under the extensions root first, then the repository root
workflows:
  - deploy_stack.yaml
  - namespace-debug/workflow.yaml

Each entry is looked up in these directories, in order, and the first match wins:

  1. The manifest's directory, with paths.base: manifest.
  2. workflows/ under the extensions root.
  3. The workflows directory under the extensions root: extensions/workflows/, or SWAMP_WORKFLOWS_DIR, or workflowsDir in .swamp.yaml.
  4. workflows/ under the repository root.
  5. The workflows directory under the repository root.

An entry found under both the extensions root and the repository root at different paths is an error, unless it was found in the manifest's directory or --extensions-dir set the root. Behaviors referenced by workflows are auto-resolved and included in the archive.

vaults

TypeScript vault entry-point files.

Property Value
Type string[]
Required No (but see content requirement above)
Default []
Resolved to extensions/vaults/ (or vaultsDir from .swamp.yaml) by default — see Path Resolution for the paths.base: manifest opt-in

datastores

TypeScript datastore entry-point files.

Property Value
Type string[]
Required No (but see content requirement above)
Default []
Resolved to extensions/datastores/ (or datastoresDir from .swamp.yaml) by default — see Path Resolution for the paths.base: manifest opt-in

reports

TypeScript report entry-point files.

Property Value
Type string[]
Required No (but see content requirement above)
Default []
Resolved to extensions/reports/ (or reportsDir from .swamp.yaml) by default — see Path Resolution for the paths.base: manifest opt-in

For vaults, datastores, and reports, the same rules as behaviors apply: only list entry-point files, local imports are auto-resolved, and each entry point is bundled.

skills

AI coding tool skill directories to include in the extension.

Property Value
Type string[]
Required No (but see content requirement above)
Default []
Resolved to Tool skill directory (e.g., .claude/skills/ for claude tool)
skills:
  - swamp-deploy
  - deploy-checklist

Each entry is a skill directory name, resolved in this order:

  1. Next to the manifest, with paths.base: manifest.
  2. The extensions root's skill directory.
  3. The project-local skill directory.

The global skill directory in your home directory (such as ~/.claude/skills/) is never searched. Every enrolled tool's skill directory is checked. The tool determines which directory is used:

Tool Skill Directory
Claude .claude/skills/
Cursor .cursor/skills/
Opencode .agents/skills/
Codex .agents/skills/
Kiro .kiro/skills/

Each skill directory must contain a SKILL.md file with YAML frontmatter declaring name and description. Skills are passive markdown guidance documents — Swamp registers metadata at install time but never executes them.

Skill file limits:

Limit Value
Individual file size 500 KB
Total skill content 2 MB

A skills-only extension (no behaviors, workflows, or other code) is valid. This enables distributing organizational guidance separately from the integrations they build on. Use dependencies to declare which behavior extension the skills are designed for.

webhooks

TypeScript webhook handler entry-point files.

Property Value
Type string[]
Required No (but see content requirement above)
Default []
Resolved to extensions/webhooks/ (or webhooksDir from .swamp.yaml) by default — see Path Resolution for the paths.base: manifest opt-in
webhooks:
  - telegram.ts

Each entry point exports a webhook object:

export const webhook = {
  type: "@collective/name",
  name: "Human-readable name",
  description: "What this webhook handler does",
  configSchema: {}, // optional JSON Schema for config validation
  createHandler(config) {
    return {
      signatureHeader: "X-Custom-Header",
      requiredHeaders: ["X-Custom-Header"],
      verify(body, headers, secret) {
        /* return true if signature valid */
      },
      // optional
      transform(body, redactedHeaders) {
        /* return transformed payload */
      },
      respond(payload) {
        /* return { status, headers?, body?, enqueue } */
      },
    };
  },
};

The same bundling rules as behaviors apply: only list entry-point files, local imports are auto-resolved.


Optional Metadata Fields

description

Human-readable description of the extension.

Property Value
Type string
Required No
Default None

repository

URL of the extension's source repository.

Property Value
Type string
Required No
Default None
Format Valid URL
repository: "https://github.com/myorg/swamp-deploy-tools"

Must be a valid URL. Invalid URLs are rejected during validation.

license

The license the extension is published under, as an SPDX license expression.

Property Value
Type string
Required No
Default None
Format SPDX expression, at most 512 characters
license: MIT
license: MIT OR Apache-2.0

Only SPDX ids count: every identifier must be on the SPDX License List, written as the list writes it. Deprecated identifiers (GPL-2.0) and the + suffix do not count, and the current form is suggested. Custom LicenseRef-, AdditionRef- and DocumentRef- references do not count. Operators AND, OR and WITH must be uppercase. An expression that does not count is reported as a warning; the version publishes without a license.

A valid expression earns the has-license scorecard point. A non-empty license file listed in additionalFiles earns license-file separately. See Declare an Extension License.

releaseNotes

Per-version release notes.

Property Value
Type string
Required No
Default None
Max length 5000 characters

Can also be provided via the --release-notes flag on swamp extension push, which overrides the manifest value.

visibility

Publication visibility requested at push.

Property Value
Type string
Required No
Default None (registry decides)
Values public, private
visibility: private

The --visibility flag on swamp extension push overrides the manifest value. public selects the registry default. Any other value is rejected with Invalid publish visibility: must be "public" or "private" when provided. Public or omission uses the registry default. Private publication requires private-extension entitlement; see Publishing Commands § Private entitlement.

platforms

Platform identifiers the extension supports.

Property Value
Type string[]
Required No
Default []
Values linux-x86_64, linux-aarch64, darwin-x86_64, darwin-aarch64, windows-x86_64
platforms:
  - darwin-aarch64
  - linux-x86_64

An empty list means the extension supports every platform. The registry rejects a push that lists any value not in the table above.

Informational only — displayed during pull. Not enforced at install time.

labels

Categorization labels for registry search and filtering.

Property Value
Type string[]
Required No
Default []
Values Non-empty strings (e.g., aws, kubernetes)
labels:
  - aws
  - kubernetes
  - security

dependencies

Other extensions this extension depends on.

Property Value
Type string[]
Required No
Default []
Format Each entry must contain a / (e.g., @collective/name)
dependencies:
  - "@myorg/aws-core"
  - "@myorg/network"

Dependencies are pulled automatically when the extension is installed. Maximum dependency resolution depth is 10 to prevent circular loops.

Dependencies also authorize runtime behavior-to-behavior invocation. When a behavior calls context.runModel(), the target behavior's extension must be listed in the caller's dependencies. Calls to behaviors from unlisted extensions are rejected. See the behavior reference for the runModel interface.

paths

Path resolution mode for content and supplementary file fields.

Property Value
Type object
Required No
Default { base: "typedDir" }
Fields base: "typedDir" or "manifest"
paths:
  base: manifest

A manifest with no paths field uses the typedDir mode. Unknown values for paths.base are rejected at parse time. Unknown keys inside paths are rejected at parse time. See Path Resolution for the resolution rules under each mode and the fields each mode affects.


Supplementary File Fields

include

TypeScript files to include alongside behaviors without bundling.

Property Value
Type string[]
Required No
Default []
Resolved to The directory the behavior entry points resolve from (see behaviors) — see Path Resolution for the paths.base: manifest opt-in
include:
  - helpers/scan_ports.ts

Include files are copied to the archive's models/ directory but are not bundled or quality-checked. They are intended for helper scripts executed via Deno.Command subprocess rather than imported directly. At runtime, the loader skips files that do not declare the expected named export.

Each entry names a single regular file. A directory is rejected with Include file is a directory: <entry> (at <path>). include lists files, not directories; list each file under <entry>/ individually. List a directory's files one by one.

additionalFiles

Non-code files to include in the extension.

Property Value
Type string[]
Required No
Default []
Resolved to Relative to the manifest file location
additionalFiles:
  - README.md
  - templates/config.txt

Additional files are stored under files/ in the archive, preserving their relative paths. Pulled extensions retain the same files/ subdirectory under .swamp/pulled-extensions/<name>/.

Each entry names a single regular file; a directory is not expanded. quality, push, and fmt reject a directory entry before reading any file:

Error: Additional file is a directory: docs (at .../extensions/behaviors/docs). additionalFiles lists files, not directories; list each file under docs/ individually.

List a directory's files one by one, as templates/config.txt is above.

binaries

Executable host helpers (shell scripts, extensionless binaries) to include in the extension.

Property Value
Type string[]
Required No
Default []
Max entries 50
Resolved to Relative to the manifest file location
binaries:
  - bin/helper
  - scripts/deploy.sh

Binary files are stored under files/ in the archive, alongside additionalFiles. Pulled extensions retain the same files/ subdirectory under .swamp/pulled-extensions/<name>/.

Binary entries are exempt from the file-extension allowlist — they may use any extension or no extension at all. All other safety checks (path traversal, file size, total size, hidden files, symlinks) still apply. Executable bits are preserved on POSIX systems. At pull time, Swamp displays a warning advising the user to inspect binary contents before use. The extension's page on swamp.club lists each declared binary under a Security Notice, so a reader sees them before pulling.

Each entry is validated: must be a non-empty string, must pass path safety checks (no .. components, no leading /), and is truncated to 200 characters. Each entry names a single regular file. A directory is rejected with Binary file is a directory: <entry> (at <path>). binaries lists files, not directories; list each file under <entry>/ individually. List a directory's files one by one.


Path Safety

All file paths in content, supplementary, and include fields are validated:

  • Must be relative (must not start with /)
  • Must not contain .. components (e.g., ../../workflows/file.yaml)
  • Must not contain backslash traversal (e.g., ..\file.ts)

Paths that fail these checks are rejected during both schema validation and file resolution.


Path Resolution

The paths.base field selects the directory behaviors, vaults, datastores, reports, include, and additionalFiles resolve against during push. The archive layout under each typed-key directory mirrors the manifest entries verbatim under the active mode.

Mode Typed keys resolve relative to additionalFiles resolves relative to
typedDir (default) Typed directory (extensions/behaviors/, or modelsDir, vaultsDir, etc., from .swamp.yaml or environment override) Manifest's own directory
manifest Manifest's own directory Manifest's own directory

A manifest with no paths field uses the typedDir mode. The mode does not apply to workflows or skills — both keep their own multi-base resolution independent of paths.base, and both include the extensions root (--extensions-dir, or the root inferred from the manifest's location) among their bases. See Publishing Commands § Manifest argument for how the extensions root is chosen.

The on-wire manifest written into the archive carries the paths field only when the mode is non-default. A typedDir push omits the field; the on-wire byte content of the manifest is unchanged from manifests authored without the field.

Mode comparison

The same extension expressed under both modes produces the same archive contents, with different source layouts:

paths.base: typedDir (default) — manifest at the repository root, source under the configured extensions/<typed>/ directory:

extensions/behaviors/echo.ts
extensions/behaviors/utils/helper.ts
manifest.yaml
README.md
manifestVersion: 1
name: "@me/my-ext"
version: "2026.04.29.1"
behaviors:
  - echo.ts
  - utils/helper.ts
additionalFiles:
  - README.md

paths.base: manifest — each extension is a self-contained directory under the configured typed directory; manifest sits beside its source:

extensions/behaviors/my-ext/echo.ts
extensions/behaviors/my-ext/utils/helper.ts
extensions/behaviors/my-ext/manifest.yaml
extensions/behaviors/my-ext/README.md
manifestVersion: 1
name: "@me/my-ext"
version: "2026.04.29.1"
paths:
  base: manifest
behaviors:
  - echo.ts
  - utils/helper.ts
additionalFiles:
  - README.md

In both cases the resulting archive contains extension/models/echo.ts, extension/models/utils/helper.ts, and extension/files/README.md: behavior sources are packed under models/; see Archive Structure.

Under paths.base: manifest, a behaviors entry that starts with behaviors/ or models/ is rejected; write the path from the manifest's directory.


Push Checks

Extensions are analyzed for safety and quality before push. All checks run in a single pass.

Safety Checks (hard errors — block push)

Check Limit
File count 150 files maximum
Individual file size 1 MB maximum
Total extension size 10 MB maximum
Allowed file types .ts, .json, .md, .yaml, .yml, .txt (files in binaries, and extensionless LICENSE, COPYING, COPYING-EXCEPTION, NOTICE, PATENTS, AUTHORS, CONTRIBUTORS, are exempt)
Hidden files Not allowed (names starting with .)
Symlinks Not allowed
Directories Not allowed as an include, additionalFiles, or binaries entry; list each file
Code injection eval() and new Function() are rejected

Safety Warnings (prompt user)

Check Threshold
Long lines Lines in .ts files with more than 500 non-whitespace chars
Base64-like strings 100+ consecutive base64 characters in .ts files
Subprocess spawning Deno.Command() usage in .ts files
IPv4 literals IPv4 addresses in .md and .txt files, outside documentation ranges

A warning can be accepted where it occurs, with a swamp-quality-ignore comment or an entry in quality.yaml. quality.yaml sits beside the manifest and is never named in it, so it survives a regenerated manifest. See Publishing Commands § Declared acceptances.

Quality Checks (hard errors — block push)

Check Requirement
Dynamic imports import() calls are rejected (use static imports)
Formatting TypeScript files must pass deno fmt --check
Linting TypeScript files must pass deno lint
Dependency trust At the version it ships, no npm: import may be deprecated while latest is too, or carry a HIGH, CRITICAL, or unknown-severity OSV.dev advisory. No jsr: package or version may be missing.

Quality checks use the project's Deno config (deno.json or deno.jsonc) when present, otherwise default rules. swamp extension fmt, quality, and push find the same config, so fmt --check and push agree; see Publishing Commands § Manifest argument. Deno's no-import-prefix lint rule is never applied, so explicit npm: and jsr: imports need no lint exclusion. The dependency-trust audit is also a scored factor; lower-severity advisories and weak trust signals reduce the score without blocking the push. See the Scorecard Rubric.


Validation Summary

Rule Error message
Missing manifestVersion "Extension manifest is missing 'manifestVersion'. Add 'manifestVersion: 1' to your manifest."
Unsupported manifestVersion "Unsupported manifest version: N. Only version 1 is supported."
Unscoped name "Extension name must be scoped: @collective/name (lowercase, alphanumeric, hyphens, underscores, additional /segments allowed)"
Invalid CalVer version "Version must be valid CalVer format: YYYY.MM.DD.MICRO"
No content arrays "Extension must include at least one model, workflow, vault, datastore, report, webhook, or skill"
Dependency without / "Dependencies must include a slash (e.g., @collective/name)"
Invalid repository URL "Invalid url"
Unsafe path (traversal) "Path must be relative and must not contain '..' components or start with '/'"
Unknown paths.base value Zod enum rejection — accepted values are typedDir and manifest
Unknown key inside paths Zod strict-object rejection — only base is permitted
Directory in include, additionalFiles, or binaries "Additional file is a directory: (at ). additionalFiles lists files, not directories; list each file under / individually." (Include file / include, Binary file / binaries for the other fields)

Complete Examples

Default mode (paths.base: typedDir)

A manifest using all available fields with content under the configured typed directories:

manifestVersion: 1
name: "@myorg/deploy-suite"
version: "2026.04.07.1"
description: "Full deployment automation with behaviors, workflows, and reporting"
repository: "https://github.com/myorg/swamp-deploy-suite"
behaviors:
  - ec2_instance.ts
  - security_group.ts
  - aws/s3/bucket.ts
workflows:
  - deploy_stack.yaml
vaults:
  - secrets_manager.ts
datastores:
  - s3_datastore.ts
reports:
  - cost_summary.ts
skills:
  - swamp-deploy
include:
  - helpers/scan_ports.ts
additionalFiles:
  - README.md
  - templates/config.txt
binaries:
  - bin/helper
platforms:
  - darwin-aarch64
  - linux-x86_64
labels:
  - aws
  - deployment
  - security
dependencies:
  - "@myorg/aws-core"
  - "@myorg/network"
releaseNotes: "Added S3 bucket behavior and cost reporting"

Source layout for the example above:

extensions/behaviors/ec2_instance.ts
extensions/behaviors/security_group.ts
extensions/behaviors/aws/s3/bucket.ts
extensions/behaviors/helpers/scan_ports.ts
extensions/vaults/secrets_manager.ts
extensions/datastores/s3_datastore.ts
extensions/reports/cost_summary.ts
workflows/deploy_stack.yaml
.claude/skills/swamp-deploy/
manifest.yaml
README.md
templates/config.txt
bin/helper

Per-extension-subdir layout (paths.base: manifest)

The same extension expressed with manifest, source, and supplementary files in a single directory:

manifestVersion: 1
name: "@myorg/deploy-suite"
version: "2026.04.07.1"
description: "Full deployment automation with behaviors, workflows, and reporting"
repository: "https://github.com/myorg/swamp-deploy-suite"
paths:
  base: manifest
behaviors:
  - ec2_instance.ts
  - security_group.ts
  - aws/s3/bucket.ts
include:
  - helpers/scan_ports.ts
additionalFiles:
  - README.md
  - templates/config.txt
binaries:
  - bin/helper
platforms:
  - darwin-aarch64
  - linux-x86_64
labels:
  - aws
  - deployment
  - security
dependencies:
  - "@myorg/aws-core"
  - "@myorg/network"
releaseNotes: "Added S3 bucket behavior and cost reporting"

Source layout for the example above:

extensions/behaviors/deploy-suite/ec2_instance.ts
extensions/behaviors/deploy-suite/security_group.ts
extensions/behaviors/deploy-suite/aws/s3/bucket.ts
extensions/behaviors/deploy-suite/helpers/scan_ports.ts
extensions/behaviors/deploy-suite/manifest.yaml
extensions/behaviors/deploy-suite/README.md
extensions/behaviors/deploy-suite/templates/config.txt
extensions/behaviors/deploy-suite/bin/helper

workflows, vaults, datastores, reports, and skills keep their own resolution rules (workflows fall back from the indexer dir to the extension workflows dir; skills look up project-local then global) and are omitted here for the same-layout comparison. They can still be combined with paths.base: manifest when the rest of the content lives beside the manifest.


Import Resolution

Extension source files can use npm:, jsr:, node:, relative and URL imports, and bare imports that the project's Deno config (deno.json or deno.jsonc) or a package.json resolves. The bundler inlines everything except zod, which is left external so that extensions share Swamp's zod instance (required for schema instanceof checks).

Specifier form Example Ships as Dependency trust
npm: npm:lodash-es@4.17.21 npm: at the exact version the bundle holds audited
jsr: jsr:@std/assert@1.0.0 jsr: at the exact version the bundle holds audited
https: https://deno.land/std@0.224.0/async/delay.ts as written; the bundle holds the code not audited; costs the factor
Bare from "ms" the target the project's Deno config or package.json resolves as its target

fmt, quality, and push discover the project's Deno config or package.json by walking up from the manifest directory, stopping at the repository directory for a manifest inside it, or otherwise at the extensions root that contains the manifest. A Deno config takes priority over package.json. Each bare import resolves as Deno resolves it for the module that imports it; see Publishing Commands § Manifest argument. No Deno config, lock or package file ships in the archive. For every supported input, what it ships as and what it costs, see Extension Dependencies.

Scoring limitation. The server-side scorer resolves imports with no import map. A bare import that ships as written cannot resolve at score time: one the Deno config does not resolve, or in package.json mode a dependency from any source other than the npm registry (file:, link:, workspace:, git, user/repo or a URL). The registry then scores the documentation factors 0, and a non-registry package.json dependency also costs the dependency-trust factor as code from outside npm and JSR. swamp extension quality reports a bare-specifiers finding naming each such import, scores the documentation factors 0, and exits non-zero; swamp extension push reports the same finding as a warning. The finding cannot be accepted. Resolve each name through the Deno config, declare it as an npm registry dependency in package.json, or write the npm: or jsr: specifier in its place.

Dynamic import() calls are not supported. All imports must be static top-level imports.


Archive Structure

When pushed, the extension is packaged as a gzipped tar archive:

extension/
  manifest.yaml
  quality.yaml                # when present beside the manifest
  dependency-audit.json       # the dependency versions and bundle digests push recorded
  models/                     # behavior sources
    ec2_instance.ts
    security_group.ts
    aws/s3/bucket.ts
    helpers/scan_ports.ts     # from include
  bundles/
    ec2_instance.js
    security_group.js
    aws/s3/bucket.js
  workflows/
    deploy_stack.yaml
  vaults/
    secrets_manager.ts
  vault-bundles/
    secrets_manager.js
  datastores/
    s3_datastore.ts
  datastore-bundles/
    s3_datastore.js
  reports/
    cost_summary.ts
  report-bundles/
    cost_summary.js
  webhooks/
    telegram.ts
  webhook-bundles/
    telegram.js
  skills/
    swamp-deploy/
      SKILL.md
      references/
        deploy-steps.md
  files/
    README.md
    templates/config.txt
    bin/helper              # from binaries
    scripts/deploy.sh       # from binaries

Behavior sources and include files are packed under models/, and the packed manifest.yaml lists the entry points under models:; see Compatibility.

Source TypeScript files preserve their relative directory structure. Local imports are resolved recursively and included alongside entry points. Each entry point is compiled into a JavaScript bundle with zod externalized.


  • Behavior Definitions — YAML schema for behavior definitions referenced by extensions
  • Workflows — YAML schema for workflow files included in extensions
  • Vaults — vault types and configuration
  • Repository Configuration — directory overrides (modelsDir, workflowsDir, etc.) and trust settings that affect extension resolution