Skip to content
Back to skills

Taskwarrior

ASecurity

Use when querying or modifying tasks via the taskwarrior CLI - dense recipes for listing, single-field lookups, multi-task batched lookups, full-text search, and the soft description-length convention. Activates on `task list`, `task add`, `task info`, `task done`, "what's on the backlog", "find a task", or any taskwarrior interaction.

  • 10 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added May 27, 2026
data-airustgoshellbash

Works with

  • cli

Security analysis

A100/100

Scanned September 20, 2026

npx -y skills add technicalpickles/pickled-claude-plugins --skill taskwarrior --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Taskwarrior?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Taskwarrior
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/technicalpickles-taskwarrior/badge)](https://www.skillsdirectory.com/skills/technicalpickles-taskwarrior)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: taskwarrior
description: Use when querying or modifying tasks via the taskwarrior CLI - dense recipes for listing, single-field lookups, multi-task batched lookups, full-text search, and the soft description-length convention. Activates on `task list`, `task add`, `task info`, `task done`, "what's on the backlog", "find a task", or any taskwarrior interaction.
---

# Taskwarrior Token-Dense Recipes

Use these recipes whenever you invoke `task` on the user's behalf. They cut output size 4-10× compared to default formats.

**Companion config:** This skill assumes `~/.taskrc` has the named `dense` report defined and `verbose=` configured to suppress override-echo noise. If `task` (with no args) doesn't run a dense report, see the design doc at `docs/superpowers/specs/2026-05-08-taskwarrior-token-density-design.md`.

## Listing tasks

**Default. Use the named report:**

```bash
task <filter> dense
```

Examples:

```bash
task project:pickled-claude-plugins dense
task +followup dense
task dense  # bare = all pending, urgency-sorted
```

**Custom shape, when you need different columns or truncation:**

```bash
task <filter> export | jq -r '.[] | "\(.uuid[0:8]) [\(.project // "-")] \(.tags // [] | join(",")) \(.due // "-")  \(.description[0:80])"'
```

This produces ~120 chars/task. The `dense` report produces ~150 chars/task with column alignment. The jq form is for when you need a specific shape (e.g., longer description, different fields).

**Never:** raw `task list` with no filter. The 320+ pending tasks at default formatting is the largest single cost in your taskwarrior I/O.

## Single-field lookup

When you need ONE field of a known task, use `_get` with a DOM reference (`<uuid>.<field>`):

```bash
task _get <uuid>.description
task _get <uuid>.project
task _get <uuid>.tags
task _get <uuid>.due
task _get <uuid>.urgency
```

You can also batch fields in one call:

```bash
task _get <uuid>.project <uuid>.tags <uuid>.due
```

`_get` returns the raw field value(s), no metadata, no formatting. Roughly 10× denser than `task <uuid> info`. Note the syntax: `_get` is the command and the DOM reference is its argument. NOT `task <uuid> _get description` (that returns empty).

**Never:** `task <uuid> info` when you only need one field. `info` dumps full metadata (entry/modified/uuid/status/etc.): useful when triaging, wasteful for field lookup.

## Multi-task lookup

When inspecting several tasks at once, pass UUIDs (or short UUIDs) as space-separated positional args to `export`:

```bash
task UUID1 UUID2 UUID3 export | jq -r '.[] | "\(.uuid[0:8])  [\(.project // "-")]  \(.description[0:120])"'
```

Or for richer output:

```bash
task UUID1 UUID2 UUID3 export | jq -r '.[] | "uuid: \(.uuid[0:8])  tags: \(.tags // [] | join(","))  due: \(.due // "-")  desc: \(.description[0:80])"'
```

Short (8-char) UUIDs work fine: `task c9dca83f 53c8850a b940d369 export` is equivalent. Comma-separated forms (`uuid:A,B,C`) do NOT work in taskwarrior 3.4.2; they return empty.

**Never:** `task A info && echo --- && task B info && echo --- && task C info && ...`. This pattern has been observed at 25,000+ chars per call (vs ~600 chars for the batched export equivalent).

## Full-text search

`task list | grep` is unreliable because descriptions wrap across lines. Use export + jq:

```bash
# Search descriptions (null-safe)
task export | jq -r '.[] | select((.description // "") | test("PATTERN"; "i")) | "\(.uuid[0:8])  \(.description[0:120])"'

# Search annotations
task export | jq -r '.[] | select(.annotations[]?.description | test("PATTERN"; "i")) | "\(.uuid[0:8])  \(.description[0:120])"'

# Search both
task export | jq -r '.[] | select((.description // "") + " " + ((.annotations // []) | map(.description) | join(" ")) | test("PATTERN"; "i")) | "\(.uuid[0:8])  \(.description[0:120])"'
```

The `"i"` flag makes the test case-insensitive. Drop it for case-sensitive matches.

## Durable references: UUID, not numeric ID

Numeric IDs are reused once a task completes, or whenever the pending list otherwise reorders — `task 197` today may be a completely different task next month, or even a few tool calls from now if other tasks completed or unrelated background work touched taskwarrior in between. They're fine for same-session interactive use (`task 197 done`, or an `annotate` right after creating the task, with nothing in between). They are **not** fine for anything that outlives the current shell: park/handoff files, commit messages, memory files, PR descriptions, beans. A numeric ID written into one of those will silently point at the wrong task later.

**Verify before you cite, and re-resolve before you act.** This has caused real, repeated damage — annotate/done calls landing on unrelated tasks in other projects, needing `task <uuid> denotate -- <text>` cleanup afterward:

- Before writing a UUID into a durable artifact, confirm it actually resolves to the task you mean (`task <uuid> info`, read the description back). A UUID is only as trustworthy as the citation that produced it — hand-typed from memory, copied from an earlier message, or captured before the task was edited elsewhere can all silently point at the wrong task despite being correctly formatted.
- Before acting on a cached integer ID (`done`, `annotate`, `modify`, `depends`), re-resolve it if it was captured more than a few commands ago in the same session. Don't trust that the number still means what it meant earlier.

Capture the UUID at creation time and cite that instead:

```bash
task add project:foo +bug "OAuth token refresh fails with 401 after 24h"
# Output: "Created task 197."
UUID=$(task entry.after:now-1m +bug export | jq -r '.[0].uuid[0:8]')
```

Short (8-char) UUIDs are fine everywhere a full UUID would go — `task <uuid> info`, `task <uuid> done`, and in prose (`task c9dca83f`).

## Description-length convention

When creating tasks (`task add ...`), aim for descriptions ≤ 100 chars. Long context goes in annotations:

```bash
# Good: short title, then annotate context.
task add project:foo +bug "OAuth token refresh fails with 401 after 24h"
# Output: "Created task 197." That numeric ID is fine for a same-shell-session
# follow-up like the annotate below. If this task will be cited anywhere durable
# (handoff, commit, memory, PR), capture the UUID first — see above.
task 197 annotate "Repro: lifecycle.test.ts:124. Happens only with refresh-token rotation enabled. Suspect cache key collision between user_id and session_id; see retro 2026-04-19."
```

```bash
# Bad: paragraph as description.
task add project:foo +bug "OAuth token refresh fails with 401 after 24h. Repro: lifecycle.test.ts:124. Happens only with refresh-token rotation enabled. Suspect cache key collision between user_id and session_id; see retro 2026-04-19. Affects all users on the canary deployment, blocks GA. Fix: split cache namespace by token_type."
```

Soft target. Existing bloated descriptions decay naturally as tasks are completed or edited; no retroactive cleanup is required.

## Other dense idioms

- **Counts:** `task <filter> count` returns a single integer, ~3 chars.
- **Project summary:** `task summary` is a project-by-project rollup, very dense.
- **Project list:** `task projects` lists all project names with counts.
- **Tag list:** `task tags` lists all tags with counts.

## Decision tree: what should I run?

| Need | Run |
|---|---|
| "What's pending in project X?" | `task project:X dense` |
| "How many open in project X?" | `task project:X count` |
| "What's on the backlog overall?" | `task summary` (then drill into a project with `dense`) |
| "What does task `<uuid>` look like?" | `task <uuid> info` (full metadata is fine for one task) |
| "What's the description of `<uuid>`?" | `task _get <uuid>.description` |
| "What about these 5 tasks?" | `task A B C D E export \| jq -r '...'` (space-separated UUIDs) |
| "Find tasks mentioning 'oauth'" | `task export \| jq -r '.[] \| select(.description \| test("oauth"; "i")) \| ...'` |
| "Add a task" | `task add project:X +tag "short title ≤100c"` then optionally `task <uuid> annotate "context"` |
| "Mark done" | `task <uuid> done` |
| "Citing a task in a handoff/commit/memory/PR" | Use the UUID (short form OK), never the numeric ID — see [Durable references](#durable-references-uuid-not-numeric-id) |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.