paperctl skill generate accepts multiple sessions and drafts one skill from all of them together. The quality of what comes out tracks the quality of the sessions that go in, so this guide is mostly about selection, and labels are the selection mechanism. It builds on Build a dataset from your sessions with labels; for the full skill command reference, see Skills from the CLI.
Curate with a second label while the work happens
When a session goes well, tag it in the moment. Use a skill: label alongside whatever intent label the session already carries:
paperctl label add <session-id> skill:cassettes-docs
The habit is the whole trick. A session where the workflow actually succeeded, where the agent found the right files, ran the right checks, and shipped, is obvious to the person who just ran it and invisible to everyone else a month later. The skill: label is a note you leave for the generator.
Because labels intersect, curation composes with the thread. decision:cassettes collects everything a decision caused; skill:cassettes-docs marks the subset worth learning from:
paperctl sessions list --label decision:cassettes --label skill:cassettes-docs --limit 200 --json
Wait for the thread to settle
Generate when the work has concluded, for two reasons. Late sessions are often the most instructive ones, the cleanup and the fix that finally worked, and a skill drafted mid-thread bakes in an approach the thread may still abandon. A simple test: the label has stopped collecting new sessions for a few weeks.
Generate from the curated set
Feed the curated ids to the generator in one call:
paperctl sessions list --label decision:cassettes --label skill:cassettes-docs --limit 200 --json \
| jq -r '.items[].id' \
| xargs paperctl skill generate --name cassettes-docs --type workflow --wait
A curated set is normally well under one page; if yours grows past 200 sessions, page through the list with the list_all helper from the dataset guide.
The stable skill behind --name is resolved, created on first use, and the generation is queued against it. The result lands as a new private revision; nothing is published by this command. --type accepts workflow, domain-knowledge, or prompt-template, and defaults to workflow.
Without --wait, the command prints a generation id you can check later:
paperctl skill status <generation-id>
Review, iterate, and sync
Pull the rendered draft into your local skills directory and read it the way you’d review a teammate’s PR. Generated drafts lift everything from their sessions, including local paths and project context you may not want to ship.
paperctl skill sync cassettes-docs
To iterate, generate again on top of the revision you liked, with more or better sessions:
paperctl skill generate --name cassettes-docs --base-revision <revision-id> <session-id>...
When the draft holds up, publish it in paper console so teammates can pull it. The full publishing walkthrough is in Publish your first skill.