/done
Finish a task - document, create PR or merge, close
$ npx -y skills add restarter/lets-workflow --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/done
Context preview
What this command does when you run it.
Finish a task - document, create PR or merge, close
Command definition
done.mddescription: Finish a task - document, create PR or merge, close
Task Done
Complete the current task. Document work, create PR or merge locally, close in the tracker.
**This is NOT session end.** Use `/lets:end` to end a session. `/lets:done` finishes a TASK.
> **Convention used in this file (per CLAUDE.md "Naming Convention: LETS_*"):** > - `{LETS_FOO}` placeholder inside ` ```bash ` snippets AND AskUserQuestion strings - the orchestrator substitutes the literal value before running / before the tool call. Required because Bash tool calls are fresh shells (`$LETS_FOO` unset) and AskUserQuestion renders strings literally. > - `$LETS_FOO` in prose and section headings only - read-only reference to the LETS Config inject. Do NOT use `$LETS_FOO` in bash blocks or AskUserQuestion strings - it silently produces wrong commands or a literal `$LETS_FOO` in the rendered question.
> **IMPORTANT:** If the spec below invokes any deferred tool (e.g. `AskUserQuestion`), you MUST load and call it as specified. Never skip the call, never substitute a default answer of your own — the tool invocation is part of the contract. This is critical.
Step 1: Active Task Detection
Use the **detect-task** skill to find the active task: `Skill(skill: "lets:detect-task")`. If no task found: ask user which task to close.
Epic Guard
Check the detected task's type via the tracker's `show` verb (beads exposes `type`; an adapter that doesn't expose a type can't epic-guard - skip it). If type is **epic** - do NOT close it automatically:
- Inform user: "This is an epic. Epics stay open for future tasks."
- Offer: close a specific child task instead, or confirm epic closure if user insists.
Trunk-mode Routing
Several steps below have a conditional branch for **trunk-mode** — when HEAD is `$LETS_MERGE_BRANCH` (user opted in via the `take-task` picker option "Stay on current branch"). The check is HEAD-based at runtime via `git branch --show-current` compared to `$LETS_MERGE_BRANCH` from LETS Config; no persistent flag.
In trunk-mode the following gates fire:
- Step 4 commit range: `start:..HEAD` (the task boundary from `.task-<slug>`, not `$LETS_MERGE_BRANCH..HEAD`, which is empty when HEAD IS the merge-branch)
- Already-Merged Guard: **skip** (PR on same-source-target is not a valid PR, nothing to detect)
- Step 6 confirm: trunk-mode wording (push + close, no PR)
- Step 7 completion comment: commit range uses `start:..HEAD` (same reason as Step 4)
- Step 8 finish: upstream-aware push + close (tracker `close` verb; no PR, no merge, no `git branch -d`)
- Step 9 output: trunk-mode "Next" options (no "Merge & close", no "Switch to merge-branch")
Trunk-mode requires `detect-task` (Step 1) to have returned an active task. If no task — abort with the standard "no task" path.
Step 2: Check Uncommitted Changes
git status --short
If uncommitted changes exist, use **AskUserQuestion**:
AskUserQuestion(
questions=[{
question: "You have uncommitted changes. What to do?",
header: "Uncommitted",
options: [
{ label: "Commit first", description: "Run /lets:commit before finishing task" },
{ label: "Skip", description: "Continue without committing (changes stay unstaged)" },
{ label: "Cancel", description: "Stop - go back to working on the task" }
],
multiSelect: false
}]
)**Handle response:**
- **Commit first** -> invoke `Skill(skill: "lets:commit")`, then continue
- **Skip** -> warn and continue
- **Cancel** -> stop, return to work
Already-Merged Guard
**Skip this entire guard if HEAD == `$LETS_MERGE_BRANCH` (trunk-mode):** PR on same-source-target is not a valid PR. Nothing to detect, nothing to short-circuit — proceed directly to Step 3.
If `$LETS_PR_FLOW == github`, the branch may already be merged - the PR was created and merged in a parallel session, so Step 8's `git push` + `gh pr create` would crash with `GraphQL: No commits between ...`.
git fetch origin --quiet 2>/dev/null
gh pr list --head "$(git branch --show-current)" --state merged --json number,url --limit 1 2>/dev/null
If this returns a merged PR, the work already shipped: skip Steps 3-8 and finish via Step 9's "After PR" Merge & close handling - with one change, since the PR is already merged, do NOT run `gh pr merge`; do Step 7's completion comment, then close (tracker `close` verb) + (if not in a worktree) `git checkout {LETS_MERGE_BRANCH} && git pull`. Report the PR number/URL.
Otherwise (no PR, or `gh` unavailable) continue to Step 3 - normal flow.
Step 3: Verify Task Scope
**Before closing - verify ALL requirements from the task description are met.**
show task=<task-id> # returns {id,title,status,url,description}; read description - plus any field the adapter's `show` declares (beads: `type`) - to verify scopeCompare the task description against actual changes:
1. Read the full task description and any design/notes fields 2. List each requirement or deliverable mentioned 3. For each one - check if it's actually implemented (read files, grep, verify) 4. Present a checklist to the user:
## Scope Verification
Task: **{title}** ({task-id})
- [x] {requirement 1} - done in {file}
- [x] {requirement 2} - done in {file}
- [ ] {requirement 3} - NOT FOUND
{if all done}
All requirements met. Proceeding.
{else}
Missing: {list}. Fix first or update task scope?**If any requirement is missing**, use **AskUserQuestion**:
AskUserQuestion(
questions=[{
question: "Some requirements are missing. How to proceed?",
header: "Scope",
options: [
{ label: "Fix first", description: "Stop closing - go back and implement missing items" },
{ label: "Update scope", description: "Adjust task description to match what was actually done" },
{ label: "PR only, keep open", description: "Create PR but keep task open - remaining work tracked in task" }
],
multiSelect: false
}]
)**Handle r
Read more
description: Finish a task - document, create PR or merge, close
Task Done
Complete the current task. Document work, create PR or merge locally, close in the tracker.
**This is NOT session end.** Use `/lets:end` to end a session. `/lets:done` finishes a TASK.
> **Convention used in this file (per CLAUDE.md "Naming Convention: LETS_*"):** > - `{LETS_FOO}` placeholder inside ` ```bash ` snippets AND AskUserQuestion strings - the orchestrator substitutes the literal value before running / before the tool call. Required because Bash tool calls are fresh shells (`$LETS_FOO` unset) and AskUserQuestion renders strings literally. > - `$LETS_FOO` in prose and section headings only - read-only reference to the LETS Config inject. Do NOT use `$LETS_FOO` in bash blocks or AskUserQuestion strings - it silently produces wrong commands or a literal `$LETS_FOO` in the rendered question.
> **IMPORTANT:** If the spec below invokes any deferred tool (e.g. `AskUserQuestion`), you MUST load and call it as specified. Never skip the call, never substitute a default answer of your own — the tool invocation is part of the contract. This is critical.
Step 1: Active Task Detection
Use the **detect-task** skill to find the active task: `Skill(skill: "lets:detect-task")`. If no task found: ask user which task to close.
Epic Guard
Check the detected task's type via the tracker's `show` verb (beads exposes `type`; an adapter that doesn't expose a type can't epic-guard - skip it). If type is **epic** - do NOT close it automatically:
- Inform user: "This is an epic. Epics stay open for future tasks."
- Offer: close a specific child task instead, or confirm epic closure if user insists.
Trunk-mode Routing
Several steps below have a conditional branch for **trunk-mode** — when HEAD is `$LETS_MERGE_BRANCH` (user opted in via the `take-task` picker option "Stay on current branch"). The check is HEAD-based at runtime via `git branch --show-current` compared to `$LETS_MERGE_BRANCH` from LETS Config; no persistent flag.
In trunk-mode the following gates fire:
- Step 4 commit range: `start:..HEAD` (the task boundary from `.task-<slug>`, not `$LETS_MERGE_BRANCH..HEAD`, which is empty when HEAD IS the merge-branch)
- Already-Merged Guard: **skip** (PR on same-source-target is not a valid PR, nothing to detect)
- Step 6 confirm: trunk-mode wording (push + close, no PR)
- Step 7 completion comment: commit range uses `start:..HEAD` (same reason as Step 4)
- Step 8 finish: upstream-aware push + close (tracker `close` verb; no PR, no merge, no `git branch -d`)
- Step 9 output: trunk-mode "Next" options (no "Merge & close", no "Switch to merge-branch")
Trunk-mode requires `detect-task` (Step 1) to have returned an active task. If no task — abort with the standard "no task" path.
Step 2: Check Uncommitted Changes
git status --short
If uncommitted changes exist, use **AskUserQuestion**:
AskUserQuestion(
questions=[{
question: "You have uncommitted changes. What to do?",
header: "Uncommitted",
options: [
{ label: "Commit first", description: "Run /lets:commit before finishing task" },
{ label: "Skip", description: "Continue without committing (changes stay unstaged)" },
{ label: "Cancel", description: "Stop - go back to working on the task" }
],
multiSelect: false
}]
)**Handle response:**
- **Commit first** -> invoke `Skill(skill: "lets:commit")`, then continue
- **Skip** -> warn and continue
- **Cancel** -> stop, return to work
Already-Merged Guard
**Skip this entire guard if HEAD == `$LETS_MERGE_BRANCH` (trunk-mode):** PR on same-source-target is not a valid PR. Nothing to detect, nothing to short-circuit — proceed directly to Step 3.
If `$LETS_PR_FLOW == github`, the branch may already be merged - the PR was created and merged in a parallel session, so Step 8's `git push` + `gh pr create` would crash with `GraphQL: No commits between ...`.
git fetch origin --quiet 2>/dev/null gh pr list --head "$(git branch --show-current)" --state merged --json number,url --limit 1 2>/dev/null
If this returns a merged PR, the work already shipped: skip Steps 3-8 and finish via Step 9's "After PR" Merge & close handling - with one change, since the PR is already merged, do NOT run `gh pr merge`; do Step 7's completion comment, then close (tracker `close` verb) + (if not in a worktree) `git checkout {LETS_MERGE_BRANCH} && git pull`. Report the PR number/URL.
Otherwise (no PR, or `gh` unavailable) continue to Step 3 - normal flow.
Step 3: Verify Task Scope
**Before closing - verify ALL requirements from the task description are met.**
show task=<task-id> # returns {id,title,status,url,description}; read description - plus any field the adapter's `show` declares (beads: `type`) - to verify scopeCompare the task description against actual changes:
1. Read the full task description and any design/notes fields 2. List each requirement or deliverable mentioned 3. For each one - check if it's actually implemented (read files, grep, verify) 4. Present a checklist to the user:
## Scope Verification
Task: **{title}** ({task-id})
- [x] {requirement 1} - done in {file}
- [x] {requirement 2} - done in {file}
- [ ] {requirement 3} - NOT FOUND
{if all done}
All requirements met. Proceeding.
{else}
Missing: {list}. Fix first or update task scope?**If any requirement is missing**, use **AskUserQuestion**:
AskUserQuestion(
questions=[{
question: "Some requirements are missing. How to proceed?",
header: "Scope",
options: [
{ label: "Fix first", description: "Stop closing - go back and implement missing items" },
{ label: "Update scope", description: "Adjust task description to match what was actually done" },
{ label: "PR only, keep open", description: "Create PR but keep task open - remaining work tracked in task" }
],
multiSelect: false
}]
)**Handle r
A development workflow plugin for Claude Code Stop babysitting your AI. Start shipping with it.
Other commands on lets-workflow.
- /ask
Ask a single expert agent a question - like a Slack ping to a colleague
Open command - /backlog
Backlog review and cleanup - multi-agent backlog review, quick no-agent pulse (--fast), or interactive triage cleanup
Open command - /check
Quick sanity check - code (inline 6-perspective) or plan (--plan).
Open command - /end
End a work session - a settlement pass that reconciles uncommitted / unpushed work + session context into git, the tracker, and a session snapshot file. --pre-compact skips settlement and only writes the shared snapshot, keeping the session going.
Open command - /execute
Execute implementation plan from /lets:plan - load plan and enter native plan mode
Open command - /github-pr
GitHub PR review lifecycle - analyze, discuss, post inline comments, follow-up, respond, approve
Open command

