---
title: "Delete Worktree"
method: DELETE
path: "/projects/{project_id}/worktrees/{worktree_id}"
---

# Delete Worktree

`DELETE /projects/{project_id}/worktrees/{worktree_id}`

## Request

- Base URL: `https://usemeridian.us` (the document declares no server; this is the origin it was published from)
- URL: `https://usemeridian.us/projects/{project_id}/worktrees/{worktree_id}`
- Auth: none declared

Mark a registered worktree as removed — and, self-hosted only, actually
remove it from disk instead of only trusting the caller already ran
`git worktree remove` (a03c0eeb).

Historically this endpoint was pure DB bookkeeping: the caller was
expected to run `git worktree remove` itself first, then call this to
flip `removed_at`. Nothing ever confirmed that actually happened, so a
skipped/forgotten/crashed cleanup left the DB saying "removed" while the
directory (and its git worktree registration) stayed on disk — the exact
leak a busy megasprint compounds fast. Self-hosted Meridian runs from
inside the very repo it coordinates, so it can perform the real removal
itself here; hosted (multi-tenant) mode has no access to the caller's
filesystem and stays DB-only, per the local-fs-access architectural law
in `meridian/_deps.py`. The row is marked removed only once the directory
is confirmed gone from disk. A guard refusal (dirty tree, live owning
process) or a failed removal leaves the row active and answers 409
Conflict with the reason, so `worktree_cleanup.sweep_stale_worktrees`
(which only selects active rows) retries it later.

## Path parameters

- `project_id` string, required
- `worktree_id` string, required

## Response `204`

Successful Response

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/usemeridian/apis/meridian.md) · [All operations](https://skmtc.dev/usemeridian/apis/meridian/llms.txt) · [OpenAPI document](https://skmtc.dev/usemeridian/apis/meridian/revisions/f37a894bd374?raw)
