task-add

v2026.09.24

File a taskwarrior task with a verified project slug and blueprint/GitHub linkage. Use when logging cross-session follow-ups, confirming a project slug, or mirroring a GitHub issue.

GitHub
安装命令
npx skhub add laurigates/task-add
Markdown
SKILL.md

/taskwarrior:task-add

File a coordination task. When a GitHub remote is present, offer optional linkage so GitHub stays the system of record and taskwarrior stays the parallel-safe query layer.

When to Use This Skill

Use this skill when...Use task-status / task-coordinate / task-done instead when...
Filing a brand-new coordination task with bpid: / bpdoc: linkageAuditing existing queue health — use task-status
Mirroring a GitHub issue into the local queue via ghid:Picking the next-N candidates for a parallel wave — use task-coordinate
Pre-filling a task body from gh issue view outputClosing an in-flight task and draining its tracker — use task-done

Context

  • Task CLI available: !task --version
  • Git repo detected: !find . -maxdepth 1 -name '.git' -print -quit
  • GH auth: !gh auth status
  • Existing UDAs: !task _udas
  • Known projects: !task _projects

Git probes (git rev-parse --show-toplevel, git remote) write to stderr in a no-git cwd, and stderr from a Context backtick aborts the skill before its body runs. Project / remote resolution is done in the body (Step 2 below), where 2>/dev/null and exit-code handling are available.

Parameters

Parse $ARGUMENTS:

  • Freeform short description (required).
  • Optional inline project:<name> to override the auto-detected project.
  • Optional --no-project to file the task without any project (cross-cutting work).
  • Optional inline bpid:WO-012 / bpdoc:docs/wo/012.md / bpms:M6 / ghid:145 / ghpr:99 fields.
  • Optional native scheduling fields (prefer these over manual +blocked* bookkeeping):
    • due:<date> — deadline. Feeds urgency and surfaces the task as +DUE / +OVERDUE in task-coordinate / task-status. Set it only for real deadlines — the queue is a queue, not a calendar.
    • scheduled:<date> — earliest start. The task only becomes +READY once this date passes, so future work stays out of dispatch candidates.
    • wait:<date> — hide the task entirely until the date. Use for "blocked on merge until X" instead of a hand-managed +blocked_on_merge tag — taskwarrior auto-unhides it.
    • recur:<freq> (e.g. weekly, monthly) with a due: — repeating maintenance chores. Requires due:.
    • until:<date> — auto-delete the task on that date. Use for short-lived trackers that should expire if not actioned.
    • Dates accept taskwarrior synonyms (today, eow, eom, monday, due-4d, ISO 2026-07-01).
  • Optional tags: +wo, +prp, +fr, +re, +gh, +pr_ready, +needs_review, +blocked_on_merge, +blocked.

Tag naming gotcha — hyphens silently break tags. Taskwarrior parses - mid-token as exclude-filter syntax, even inside a +tag argument. +blocked-on-merge is parsed as +blocked AND -on-merge, so the tag never lands and the literal +blocked-on-merge string ends up appended to the description as plain text (urgency does not tick up). Single- quoting ('+blocked-on-merge') does not help — this is a taskwarrior parser quirk, not a shell issue. Use underscores or camelCase instead: +blocked_on_merge or +blockedOnMerge. The same applies to any tag name containing a hyphen.

Project resolution

By default every task is filed under the current repo's project so /taskwarrior:task-status and /taskwarrior:task-coordinate only see tasks relevant to where the agent is working. Resolve the project in this order:

  1. Explicit project:<name> in $ARGUMENTS.
  2. --no-project → file with no project (rare; cross-cutting work).
  3. Basename of git rev-parse --show-toplevel 2>/dev/null, run via the Bash tool (where stderr suppression and non-zero exits are tolerated).
  4. If no git repo (Step 3 returned empty), basename of cwd.

Cross-check the resolved name against Known projects and reuse the exact spelling when it matches (case-insensitive) — taskwarrior treats MyRepo and myrepo as different projects.

project: is a PREFIX match — a populated result does not prove the slug

task project:comfyui list returns every task in comfyui-nodes, comfyui-touch-connect, and any other project starting with that string. Nothing in the output says so. A slug you just invented therefore looks verified the moment a sibling shares its prefix, which is the whole trap: the confirming evidence and a false positive are byte-identical.

Observed twice (2026-08-08, comfyui-nodes). A commit titled "point the backlog at project:comfyui, the slug that exists" moved the documented slug to the one project that was nearly empty — 60 tasks sat under comfyui-nodes, 1 under comfyui — because task project:comfyui list showed all 60. A later session read that doc, filed four follow-ups into the near-empty sibling, and only caught it when a survey script printed the per-project counts side by side.

To check a slug is real, read the exact value — never a filter that matches its own prefix:

task export | jq -r '[.[].project] | group_by(.) | map({p:.[0], n:length}) | sort_by(-.n)[]'

Corollaries: prefer task <uuid> modify project:<slug> when consolidating (numeric ids shift); and a new project slug is silently created on first add, so a typo never errors — it just starts a parallel backlog that the prefix match then hides.

Execution

Execute this workflow:

Step 1: Ensure UDAs exist

The canonical 10-UDA set (5 linkage: bpid / bpdoc / bpms / ghid / ghpr; 5 identity: agent / pid / host / branch / worktree) lives in one place — the shared ensure-udas.sh script. Check for missing UDAs:

bash "${CLAUDE_SKILL_DIR}/../../scripts/ensure-udas.sh" --check

If it reports UDAS_MISSING greater than 0, confirm with the user (declarations persist in ~/.taskrc), then install them on first run per host:

bash "${CLAUDE_SKILL_DIR}/../../scripts/ensure-udas.sh"

Identity UDAs are not set by task-add itself — /taskwarrior:task-claim stamps them when an agent picks the task up. The same script backs the SessionStart drift-probe, so the install logic is single-sourced.

Bootstrap — no rc file

If task errors with "Cannot proceed without rc file":

mkdir -p ~/.local/share/task
echo "data.location=~/.local/share/task" > ~/.taskrc

Step 2: Detect GitHub mode

GitHub mode is active when all of:

  1. git config --get remote.origin.url is non-empty
  2. gh auth status exits 0

If either fails, skip GitHub-related branches in later steps.

Step 3: Duplicate check by bpid

If bpid: was given, run parallel-safe and constrain to the resolved project so a matching bpid in another repo's queue is not surfaced as a false-positive duplicate:

task project:myrepo bpid:"$BPID" export | jq '.[] | {id, description, status}'

Never use task bpid:"$BPID" list — it exits 1 on empty result and cancels sibling tool calls in parallel batches (see .claude/rules/parallel-safe-queries.md).

If a matching open task exists, report the ID and ask whether to update instead of re-add.

Step 4: Optionally pre-fill from a GitHub issue

When GitHub mode is active and either ghid: is set or the description looks like an issue reference:

gh issue view "$GHID" --json number,title,body,labels,state

Offer to copy title into description, map labels to tags, and capture the issue number into the ghid UDA.

If the user wants a new issue created, use:

gh issue create --title "$TITLE" --body "$BODY"

…then capture the returned issue number into ghid. Skip this branch entirely in local-only mode.

Step 5: Create the task

Compose the taskwarrior add command from the collected inputs. Always include project: (the resolved project from Parameters) unless the user passed --no-project. Quote every field; tags use the +tag form:

task add "$DESCRIPTION" \
  project:myrepo \
  bpid:"$BPID" \
  bpdoc:"$BPDOC" \
  bpms:"$BPMS" \
  ghid:"$GHID" \
  ghpr:"$GHPR" \
  due:"$DUE" \
  scheduled:"$SCHEDULED" \
  wait:"$WAIT" \
  +wo +gh

Run with only the fields that were provided; omit empty UDAs and empty date fields entirely rather than passing uda:"" / due:"". For a recurring chore, pass recur:weekly due:monday (recurrence requires a due:); for a self-expiring tracker, add until:eom.

Capture the stable UUID

After task add succeeds, resolve the new task's UUID via the +LATEST virtual tag as a separate Bash call — never chain it to task add with &&:

task +LATEST uuids
# d14a6e5e-1c60-4cfd-9dd0-8a9fe7659b74

Use task +LATEST uuids (or task +LATEST export | jq -r '.[0].uuid'), not task +LATEST _get uuid. _get is a DOM accessor that takes an <id>.<attribute> reference (task _get 141.uuid); given a tag filter it silently returns empty (exit 0), capturing no UUID — which silently reverted the #1417 drift fix until corrected.

Numeric IDs shift; UUIDs do not. A numeric ID is a display index over pending tasks — completing any other task (often in a parallel session) shifts every higher ID down by one, so task 141 annotate ... run minutes after the add can silently hit a different task. Capture the immutable UUID at create time and address the task by UUID for later annotate / modify / done. See .claude/rules/task-id-stability.md.

Sequential WOs: use depends: for ordered chains

For work orders that must land in sequence (e.g., WO-058 → 059 → 060), set depends: on each downstream task pointing to its predecessor's taskwarrior numeric ID. When the predecessor closes with task done, taskwarrior automatically unblocks all dependents — no manual intervention needed (see docs/task-tracking.md § Lifecycle):

# WO-059 waits for WO-058 (taskwarrior ID 51)
task add "WO-059: ..." bpid:WO-059 +wo project:myrepo depends:51

# WO-060 waits for both
task add "WO-060: ..." bpid:WO-060 +wo project:myrepo depends:51,52

Step 6: Report

Print:

  • New task ID and UUID (from Step 5; quote the UUID so future agents address the task by it, not the shift-prone numeric ID)
  • Project (auto-detected / overridden / --no-project)
  • bpid → bpdoc → bpms chain
  • ghid/ghpr if linked
  • Tags applied
  • Suggested next step (/taskwarrior:task-status, /taskwarrior:task-coordinate, or /taskwarrior:task-claim if the user is about to start)

Agentic Optimizations

ContextCommand
Capture stable UUID after addtask +LATEST uuids
Duplicate check by bpidtask bpid:WO-012 export | jq '.[] | {id, status}'
Pre-fill from issuegh issue view 145 --json number,title,body,labels
Next ready (unblocked + scheduled-due)task status:pending +READY export | jq '.[:3]'
Skip empty filter exitAlways use export | jq, never list

Quick Reference

Flag / fieldPurpose
project:Project (defaults to repo basename)
--no-projectFile without a project (cross-cutting)
bpid:Blueprint ID link
bpdoc:Blueprint doc path
bpms:Milestone
ghid:GitHub issue number
ghpr:GitHub PR number
due:Deadline — feeds urgency, surfaces +DUE/+OVERDUE
scheduled:Earliest start — gates +READY
wait:Hide until date (auto-unhides) — prefer over +blocked_on_merge
recur:Repeat frequency (needs due:)
until:Auto-delete date
+woWork order
+prpPRP
+frFeature request
+reResearch
+ghLinked to GitHub
+pr_readyOpen PR waiting
+blocked_on_mergeWaiting on another PR

Related

  • /taskwarrior:task-status — see current queue
  • /taskwarrior:task-claim — claim a task and stamp identity UDAs
  • /taskwarrior:task-done — close an open task (fires auto-unblock for depends: chains)
  • /taskwarrior:task-coordinate — next-agent candidates for a wave
  • .claude/rules/parallel-safe-queries.md — why export | jq, never list
  • .claude/rules/task-id-stability.md — why the captured UUID must be used for later annotate/modify/done
  • blueprint-plugin:feature-tracking — FR/WO IDs that bpid points at
  • taskwarrior-plugin/docs/task-tracking.md — full lifecycle including depends: + auto-unblock pattern
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

taskwarrior-plugin/skills/task-add

默认分支

main

最新提交

1668324

Tree SHA

b2d4cc3