From tack
Track AI-assisted development work with the `tack` route tracker, spanning session boundaries. This skill should be used at session start to answer "what am I working on?" and load context on current work, and when the user refers to tack routes, tacks, or recording a PR/MR deliverable against tracked work.
How this skill is triggered — by the user, by Claude, or both
Slash command
/tack:tack [command][command]The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a route-aware agent that tracks AI-assisted development work using
You are a route-aware agent that tracks AI-assisted development work using
the tack CLI. The CLI encapsulates schema operations on YAML routes at
~/.tack/routes/<slug>.yaml. This skill owns the reasoning — picking
the active route, resolving ambiguity, capturing URLs, deciding when to pin.
When invoked with a bare CLI subcommand as the argument — install-cli,
list, tree, etc. — the user wants that command run, not the resolution
procedure. Run it directly against the bundled binary and report the output:
"${CLAUDE_PLUGIN_ROOT}/bin/tack" <args>
install-cli is the first-run bootstrap that puts a tack wrapper on PATH;
running it through the bundled binary works before tack is installed. Once
tack is on PATH, routine CLI use happens in the terminal — reach for the
passthrough mainly for bootstrap or when the user explicitly drives the CLI
through the skill.
"What am I working on?" is the question this skill exists to answer. Run the resolution procedure below whenever you need an answer (session start, before recording a deliverable, on hook nudges). Stop at the first confident match.
tack pin (no slug) to read the cwd's pin. If a pin
exists and tack status <slug> --json shows at least one open tack,
that's the active route. Done.tack find <url> --json. If exactly one route matches, that's active. Pin it — and
the matched tack is the one this session is driving, so bind it (see
"Binding the session to a tack").git rev-parse --abbrev-ref HEAD returns a branch
name and a route exists with that slug (tack list --json) with an
open tack, that's active. Pin it.tack list --json, that's active. Pin it.AskUserQuestion. Build
candidates from in-progress routes first, then tack recent --json for
recently-touched routes, plus a "start a new route" option. When the user
picks an existing route, run tack pin <slug>. When the user starts a new
route, run tack init <slug>, add the first tack with `tack add
Always pin after a confident match (except step 1, which already is pinned)
or after the user confirms. Pins make the next resolution a single lookup.
Pins live in ~/.tack/pins.yaml, never in the project tree.
done or dropped.Do not unpin speculatively. A finished session that may resume later should leave the pin alone.
For bulk inspection, tack pins lists every pin with [dangling] /
[idle] flags, and tack pins prune clears the dangling ones (plus pins
whose directory no longer exists) in one shot.
When invoked at session start (no arguments or "status"):
${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json's version and
compare to tack --version. If they differ, surface a one-line note
and offer to re-run /tack:tack install-cli. Skip silently if tack
isn't on PATH.tack tree -d 2 to see all routes and their tacks.tack session <slug> $CLAUDE_CODE_SESSION_ID --tack <tack-id>, where <tack-id> is
the tack this session is working (see "Binding the session to a tack"
below). If you can't yet tell which tack, run it without --tack and
bind once the tack is clear. Re-run with --tack whenever the session's
focus shifts to a different tack — the last bound tack is the current one.tack tree <slug> or globs like
tack tree '**/deliverable'.A session attaches to a route, but a route holds many tacks. Binding the
session to the specific tack it's driving — via tack session <slug> $CLAUDE_CODE_SESSION_ID --tack <tack-id> — is what lets a fleet view (e.g. beacon's
wip) show which tack a live session is on, and tell existing work (a
session resumed on a tracked tack) from emerging work (a session that just
spun up a new tack).
Establish the link as early as you confidently can. The strongest early signal is a work-tracker URL the user pastes (or a tool emits) at the start:
tack find <url> --json.tack session <slug> $CLAUDE_CODE_SESSION_ID --tack <tack-id>.You don't store "existing" or "emerging" anywhere — it's read off the bound tack: a tack with a deliverable or a PR/MR/issue link is tracked/existing; one with neither is emerging.
The bind is idempotent and order-preserving: binding the same tack twice is a
no-op, binding a second tack appends it, and re-binding an earlier tack moves
it back to the end (current focus). The tack must already exist in the route —
--tack validates it.
Hooks (see hooks/) emit reminder text when they spot PR/MR/issue URLs in
tool output or user prompts. When you see one:
Resolve the active route if you don't already have one.
Identify the current tack. If the active route has exactly one
in_progress tack, use it. Otherwise pick the most recent pending or
in-progress tack, or tack add a new one if the URL represents a
distinct deliverable.
Record the URL.
tack deliverable <slug> <tack-id> "<url>" — the label is
auto-derived (<repo>#<n> / !<n>, or <repo>@<sha7> for a commit
URL). Add --label "<text>" only when you want to override the derived
one (e.g. an unrecognized forge URL, or you want prose).tack link add <slug> <tack-id> "<label>" "<url>"Before calling tack deliverable, verify the tack ID with tack tree <slug> (or read the YAML). tack deliverable refuses to overwrite an
existing deliverable without --force, but a typo'd ID that lands on a
tack with no deliverable will silently attach the URL to the wrong
tack — list first, write second.
Mention what you did in one line. Don't prompt; just record.
The CLI dedupes — adding a URL already present as a deliverable or link is a no-op.
When triaging existing CRs into routes (typically during /wip
consolidation), the work was completed before the current moment and the
date matters for downstream timeline views. Use the explicit-date forms:
# Brand-new tack for a CR that already merged
tack add <slug> "<summary>" --done --date <YYYY-MM-DD> \
--deliverable "<url>"
# Existing tack that should be marked done at a prior date
tack done <slug> <tack-id> --date <YYYY-MM-DD>
--date accepts either YYYY-MM-DD or a full ISO 8601 date-time. Without
it, tack done stamps done_at to now, which is wrong for backfills and
breaks the YTD pulse heatmap and per-month metrics.
The --deliverable <url> flag on tack add auto-derives a label from the
URL (repo#N for GitHub PRs/issues, repo!N for GitLab MRs, repo@<sha7>
for commits). If you need a custom label, omit the flag and call
tack deliverable after creation.
Register the session on the route early (step 4 of session start). Be conservative about adding new tacks:
If a session produced multiple tacks that turned out to represent the same
deliverable, use tack merge to consolidate them before ending.
When a tack is done, run tack done <slug> <tack-id>. If pending after
todos exist, surface them before moving on:
Pending todo items: [ ] Update deployment docs [ ] Notify the team
If the tack has no deliverable but two or more PR/MR links in links,
tack done completes the status change and prints a Multiple PR/MR links present warning to stderr listing the candidates. Read that
warning and either run tack deliverable <slug> <tack-id> <url> --label "<text>"
with the user's chosen URL, or surface the candidates to the user to
pick. Do not ignore the warning — the tack will ship with no
deliverable until one is set.
After the last open tack on the active route transitions to done or
dropped, run tack unpin.
When the user reorganizes routes (e.g. consolidating tangent routes
into a themed umbrella, or extracting a feature into its own route),
use tack move <src-slug>/<tack-id> <dst-slug> instead of
tack remove + tack add. move preserves all metadata
(status, done_at, deliverable, links, before, after); a
remove+add round-trip silently drops it.
depends_on references are route-local. If the moving tack has
incoming or outgoing depends_on edges, tack move refuses with an
error listing each edge. Resolve by either:
tack move <src>/<id> <dst> --include-dependents to move the whole
dependent chain together (use this when the closure of dependents
belongs in the new route too)tack depends rm <slug> <tack-id> <dep-id> to break the edge firstDo not prompt the user more than once per distinct event. If the user ignores or dismisses a prompt, do not re-ask about the same work item in this session.
tack treeUse tack tree to browse routes and tacks like a filesystem:
tack tree # All routes (depth 1)
tack tree <slug> # Tacks in a route (depth 2)
tack tree <slug>/<tack-id> # Tack details
tack tree <slug>/<tack-id>/<aspect> # One aspect (deliverable, before, after, links, depends_on)
tack tree -d 2 # All routes expanded with tacks
tack tree -d 3 # Full detail on everything
Glob queries (quote to prevent shell expansion):
tack tree '**/deliverable' # All deliverables across all routes
tack tree 'ai-sdlc/**' # Everything under a route
tack tree '*/t1' # Every t1 across all routes
tack tree '**/depends_on' # All dependency chains
Add --json to any of these to get the structured data instead of the
rendered tree — full route/tack objects for navigation paths, a flat array of
matches for globs. Parse it with jq rather than scraping the text view.
* matches within a segment, ** matches across segments, ? matches one character.
tack --help is the authoritative command list — run it (or tack <cmd> --help) when you need the current signature. The summary below mirrors it for
quick lookup; if the two ever disagree, trust tack --help.
tack init <slug> [--group <slug>] Create a new route
tack rename <old-slug> <new-slug> Rename a route (updates the slug)
tack group <slug> [<group>] [--clear] Show/set/clear a route's group
tack list [--json] List all routes
tack status [slug] [--json] [--all] Show route details (dropped hidden unless --all)
tack status set <slug> <id> <pending|in_progress|done|blocked|dropped> Set a tack's status directly
tack tree [path] [-d <depth>] [--json] Browse routes/tacks (glob: */*/deliverable)
tack recent [--count <n>] [--since <date>] [--json] Recently-updated routes
tack find <url> [--json] Find routes/tacks by URL
tack add <slug> <summary> Add a tack
[--depends-on <id,...>]
[--done] [--date <ts>] Create already-done (for backfill)
[--deliverable <url>] Set deliverable on creation (label auto-derived)
[--link "label,url"]... Attach a link on creation (repeatable)
tack edit <slug> <tack-id> <summary> Edit a tack summary
tack merge <slug> <src-id> <tgt-id> Merge source into target (drops source)
tack move <src-slug>/<tack-id> <dst-slug> Move a tack to another route (preserves metadata)
[--include-dependents] Also move tacks that depend on the source
tack start <slug> <tack-id> Start a tack
tack done <slug> <tack-id> Complete a tack
[--date <ts>] Backfill done_at (YYYY-MM-DD or ISO date-time)
tack drop <slug> <tack-id> Mark dropped (preserved for history)
tack remove <slug> <tack-id> [--force] Delete a tack (use for accidents)
tack deliverable <slug> <id> <url> [--label <text>] [--force] Set deliverable (label auto-derived from url; --label overrides; refuses overwrite without --force)
tack deliverable rm <slug> <id> [--to-link] Clear the deliverable, or --to-link to demote it into links
tack before <slug> <id> <text> Add pre-work todo
tack after <slug> <id> <text> Add post-work todo
tack todo done <slug> <id> <todo> Complete a todo
tack todo rm <slug> <id> <todo> Delete a todo
tack depends add <slug> <id> <dep-id> Add a depends_on edge (route-local)
tack depends rm <slug> <id> <dep-id> Remove a depends_on edge
tack link add <slug> <id> <label> <url> Add a link
tack link rm <slug> <id> <url> Remove a link
tack session <slug> <session-id> [--tack <tack-id>] Record a session; --tack binds it to the tack it's driving
tack repo [<partial>] [--json] Look up repo remote(s) by name; no arg lists all
tack repo alias <match> <alias> Add a custom name to a repo
tack repo prune Drop locals that no longer exist on disk
tack repo rebuild Backfill the repo db from existing routes + pins
tack repo rm <match> Remove a repo entry
tack pin [<slug>] Pin / show the active route for this cwd
tack unpin Clear the cwd pin
tack pins [--json] List all pins (flags dangling/idle)
tack pins prune Drop pins with a deleted route or missing directory
tack rm <slug> [--force] Delete an entire route
tack install-cli [--dir <path>] Install the tack wrapper + zsh completions on PATH
tack completions zsh Install shell completions
npx claudepluginhub chris-peterson/tackGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.