Skip to content

Feature: .bb-env-teardown.sh, a teardown counterpart to the worktree setup hook #2477

Description

@MisterMunchkin

The workflow

Summary

bb runs a setup hook when it creates a managed worktree, but nothing when it destroys one. I'd like a symmetric .bb-env-teardown.sh, so a repo can release what its setup hook provisioned.

The asymmetry

Reading the shipped source maps on 0.40.0:

Createpackages/host-workspace/src/provisioning.tscreateWorktree does, in order:

  1. git worktree add -B <branch> <target> <base>
  2. copyIncludedFiles (.worktreeinclude)
  3. runSetupScript (.bb-env-setup.sh)

Destroy — same file, removeWorktree: git worktree remove --force, then fs.rm -rf. No hook, no script, no notification.

.bb-env-setup.sh and .worktreeinclude are the only two script filenames in the codebase, so there is currently no extension point on the teardown side.

Why it matters

A setup hook that only installs dependencies is symmetric by accident — rm -rf undoes it. But setup hooks routinely provision things that live outside the worktree:

  • a per-worktree database or schema
  • a registered local dev site / vhost / proxy entry
  • a file watcher or daemon rooted at the worktree path
  • a container, tunnel, or port reservation

Every one of those survives removeWorktree and accumulates silently, once per archived thread. There's no way for a repo to clean up after itself today.

This overlaps with #1660 (orphaned dev processes in deleted managed worktrees compounding a host leak). A teardown hook wouldn't fix that on bb's side, but it would let affected repos stop their own processes before the worktree goes away, which is the part bb can't do generically.

Proposed contract

Mirror the setup hook as closely as possible:

  • .bb-env-teardown.sh at the worktree root, resolved the same way as .bb-env-setup.sh; absent means no-op.
  • Invoked as env bash .bb-env-teardown.sh, cwd set to the worktree, same sanitized environment.
  • Runs inside removeWorktree, before git worktree remove, so the tree is still intact and the script can read it.
  • Only for managed worktrees being destroyed.
  • Its own timeout, and progress in the transcript the same way setup reports.

One thing I'd ask for explicitly: make it non-blocking

The setup hook is correctly fail-closed — a non-zero exit removes the worktree and fails provisioning. Teardown should be the opposite: best-effort and unable to block removal.

A failing or hanging teardown script must not be able to leave a worktree undeletable, or the feature turns a cleanup convenience into a way to wedge cleanup entirely. Concretely: kill it at the timeout, report the failure in the transcript, and remove the worktree regardless.

Alternatives considered

  • A plugin. Thread lifecycle events are observe-only and fire-and-forget, so a plugin can't reliably run teardown before bb reclaims; making it reliable means taking over worktree creation entirely, which is a large amount of machinery for one missing hook.
  • External reconciliation. Works if every provisioned resource is named deterministically from the branch, so an out-of-band sweep can diff live resources against git worktree list. That's a real workaround, but it pushes the burden onto every repo and can't handle anything not name-addressable.

Happy to send a PR if this shape sounds right.

I searched open and closed issues for the same request.
AGENT GENERATED

What happens today

On create, createWorktree runs git worktree add, then copyIncludedFiles for .worktreeinclude, then runSetupScript for .bb-env-setup.sh.

On destroy, removeWorktree runs git worktree remove --force and then fs.rm(..., { recursive: true, force: true }). No hook, no notification.

.bb-env-setup.sh and .worktreeinclude are the only two script filenames in the tree, so there is no extension point on the teardown side.

The practical effect: everything a setup hook provisions outside the worktree survives the worktree and accumulates once per archived thread. Nothing in the repo can clean up after itself.

What you would expect

A .bb-env-teardown.sh that mirrors the setup hook:

  • Resolved from the worktree root the same way .bb-env-setup.sh is; absent means no-op.
  • Invoked as env bash .bb-env-teardown.sh, cwd set to the worktree, same sanitized environment.
  • Runs inside removeWorktree before git worktree remove, while the tree is still intact.
  • Only for managed worktrees being destroyed.
  • Its own timeout, and transcript progress the way setup reports it.

teardown should be best-effort and must not be able to block removal. Setup is correctly fail-closed — a non-zero exit removes the worktree and fails provisioning. Teardown wants the opposite. If a teardown script can fail or hang its way into an undeletable worktree, the feature converts a cleanup convenience into a way to wedge cleanup entirely. Kill it at the timeout, report the failure, remove the worktree regardless.

Context and alternatives

Verified on: bb 0.40.0 desktop app; code read at f3cab2d (desktop-v0.40.0). I confirmed the create side end to end — spawned a thread with --new-environment worktree, watched .bb-env-setup.sh run in the new worktree, and confirmed a non-zero exit fails provisioning and removes the worktree. The teardown gap is the absence of any equivalent call in removeWorktree.

Workaround I use now. Name every provisioned resource as a pure function of the branch, then reconcile out of band: list live resources, diff against git worktree list, release the orphans. It works, but it pushes the burden onto every repo and cannot handle anything that is not name-addressable.

Ruled out: a plugin. Thread lifecycle events are observe-only and fire-and-forget, so a plugin cannot reliably run teardown before bb reclaims the environment. Making it reliable means taking over worktree creation so the plugin owns removal too — a large amount of machinery, and it leaves bb's own worktree button still leaking. I scoped that plugin out and abandoned it in favour of filing this.

Related: #1660 (orphaned dev processes in deleted managed worktrees compounding a host leak). A teardown hook would not fix that on bb's side, but it would let affected repos stop their own processes before the worktree disappears, which is the part bb cannot do generically.

Checks

  • I searched open and closed issues for the same request.
  • If an agent wrote this, the body ends with > AGENT GENERATED.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions