Skip to main content
← Back to list
01Issue
BugShippedSwamp CLI
Assigneeskeeb

#383 `swamp extension rm` leaves empty scaffold dirs behind

Opened by keeb · 5/20/2026· Shipped 5/20/2026

Summary

After swamp extension rm <name> --force, the per-extension subtree under .swamp/pulled-extensions/<collective>/<name>/ is not fully removed — empty kind directories (datastores/, drivers/, reports/, vaults/, workflows/, etc.) remain. The CLI reports e.g. "Pruned 3 empty directory(ies)" but the extension root is still on disk.

Reproduction

swamp extension pull @alvagante/docker-image-test   # an extension that only ships models + files
swamp extension rm @alvagante/docker-image-test --force
ls .swamp/pulled-extensions/@alvagante/docker-image-test/
# datastores  drivers  reports  vaults  workflows   ← still there, all empty

Manifest of the example extension declares models: [docker_image_test.ts], additionalFiles: [README.md, LICENSE.txt], and empty workflows/vaults/drivers/datastores/reports.

Expected

rm removes the entire .swamp/pulled-extensions/<collective>/<name>/ subtree when no tracked file remains.

Actual

rm removes tracked files and prunes their immediate parents, but the extension root retains empty kind dirs that pull scaffolded.

Root cause

src/libswamp/extensions/pull.ts:866-954 unconditionally Deno.mkdirs every kind dir (models, workflows, vaults, drivers, datastores, reports, files) regardless of whether the extension ships content for that kind. These scaffold dirs are never recorded in the lockfile's tracked-file list.

src/libswamp/extensions/remove_extension_service.ts:134-153 builds parentDirs only from dirname(trackedFile) and hands them to pruneEmptyDirs. The upward walk in pruneEmptyDirs (:170-199) stops at the first non-empty dir — so when it visits .../<extension>/, it sees the un-tracked scaffold subdirs as entries, treats the root as non-empty, and bails.

Suggested fix

One of:

  1. Make pull lazy — mkdir a kind dir only when there's at least one file to copy into it.
  2. Strengthen pruneEmptyDirs to recursively remove empty subtrees (not just dirs that are already empty at visit time), bounded by the extension root.
  3. Have rm enumerate the scaffold dirs from PULLED_TYPE_DIRS (layout.ts:48-57) for each removed extension and add them to parentDirs.

(1) keeps the on-disk shape honest; (2) and (3) tolerate the existing scaffold behavior.

Environment

  • swamp 20260206.200442.0-sha. (dev build; reproduced against main source — fix not yet present).
  • Linux 6.19.13-arch1-1, zsh.
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 3 MOREPR_MERGEDSHIPPED

Shipped

5/20/2026, 4:57:56 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
keeb assigned keeb5/20/2026, 6:02:47 AM

Sign in to post a ripple.