Skip to main content

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=/home

The 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 check

The 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
  - filesystem

The 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.yaml

You 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.yaml

To check without modifying files, add --check:

$ swamp extension fmt extensions/models/manifest.yaml --check

You 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-run

The 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.yaml

You 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-usage

The 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.