Skip to content
Agentmart
Submit a tool

executor-epic-sequential-worktree

Use when you want to deliver a whole epic unattended as ONE branch and ONE PR WITHOUT disturbing in-flight work in the main checkout.

Skill by jsiovn

IndexedMIT★ 2
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/jsiovn-executor-epic-sequential-worktree

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Use when you want to deliver a whole epic unattended as ONE branch and ONE PR WITHOUT disturbing in-flight work in the main checkout. Runs every ready child bead of one epic sequentially in a fresh sibling git worktree checked out on the epic branch (epic/<epic-bead-id>) so the main working tree is never touched — each bead executes in its own fresh headless `claude -p` session (clean context per task), committing directly onto the single epic branch; a failed bead is marked blocked and skipped (along with its dependents) and the run continues; finishes with one PR from the epic branch to the default branch and leaves the worktree in place for follow-up (review comments, CI fixes). Use the `cleanup-worktree` skill to remove the worktree once the PR has landed.

Use cases: devops, productivity

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/executor-epic-sequential-worktree

What's inside

Skill name
executor-epic-sequential-worktree
Description
Use when you want to deliver a whole epic unattended as ONE branch and ONE PR WITHOUT disturbing in-flight work in the main checkout. Runs every ready child bead of one epic sequentially in a fresh sibling git worktree checked out on the epic branch (epic/<epic-bead-id>) so the main working tree is never touched — each bead executes in its own fresh headless `claude -p` session (clean context per task), committing directly onto the single epic branch; a failed bead is marked blocked and skipped (along with its dependents) and the run continues; finishes with one PR from the epic branch to the default branch and leaves the worktree in place for follow-up (review comments, CI fixes). Use the `cleanup-worktree` skill to remove the worktree once the PR has landed.
License
MIT
Instructions
218 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Executor Epic Sequential Worktree

Drive an entire epic to completion in one go **without touching the main working tree**: create **one** sibling git worktree checked out on the epic branch (`epic/<epic-bead-id>`), then execute **every ready child bead** of that epic, one after another, each in its **own fresh headless `claude -p` session** so no task's context leaks into the next. Every task commits directly onto the single epic branch **inside the worktree**. At the end, open **one** PR from the epic branch to the default branch and leave the worktree in place for follow-up.

This is the worktree-isolated sibling of `executor-epic-sequential`. Both deliver a whole epic unattended as one branch and one PR; the difference is **where** the work happens:

- `executor-epic-sequential` checks the **main working tree** out onto the epic branch (requires a clean main tree, switches branches).
- **this skill** never touches the main working tree — it cuts a sibling worktree at `../<repo>-epic-<epic-bead-id>` and runs the whole epic there, so the main checkout keeps its in-flight work undisturbed.

Use this variant when the main tree has active work that must not be disturbed, or when you want the epic to run in an isolated directory you can `cd` into for the PR's review comments and CI fixes afterward.

## Iron Law

**ONE epic branch in ONE worktree. The main working tree is NEVER modified. EVERY bead runs in its own fresh headless `claude -p` session inside the worktree. The driver NEVER implements bead work in its own context.**

The entire point of this skill is to keep the driver session thin: only short per-task summaries and `git`/`bd` output land in the driver's context, while the heavy implement/test/review transcript for each bead lives in a disposable headless session that is thrown away when the bead finishes. The model cannot `/clear` itself mid-run, so the _only_ way to get a clean slate per task is to spawn a fresh process per task. Doing a bead "inline" — even a one-line one — re-pollutes the driver context and defeats the skill.

## Requires fresh-session-safe beads

Each headless worker starts with **zero memory** of the planner chat or of the beads that ran before it. It can only see the bead contract, persisted inputs, and the code on the epic branch in the worktree. If the epic's beads are not fresh-session-safe, workers will fail. Recommend running `validate-beads` on the epic first (don't force it).

## Implementor argument

Optional. Pass `opencode` (or `--implementor opencode` / `implementor=opencode`, plus an optional `model=<provider/model[#variant]>`) to have each worker delegate its **implementation step** to a headless OpenCode implementor via the `implement-with-opencode` skill. Record `<IMPLEMENTOR>` (`claude` by default, `opencode` when requested) and `<MODEL>`. The per-bead worker is still a headless `claude -p` session that runs every other step — claim, plan, build-and-test, verification, code review, close. Without the argument, each worker implements inline.

## Steps

1. If the current repo is not initialized for Beads, stop and tell the user to run the template bootstrap script or at minimum `bd init --prefix <prefix>` plus the repo scaffolding steps. If `bd where` fails, repair with `bd bootstrap --yes` before continuing.

2. **Resolve the epic — before touching anything:**
   - if the user supplied an epic id, use it
   - otherwise infer the epic from the current request/context and confirm
   - verify it is actually an epic: `bd show <EPIC_BEAD_ID> --json` and check `type == epic`. If it is not an epic, stop and ask for the epic id.
   - record the epic bead id as `<EPIC_BEAD_ID>` and `<EPIC_BRANCH>` as `epic/<EPIC_BEAD_ID>` — **no slug** (same convention as `executor-epic-task`/`executor-epic-task-worktree`; using just the bead id prevents duplicate branches when different sessions derive different slugs).

3. **Preflight (fail fast, stop on any failure):**
   - **Do not modify the main working tree, and do not require it to be clean.** No dirty-state check, no WIP commit, no branch switch — the main tree stays on whatever branch it is currently on. (Step 7 below _reads_ git-ignored `.env*` files out of it to seed the worktree, but never writes to it.) This is the key divergence from `executor-epic-sequential`, which switches the main tree to the epic branch and therefore demands a clean tree.
   - **The headless runner must exist.** Run `command -v claude`. If it is missing, stop and tell the user this skill needs the `claude` CLI on `PATH` to spawn per-task sessions.
   - **If `<IMPLEMENTOR>`=`opencode`, the implementor must exist too.** Run `command -v opencode`; if it is missing, stop (see `implement-with-opencode` preflight). The `.opencode/agents/implementor.md` check runs inside the worktree in step 9.
   - Record `<MAIN_ROOT>` = `git rev-parse --show-toplevel`, `<REPO_NAME>` = `basename <MAIN_ROOT>`, and the main tree's current branch (`git rev-parse --abbrev-ref HEAD`) as `<MAIN_BRANCH>` so you can report it. Paths derive from the current toplevel, so running this from inside an existing worktree is fine.
   - **Clear stale worktree registrations, then ensure the epic branch is not checked out elsewhere.** First run `git worktree prune` — if a previous run's worktree directory was removed manually (`rm -rf` instead of `cleanup-worktree`/`git worktree remove`), git still registers the branch as checked out at the now-missing path and `git worktree add` would later refuse it with "already used by worktree at &lt;missing path&gt;". Then run `git worktree list --porcelain`. A branch can only be checked out in one worktree at a time, so if `<EPIC_BRANCH>` is *still* checked out (in the main tree or another live worktree), `git worktree add` will refuse. Stop and tell the user: if the conflicting directory no longer exists, `git worktree prune` already cleared it — retry; otherwise either switch that checkout off `<EPIC_BRANCH>`, or — if the epic branch is checked out in the main tree — use the non-worktree `executor-epic-sequential` instead.

4. **Compute the worktree path** (slashes → dashes, mirroring the worktree-skill convention — the epic branch `epic/<EPIC_BEAD_ID>` becomes the suffix `epic-<EPIC_BEAD_ID>`):

   ```
   WORKTREE_PATH="../${REPO_NAME}-epic-${EPIC_BEAD_ID}"
   ```

   - If `<WORKTREE_PATH>` already exists on disk, stop and ask the user (it may be a half-finished run — offer to resume into it or remove it via `cleanup-worktree` first).
   - Guard: if the computed parent resolves to `/`, stop and ask for an explicit target path rather than creating a worktree at the filesystem root.

5. **Detect `<DEFAULT_BRANCH>`:** `git symbolic-ref refs/remotes/origin/HEAD` (strip the `origin/` prefix) if present; otherwise `main` if it exists, else `master`.

6. **Resolve the epic branch and make sure it exists on `origin`** so the worktree can always be cut from the up-to-date `origin/<EPIC_BRANCH>`. Probe and **record both results** (step 7 chooses its worktree-add command from `LOCAL_REF`, so do not skip recording it):
   - `LOCAL_REF` = does `git rev-parse --verify <EPIC_BRANCH>` succeed? (a local branch exists)
   - `ORIGIN_REF` = does `git ls-remote --exit-code --heads origin <EPIC_BRANCH>` succeed? (the branch is on origin)

   Then act on the combination:
   - **on origin (`ORIGIN_REF`=yes):** `git fetch origin <EPIC_BRANCH>` (this covers both "origin only" and "origin + local").
   - **local only (`ORIGIN_REF`=no, `LOCAL_REF`=yes):** push it so the worktree can branch from `origin/<EPIC_BRANCH>` (do not move or check out the local ref); now `ORIGIN_REF`=yes:
     ```
     git push -u origin <EPIC_BRANCH>:<EPIC_BRANCH>
     git fetch origin <EPIC_BRANCH>
     ```
   - **nowhere (`ORIGIN_REF`=no, `LOCAL_REF`=no):** create it from the latest default branch **without disturbing the main tree** (use `git branch`, which never touches the working tree), then push it; this sets both `LOCAL_REF`=yes and `ORIGIN_REF`=yes. Note in the final summary that the epic branch was created.
     ```
     git fetch origin <DEFAULT_BRANCH>
     git branch <EPIC_BRANCH> origin/<DEFAULT_BRANCH>
     git push -u origin <EPIC_BRANCH>
     git fetch origin <EPIC_BRANCH>
     ```

7. **Create the worktree checked out ON the epic branch** (not a new feature branch — every bead commits directly onto the epic branch), always anchored to the freshly fetched `origin/<EPIC_BRANCH>`. Choose strictly by the **recorded `LOCAL_REF`** (do not re-derive it):
   - **`LOCAL_REF`=no** (the branch exists only on origin, or was just pushed there): create the local tracking branch as part of the worktree add:
     ```
     git worktree add <WORKTREE_PATH> -b <EPIC_BRANCH> origin/<EPIC_BRANCH>
     ```
   - **`LOCAL_REF`=yes** (a local branch already existed, or you just created it with `git branch`): check it out into the worktree, then fast-forward it to the fetched origin tip so the run never starts from a stale local ref:
     ```
     git worktree add <WORKTREE_PATH> <EPIC_BRANCH>
     git -C <WORKTREE_PATH> merge --ff-only origin/<EPIC_BRANCH>
     ```
     If `merge --ff-only` fails (the local branch has diverged from origin), stop and ask — never force or rebase silently. (`merge --ff-only origin/<EPIC_BRANCH>` is used instead of `pull` so it needs no tracking config and deterministically lands on the up-to-date origin tip — picking the wrong command here is the difference between a clean start and either a hard `-b ... already exists` failure or committing the whole epic onto a stale tip that the final push then rejects non-fast-forward.)

   After this step there is a worktree at `<WORKTREE_PATH>` on a clean `<EPIC_BRANCH>` sitting at the `origin/<EPIC_BRANCH>` tip. **All remaining `git`/`bd`/`claude` work runs from inside `<WORKTREE_PATH>`** — the driver never `cd`s the main tree or switches its branch.

8. **Seed git-ignored local env files into the worktree — REQUIRED before any worker runs `build-and-test`.** A fresh worktree checks out only _tracked_ files, so git-ignored local config the build needs — `.env.local`, `.env`, and the rest of the `.env*` family — is absent, and the first worker's `build-and-test` would otherwise run against a worktree with no environment. Do this **once, up front, before the loop**, and unconditionally; do **NOT** skip or defer it on the assumption that `build-and-test` will synthesize a default environment. Run this from the main checkout (`<MAIN_ROOT>`); it reads from the main tree but never writes to it:

   ```
   git -C <MAIN_ROOT> ls-files --others --ignored --exclude-standard --directory \
     | grep -E '(^|/)\.env(\.[^/]*)?$' \
     | while IFS= read -r f; do
         mkdir -p "<WORKTREE_PATH>/$(dirname "$f")"
         cp -p "<MAIN_ROOT>/$f" "<WORKTREE_PATH>/$f"
       done
   ```

   - `--directory` collapses fully-ignored directories (`node_modules/`, `dist/`, `.beads/`, `*.db`) to a single entry so the `grep` skips them — only `.env*` files are copied, never dependencies or build output. `cp -p` preserves the source permissions (env files are often `600`).
   - Always **run** the detection command — never skip running it because you expect the output to be empty; only treat it as a no-op when its _actual_ output is empty. Never pre-judge that no `.env*` files exist because the worktree _looks_ build-ready (`.env.example` is tracked and proves nothing).
   - This `.env*` seed is the up-front, non-negotiable part. _Separately_, if a worker's `build-and-test` later fails because some **other** git-ignored config is missing (e.g. `.dev.vars`, a local service-account JSON), copy that one file the same way — but that reactive copy never replaces the up-front `.env*` seed above. Do not bulk-copy all ignored files.
   - **Do NOT seed `.beads/`, `*.db`, or `.dolt/` into the worktree** the way `.env*` is seeded. `bd` already resolves to the shared main-clone database (see step 9); copying beads state in would create a divergent or empty view — the exact failure to avoid. The `.env*` seed is the only thing copied into the worktree.

9. **Verify Beads health and connectivity inside the worktree.** The driver loop and every worker read and write bead state from within `<WORKTREE_PATH>`. This works because **`bd` is git-worktree-aware**: from inside a worktree it resolves `.beads` to the MAIN repo root via the git common dir and connects to the shared Dolt server, so the worktree and the main tree are **one** beads view (`.beads/dolt`, `issues.jsonl`, and `*.db` are git-ignored and deliberately not seeded into the worktree — see step 8).

   The authoritative health check is **`bd show <EPIC_BEAD_ID>`, not `bd where`**:

   ```
   (cd <WORKTREE_PATH> && bd show <EPIC_BEAD_ID> --json)
   ```

   - It must resolve the **same epic** AND prove the Dolt server is reachable. `bd where` only prints resolved config and **succeeds even when the server is down**, so it is not a connectivity check — rely on `bd show`.
   - **If `bd show` fails:** the most likely cause is the Dolt server being down — start it (`bd dolt start`; check `bd dolt status`) and retry. Do **not** reach for `bd bootstrap --yes` to "fix" a down server: it errors on shared-server reconcile, and in a healthy worktree it is only a no-op (it detects the existing main-clone DB). If `bd` is missing entirely, stop and report — the run cannot proceed without it.
   - **If `bd show` resolves a different or empty epic**, stop and report rather than running the loop against the wrong beads view.
   - **If `<IMPLEMENTOR>`=`opencode`:** confirm `<WORKTREE_PATH>/.opencode/agents/implementor.md` exists (it is committed, so it travels with `<EPIC_BRANCH>`). If missing, stop: run `agent-workflow-beads update --with-opencode <repo>`, commit `.opencode/agents/` onto the epic branch, and retry.

10. **Show the plan, then run unattended.** Print the resolved epic, `<WORKTREE_PATH>`, `<EPIC_BRANCH>`, `<DEFAULT_BRANCH>` (the PR base), and the initial ready set (`(cd <WORKTREE_PATH> && bd ready --parent <EPIC_BEAD_ID> --json)`). State that the run will now proceed bead-by-bead without further confirmation, that the main working tree (`<MAIN_BRANCH>`) will not be touched, and that the worktree will be left in place at the end. Do not ask for per-bead confirmation after this point.

11. **The loop.** Keep three sets — `done`, `blocked`, `attempted` — and a hard iteration cap (≈ the epic's descendant count, backstop 50). **Run every `bd` and `git` command from inside `<WORKTREE_PATH>`.** Each iteration:
    1. `(cd <WORKTREE_PATH> && bd ready --parent <EPIC_BEAD_ID> --json)`; drop any bead already in `done` or `blocked`.

From jsiovn/agent-workflow-beads, MIT.

More from jsiovn/agent-workflow-beads

Signals

Stars
2
Forks
0
Open issues
0
Last commit (this folder)
Oct 1, 2026 (28 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from jsiovn

Cite this page

executor-epic-sequential-worktree skill. Agent Mart. https://agentmart.dev/skills/jsiovn-executor-epic-sequential-worktree (last updated 2026-10-24)