taskwarrior-plugin/skills/task-done/SKILL.md
Close a taskwarrior task with landing commit annotation and optional GitHub issue/PR close. Use when finishing a coordination task or marking a work order complete.
npx skillsauth add laurigates/claude-plugins task-doneInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Close a task with full coordination hygiene: annotate with the landing commit, drain the tracker entry, optionally close the GitHub issue.
| Use this skill when... | Use task-add / task-status / task-coordinate instead when... |
|---|---|
| Closing a task whose work has landed in a commit | Filing a brand-new task — use task-add |
| Draining a linked blueprint tracker entry to done | Reading current queue state without mutating it — use task-status |
| Closing a ghid-linked GitHub issue or commenting on a ghpr PR | Picking the next dispatch candidate from the queue — use task-coordinate |
| Closing many tasks in one pass (queue cleanup, triage sweep) | See Bulk-close patterns below — the naive for id in 1 2 3; do task $id done; done loop silently closes the wrong tasks |
task --versionfind . -maxdepth 1 -name '.git' -print -quitgh auth statusGit probes (git remote, git rev-parse --short HEAD,
git branch --show-current) write to stderr in a no-git cwd, and stderr
from a Context backtick aborts the skill before its body runs. HEAD
commit, current branch, and remote-presence checks happen in the body
(Steps 2 and 5) via the Bash tool where 2>/dev/null and exit-code
handling are tolerated.
Parse $ARGUMENTS:
$0 — task ID (required)$1 — commit hash (optional; defaults to HEAD)--no-gh — skip GitHub close/comment even when remote is present--no-tracker — skip blueprint tracker drain--drain-identity — also clear agent / pid / host / branch / worktree UDAs after closing (default keeps them as audit trail)--no-coworker-marker — skip the /git:coworker-check --release stepExecute this workflow:
task "$TASKID" export | jq '.[0]'
Never use task $TASKID info or task $TASKID list — both can exit 1 and
cancel parallel siblings. export | jq returns valid JSON even when the
task is already closed (treat empty as "no such open task" and abort).
Capture: bpid, bpdoc, ghid, ghpr, tags, description, plus
identity UDAs agent, pid, host, branch, worktree, and start
(if the task was claimed via /taskwarrior:task-claim).
If $1 is unset, read git rev-parse --short HEAD. Confirm the HEAD commit
actually touches work this task covers before annotating — a stale HEAD is
a common footgun.
task "$TASKID" annotate "landed: $COMMIT_SHORT $COMMIT_SUBJECT"
task "$TASKID" done
Annotation first, then done — if close fails (e.g. dependencies), the annotation is still captured.
Taskwarrior auto-stops a +ACTIVE task on done, so an explicit
task stop is not needed. The task transition removes +ACTIVE and
records the duration. If you want to drain the identity UDAs (so the
closed task does not retain the stamp), do so separately after the
close — see Step 4b below.
After the task is closed, optionally clear the identity stamp left by the original claim:
task "$TASKID" modify agent: pid: host: branch: worktree:
Default behaviour is to leave these set on closed tasks — the audit
trail of "who claimed and landed this" is useful in task-status
recently-completed reports. Drain them only when the user explicitly
asks (e.g. compliance / privacy hygiene), or when handing the queue
file off to another team.
If bpdoc is set and points to a valid path, read the file and advance
its status marker in place. Typical patterns by tracker format:
status: in_progress → status: done, append
evidence entry citing the commitUse Edit with a narrow old_string / new_string pair — do not rewrite
the file. When bpdoc references a shared tracker (manifest.json, global
feature-tracker), fall back to reporting "manual tracker update required"
rather than concurrent-write the shared file.
When GitHub mode is active and --no-gh was not passed:
ghid set → offer gh issue close "$GHID" --comment "Closed by $COMMIT_SHORT (branch $BRANCH)"ghpr set → offer gh pr comment "$GHPR" --body "Linked task closed: $COMMIT_SHORT"Always confirm before mutating GitHub state — the user may want to close the issue as part of the PR merge rather than ahead of time.
If the task was +ACTIVE (claimed via /taskwarrior:task-claim), the
matching git-side session marker should be released so destructive ops
in this clone are no longer guarded:
Use SlashCommand to invoke `/git:coworker-check --release`.
Skip when the user has more work in flight on this branch — releasing the marker lifts the cross-agent guard.
Print:
$COMMIT_SHORTdepends: pointed at this one now
free to start (query via task depends:$TASKID export | jq)| Context | Command |
|---------|---------|
| Load task | task "$TASKID" export \| jq '.[0]' |
| Annotate + close | Two separate calls (hook-friendly) |
| Blocked children | task depends:"$TASKID" export \| jq '.[]' |
| Skip empty-result failures | Always export \| jq |
| Step | Command |
|------|---------|
| Load | task ID export \| jq |
| Annotate | task ID annotate "msg" |
| Close | task ID done |
| Check unblocked siblings | task depends:ID export \| jq '.[]' |
| GitHub close | gh issue close N --comment "msg" |
| PR comment | gh pr comment N --body "msg" |
Closing many tasks in one pass has two silent foot-guns. The obvious shape — for id in 1 2 3; do task $id done; done — reports success while doing the wrong thing.
task doneNumeric IDs are a display index over pending tasks. The moment one closes, every higher ID shifts down by one. A loop over numeric IDs closes the original first task, then keeps targeting wrong tasks as IDs slide underneath the iterator. No error surfaces.
Fix: use UUIDs (immutable). The same applies to any iterated state-changing op — annotate, modify, delete.
# WRONG — IDs shift mid-loop
for id in 35 36 37 38 39; do task "$id" done; done
# Correct — capture immutable UUIDs first
UUIDS=$(task status:pending project:myrepo export | jq -r '.[].uuid')
for u in $UUIDS; do task "$u" done </dev/null; done # stdin redirect — see below
task done consumes loop stdintask done reads from stdin (for confirmation prompts). In a shell for loop, the loop's input is also stdin — so task done eats subsequent iterations and the loop exits early, usually after one or two passes, with no error.
Symptom: a loop over 15 UUIDs reports "processed 15" but only 1 task closed.
# Fix A — redirect stdin per inner command
for u in $UUIDS; do
task "$u" rc.confirmation=no done </dev/null
done
# Fix B — xargs (preferred; each invocation runs in its own subshell with no
# stdin link to the source loop)
echo "$UUIDS" | xargs -I {} sh -c 'task rc.confirmation=no {} done'
rc.confirmation=no for batch closesWithout it, taskwarrior may prompt "this task is blocked by N other tasks, complete anyway? (yes/no)" per task, hanging the loop. rc.confirmation=no makes batch closes deterministic.
done, not afterOnce completed, a task's id becomes 0 and task <id> no longer addresses it — only the UUID does. Annotate first to keep the UUID-or-ID workflow uniform.
Use export | jq (never list — it exits 1 on empty filters and cancels parallel siblings; see .claude/rules/parallel-safe-queries.md):
task status:pending project:myrepo +pr_ready export | jq -r '.[].uuid'
# Tasks with no project (CLI filter quirk — empty value as first filter
# errors; sidestep through jq)
task status:pending export | jq -r '.[] | select(.project == null) | .uuid'
# Substring matches on description (for markers that aren't real tags)
task status:pending export \
| jq -r '.[] | select(.description | test("\\[triage\\]")) | .uuid'
UUIDS=$(task status:pending project:myrepo +pr_ready export | jq -r '.[].uuid')
echo "$UUIDS" | xargs -I {} sh -c 'task rc.confirmation=no {} done'
/taskwarrior:task-add — file a task (use depends: for sequential WO chains)/taskwarrior:task-claim — claim a task before working on it (this skill closes a claimed task)/taskwarrior:task-release — release a claim without closing (handoff)/taskwarrior:task-status — see what's left/git:coworker-check — the matching session marker that --no-coworker-marker controlsblueprint-plugin:feature-tracking — tracker format that bpdoc points atblueprint-plugin:blueprint-docs-currency — companion discipline for the bpdoc update.claude/rules/parallel-safe-queries.md — the export | jq idiomtaskwarrior-plugin/docs/task-tracking.md — full lifecycle: depends: + auto-unblock patterntools
Scaffold a new ComfyUI custom-node repo (pyproject, CI, release-please, vitest+pytest, JS extension skeleton) in the picker/gesture vein. Use when bootstrapping or init-ing a comfyui node pack.
tools
Orchestrate a ComfyUI node pack from idea to registry: scaffold, create + seed the repo, open the gitops adoption PR. Use when releasing or spinning up a new comfyui node pack.
testing
macOS EndpointSecurity/EDR high CPU & battery drain. Use when Kandji ESF / XProtect pegs a core; trace the exec storm via powermetrics + eslogger.
development
odiff pixel-by-pixel image diffing. Use when comparing screenshots, detecting visual regressions, diffing before/after PNGs, asserting golden images.