CREATE AND PUBLISH AN EXTENSION
This guide shows you how to create a TypeScript extension, publish it to the swamp registry, and install it in another repo.
Prerequisites
- A swamp repository (
swamp repo init) - A swamp account (
swamp auth login)
Write the extension model
Create the extension file at extensions/models/disk_usage.ts:
import { z } from "npm:zod@4";
export const model = {
type: "@mycollective/disk-usage",
version: "2026.04.03.1",
globalArguments: z.object({
path: z.string().describe("Filesystem path to check"),
}),
resources: {
result: {
description: "Disk usage statistics",
schema: z.object({
path: z.string(),
totalBytes: z.number(),
usedBytes: z.number(),
availableBytes: z.number(),
usedPercent: z.number(),
}),
lifetime: "infinite" as const,
garbageCollection: 10,
},
},
methods: {
check: {
description: "Check disk usage at the configured path",
arguments: z.object({}),
execute: async (
_args: Record<string, unknown>,
context: Record<string, unknown>,
) => {
const globalArgs = context.globalArgs as { path: string };
const cmd = new Deno.Command("df", {
args: ["-B1", globalArgs.path],
stdout: "piped",
stderr: "piped",
});
const output = await cmd.output();
const stdout = new TextDecoder().decode(output.stdout);
const lines = stdout.trim().split("\n");
const parts = lines[1].split(/\s+/);
const totalBytes = parseInt(parts[1]);
const usedBytes = parseInt(parts[2]);
const availableBytes = parseInt(parts[3]);
const usedPercent = Math.round((usedBytes / totalBytes) * 100);
const writeResource = context.writeResource as (
spec: string,
name: string,
data: Record<string, unknown>,
) => Promise<{ name: string }>;
const resultHandle = await writeResource("result", "result", {
path: globalArgs.path,
totalBytes,
usedBytes,
availableBytes,
usedPercent,
});
return { dataHandles: [resultHandle] };
},
},
},
};Replace @mycollective with your collective name. Run swamp auth whoami to
check your username and collectives.
Test the model locally
Create a model definition from the new type:
$ swamp model create @mycollective/disk-usage home-disk --global-arg path=/homeThe output confirms the model was created and lists its global arguments and methods.
Run the method to confirm it executes:
$ swamp model method run home-disk checkThe report at the end shows succeeded and the number of resources produced.
Create the manifest
Create extensions/models/manifest.yaml:
manifestVersion: 1
name: "@mycollective/disk-usage"
version: "2026.04.03.1"
description: "Check disk usage statistics for a filesystem path"
models:
- disk_usage.ts
labels:
- monitoring
- filesystemThe name must start with your collective prefix (@username/ or @org/). Run
swamp auth whoami to check which collectives you belong to.
Bump the version
Before each publish, get the next version from the registry:
$ swamp extension version --manifest extensions/models/manifest.yamlYou will see output like:
info extension·version Current published: (none — not yet published)
info extension·version Next version (today): "2026.04.13.1"Update manifest.yaml with the next version. If the model source file also
contains a version field, update it to match.
Format, lint, and validate
Format the extension source:
$ swamp extension fmt extensions/models/manifest.yamlTo check without modifying files, add --check:
$ swamp extension fmt extensions/models/manifest.yaml --checkYou will see output like:
info extension·fmt All quality checks passed.Validate with a dry run before publishing:
$ swamp extension push extensions/models/manifest.yaml --dry-runThe dry run validates the extension without uploading. If the push reports
safety warnings (e.g., Deno.Command() usage), you will be prompted to confirm.
Publish to the registry
$ swamp extension push extensions/models/manifest.yamlYou will see output like:
info extension·push Pushed "@mycollective/disk-usage"@"2026.04.13.1"
info extension·push Extension ID: "bbc4f071-..."
info extension·push Archive size: "1.4KB"
info extension·push "Models: 1, Workflows: 0, Vaults: 0, Bundles: 1"If the version already exists, the CLI offers to bump the MICRO component.
Add --release-notes "description of changes" to attach release notes, or add a
releaseNotes field to the manifest.
Tip
If you use Claude Code, the /swamp-extension-publish skill walks you through
the full publishing prerequisites — repo initialization, authentication,
manifest validation, collective ownership, version bumping, formatting, and
dry-run — before allowing the push.
Install the extension in another repo
In a different swamp repo, pull the extension:
$ swamp extension pull @mycollective/disk-usageThe model type is now available. Create definitions from it with
swamp model create @mycollective/disk-usage <name>.
To restore pulled extensions after cloning (e.g., in CI), run
swamp extension install.