# Task Claim

> Claim a taskwarrior task as in-flight (+ACTIVE) and write a coworker marker. Use when picking up a task from task-coordinate output before starting implementation.

- Skill: `laurigates/task-claim` (Agent Skill)
- Install (CLI): `npx skillmds@latest add laurigates/task-claim`
- Raw SKILL.md: https://api.skillmd.com/api/skills/laurigates/task-claim/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: laurigates (https://skillmd.com/u/laurigates)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/laurigates/task-claim

---


# /taskwarrior:task-claim

Take ownership of a pending task. Stamps the task with this agent's identity and marks it `+ACTIVE` so concurrent agents see it is in flight and `/taskwarrior:task-coordinate` skips it on the next wave.

## When to Use This Skill

| Use this skill when... | Use a sibling skill instead when... |
|---|---|
| Starting work on a task surfaced by `/taskwarrior:task-coordinate` | Filing a brand-new task — use `/taskwarrior:task-add` |
| Resuming a task after a context break (re-stamps `started` time) | Pausing for handoff without closing — use `/taskwarrior:task-release` |
| Forcing a stale claim onto yourself with `--force` | The task is done and ready to land — use `/taskwarrior:task-done` |

## Context

- Task CLI available: !`task --version`
- Git repo detected: !`find . -maxdepth 1 -name '.git' -print -quit`
- Hostname: !`hostname`
- Existing UDAs: !`task _udas`

Git probes (`git rev-parse --show-toplevel`, `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. Git toplevel and current-branch
resolution are done in the body via the Bash tool (where
`2>/dev/null` and exit-code handling are tolerated).

## Parameters

Parse `$ARGUMENTS`:

- `$0` — task ID (required).
- `--no-coworker-marker` — skip the `/git:coworker-check --claim` step (use when the repo is intentionally shared and another agent will claim its own scope).
- `--force` — claim even when the task is already `+ACTIVE` (the previous claim is overwritten with an annotation noting the takeover).

## Execution

Execute this claim workflow:

### Step 1: Ensure identity UDAs exist

The identity UDAs (`agent` / `pid` / `host` / `branch` / `worktree`) are part of
the canonical set in the shared `ensure-udas.sh` script. Check for missing UDAs:

```bash
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`) and install — the script is idempotent and installs the
full linkage + identity set in one pass:

```bash
bash "${CLAUDE_SKILL_DIR}/../../scripts/ensure-udas.sh"
```

### Step 2: Load the task and check active state

```bash
task "$TASKID" export | jq '.[0] | {id, uuid, description, status, start, agent, pid, host, branch, worktree}'
```

Use `export | jq` — never `task <id> info` or `task <id> list` (both exit 1 on empty / closed tasks and cancel parallel siblings; see `.claude/rules/parallel-safe-queries.md`).

Capture the `uuid` field as `$TASK_UUID` — every mutating call from Step 3
onward addresses the task by `$TASK_UUID`, never `$TASKID`. `$TASKID` may be a
numeric ID that renumbers if another agent closes an unrelated task during the
coworker-check pause in Step 3; `$TASK_UUID` does not (see
`.claude/rules/task-id-stability.md`).

Read the JSON. Decide:

| Condition | Action |
|---|---|
| `status` is not `pending` | Abort. Tasks must be pending to claim. |
| `start` is set and `--force` not passed | Abort. Report current `agent` / `pid` / `host` / `branch` so the user can either `--force` or pick another task. |
| `start` is set and `--force` passed | Annotate with takeover notice (Step 6) and proceed. |
| `start` is unset | Proceed cleanly. |

#### Read a task's annotations before working it

`task list` truncates them, hiding what past sessions established:
`task <uuid> export | jq -r '.[0].annotations[].description'`. 2026-08: a
session re-derived and announced a finding task 48517b52 already held.

### Step 3: Coworker-check claim (default on)

Unless `--no-coworker-marker` was passed, write the session marker so destructive git ops in this clone (stash, reset, checkout --) trigger the cross-agent guard:

```
Use SlashCommand to invoke `/git:coworker-check --claim`.
```

The git-side marker (`<git-dir>/.claude-session-<pid>`) and the taskwarrior `+ACTIVE` claim are independent signals. Together they reinforce: a stash hook can read either one, and either is enough to pause a destructive op.

If the SlashCommand tool is unavailable in the current session, fall back to running the script directly:

```bash
bash "$(git rev-parse --show-toplevel)/git-plugin/skills/git-coworker-check/scripts/claim-session.sh" --project-dir "$(pwd)"
```

### Step 4: Resolve identity values

Capture once and reuse across the next two steps:

| Value | Source |
|---|---|
| `AGENT` | `claude-${CLAUDE_SESSION_ID:0:8}` (short, stable for the session) |
| `PID` | `$$` (the bash subshell PID — sufficient to cross-link with the git marker since both are taken at the same moment) |
| `HOST` | `hostname` |
| `BRANCH` | `git branch --show-current` (may be empty on a detached HEAD — leave the UDA unset rather than writing the literal "HEAD") |
| `WORKTREE` | `git rev-parse --show-toplevel` |

### Step 5: Start the task and stamp identity

Two calls — start first so `+ACTIVE` is set even if the modify step fails:

```bash
task "$TASK_UUID" start
task "$TASK_UUID" modify \
  agent:"$AGENT" \
  pid:"$PID" \
  host:"$HOST" \
  branch:"$BRANCH" \
  worktree:"$WORKTREE"
```

Omit `branch:` when `BRANCH` is empty (detached HEAD). Quote every value — `worktree:` paths frequently contain spaces.

### Step 6: Annotate the claim

```bash
task "$TASK_UUID" annotate "claimed by $AGENT (pid $PID) on $BRANCH from $HOST:$WORKTREE"
```

When `--force` is used over an existing claim, annotate the takeover separately first so the previous owner's identity is preserved in the audit trail:

```bash
task "$TASK_UUID" annotate "force-claim by $AGENT — previous: agent=$PREV_AGENT pid=$PREV_PID host=$PREV_HOST"
```

### Step 7: Report

Print:

- Task ID, description, urgency
- Identity stamp: `agent` / `pid` / `host` / `branch` / `worktree`
- Coworker-check status: claim written / skipped
- Suggested next step:
  - implementation work
  - `/taskwarrior:task-release <id>` to hand off without closing
  - `/taskwarrior:task-done <id>` once the work has landed

## Agentic Optimizations

| Context | Command |
|---|---|
| Active filter (parallel-safe) | `task +ACTIVE export \| jq '.[] \| {id, agent, branch, host}'` |
| Single-field DOM read | `task _get "$TASKID".agent` (exit 0 even when unset) |
| Cross-project active scan | `task status:pending +ACTIVE export \| jq` |
| Stale-claim probe | `task +ACTIVE start.before:now-4h export \| jq` |
| Skip empty-result failures | Always `export \| jq`, never `task active list` |

## Quick Reference

| Field | Type | Source on claim |
|---|---|---|
| `agent` | string | `claude-${CLAUDE_SESSION_ID:0:8}` |
| `pid` | numeric | `$$` at claim time |
| `host` | string | `hostname` |
| `branch` | string | `git branch --show-current` (omit on detached HEAD) |
| `worktree` | string | `git rev-parse --show-toplevel` |
| `start` (built-in) | date | Set automatically by `task start`; cleared by `task stop` |

| Tag (virtual) | Set by | Cleared by |
|---|---|---|
| `+ACTIVE` | `task start` | `task stop` / `task done` |

## Related

- `/taskwarrior:task-coordinate` — surfaces unblocked candidates to claim
- `/taskwarrior:task-release` — release without closing (handoff)
- `/taskwarrior:task-done` — close after landing (auto-releases the claim)
- `/git:coworker-check` — sister signal: process-scan + session marker
- `.claude/rules/agent-coworker-detection.md` — combined-signal rationale
- `.claude/rules/parallel-safe-queries.md` — `export | jq` idiom
- `.claude/rules/task-id-stability.md` — why this skill resolves `$TASK_UUID` once and mutates by UUID

