Skip to content

Releases: systeminit/swamp

swamp 20260317.212534.0-sha.5ac636c1

17 Mar 21:26
Immutable release. Only release title and notes can be modified.
5ac636c

Choose a tag to compare

What's Changed

  • fix: use pre-built bundle when dependency freshness check fails (#742)

Closes #737

Summary

When an extension is pulled from the registry, swamp discards the valid pre-built bundle and fails with Module not found if any local dependency file is missing from disk. This fix makes bundleWithCache fall back to the cached bundle when the freshness check fails, rather than attempting a re-bundle that will also fail.

Root cause

bundleWithCache validates cache freshness by resolving all local imports from the .ts source file and comparing mtimes. If a dependency file is missing (because the extension was pushed with an older swamp that had a single-line import regex and missed multi-line import declarations), Deno.stat() throws inside the try block. The catch block then falls through to re-bundle from source — which fails with the same Module not found error.

The @keeb/grafana extension hits this exactly: grafana_instance.ts has a multi-line import for ./lib/grafana.ts. The older push regex only matched single-line imports, so lib/grafana.ts was never included in the archive. The pre-built bundle at .swamp/bundles/grafana_instance.js is perfectly valid (compiled at push time with all deps), but every load attempt discards it and fails.

The catch block comment said "Bundle doesn't exist, stat failed, or import resolution failed — rebundle", conflating two distinct cases:

  1. Bundle file does not exist → rebundle from source ✅ correct
  2. Bundle exists but freshness check threw → rebundle from source ❌ wrong — the bundle is valid

Fix

Track bundleExists before entering the try/catch. If the bundle file exists but the freshness check throws for any reason, use the cached bundle as a fallback and log at debug level. Only attempt a re-bundle when the bundle genuinely doesn't exist.

Applied to all four loaders: model, vault, driver, datastore.

User impact

Before: swamp extension install @keeb/grafana succeeds but swamp model type search grafana fails with deno bundle failed ... Module not found "lib/grafana.ts".

After: The pre-built bundle is used as a fallback. @keeb/grafana/instance appears in search results with no errors.

Verification

  • deno check — passes
  • deno lint — passes
  • deno fmt — passes
  • deno run test — 3161 passed, 0 failed
  • deno run compile — binary compiles
  • Manual: swamp extension install @keeb/grafanaswamp model type search grafana returns @keeb/grafana/instance

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.212534.0-sha.5ac636c1/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/v20260317.212534.0-sha.5ac636c1/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/v20260317.212534.0-sha.5ac636c1/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/v20260317.212534.0-sha.5ac636c1/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.212014.0-sha.ede9f2a1

17 Mar 21:21
Immutable release. Only release title and notes can be modified.
ede9f2a

Choose a tag to compare

What's Changed

  • fix: skip extension loading for help/version commands, parallelize loaders (#738) (#741)

Problem

Every CLI invocation — including swamp --help — was unconditionally loading all user extensions before running any command. This caused a ~42 second startup time, making even basic usage feel broken.

The root cause was four sequential loader calls, each independently:

  • Creating a RepoMarkerRepository and reading the marker file from disk
  • Creating an EmbeddedDenoRuntime and calling ensureDeno()
  • Spawning deno bundle subprocesses to compile extension files

With 4 sequential loaders and potentially many extension files, startup time was dominated by this overhead even when no extensions were needed.

Changes

1. Skip extension loading for commands that don't need it

Added commandNeedsExtensions() which checks the pre-parsed command against a set of commands that never use user extensions:

"", "help", "version", "completions", "init", "update", "auth", "telemetry", "issue"

swamp --help, swamp version, swamp completions bash, etc. are now instant.

2. Read marker and runtime once, share across all loaders

Previously each of the 4 loadUser* functions independently read the repo marker and created an EmbeddedDenoRuntime. Now the marker is read once (reusing the value already needed for resolveLogLevel) and a single EmbeddedDenoRuntime instance is shared — eliminating 3 redundant disk reads and 3 redundant runtime instantiations.

3. Run all 4 loaders in parallel

Replaced sequential await calls with Promise.all():

await Promise.all([
  loadUserModels(repoDir, marker, denoRuntime),
  loadUserVaults(repoDir, marker, denoRuntime),
  loadUserDrivers(repoDir, marker, denoRuntime),
  loadUserDatastores(repoDir, marker, denoRuntime),
]);

This is safe because each loader writes to its own registry, reads from a separate source directory, and writes to a separate bundle cache directory. ensureDeno() is idempotent (checks a version marker file before extracting). JavaScript's single-threaded event loop means Map.set() calls within registries are atomic within a tick.

User Impact

Command Before After
swamp --help ~42 seconds < 1 second
swamp version ~42 seconds < 1 second
swamp completions bash ~42 seconds < 1 second
swamp model type search aws ~42 seconds significantly faster (parallel loading)

Commands that need extensions (e.g. model, workflow, data, vault) still load all extensions, but now in parallel rather than sequentially.

Files Changed

  • src/cli/mod.ts — all changes in this single file

Test Plan

  • deno check — type checking passes
  • deno lint — no lint errors
  • deno fmt --check — formatting correct
  • deno run test — 3156 tests passed, 0 failed
  • deno run compile — binary compiled successfully

Fixes #738


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.212014.0-sha.ede9f2a1/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/v20260317.212014.0-sha.ede9f2a1/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/v20260317.212014.0-sha.ede9f2a1/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/v20260317.212014.0-sha.ede9f2a1/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.201339.0-sha.bad69941

17 Mar 20:14
Immutable release. Only release title and notes can be modified.
bad6994

Choose a tag to compare

What's Changed

  • fix: resolve CJS/ESM interop failure loading Azure Key Vault extension bundle (#740)

Closes #733

Summary

  • Fix @swamp/azure-kv extension vault bundle failing to load in the compiled binary due to a CJS/ESM interop issue in the esbuild-generated __toESM helper
  • Fix silent error swallowing in all four extension loaders that hid the real error and dumped ~2.1MB of base64-encoded bundle content to the terminal
  • Apply the same fix to all four loaders (model, vault, driver, datastore) for consistency

Root cause

When deno bundle (esbuild) bundles npm packages with --platform deno, it generates a __toESM helper that conditionally sets a .default property on CJS module wrappers. The condition checks an isNodeMode flag that is false for Deno platform builds. CJS modules that set module.exports.__esModule = true (like tslib) do NOT get a .default property on their ESM wrapper.

The Azure SDK depends on tslib, and the bundled code destructures import_tslib.default to get __extends, __awaiter, etc. Since .default was never set, the destructuring gets undefined, crashing with:

Cannot destructure property '__extends' of 'import_tslib.default' as it is undefined

This real error was silently swallowed by a bare catch {} in the file URL import path. The data URL fallback also failed (because createRequire(import.meta.url) doesn't accept data URLs), and THAT error message included the entire 1.6MB base64-encoded bundle — dumping ~2.1MB of "encrypted looking" data to the terminal.

Fix (3 parts)

  1. fixCjsEsmInterop() — Post-processes bundles to patch the __toESM helper so it always sets .default on CJS module wrappers, matching --platform node behavior. Applied at both bundle time and import time (auto-fixes old cached bundles on disk).

  2. Log file URL import errors — Silent catch {} blocks now log the actual error at debug level, making future bundle issues diagnosable with SWAMP_DEBUG=1.

  3. sanitizeDataUrlError() — Truncates base64 data URLs in error messages to prevent flooding the terminal.

Why this is the correct fix

  • The __toESM change is equivalent to what esbuild generates with --platform node. Since Deno has full Node compat, always setting .default is correct.
  • The fix targets a specific esbuild-generated pattern via regex (isNodeMode || !mod || !mod.__esModule ? __defProp(...) : target), so it only affects the exact helper function and is idempotent.
  • Old cached bundles are automatically fixed on first load and written back to disk — no manual cache clearing needed.
  • Extensions without tslib (e.g., @swamp/aws/ec2 with 104 model types) are completely unaffected — the regex simply doesn't match.
  • No extension re-upload required — the fix is in swamp's runtime, not the extension.

User impact

Before: swamp extension install @swamp/azure-kv succeeds but every subsequent command dumps ~2.1MB of base64 to terminal with a confusing filename must be a file URL error.

After: The extension loads cleanly and appears in swamp vault type list.

Verification

  • deno check — passes
  • deno lint — passes
  • deno fmt — passes
  • deno run test — 3166 passed, 0 failed (5 new tests for fixCjsEsmInterop and sanitizeDataUrlError)
  • deno run compile — binary compiles
  • Manual: swamp repo initswamp extension install @swamp/azure-kvswamp vault type list shows @swamp/azure-kv with no errors
  • Manual: swamp extension install @swamp/aws/ec2 → all 104 model types load with zero warnings

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.201339.0-sha.bad69941/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/v20260317.201339.0-sha.bad69941/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/v20260317.201339.0-sha.bad69941/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/v20260317.201339.0-sha.bad69941/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.193300.0-sha.d7a919c1

17 Mar 19:33
Immutable release. Only release title and notes can be modified.
d7a919c

Choose a tag to compare

What's Changed

  • feat: move AWS, Azure, and 1Password vault providers to extensions (#736)

Closes #665

Summary

Moves the aws-sm, azure-kv, and 1password vault providers from built-in types to extension vaults published at swamp.club. After this change, only local_encryption (and mock for testing) remain as built-in vault types. The three cloud/external vault providers are now independently versioned extensions that auto-resolve from the registry on first use.

What changed

Removed from core:

  • Deleted aws_vault_provider.ts, azure_kv_vault_provider.ts, onepassword_vault_provider.ts and their test files (-1,545 lines)
  • Removed aws-sm, azure-kv, 1password from BUILT_IN_VAULT_TYPES in vault_types.ts — only local_encryption remains
  • Removed their switch cases from VaultService.registerVault()
  • Removed @aws-sdk/client-secrets-manager, @azure/identity, @azure/keyvault-secrets from deno.json dependencies

Migration path via RENAMED_VAULT_TYPES:

  • aws / aws-sm@swamp/aws-sm
  • azure / azure-kv@swamp/azure-kv
  • 1password@swamp/1password

When VaultService.fromRepository() loads an existing vault config with an old type name, it remaps to the @swamp/* extension type and auto-resolves it from the registry (installed by PR #725's auto-resolution infrastructure).

vault create simplified:

  • Removed --region, --vault-url, --op-vault, --op-account flags
  • All extension vault types now use --config <json> for provider configuration
  • resolveProviderConfig() only handles local_encryption now

ensureDefaultVaults() is now a no-op:

  • Previously auto-created an AWS vault when AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_REGION were set
  • This behavior is removed since AWS is now an extension

Error messages updated:

  • "No vaults configured" error now suggests swamp extension pull @swamp/aws-sm instead of setting AWS env vars

Published extensions

The three vault providers have been published to swamp.club as:

  • @swamp/1password@2026.03.17.1 — shells out to op CLI, no npm SDK deps
  • @swamp/aws-sm@2026.03.17.1 — uses @aws-sdk/client-secrets-manager@3.1010.0
  • @swamp/azure-kv@2026.03.17.1 — uses @azure/identity@4.13.0 + @azure/keyvault-secrets@4.10.0

Source lives at https://github.com/systeminit/swamp-extensions

User impact

Existing users with vault configs on disk

No action required. Existing .swamp/vault/*.yaml files with type: aws-sm, type: azure-kv, or type: 1password continue to work. On first use, swamp will:

  1. Log a deprecation warning about the old type name
  2. Remap it to the @swamp/* extension type
  3. Auto-resolve and install the extension from the registry
  4. Load the vault and proceed normally

Creating new vaults

The CLI syntax changes from dedicated flags to --config <json>:

# Before
swamp vault create aws-sm my-vault --region us-east-1
swamp vault create azure-kv my-vault --vault-url https://myvault.vault.azure.net/
swamp vault create 1password my-vault --op-vault Engineering

# After
swamp vault create @swamp/aws-sm my-vault --config '{"region":"us-east-1"}'
swamp vault create @swamp/azure-kv my-vault --config '{"vault_url":"https://myvault.vault.azure.net/"}'
swamp vault create @swamp/1password my-vault --config '{"op_vault":"Engineering"}'

Offline users

Users without registry access can manually install extensions by placing the .ts source files in extensions/vaults/.

Binary size

The compiled binary no longer includes the AWS SDK, Azure SDK, or 1Password provider code. These dependencies are now bundled into the extensions at publish time.

Known issues

  • Azure Key Vault extension bundle fails to load in compiled binary due to large bundle size (#733)
  • Auto-resolver fails when extensions/models/ directory doesn't exist for vault-only extensions (#734)

Verification

  • deno check — passes
  • deno lint — passes
  • deno fmt — passes
  • deno run test — 3138 passed, 0 failed
  • deno run compile — binary compiled successfully
  • Manual testing: auto-resolution verified for all three extensions (1password fails at op CLI check, aws-sm fails at credential check — both expected)

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.193300.0-sha.d7a919c1/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/v20260317.193300.0-sha.d7a919c1/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/v20260317.193300.0-sha.d7a919c1/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/v20260317.193300.0-sha.d7a919c1/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.192830.0-sha.8c163926

17 Mar 19:29
Immutable release. Only release title and notes can be modified.
8c16392

Choose a tag to compare

What's Changed

  • feat: add datastore type registry and user datastore loader (#735)

Summary

  • Add extension infrastructure for user-defined datastores, mirroring the existing patterns for drivers, models, and vaults
  • Users can place TypeScript files in extensions/datastores/ that export a datastore object with a type, name, description, and createProvider factory — they are discovered, bundled, validated, and registered on CLI startup
  • This is the first step toward allowing custom datastores to be packaged and distributed via the swamp extension system (PR 1 of 4)

What this PR does

New domain types

  • DatastoreSyncService interface — pull/push contract for remote sync
  • DatastoreProvider interface — factory for locks, verifiers, and sync
  • DatastoreTypeRegistry class + singleton — register/lookup datastore types
  • Built-in type registration for filesystem and s3 (via datastore_types.ts)

Loader infrastructure

  • UserDatastoreLoader — discovers .ts files in extensions/datastores/, bundles with mtime-based caching to .swamp/datastore-bundles/, validates the export const datastore shape via Zod, and registers with the global registry
  • resolveDatastoresDir — resolution priority: SWAMP_DATASTORES_DIR env var > .swamp.yaml datastoresDir > default extensions/datastores

Modified files

  • DatastoreHealthResult.datastoreType widened from "filesystem" | "s3" to string so custom datastores can report their own type
  • SWAMP_SUBDIRS gains datastoreBundles: "datastore-bundles" for bundle cache
  • RepoMarkerData gains optional datastoresDir field
  • CLI startup calls loadUserDatastores() alongside existing model/vault/driver loaders
  • DDD ratchet count bumped 17→18 for the new domain→infrastructure import (same pattern as UserDriverLoader)

User-facing behavior

No user-visible changes. This PR is purely additive infrastructure. Existing CLI commands, config files, and workflows behave identically. The loader silently no-ops when extensions/datastores/ does not exist (which is the case for all current repos). Users who place a valid datastore extension file in that directory will see it loaded at startup (visible with SWAMP_DEBUG=1).

Why this is correct

  • Follows the exact same architecture as UserDriverLoader and UserVaultLoader — same bundling, caching, validation, and error handling patterns
  • All 3161 tests pass (3143 existing + 18 new)
  • deno check, deno lint, deno fmt all clean
  • Binary compiles successfully
  • Manually verified end-to-end: init repo → place extension → confirm Loaded user datastore type from my_store.ts at startup → bundle cached at .swamp/datastore-bundles/

What comes next

This is PR 1 of 4 in the Extension Drivers & Datastores series:

  1. This PR — Datastore registry & loader infrastructure
  2. Extension manifest + push/pull support for drivers & datastores
  3. Wire custom datastores into repo context (datastore commands)
  4. Skills & documentation

Test plan

  • deno check — type checking passes
  • deno lint — no lint errors
  • deno fmt — formatting clean
  • deno run test — 3161 passed, 0 failed
  • deno run compile — binary compiles
  • Manual: swamp init → place .ts in extensions/datastores/SWAMP_DEBUG=1 swamp model type search shows Loaded user datastore type from my_store.ts

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.192830.0-sha.8c163926/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/v20260317.192830.0-sha.8c163926/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/v20260317.192830.0-sha.8c163926/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/v20260317.192830.0-sha.8c163926/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.170454.0-sha.55c7632b

17 Mar 17:06
Immutable release. Only release title and notes can be modified.
55c7632

Choose a tag to compare

What's Changed

  • feat: add libswamp event stream library and renderer pattern (#732)

Introduce a reusable library layer (src/libswamp/) that decouples domain orchestration from presentation. Every operation is an async generator yielding typed events through a discriminated union, with compile-time exhaustiveness checking via EventHandlers. This enables future presentation layers (web UI, API) without modifying domain logic.

Core infrastructure:

  • LibSwampContext with hierarchical cancellation (withTimeout, withSignal)
  • consumeStream/result/withDefaults for type-safe event consumption
  • AsyncQueue, merge(), and withEventBridge() for concurrent stream composition
  • SwampError structured errors yielded as events, not thrown
  • collect/assertCompletes/assertErrors test utilities

Ported operations:

  • auth whoami: credentials + server contact as event stream
  • workflow run: parallel job/step execution with interleaved events
  • model method run: expression evaluation, execution, data artifacts

Renderer pattern (src/presentation/renderers/):

  • Renderer interface producing EventHandlers for consumeStream()
  • Log-mode renderers: scoped loggers, human-readable progress
  • JSON-mode renderers: serialize view types directly, no backward-compat shims
  • Factory functions select renderer by OutputMode
  • Command handlers reduced to pure orchestration (wire deps, pick renderer, consume stream)

Design documents:

  • design/libswamp.md: event stream architecture, concurrency model, migration strategy
  • design/rendering.md: renderer pattern, logging boundaries, dependency direction

Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.170454.0-sha.55c7632b/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/v20260317.170454.0-sha.55c7632b/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/v20260317.170454.0-sha.55c7632b/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/v20260317.170454.0-sha.55c7632b/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.105237.0-sha.7095a535

17 Mar 10:53
Immutable release. Only release title and notes can be modified.
7095a53

Choose a tag to compare

What's Changed

  • fix: resolve stack overflow when loading extension bundles with large npm deps (#731)

Summary

Fixes #728.

  • Root cause: String.fromCharCode(...new TextEncoder().encode(js)) spreads every byte of a bundle onto the call stack as a function argument. Large inlined npm dependency trees (e.g., @octokit/rest, @slack/web-api) produce bundles of hundreds of KB, exceeding V8's maximum call stack size.
  • Cached bundles: Restore toFileUrl() imports (the pre-#724 approach) with on-disk zod rewriting so old cached bundles are fixed permanently.
  • Fallback path: Add uint8ArrayToBase64() which processes bytes in 8KB chunks, avoiding the stack overflow for the no-repo-dir codepath.
  • All three loaders fixed: UserModelLoader, UserDriverLoader, UserVaultLoader all had the identical bug from #724.

Test plan

  • deno check — type checking passes
  • deno lint — linting passes
  • deno fmt — formatting passes
  • deno run test — 3033/3033 tests pass
  • deno run compile — binary compiles
  • New uint8ArrayToBase64 unit tests (small input, empty input, 1MB input)
  • Manual verification: swamp repo initswamp extension pull @bixu/githubswamp model type search --json loads all 4 Octokit-based models without warnings

🤖 Generated with Claude Code

Co-authored-by: Blake Irvin blakeirvin@me.com


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.105237.0-sha.7095a535/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/v20260317.105237.0-sha.7095a535/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/v20260317.105237.0-sha.7095a535/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/v20260317.105237.0-sha.7095a535/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.010646.0-sha.40d70e64

17 Mar 01:07
Immutable release. Only release title and notes can be modified.
40d70e6

Choose a tag to compare

What's Changed

  • feat: auto-trust collectives from user membership (#727)

Summary

  • Cache the user's collective memberships in auth.json during auth login and auth whoami, then merge them into the trusted collectives list at CLI startup
  • Removes friction of manually adding each collective to trustedCollectives in .swamp.yaml — if you're a member of a collective, its extensions auto-resolve automatically
  • Adds trustMemberCollectives option to .swamp.yaml for opt-out

Design Decisions

Cache at login time, not per-invocation. Calling the whoami API on every CLI invocation would add latency. Instead, collectives are cached in auth.json during auth login (already makes a whoami call) and refreshed on auth whoami. This means membership changes require a swamp auth whoami to take effect — an acceptable tradeoff for zero-latency startup.

Merge, don't replace. Membership collectives are merged with the explicit trustedCollectives list (deduplicated via Set). This means explicit config is never lost, and membership adds to it additively.

Opt-out via trustMemberCollectives: false. Defaults to true (absent = true). When set to false, only the explicit trustedCollectives list is used — exactly matching the previous behavior. This gives security-conscious users full control.

Graceful degradation. If not authenticated, auth.json is missing/unreadable, or the collectives field doesn't exist (old auth.json), the feature silently falls back to the current behavior with no errors.

User Impact

Before: Users who are members of collectives (e.g., their org's @myorg collective) had to manually add myorg to trustedCollectives in every repo's .swamp.yaml to get auto-resolution working. Without this, swamp model create @myorg/some-type my-model would fail with "Unknown model type".

After: After logging in, membership collectives are automatically trusted. Extensions from any collective the user belongs to auto-resolve on first use with zero configuration.

Changes

File Change
src/domain/auth/auth_credentials.ts Added collectives?: string[] to AuthCredentials
src/cli/commands/auth_login.ts Cache collectives from whoami response during login
src/cli/commands/auth_whoami.ts Refresh cached collectives on whoami
src/infrastructure/persistence/repo_marker_repository.ts Added trustMemberCollectives?: boolean to RepoMarkerData
src/cli/mod.ts Added resolveTrustedCollectives() to merge membership + explicit collectives; load auth at startup
src/cli/mod_test.ts 8 new tests for resolveTrustedCollectives
src/infrastructure/persistence/auth_repository_test.ts 2 new tests for collectives round-trip
Skills & design docs (5 files) Updated to document membership-based trust and trustMemberCollectives opt-out

Test Plan

  • deno check — all modified files pass type checking
  • deno lint — no lint errors
  • deno fmt --check — formatting clean
  • deno run test src/cli/mod_test.ts — 51 tests pass (8 new resolveTrustedCollectives tests)
  • deno run test src/infrastructure/persistence/auth_repository_test.ts — 7 tests pass (2 new)
  • Manual E2E test:
    1. Compiled binary with deno run compile
    2. Created fresh repo in /tmp/swamp-test-autotrust with swamp repo init
    3. Ran swamp auth whoami → cached collectives ["swamp", "system-initiative", "stack72"] in auth.json
    4. Ran swamp model create @stack72/unifi-traffic test-traffic → auto-resolved and installed @stack72/ubiquity extension successfully
    5. The stack72 collective was NOT in .swamp.yaml's trustedCollectives — it was trusted purely via membership

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.010646.0-sha.40d70e64/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/v20260317.010646.0-sha.40d70e64/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/v20260317.010646.0-sha.40d70e64/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/v20260317.010646.0-sha.40d70e64/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.005011.0-sha.2f69cc55

17 Mar 00:51
Immutable release. Only release title and notes can be modified.
2f69cc5

Choose a tag to compare

What's Changed

  • fix: data GC never fully removes expired data from disk (#722)

Summary

Fixes #720

swamp data gc reported expired data but never reclaimed any disk space. The deleteExpiredData() method only called removeLatestMarker(), which removed the latest symlink but left all version directories and content files on disk.

This was a two-part problem:

  1. Phase 1 (expired data cleanup) only performed a soft-delete — no version directories were removed, zero bytes freed
  2. Phase 2 (collectGarbage()) always protects the latest version, and the single-version delete() path recreates the latest marker, effectively undoing Phase 1's soft-delete

User impact

Before this fix, running swamp data gc would report expired entries but disk usage would remain unchanged. Users had no way to reclaim space from expired data without manually deleting directories from the datastore.

After this fix, swamp data gc fully removes expired data directories, correctly reports versionsDeleted and bytesReclaimed, and actually frees disk space.

What changed

  • data_lifecycle_service.ts: Replaced removeLatestMarker() (soft-delete) with delete(type, modelId, dataName) (hard-delete) in deleteExpiredData(). Before deleting, stats each version's content file to report accurate bytes reclaimed. Updated LifecycleGCResult doc comments to reflect the new behavior.

  • data_lifecycle_service_test.ts: Added delete and getContentPath mocks to MockDataRepository. Added two new tests:

    • Verifies expired data triggers delete() (not removeLatestMarker()) and reports correct versionsDeleted
    • Verifies dry run does not call delete()

Why this is correct

The no-version delete(type, modelId, dataName) path in UnifiedDataRepository does a clean Deno.remove(dataNameDir, { recursive: true }) — it removes the entire data directory without recreating any markers. After Phase 1 hard-deletes expired entries, Phase 2's findAllForModel() naturally skips them since their directories no longer exist. No changes needed to collectGarbage() or the delete() implementation.

Test plan

  • deno check — type checking passes
  • deno lint — no lint errors
  • deno fmt — properly formatted
  • deno run test — all 2997 tests pass (including 2 new tests)
  • deno run compile — binary compiles successfully

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.005011.0-sha.2f69cc55/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/v20260317.005011.0-sha.2f69cc55/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/v20260317.005011.0-sha.2f69cc55/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/v20260317.005011.0-sha.2f69cc55/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/

swamp 20260317.003631.0-sha.7ef34bda

17 Mar 00:37
Immutable release. Only release title and notes can be modified.
7ef34bd

Choose a tag to compare

What's Changed

  • docs: update skills and design docs for auto-resolution feature (#726)

Summary

  • Add "Automatic Resolution" section to design/extension.md covering trusted collectives, resolution algorithm, hot-loading, re-entrancy guard, and architecture
  • Add trustedCollectives config option to design/repo.md and expand .swamp.yaml example in repo structure reference
  • Update extension-model skill with auto-resolution notes and new example decision flow showing auto-resolve in action
  • Add auto-resolution troubleshooting entries to both model and extension-model troubleshooting references
  • Add vault type auto-resolution note to vault skill

Test plan

  • deno fmt passes on all changed files
  • deno run compile succeeds with updated skills embedded

🤖 Generated with Claude Code


Installation

macOS (Apple Silicon):

curl -L https://github.com/systeminit/swamp/releases/download/v20260317.003631.0-sha.7ef34bda/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/v20260317.003631.0-sha.7ef34bda/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/v20260317.003631.0-sha.7ef34bda/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/v20260317.003631.0-sha.7ef34bda/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/