Matt Docket
A Tickets section in the Claude Code sidebar: the open project's .scratch/, in the
issue-tracker format from mattpocock-skills, with every agent-ready ticket one press away from a
fresh Claude Code conversation.
The extension is not tied to any particular repository. It wakes up when the open folder has a
.scratch/, and shows the section only while one is there.
▣ Open ▤ Resolved
▾ Checkout flow 3/5
▤ Spec
● 01 Guest checkout Ready for agent
● 02 Validate the ship… Ready for agent
● Unnumbered ticket No status
▾ Receipts 0/0
▤ Spec ✳
No tickets yet
A feature is a section under the same group header the session list above it uses: its name, a
badge counting the tickets under it against the ones it has in all, and then its rows, on the
header's own line rather than indented under it. The first of those rows is the feature's brief —
Spec or Map — standing a little taller than the tickets it was sliced into, so the phase reads
before the work does; a press opens it. A ticket is a status dot, its number, its title — which
stops at the middle of the row however long it runs — and its triage label at the right edge. Hover
a ticket and the label gives way to Claude's mark in its place; press that and the ticket goes off
to a fresh conversation.
Above the list, Open and Resolved split the docket rather than merely selecting a side of it. A
ticket whose status says the work is over — resolved, or wontfix — leaves the open half and
stands under Resolved instead, beneath the same feature headers, so the two halves differ in what
they list and not in how it reads. A feature with nothing on the side you are on drops out of it,
and the strip remembers which side that was.
Neither half hides the other. The badge on a feature header counts the rows you can see against
every ticket the feature has — three of five open reads 3/5 here and 2/5 under Resolved — so
what the cut took away is on the header that took it, and the tooltip goes on tallying the whole
feature by status either way.
The brief row also says which phase the feature is in. A Spec means the deciding is done and the
tickets are work to build. A Map means the effort is still being charted by /wayfinder, and its
tickets are questions to settle rather than work — so they carry no send button until /to-spec
lays a spec beside the map.
What it reads
.scratch/
<feature-slug>/
spec.md # or map.md, for a wayfinder effort
issues/
<NN>-<slug>.md # one ticket per file
A ticket's title is its first heading, wherever in the file's opening lines that heading sits; its
number comes from the file name, or from the title when the file name carries none. Status:,
Type: and Blocked by: are read on both sides of that heading — bold or plain, bulleted or
quoted, in front matter, or as ## Status sections of their own — so the order the fields were
written in does not matter, only that they are there. A ticket with no heading anywhere is named
after its file: 03-empty-states.md reads as Empty states. The tally of - [ ] acceptance
criteria comes from the whole file. Only the status reaches the row; the rest wait in its tooltip.
The five triage labels — needs-triage, needs-info, ready-for-agent, ready-for-human,
wontfix — and the wayfinder's claimed and resolved each get their own colour. Any other label
is shown as written.
Nothing is ever written back into .scratch/. A file watcher picks up edits made in the editor.
Pressing the one on a ticket opens a fresh Claude Code conversation carrying
mattDocket.promptTemplate, which defaults to:
/mattpocock-skills:implement ${ticket}
${ticket} is the ticket's path from the workspace folder, ${title} its title, ${number} its
number, ${feature} its feature slug, and ${brief} the path of that feature's spec.md or
map.md. The button's tooltip shows the prompt it will send, filled in.
It waits for a hover, the way a session's own actions do, and stays grey until the pointer is on
it. Nothing in the Resolved half carries one — there is nothing left to hand over — and neither
do the questions of an effort still on a map.
The brief row carries a button of its own, for the step that phase is waiting for rather than for
the work under it:
mattDocket.specPromptTemplate /mattpocock-skills:to-tickets ${brief}
mattDocket.mapPromptTemplate /mattpocock-skills:to-spec ${brief}
Those templates name ${brief}, ${title} and ${feature} — a brief is not a ticket, so
${ticket} and ${number} are left standing rather than blanked if you write them in. A map's
button is on offer always; a spec's only while the feature has no tickets, because tickets are what
/to-tickets produces and their being there says it has already run.
Either one appears the way a ticket's does — on a hover, grey until the pointer is on the button
and then Claude's orange — but on a hover anywhere in the feature rather than on its own row alone,
because the step it offers belongs to the feature and not to that one row.
If Claude Code cannot be reached, the prompt falls back to its URI handler and then to the
clipboard. It is never lost.
The title bar
Three actions sit above the list: Refresh, Expand All, Collapse All, in that order, so
the fold lands where a tree gives it for free. Refreshing is rarely needed — a file watcher brings
editor changes back on its own — but the watcher follows what is inside .scratch/, so a
directory that has just been created, and is still empty, is the one state it has nothing to report.
Refresh is what notices it, which is why it stays in the command palette even when there is no view
to press it in. Expand All and Collapse All only appear there once there is.
The view is a webview drawing from the same --vscode-* theme variables Claude Code's own webview
builds on, at the same sizes, with icons from the same set. Themes and high-contrast modes are
followed without the view being told about them, and nothing here animates. See
.claude/docs/ARCHITECTURE.md.
Installing
From the Marketplace — Extensions, search for Matt Docket — or from a .vsix when you would
rather have a build than a release:
code --install-extension matt-docket-0.1.0.vsix
That file is attached to every release, and is a
build artifact on every green CI run; VS Code's Extensions: Install from VSIX… command takes it
as well.
It is installed once and follows you between projects. It wakes on any folder that has a
.scratch/ and stays out of the way of the ones that do not, so nothing is per-repository except
the docket it finds. Claude Code is not a requirement either: without anthropic.claude-code the
section lands in the Explorer instead, and the send buttons fall back to the clipboard.
Development
npm install
npm run watch # both bundles, in watch mode
npm run check-types # esbuild only transpiles; types are checked separately
npm test # the domain and the view model, on plain Node
F5 (Run Extension) starts an Extension Development Host on sample-workspace/, whose .scratch/
carries fixtures for every triage label plus the awkward shapes: a feature with no spec, a feature
with no tickets, a wayfinder effort mapped rather than specified, a ticket with no status, and a
file with no leading number.
It opens that folder rather than the repository root because VS Code refuses to open a folder in the
development host while another window already has it — the host comes up empty instead, and the
extension never activates.
The "Tickets" section appears in the Claude Code sidebar below the session list. Run Extension (no Claude) starts the same host with anthropic.claude-code disabled, where the view should land in
the Explorer instead, quietly, and the send button should fall back to the clipboard.
Releasing
npm run package # minified dist/
npm run vsix # the .vsix, through vscode:prepublish
A release is a tag. Bump version in package.json, put the CHANGELOG.md entries under it, then
push v0.1.0: .github/workflows/release.yml refuses a tag the
manifest disagrees with, runs the checks, attaches the .vsix to a GitHub release, and hands that
same file to the Marketplace — signed in as a managed identity GitHub vouches for, so there is no
token in the repository to leak or to expire. That last step waits on an AZURE_CLIENT_ID variable
and is skipped until one is there, so the release stands on its own and the .vsix can be uploaded
by hand. .claude/docs/PUBLISHING.md is the one-time setup, and why it
is not the personal access token every other guide reaches for.
Third-party notices, including the one for the Claude mark on the send button, are in
THIRD-PARTY.md.