Skip to content

Releases: systeminit/swamp

swamp 20260227.211429.0-sha.5a88d8c5

27 Feb 21:15
Immutable release. Only release title and notes can be modified.
5a88d8c

Choose a tag to compare

What's Changed

  • fix: detectConflicts uses correct nested paths for bundles (#530)

Summary

  • Fixes detectConflicts to use relative(bundlesSrc, file) instead of basename(file) for bundle paths, aligning it with how copyDir actually installs bundles and how models/additional files already handle paths.
  • Adds a unit test verifying nested bundle conflict detection.
  • Exports detectConflicts to enable direct testing.

Context

Commit c637ddd (#509) fixed extension push to preserve nested directory structure for bundles, but detectConflicts (which runs during pull) was not updated. It still used basename(file) — the old flat-path pattern from before the fix.

User impact

Before this fix, extensions with nested bundles (like @john/k8s which installs 15 bundles under .swamp/bundles/k8s/) had broken conflict detection:

  1. Missed conflicts — Re-pulling would silently overwrite files without the "files already exist" warning, because detectConflicts checked flat paths (.swamp/bundles/netpol.js) while copyDir installed to nested paths (.swamp/bundles/k8s/netpol.js).

  2. False positives — Stale files from pre-fix flat installs could trigger spurious conflict warnings for paths that didn't match actual installed files.

  3. Inconsistent path outputextension rm (which uses correct nested tracking from upstream_extensions.json) reported different paths than extension pull conflict detection.

After this fix, detectConflicts checks the same nested paths that copyDir writes to, so conflict detection is accurate for all extensions regardless of bundle nesting depth.

Verified with

  • @john/k8s — 57 files including 15 nested bundles under .swamp/bundles/k8s/; all conflicts correctly detected on re-pull
  • @stack72/system-extensions — flat bundles continue to work correctly
  • Full test suite (2316 tests passing)

Test plan

  • deno check passes
  • deno lint passes
  • deno fmt passes
  • deno run test — all 2316 tests pass, including new detectConflicts test
  • deno run compile — binary compiles
  • Manual: init repo, pull @john/k8s, pull again → all 57 conflicts detected at correct nested paths
  • Manual: init repo, pull @stack72/system-extensions, pull again → flat bundles still detected correctly

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.211429.0-sha.5a88d8c5/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.211429.0-sha.5a88d8c5/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.211429.0-sha.5a88d8c5/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.211429.0-sha.5a88d8c5/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.203155.0-sha.15f9ec56

27 Feb 20:32
Immutable release. Only release title and notes can be modified.
15f9ec5

Choose a tag to compare

What's Changed

  • feat: add extension list command to show installed extensions (#526)

Fixes: #525

  • Add extension list (alias ls) command that reads upstream_extensions.json
    and displays installed upstream extensions
  • Supports --json for structured output and --verbose to show individual files
  • Log mode output is column-aligned for readability, sorted alphabetically by name

Why this design

Before this change, the only way to see what extensions were installed was to
manually read upstream_extensions.json. This completes the extension lifecycle
CLI surface alongside push, pull, and rm.

The command follows the same patterns as extension rm — reusing
readUpstreamExtensions(), createContext(), requireInitializedRepo(), and
the established output rendering split. Column-aligned output keeps the list
scannable as extension names vary in length.

User impact

Users can now run swamp extension list (or swamp extension ls) to see all
installed upstream extensions at a glance, with version and pull date. The
--json flag gives machine-readable output for scripting, and --verbose lists
every file belonging to each extension.

Test plan

  • extension list --help shows usage
  • extension --help shows list subcommand
  • Requires initialized repo
  • Empty repo shows "No upstream extensions installed" with CTA
  • --json with no extensions returns { extensions: [] }
  • Populated repo displays entries sorted alphabetically
  • --json returns structured data with name, version, pulledAt, files
  • --verbose shows individual file paths
  • ls alias works

Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.203155.0-sha.15f9ec56/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.203155.0-sha.15f9ec56/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.203155.0-sha.15f9ec56/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.203155.0-sha.15f9ec56/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.202847.0-sha.a7fb3475

27 Feb 20:29
Immutable release. Only release title and notes can be modified.
a7fb347

Choose a tag to compare

What's Changed

  • fix: redirect to swamp.club/cli/success after CLI auth (#527)

Summary

  • Replace the localhost HTML success page with a 302 Found redirect to {serverUrl}/cli/success after the CLI captures the auth token
  • Pass serverUrl through to startCallbackServer so the redirect respects SWAMP_CLUB_URL env var
  • Remove the now-unused SUCCESS_HTML constant

Fixes systeminit/swamp-club#118

Test Plan

  • Updated callback_server_test.ts to verify 302 status and Location header
  • All 2315 tests pass, deno check, deno lint, and deno fmt clean

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.202847.0-sha.a7fb3475/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.202847.0-sha.a7fb3475/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.202847.0-sha.a7fb3475/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.202847.0-sha.a7fb3475/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.190729.0-sha.af5789db

27 Feb 19:08
Immutable release. Only release title and notes can be modified.
af5789d

Choose a tag to compare

What's Changed

  • Design Doc: Extensions (#524)

Should have published this before I did the work - bad me!!


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.190729.0-sha.af5789db/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.190729.0-sha.af5789db/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.190729.0-sha.af5789db/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.190729.0-sha.af5789db/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.184721.0-sha.c0205c99

27 Feb 18:48
Immutable release. Only release title and notes can be modified.
c0205c9

Choose a tag to compare

What's Changed

  • feat: add extension rm command to remove pulled extensions (#523)

Fixes: #522

  • Add swamp extension rm (aliased as extension remove) to cleanly remove pulled extensions by deleting all tracked files and removing the entry from upstream_extensions.json
  • Support --force to skip confirmation, --verbose for per-file deletion output, and --repo-dir for non-default repos
  • Handle edge cases: already-deleted files (skipped gracefully), legacy entries without file tracking (error with re-pull hint), dependent extensions (warning before removal), empty parent directory pruning
  • Fix missing-argument errors globally — swamp extension rm, swamp extension pull, swamp model delete, and all other commands with required arguments now show a clean error message instead of a raw stack trace with Cliffy internals

Why this approach

The recent addition of file tracking in upstream_extensions.json (PR #520) made clean removal possible — we know exactly which files an extension installed. The removeUpstreamExtension and readUpstreamExtensions functions are co-located with updateUpstreamExtensions in extension_pull.ts so all JSON mutations share the same lockfile and atomic-write pattern, preventing corruption from concurrent operations.

The missing-argument fix lives in error_output.ts (the global error renderer) rather than as a per-command .error() handler because this is a Cliffy framework issue that affects every command with required arguments. Fixing it at the render layer means all current and future commands benefit without needing individual error handlers.

Dependency checking scans locally-installed extensions' manifest.yaml files for references to the target extension. This is best-effort for v1 — it works without registry calls and covers the common case where dependents were pulled into the same repo.

Test Plan

  • 5 unit tests for removeUpstreamExtension and readUpstreamExtensions (removes entry preserving others, handles missing extension, handles missing JSON file, reads existing entries, returns empty map when file missing)
  • 5 output renderer tests (JSON output for removal success, cancellation, dependency warning, file delete, file missing)
  • 1 error output test for Cliffy missing-argument rendering
  • 6 integration tests (--help output, extension --help shows rm, invalid name error, non-installed extension error, requires initialized repo, end-to-end pull-then-rm verifying files deleted and JSON entry removed)
  • All 2312 tests pass, deno check, deno lint, deno fmt clean

Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.184721.0-sha.c0205c99/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.184721.0-sha.c0205c99/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.184721.0-sha.c0205c99/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.184721.0-sha.c0205c99/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.175155.0-sha.0e6e91c3

27 Feb 17:52
Immutable release. Only release title and notes can be modified.
0e6e91c

Choose a tag to compare

What's Changed

  • refactor: rename tags to labels in extension manifest (#521)

Summary

Renames the tags field to labels in the extension manifest, introduced
in #508. This is a follow-up rename before the field sees any adoption.

Test plan

  • All existing tests updated and passing
  • deno check passes
  • Skill docs updated

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.175155.0-sha.0e6e91c3/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.175155.0-sha.0e6e91c3/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.175155.0-sha.0e6e91c3/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.175155.0-sha.0e6e91c3/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.173856.0-sha.27f1a954

27 Feb 17:39
Immutable release. Only release title and notes can be modified.
27f1a95

Choose a tag to compare

What's Changed

  • feat: track extracted files in upstream_extensions.json (#520)

Summary

  • Persist the list of extracted files in upstream_extensions.json when an extension is pulled
  • Add optional files: string[] field to UpstreamExtensionEntry (backward compatible — existing JSON files without it parse fine)
  • Add 3 unit tests and 1 integration test

Why this is needed

When an extension is pulled, the list of extracted files is computed and displayed to the user but never persisted. This means there's no way to know which files belong to which extension after the fact.

This is a prerequisite for extension rm — without knowing which files an extension installed, a remove command would have to guess or require the user to manually specify files. By recording the file list at pull time, a future extension rm can cleanly remove exactly the files that were installed.

The extractedFiles array was already computed during pull; this change simply saves it alongside the existing version and pulledAt fields.

Example output

After pulling an extension, upstream_extensions.json now looks like:

{
  "@keeb/ssh": {
    "version": "2026.02.26.1",
    "pulledAt": "2026-02-27T17:32:41.000Z",
    "files": [
      "extensions/models/ssh/ssh.yaml",
      "extensions/models/ssh/ssh.ts"
    ]
  }
}

Test plan

  • deno check — type checking passes
  • deno lint — linting passes
  • deno fmt — formatting passes
  • deno run test — all 2294 tests pass
  • Unit tests verify files are persisted, existing entries preserved, and empty arrays handled
  • Integration test pulls @keeb/ssh from registry and asserts files array is present and non-empty

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.173856.0-sha.27f1a954/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.173856.0-sha.27f1a954/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.173856.0-sha.27f1a954/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.173856.0-sha.27f1a954/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.173715.0-sha.547868b4

27 Feb 17:38
Immutable release. Only release title and notes can be modified.
547868b

Choose a tag to compare

What's Changed

  • fix: coerceInputTypes handles flat InputsSchema without properties wrapper (#519)

Summary

  • coerceInputTypes() only checked schema.properties, skipping type coercion entirely for flat schemas (properties directly on the schema object without a properties wrapper). This caused --input key=value with numeric/boolean types to fail validation since strings were never coerced.
  • Applied the same schema.properties ?? schema fallback pattern already used by InputValidationService and other InputsSchema consumers.
  • Added test covering flat schema coercion for number and boolean types.

Test Plan

  • Added coerceInputTypes: flat schema without properties wrapper test
  • All 2294 existing tests pass
  • deno check, deno lint, deno fmt all clean

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.173715.0-sha.547868b4/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.173715.0-sha.547868b4/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.173715.0-sha.547868b4/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.173715.0-sha.547868b4/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.171331.0-sha.4405553a

27 Feb 17:14
Immutable release. Only release title and notes can be modified.
4405553

Choose a tag to compare

What's Changed

  • feat: add optional platforms and tags fields to extension manifest (#508)

Summary

Platforms

Extensions can contain platform-specific code that won't work across
OS/architecture boundaries:

  • Deno.Command() calls to OS-specific binaries (e.g. xdg-open on Linux)
  • FFI via Deno.dlopen() with platform-specific library paths (e.g.
    /usr/lib/libfoo.dylib vs /usr/lib/libfoo.so)
  • npm packages that conditionally load native bindings

The bundled output is pure JavaScript, so the system can't automatically
detect these cases — but extension authors know when their code has
platform dependencies. Today there's no way to communicate that to
consumers pulling an extension.

This adds an optional platforms string array to the manifest so authors
can declare which platforms their extension supports. The field is a
non-enforced hint — surfaced during extension push (in the resolved
summary) and during extension pull (as a warning-level message after
the archive is downloaded and the manifest is parsed).

This is the right solution because:

  • The system cannot auto-detect platform-specific code inside bundled JS
  • Enforcement would be wrong — we can't verify the author's claims
  • A manifest hint lets authors document known limitations so consumers can
    make informed decisions before adopting an extension

Tags

Adds an optional tags string array for categorization and discoverability
(e.g. aws, kubernetes, security). Displayed during push and pull.

Both fields

Both fields are fully optional — when omitted they default to [] and are
excluded entirely from the serialized archive manifest (no empty arrays
cluttering the YAML).

manifestVersion: 1
name: "@myorg/my-extension"
version: "2026.02.27.1"
platforms:
  - darwin-aarch64
  - linux-x86_64
tags:
  - aws
  - security
models:
  - my_model.ts

Test plan

  • parseExtensionManifest parses manifests with platforms field
  • parseExtensionManifest parses manifests with tags field
  • parseExtensionManifest defaults both to [] when omitted
  • Push output renders platforms and tags when present
  • Pull output renders platform hint when present
  • Empty fields are omitted from serialized archive manifest
  • deno check passes
  • deno lint passes
  • deno fmt passes
  • All tests pass

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.171331.0-sha.4405553a/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.171331.0-sha.4405553a/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.171331.0-sha.4405553a/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.171331.0-sha.4405553a/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260227.170532.0-sha.3923790a

27 Feb 17:06
Immutable release. Only release title and notes can be modified.
3923790

Choose a tag to compare

What's Changed

  • fix: skip macOS resource fork files during extension pull (#517)
  • Skip macOS AppleDouble resource fork files (._*) during extension pull extraction, file listing, and file copying
  • Set COPYFILE_DISABLE=1 on the tar extraction command to prevent macOS tar from creating resource fork files during extraction
  • Add debug-level logging of extracted archive contents for diagnosing pull issues

Context

A user on Arch Linux reported that swamp extension pull failed with:

"/tmp/swamp_pull_.../extension/models/._zfs_health.ts":
"Hidden files are not allowed in extensions."

The extension archive itself is clean — tar -tzf confirms it only contains zfs_health.ts, not .zfs_health.ts. The . file was
being created on the user's filesystem during or after extraction, not bundled in the archive.

Why this is the right fix

PR #516 added COPYFILE_DISABLE=1 to the push side, which prevents macOS tar from including ._ files when creating archives.
That fix is correct but insufficient — the ._ files can also appear on the pull side:

  1. macOS tar extraction — On macOS, tar can create ._ resource fork files when extracting, even if the archive doesn't contain
    them. Setting COPYFILE_DISABLE=1 on the extraction command prevents this.
  2. Filesystem-level creation — The reporting user was on Arch Linux with ZFS. Certain filesystem configurations or tools can
    create ._ AppleDouble files independently of tar. The archive was verified clean, yet the ._ file appeared in the temp
    extraction directory.
  3. Older archives — Archives pushed before PR #516 may still contain ._ files bundled inside them.

By filtering .* files in listFiles() and copyDir(), we handle all three cases regardless of origin. These files are
universally recognized as macOS metadata artifacts — they are never legitimate model files (they'd fail the existing hidden
file safety check anyway, and no model should start with .
).

The safety analyzer's hidden file check remains unchanged — it still catches genuinely suspicious hidden files like .env or
.secret. The ._* files simply never reach it because they're filtered out during file enumeration.

Test plan

  • Verify deno check passes
  • Verify deno run test passes
  • Verify deno run test integration/extension_pull_test.ts passes
  • Test swamp extension pull @bixu/zfs completes without resource fork errors
  • Test swamp extension pull @bixu/zfs --log-level debug shows "Archive contains:" lines

Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.170532.0-sha.3923790a/swamp-darwin-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

macOS (Intel):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.170532.0-sha.3923790a/swamp-darwin-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (x86_64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.170532.0-sha.3923790a/swamp-linux-x86_64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

Linux (aarch64):

curl -L https://github.com/systeminit/swamp/releases/download/v20260227.170532.0-sha.3923790a/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/