Skip to content

feat: add commands for removing devcontainers#128

Open
darttie wants to merge 1 commit into
athal7:mainfrom
darttie:devcontainer-rm-commands
Open

feat: add commands for removing devcontainers#128
darttie wants to merge 1 commit into
athal7:mainfrom
darttie:devcontainer-rm-commands

Conversation

@darttie
Copy link
Copy Markdown

@darttie darttie commented May 22, 2026

Summary

Add /devcontainer rm <branch> and /devcontainer rm all commands to fully tear down devcontainer workspaces, with pre-removal warnings for uncommitted changes and other active sessions.

What it does

Remove commands

  • /devcontainer rm <branch> — Finds the Docker container for the workspace, stops and removes it, removes the image, releases the port, deletes the job entry, removes the override config, deletes the clone folder, and cleans up session files.
  • /devcontainer rm all — Same cleanup applied to every tracked devcontainer (collected from clones directory, ports.json, and jobs.json).

Confirmation flow

Before removing, the tool checks for:

  1. Uncommitted changes via getWorkspaceStatus() (which runs git status --porcelain)
  2. Other active sessions using the workspace(s) being deleted (by scanning session files in the sessions directory)

If any warnings are found, the tool returns a message stating that explicit user confirmation is required. The LLM asks the user, and if they agree, calls the tool again with confirmed: true to proceed.

For rm all, the check is optimized: scans all entries until it finds one with uncommitted changes, and checks for any other session files regardless of workspace.

Implementation

plugin/core/devcontainer.js

  • remove() — Orchestrates full 10-step cleanup: find container → stop → get image ref → docker rmdocker rmi → release port → remove job → delete override → delete clone → clean sessions. Returns a detailed summary of what was done.
  • findContainerId() — Finds Docker container ID for a workspace using the devcontainer.local_folder label.
  • cleanupWorkspaceSessions() — Scans all session files in ~/.cache/opencode-devcontainers/opencode-sessions/ and deletes any whose .workspace matches the given path.

plugin/core/jobs.js

  • removeJob() — New export. Removes a job entry for a workspace, returns true if one existed.

plugin/index.js

  • handleRemoveSingle() and handleRemoveAll() — Orchestrate the rm flow: resolve workspace, run pre-removal warnings, call remove(), clear current session.
  • countOtherSessions() — Counts session files (excluding current) by workspace path (or all if null).
  • formatRemoveSummary() — Formats the remove result for display.
  • confirmed parameter added to the devcontainer tool definition.
  • Imported remove, listClones, readPorts, readJobs from core modules.

Tests

  • Unit tests (test/unit/devcontainer.test.js): 5 tests covering remove() with full state, missing clone folder, no port/job entries, completely unknown workspace, and idempotency.
  • Integration test (test/integration/devcontainer-remove.test.js): actual Docker lifecycle — creates real containers with the devcontainer label, runs remove(), verifies container/image are gone and a decoy container is untouched.

All 219 tests pass.

Running integration tests manually

Requires Docker daemon running:

node --test test/integration/devcontainer-remove.test.js

Documentation

Updated plugin/command/devcontainer.md with rm command and the confirmation info for the LLM.

Notes

  • Only removes devcontainer clones. Worktree-based workspaces are unaffected.
  • The rm prefix is parsed from the tool target argument, so it works naturally as /devcontainer rm feature-x.
  • If warnings are present, the LLM must pass confirmed: true on the second call to proceed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant