Releases: systeminit/swamp
swamp 20260320.003311.0-sha.6c7df52d
What's Changed
- The Machine: Ensure we don't run Stop hook without changes (#786)
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260320.003311.0-sha.6c7df52d/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/v20260320.003311.0-sha.6c7df52d/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/v20260320.003311.0-sha.6c7df52d/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/v20260320.003311.0-sha.6c7df52d/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260320.002515.0-sha.3922fd11
What's Changed
- fix: delete methods return last known state data (#788)
Summary
Closes #636
When a model's delete method succeeds, the deletion marker (tombstone) now includes the last known active state attributes merged with the deletion metadata. This fixes two problems reported in the issue:
-
Delete responses now include
dataArtifacts— Previously the JSON response had nodatafield, making it impossible to confirm what was deleted without a separate query. Now the response includes the full resource attributes alongsidedeletedAt/deletedByMethod. -
data.latest()resolves original attributes after deletion — Previously, tombstones only contained{deletedAt, deletedByMethod}, which broke CEL expressions likedata.latest("x", "y").attributes.RouteTableIdon workflow re-runs. Now those expressions resolve correctly, enabling idempotent re-runs of complex delete workflows.
Design decisions
Enrich the tombstone, not data.latest() — We considered making data.latest() lifecycle-aware (skip tombstones, return last active version) but rejected it because:
- It would be a breaking change for anyone checking
data.latest()to detect deletion - Users would need to update existing CEL expressions to use a new function
- The enriched tombstone approach requires zero changes to existing workflows on both sides — delete detection (
deletedAtis still there) and re-runs (original attributes are still there)
Flat merge, accepted collision risk — Deletion metadata (deletedAt, deletedByMethod) is merged into the same JSON object as resource attributes. We considered namespacing (e.g. _deleted.at) but accepted the theoretical collision risk since cloud APIs don't use these field names, and the added complexity wasn't justified.
Deletion markers as data handles — Rather than adding special-case logic in run.ts, deletion markers are appended to currentHandles in method_execution_service.ts so they flow through the existing data artifact pipeline. This means run.ts, the JSON renderer, and all presentation code required zero changes.
Before
{
"modelId": "ca9547ff-...",
"modelName": "test-volume",
"type": "@stack72/digitalocean/volume",
"methodName": "delete",
"dataArtifacts": []
}After
{
"modelId": "ca9547ff-...",
"modelName": "test-volume",
"type": "@stack72/digitalocean/volume",
"methodName": "delete",
"dataArtifacts": [
{
"name": "main",
"attributes": {
"id": "8290fa55-...",
"name": "swamp-crud-test-vol",
"region": "us-east-1",
"status": "active",
"deletedAt": "2026-03-20T00:02:15.524Z",
"deletedByMethod": "delete"
}
}
]
}Changes
| File | Change |
|---|---|
src/domain/models/method_execution_service.ts |
Read active content before writing tombstone; merge into marker; append as data handle |
src/domain/models/method_execution_service_test.ts |
Updated tests to verify enriched markers + new test for graceful degradation when no content exists |
Test plan
- All 3402 tests pass
- E2E verified: create → delete returns enriched tombstone with full attributes
- E2E verified: re-create after delete still works
- Tombstone on disk contains merged state for
data.latest()resolution - Graceful degradation when active content is missing (marker-only metadata)
- CI passes
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260320.002515.0-sha.3922fd11/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/v20260320.002515.0-sha.3922fd11/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/v20260320.002515.0-sha.3922fd11/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/v20260320.002515.0-sha.3922fd11/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260320.000108.0-sha.ae04a931
What's Changed
- The Machine: Writing the plan rather than presenting it slows the machine (#787)
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260320.000108.0-sha.ae04a931/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/v20260320.000108.0-sha.ae04a931/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/v20260320.000108.0-sha.ae04a931/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/v20260320.000108.0-sha.ae04a931/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260319.231448.0-sha.4ded1936
What's Changed
- fix: upgrade AWS SDK to resolve fast-xml-parser vulnerabilities (#785)
Summary
- Upgrades
@aws-sdk/client-cloudcontroland@aws-sdk/client-s3from^3.1002.0to^3.1013.0 - This pulls in
@aws-sdk/xml-builder@3.972.14(up from3.972.10) which depends onfast-xml-parser@5.5.6instead of the vulnerable5.4.1 - Resolves two transitive dependency vulnerabilities flagged by our dependency audit:
Details
The vulnerability chain was:
@aws-sdk/client-cloudcontrol@3.1002.0
→ @aws-sdk/core@3.973.19
→ @aws-sdk/xml-builder@3.972.10
→ fast-xml-parser@5.4.1 ← vulnerable
After the upgrade:
@aws-sdk/client-cloudcontrol@3.1013.0
→ @aws-sdk/core@3.973.22
→ @aws-sdk/xml-builder@3.972.14
→ fast-xml-parser@5.5.6 ← patched
No code changes were required — this is a version bump in deno.json and the resulting deno.lock update. Type-checking (deno check) passes cleanly.
Test plan
-
deno check main.tspasses - CI passes (type-check, lint, tests)
-
deno run auditno longer flags fast-xml-parser
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260319.231448.0-sha.4ded1936/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/v20260319.231448.0-sha.4ded1936/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/v20260319.231448.0-sha.4ded1936/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/v20260319.231448.0-sha.4ded1936/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260319.230601.0-sha.2484d1c6
What's Changed
- feat: warn when model definitions use env var expressions (#784)
Summary
Closes #759.
When a model definition uses ${{ env.* }} expressions, it's easy to
accidentally run a prod-named model against dev infrastructure (or vice versa)
because env vars silently change which environment the model targets. Data
artifacts stored under that model name then contain results from the wrong
environment, contaminating workflows that reference data.latest("prod-jenkins", ...).
This PR adds validation warnings (not failures) that surface env var usage
in two places:
swamp model validate— lists which fields reference which env varsswamp model method run— emits warnings before execution starts
What it looks like
Log mode (model validate):
Validating: prod-jenkins (command/shell)
✓ Definition schema
✓ Global arguments
✓ Method arguments
✓ Expression paths
✓ Check selection
⚠ Environment variables detected
globalArguments.shell uses JENKINS_SHELL
methods.execute.arguments.run uses JENKINS_BASE_URL
→ Data stored under this model will vary depending on these
environment variables at runtime. Consider using separate
models per environment, or vault.get() for sensitive values.
Summary: 5/5 validations passed, 1 warning
Result: PASSED
JSON mode (model validate --json):
{
"warnings": [
{
"name": "Environment variables detected",
"message": "Data stored under this model will vary...",
"envVars": [
{ "path": "globalArguments.shell", "envVar": "JENKINS_SHELL" },
{ "path": "methods.execute.arguments.run", "envVar": "JENKINS_BASE_URL" }
]
}
]
}Method run warnings:
WRN Environment variables detected in model definition
WRN "globalArguments.shell" uses "JENKINS_SHELL"
WRN "methods.execute.arguments.run" uses "JENKINS_BASE_URL"
WRN "Data stored under this model will vary..."
Design decisions
- Warning, not error — env vars are a legitimate feature, we just want
visibility. Validation still passes. - Shows field paths and env var names, but not values — values could be
secrets. - Suggests alternatives — separate models per environment, or
vault.get()
for sensitive values. - Surfaces during method run too — so agents/users see the warning even if
they skip validation.
Changes
New files:
src/domain/models/env_var_detector.ts— standalone function that scans
definitions for${{ env.* }}patternssrc/domain/models/env_var_detector_test.ts— 6 unit tests
Domain layer:
validation_service.ts— addedValidationWarningvalue object,
EnvVarUsageDetailinterface,ModelValidationOutcomereturn type.
validateModel()now returns{results, warnings}.execution_service.ts— updated to destructure the new return type
Application layer (libswamp):
validate.ts— addedValidationWarningDatatype,warningsfield to
ModelValidateData,totalWarningstoModelValidateAllDatarun.ts— addedenv_var_warningevent toModelMethodRunEvent, emitted
after model resolutionmod.ts— exported new types
Presentation layer:
model_validate.ts— renders warnings with yellow ⚠ markers in log mode,
includes warning count in summarymodel_method_run.ts— handlesenv_var_warningevent in both log and JSON
renderers
Skill update:
.claude/skills/swamp-model/SKILL.md— added "Handling Validation Warnings"
section instructing AI agents to STOP and ask the user before proceeding when
warnings are present. Updated workflow steps and method run docs.
User impact
- Existing models without env vars: zero change — no warnings, same output
- Models with env vars: validation now shows a yellow warning with actionable
guidance. Validation still passes. - AI agents (Claude, etc.): the skill update and CLI warnings together ensure
agents pause and confirm with the user before running models that depend on
environment variables — which was the original reporter's key concern.
Test plan
- 3401 existing tests pass (no regressions)
- 6 new unit tests for env var detection
- 1 new integration test for warning propagation
- Manual verification with compiled binary:
model validateon clean model → no warningsmodel validateon model with env vars → warning with paths + var namesmodel validate --json→ structured warnings arraymodel validate(all) → warning count in summarymodel method runwith env vars → warnings before execution
🤖 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/v20260319.230601.0-sha.2484d1c6/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/v20260319.230601.0-sha.2484d1c6/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/v20260319.230601.0-sha.2484d1c6/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/v20260319.230601.0-sha.2484d1c6/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260319.214938.0-sha.16f2cc42
What's Changed
- The Machine: Fixup issues with the machine (#783)
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260319.214938.0-sha.16f2cc42/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/v20260319.214938.0-sha.16f2cc42/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/v20260319.214938.0-sha.16f2cc42/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/v20260319.214938.0-sha.16f2cc42/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260319.210746.0-sha.16d16c05
What's Changed
- The Machine: Improving the machine that builds the machine (#782)
Cleaning up claude.md and adding hooks and updating CI
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260319.210746.0-sha.16d16c05/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/v20260319.210746.0-sha.16d16c05/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/v20260319.210746.0-sha.16d16c05/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/v20260319.210746.0-sha.16d16c05/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260319.193638.0-sha.bb9503f2
What's Changed
- docs: add CLAUDE.md rule to prefer fan-out methods over shell loops (#781)
Summary
Closes #729
Adds rule 6 to the generated CLAUDE.md instructions: Prefer fan-out methods
over loops.
Why a CLAUDE.md rule instead of tooling/metadata changes?
Investigation of #729 found that the core problem is already largely addressed
by existing swamp features, and the remaining gap is best solved at the
guidance level rather than with new tooling:
What's already in place:
- Per-model locks — Locking is now per-model instead of global, eliminating
cross-model contention. The original issue hit global lock contention where
45/50 parallel CLI calls timed out. - Factory model pattern — The
swamp-extension-modelskill already documents
the factory pattern (one method call, N targets, N outputs), which is the
correct way to build fleet-aware models. AWS and other models already use this. - "Search before you build" — Existing CLAUDE.md rules guide agents to find
existing model types before building from scratch.
Why the issue's proposed solutions weren't needed:
- Model type metadata (
fleetAware,fanOutMethods) — This puts the burden
on extension authors to understand and flag fleet patterns. The factory model
pattern already solves this architecturally — extension authors who follow the
documented pattern naturally produce fan-out capable models. - CLI hints — The factory pattern and per-model locks make the "wrong path"
(shell-looping) less catastrophic but the real fix is guiding agents to the
right path upfront.
The remaining gap: When an agent runs swamp model type describe and sees
multiple methods, nothing tells it to prefer a fan-out method over looping
single-target calls. A single CLAUDE.md rule fills this gap by explaining both
the what (use fan-out methods) and the why (per-model lock contention).
Verified effective: Tested by prompting an agent with "run execute on
server-1, server-2, and server-3" — the agent cited rule 6, mentioned lock
contention, and checked for fan-out methods before proceeding.
Test plan
-
deno checkpasses -
deno run test src/domain/repo/repo_service_test.ts— all 77 tests pass - Run
swamp repo initin a scratch directory and verify rule 6 appears in
the generated CLAUDE.md - In a fresh Claude Code session with the updated CLAUDE.md, prompt:
"I need to run the execute method on server-1, server-2, and server-3" —
agent should check for fan-out methods instead of shell-looping
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260319.193638.0-sha.bb9503f2/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/v20260319.193638.0-sha.bb9503f2/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/v20260319.193638.0-sha.bb9503f2/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/v20260319.193638.0-sha.bb9503f2/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260319.184717.0-sha.0e4c970c
What's Changed
- docs: document --input key=value syntax in skills (#780)
Summary
- Update swamp-model and swamp-workflow skills to document the
--input key=valuesyntax as the preferred form for simple scalar inputs - Keep JSON blob syntax (
--input '{}') as a documented alternative for complex structures (arrays, nested objects) - Fix options tables that described
--inputas--input <json>to--input <value>
Context
A user filed #760 requesting --arg key=value support, not knowing that --input key=value already works. Every example in our skills only showed the JSON blob form, making the key-value syntax invisible. This PR fixes that documentation gap.
Files changed
.claude/skills/swamp-model/SKILL.md— Quick reference, examples, options table.claude/skills/swamp-model/references/examples.md— Runtime inputs section.claude/skills/swamp-model/references/scenarios.md— Runtime inputs scenario.claude/skills/swamp-workflow/SKILL.md— Quick reference, examples, options table.claude/skills/swamp-workflow/references/scenarios.md— Nested workflow example
Test plan
- Verify
swamp model method run <name> <method> --input key=value --jsonworks as documented - Verify
swamp workflow run <name> --input key=value --jsonworks as documented - Verify JSON form still works:
--input '{"key": "value"}' - Verify dot notation works:
--input config.timeout=30
Closes #760
🤖 Generated with Claude Code
Installation
macOS (Apple Silicon):
curl -L https://github.com/systeminit/swamp/releases/download/v20260319.184717.0-sha.0e4c970c/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/v20260319.184717.0-sha.0e4c970c/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/v20260319.184717.0-sha.0e4c970c/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/v20260319.184717.0-sha.0e4c970c/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/swamp 20260319.180241.0-sha.12ca0b71
What's Changed
- feat: support environment variable expansion in datastore paths (#779)
Summary
Fixes #775
The filesystem datastore path in .swamp.yaml was stored as an absolute path (e.g. /Users/blake.irvin/.swamp/hello-swamp), which breaks portability when the repo is cloned on a different machine or user account.
This PR adds environment variable expansion to datastore paths, so .swamp.yaml can store portable paths like $HOME/.swamp/hello-swamp that resolve correctly at runtime on any machine.
What changed
- New
expandEnvVars(path)— expands~,$VAR, and${VAR}references from the environment at runtime. Throws a clearUserErrorif a referenced variable is not set. - New
collapseEnvVars(path)— whenswamp datastore setup filesystemwrites to.swamp.yaml, it collapses the$HOMEprefix back to$HOME/...so the stored path is portable by default. - Applied at both read points — env var / CLI
--datastorearg and.swamp.yamlfilesystem path both expand env vars before use.
Why general env var expansion (not just $HOME)
We considered special-casing only $HOME/~, but teams may use other env vars too — $XDG_DATA_HOME for XDG compliance, $SWAMP_DATA_ROOT for shared NFS mounts, or $PROJECT_DATA_DIR in CI. General $VAR/${VAR} expansion covers all these cases with the same small amount of code.
Manual verification
Compiled the binary, then:
$ mkdir /tmp/swamp-env-test && cd /tmp/swamp-env-test
$ swamp repo init
$ swamp datastore setup filesystem --path ~/.swamp/env-test-store
Confirmed .swamp.yaml stores the portable path:
datastore:
type: filesystem
path: $HOME/.swamp/env-test-storeConfirmed swamp datastore status resolves it correctly:
Datastore Status
Type: filesystem
Path: /Users/stack72/.swamp/env-test-store
Health: ● healthy (1ms)
Test plan
- 14 new unit tests for
expandEnvVarsandcollapseEnvVars(tilde,$VAR,${VAR}, undefined vars throw, passthrough, roundtrip) - All 3393 existing tests pass
-
deno check,deno lint,deno fmtall clean - Manual end-to-end test with compiled binary
🤖 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/v20260319.180241.0-sha.12ca0b71/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/v20260319.180241.0-sha.12ca0b71/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/v20260319.180241.0-sha.12ca0b71/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/v20260319.180241.0-sha.12ca0b71/swamp-linux-aarch64 -o swamp
chmod +x swamp && sudo mv swamp /usr/local/bin/