From accelerator
Lists and filters work items from the configured work directory by status, kind, priority, parent, or tag. Useful for discovering existing work items or viewing the hierarchy.
How this skill is triggered — by the user, by Claude, or both
Slash command
/accelerator:list-work-items [filter description][filter description]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
!`${CLAUDE_PLUGIN_ROOT}/scripts/config-read-context.sh`
!${CLAUDE_PLUGIN_ROOT}/scripts/config-read-context.sh
!${CLAUDE_PLUGIN_ROOT}/scripts/config-read-skill-context.sh list-work-items
!${CLAUDE_PLUGIN_ROOT}/scripts/config-read-agents.sh
If no "Agent Names" section appears above, use these defaults: accelerator:reviewer, accelerator:codebase-locator, accelerator:codebase-analyser, accelerator:codebase-pattern-finder, accelerator:documents-locator, accelerator:documents-analyser, accelerator:web-search-researcher.
Work items directory: !${CLAUDE_PLUGIN_ROOT}/scripts/config-read-path.sh work
Work item ID pattern: !${CLAUDE_PLUGIN_ROOT}/scripts/config-read-work.sh id_pattern
Default project code: !${CLAUDE_PLUGIN_ROOT}/scripts/config-read-work.sh default_project_code
Active integration: !${CLAUDE_PLUGIN_ROOT}/scripts/config-read-work.sh integration
The Active integration line above gates the sync-status rendering (Step 4).
config-read-work.sh integration exits 0 with an empty line when no
integration is configured, so branch on the string, not the exit code:
treat a non-empty value as integration configured and an empty value as not
configured.
The following template defines the work item schema and field defaults.
Hint values for filter parsing are extracted at runtime via
work-item-template-field-hints.sh.
!${CLAUDE_PLUGIN_ROOT}/scripts/config-read-template.sh work-item
You are tasked with listing and filtering work items from the configured
work items directory. This is a read-only skill — never write any files
and never spawn sub-agents. The entire flow uses filesystem reads and the
companion scripts listed in allowed-tools.
If an argument was provided, parse it as a filter expression using the following precedence rules. The first rule that matches wins.
Before applying rules 3–4, call work-item-template-field-hints.sh for
each of kind, status, and priority to populate the known
template-comment values:
${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-item-template-field-hints.sh kind
${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-item-template-field-hints.sh status
${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-item-template-field-hints.sh priority
Each call outputs one value per line. Collect these into three sets:
known kinds, known statuses, and known priorities. These hints inform
the shorthand rules below but do not restrict what values may appear on
work items — legacy values like todo, done, or adr-creation-task are
matchable only via the explicit structured form (rule 2).
Rule 1 — Presentation keywords (changes rendering, not filtering):
hierarchy, as a tree, show hierarchy. These may combine with a
filter (e.g. hierarchy under 0042). Strip the keyword from the
argument and continue parsing the remainder, if any, through rules 2–5.
Rule 2 — Explicit structured forms (keyword identifies the field):
tagged <value> or with tag <value> → filter by tagunder <value> or children of <value> → filter by parentstatus <value> → filter by status (matches any value on any work item)kind <value> → filter by kind (matches any value on any work item)priority <value> → filter by priorityabout <text> → free-text title search (case-insensitive substring)Rule 3 — Multi-token template-value shorthand: two or more tokens
that each match a known template-comment value in different fields.
For example, bugs in review → kind: bug AND status: review (after
singularising bugs to bug and recognising in-progress, review,
etc. as status values with filler words like in, only, all
stripped). Both tokens must match values from distinct fields. If either
token is ambiguous across fields, fall through to rule 5.
Rule 4 — Single-token template-value shorthand: one token matching a
known kind, status, or priority value from the template comments. Map
common plurals (bugs→bug, epics→epic, stories→story,
tasks→task, spikes→spike) and common synonyms
(drafts→draft). If the token matches values in more than one field,
ask the user for disambiguation rather than guessing.
Rule 5 — Free-text title search: anything that does not match rules
1–4 is treated as a case-insensitive substring search against the
title: frontmatter field.
Always echo the interpreted filter before showing results so the
user can rephrase if the parse was wrong. Example: Filter: status=draft (3 matches).
If no argument was provided: filter is "all work items, no filter".
Check that {work_dir} exists. If not, print:
Work items directory `{work_dir}` not found.
Check the `paths.work` configuration or run `/create-work-item` to
create the first work item.
and exit cleanly.
List all *.md files in {work_dir}. The discovery glob is broadened
from a literal numeric prefix to *.md because the work-item ID
pattern is configurable (work.id_pattern) and legacy NNNN-*.md
files may coexist with project-coded files (PROJ-NNNN-*.md) during
a pattern transition. A file is treated as a work item iff
work-item-common.sh:wip_is_work_item_file returns success — that is,
the file has YAML frontmatter and a non-empty id field (or
work_item_id on legacy files).
Files lacking either are silently excluded; files with malformed
frontmatter emit a one-line warning to stderr and are skipped.
If no work-item files exist after filtering, print:
No work items found in `{work_dir}`.
and exit cleanly.
Extract frontmatter from all work items in a single pass. Work item directories can contain dozens of files, so reading each one individually would be too slow. Instead, use a single Bash command to extract the frontmatter fields from every matching file at once.
Example approach — run one awk command across all *.md files:
for f in {work_dir}/*.md; do
# Filter to true work items via wip_is_work_item_file
if ! bash -c "source ${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-item-common.sh && wip_is_work_item_file '$f'"; then
continue
fi
awk -v file="$f" '
NR==1 && /^---[[:space:]]*$/ { in_fm=1; next }
NR==1 { print file "\tERROR\tno frontmatter"; exit }
in_fm && /^---[[:space:]]*$/ { closed=1; exit }
in_fm { print file "\t" $0 }
END { if (in_fm && !closed) print file "\tERROR\tunclosed frontmatter" }
' "$f"
done
This outputs one line per frontmatter field per file (tab-delimited: filepath, field line) plus ERROR lines for malformed files. Parse the output to build the work item list in memory.
ERROR no frontmatter: warn
"<filename>: skipped — no frontmatter" and exclude the file.ERROR unclosed frontmatter: warn
"<filename>: skipped — unclosed frontmatter" and exclude.wip_extract_id_from_filename. The compiled scan regex respects
the configured work.id_pattern; a legacy 0042-foo.md file
under a {project}-{number:04d} pattern is matched by a
legacy-fallback path so the file remains visible in the listing.
The filename prefix remains the authoritative work item ID, even
if the id field (or work_item_id on legacy files) in frontmatter
differs.Mixed-prefix discoverability hint: when the listing detects both
files matching the legacy [0-9]{4}- shape AND files matching the
configured {project} pattern in the same corpus, prepend a single
informational line to the output before the table:
note: mixed prefix corpus detected — N legacy items, M project-prefixed
items. Run /accelerator:migrate to normalise.
The note appears once per invocation (not per file) and is suppressed
when the configured pattern lacks {project}.
From the extracted frontmatter lines, parse these fields for each work item (all optional — missing fields are recorded as absent, not as errors):
title — the human-readable titlekind — the work item kindstatus — the current statuspriority — the priority leveltags — a YAML inline array (e.g. [backend, api])parent — the parent work item numberexternal_id — the remote tracker's identifier, used only for the
sync-status label in Step 4. It is already present in the single-pass
frontmatter stream above (the awk prints every frontmatter line), so
reading it adds no extra per-file process. Read it only when an
integration is configured; otherwise ignore it.Sync classification (only when an integration is configured). For each file that passed the frontmatter validity check above, classify it presence-based:
external_id absent → unsynced (never an error — the item was simply
never pushed).external_id present but normalising to empty (after stripping surrounding
quotes and whitespace — e.g. external_id: "") → unsynced.external_id present and non-empty after normalisation → synced.Do not hand-roll the normalisation: pass the raw external_id value (or
nothing, when the field is absent) to the authoritative classifier
work-item-sync-label.sh (Step 4), which owns the trimming rule and the
label vocabulary. A file that Step 2 already flagged as malformed stays a
skip, not an unsynced row. The filename remains the authoritative
displayed ID — external_id never changes the displayed ID.
This presence-only synced/unsynced split is the floor. When a
last-sync.json baseline exists, Step 4 upgrades tracked items (those
with an external_id and a baseline entry) to the three baseline-dependent
states — locally-modified, remotely-modified, conflict — via a single
bulk remote read and the shared change-detection engine, degrading back to
this presence-only floor whenever the remote is unreachable or no baseline
exists. See "Sync Status Labels" in Step 4.
Apply the parsed filter from Step 1 to the scanned work items.
tags value (e.g. [backend, api])
into individual tag strings. A work item matches if any tag equals the
filter value. Work items with tags: [], empty tags:, or absent tags
field do not match (and are not errors).under X): normalise both the filter value and
each work item's parent field via
work-item-common.sh:wip_canonicalise_id before comparison. The
canonicaliser strips quotes, accepts short and long forms, and
zero-pads to the configured pattern's width (or pre-pends the
default project code when the pattern requires {project} and the
input is a bare number). So under default config parent: "0042",
parent: 0042, parent: 42, and parent: "42" all match
under 0042 or under 42. Under {project}-{number:04d} config
with default_project_code: PROJ, parent: "PROJ-0042",
parent: "0042" (legacy), and parent: 42 all canonicalise to
PROJ-0042 and match under PROJ-0042 or under 42.about X or rule 5): case-insensitive
substring match against the title: frontmatter value. Work items
without a title field are excluded.When the Active integration read at the top of this skill is a non-empty string, each rendered work item carries a sync-status label. When it is empty, render exactly as today — no Sync column, no label, output unchanged.
All five label states are owned by one source of truth so the table and hierarchy views never drift:
${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-item-sync-label.sh --label <state>
where <state> ∈ synced, unsynced, locally-modified, remotely-modified,
conflict renders the markdown-native label (🟢 synced, ⚪ unsynced,
🔵 locally modified, 🟣 remotely modified, 🔴 conflict). Every pair differs
in both glyph and text, and the labels are markdown-native (a Unicode
glyph + text) emitted into the conversation's table — never ANSI escape
codes, which would surface as literal \033[…] text.
Resolve the baseline path:
${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-item-sync-baseline.sh path
No last-sync.json baseline file (the resolved path does not exist):
there is no referent for change detection, so classify every item
presence-only — external_id non-empty → synced, else unsynced (pass
the raw value to work-item-sync-label.sh <external-id-value>, which owns the
trimming rule). Do no remote read. This is exactly the 0047 behaviour.
Baseline exists: render the full five-state set for tracked items, driven
by a SINGLE bulk remote read plus the shared engine. Items with no
external_id, or no baseline entry, stay presence-only.
Bulk pre-filter read — one call, never N. Collect the non-empty
external_ids of all listed items and fetch their remote updated stamps in
one call:
${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-item-fetch-remote.sh \
--integration <sys> search --keys <comma-separated external_ids>
It returns { "found": {<key>:{updated}}, "absent": [...], "indeterminate": [...] } — the adapter chose the per-tracker strategy, so you
never branch on tracker. Graceful degradation: if the bridge exits
non-zero (remote unreachable / timed out), do not retry or hang — fall
back to presence-only for every item, render the listing, and exit 0. One
bulk call bounds the whole degradation path; a key that lands in
indeterminate is likewise treated as unknown, never as remote-absent.
Per item, derive the remote status to hand the engine:
external_id → presence-only unsynced (skip the engine).external_id present but no baseline entry
(work-item-sync-baseline.sh get <id> prints nothing) → presence-only
(synced); skip the engine.indeterminate, or the bulk read degraded → --remote-status indeterminate.absent → --remote-status absent.found → --remote-status present --remote-updated <its updated>.
If that updated differs from the baseline entry's remote_updated_at,
this item is in the genuinely-changed minority: fetch its body
(work-item-fetch-remote.sh … show --external-id <key>), project +
canonicalise it to the comparable local shape (jira: .fields.summary →
title, .fields.description ADF through jq -S; linear:
.data.issue.title + .data.issue.description Markdown, no jq -S),
write it to a temp file, and pass --remote-body-file. Reserve show for
this minority and emit classifying item k of N progress so a long pass
never reads as a hang.Classify via the shared engine and render its keyword:
${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-item-sync-classify.sh \
--file <path> --external-id <key> \
--baseline "$(work-item-sync-baseline.sh get <id>)" \
--timestamp "$(jq -r '.timestamp // 0' "$(work-item-sync-baseline.sh path)")" \
--remote-status <present|absent|indeterminate> \
[--remote-updated <iso>] [--remote-body-file <tmp>]
The engine prints one of synced | unsynced | locally-modified | remotely-modified | conflict | remote-absent | indeterminate. Feed the first
five straight to work-item-sync-label.sh --label <state>. For
remote-absent and indeterminate, render the presence-only label
(synced, since the item carries an external_id): the remote state is
unknown or the issue is gone, and the listing must never fail or hang on it.
The canonical-tree-fence example below stays label-free.
Present the filtered work items as a markdown table with these columns:
| ID | Title | Kind | Status | Priority |
When an integration is configured (see "Sync Status Labels" above), append a Sync column carrying each item's label:
| ID | Title | Kind | Status | Priority | Sync |
—.— for every row in the current result set,
suppress that column entirely to reduce noise. For example, a listing
of only legacy work items (which lack priority) would omit the Priority
column. The Sync column follows the same rule in reverse: it is present
only when an integration is configured, and suppressed entirely when one
is not (there is no label to show).If a hierarchy presentation keyword was detected in Step 1:
parent (or empty parent) appear at the top level.parent points to a work item in the current result
set are rendered as children. Each parent→children group prints
as a tree using Unicode box-drawing characters. Children use
├── for all entries except the last in the group, which uses
└── . Indent two spaces per depth level. Example:NNNN — parent title (kind: , status: ) ├── NNNN — child 1 title (kind: , status: ) ├── NNNN — child 2 title (kind: , status: ) └── NNNN — last child title (kind: , status: )
No ASCII fallback is attempted; terminals without Unicode support will render mojibake. Users on such terminals can re-display the hierarchy via /list-work-items.
Sync labels in the tree (only when an integration is configured): append
each item's sync label — obtained from work-item-sync-label.sh, the same
source of truth the table uses — to the end of its line, after the
(kind: …, status: …) segment. For example:
0042 — User Auth Rework (kind: epic, status: ready) 🟢 synced
└── 0043 — Login form (kind: story, status: draft) ⚪ unsynced
The shared canonical-tree-fence example above is deliberately kept
label-free: it is an integration-agnostic static example shared
byte-for-byte with /refine-work-item (which has no integration gate), so the
sync label is applied to the live rendered output, never to that example.
Work items whose parent points to a work item number that does not exist
in the result set appear at the top level with a suffix:
(parent NNNN not found).
Cycle detection: before rendering, walk the parent chain for each
work item. If a work item is visited twice during a walk, it is part of a
cycle. Render all cyclic work items at the top level with a (cycle)
marker. This ensures bounded execution — no infinite loops.
No work items matched: <filter description>.
Do not render an empty table. If the active filter was a free-text
title search (rule 5), append:
Tip: to filter by field value, use `status <value>`, `kind <value>`,
or `tagged <value>`.
Always print the interpreted filter and match count above the table:
Filter: status=draft (3 matches)
or for a parent filter:
Children of 0042 (2 matches)
or for no filter:
All work items (29 total)
status <value>,
kind <value>, etc. match any value present on any work item, not just
template defaults. This is how legacy values like todo or
adr-creation-task are reachable.work-item-read-field.sh:
"no frontmatter" / "unclosed frontmatter".wip_extract_id_from_filename) is the work item ID, even if
the id field (or work_item_id on legacy files) in frontmatter
differs. This applies to both legacy bare-number filenames and
project-coded filenames.!${CLAUDE_PLUGIN_ROOT}/scripts/config-read-skill-instructions.sh list-work-items
npx claudepluginhub atomicinnovation/accelerator --plugin acceleratorGenerates hierarchical project dashboard of work items organized by container, showing IDs, tags, status, priority. Use for project status, summaries, overviews.
Reconciles local work items with remote trackers (Jira, Linear). Supports push, pull, and preview modes to safely sync state between local files and the active integration.
Creates, lists, and updates persistent work items to track tasks, priorities, and statuses across sessions, mitigating context rot in long-running Claude conversations.