skills/paper-cluster-by-theme/SKILL.md
Groups a set of kept papers into 2-5 thematic clusters before synthesis, using abstract semantics + matched-keyword overlap. Names each cluster with a short noun phrase that describes what the cluster argues, not just the topic. Surfaces an "outliers" bucket for single-paper themes that don't fit. Domain-neutral - usable for any literature-scan workflow. Use after relevance filtering and before writing the synthesis report. Trigger keywords - cluster papers, group by theme, thematic clusters, paper themes, organize papers.
npx skillsauth add lyndonkl/claude paper-cluster-by-themeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Take a list of relevance-filtered papers and produce thematic clusters that the synthesis layer can write about rather than list.
A "cluster" here is not a topic label — it's an argument. "Diffusion models for protein design" is a topic. "Diffusion models are converging on AlphaFold-comparable accuracy without MSAs" is a theme. The synthesis is much stronger when clusters describe what the papers collectively argue.
- [ ] Step 1: Read all kept papers' titles, abstracts, and matched keywords
- [ ] Step 2: Identify 2-5 candidate themes from the abstract content
- [ ] Step 3: Assign each paper to its best-fit theme (or to outliers)
- [ ] Step 4: Re-name each theme as an argument-shaped phrase
- [ ] Step 5: Validate clusters (no empty cluster, no over-stuffed cluster, no paper in two)
- [ ] Step 6: Return clusters + outliers + assignment rationale
Step 1 — Read inputs
The skill takes a list of records (the KEEP set from paper-relevance-filter). It needs id, title, abstract, and matched_keywords for each.
Step 2 — Candidate themes
Two signals to use, in order:
Aim for 2-5 clusters. Hard cap at 5 — beyond that, the synthesis layer cannot say anything coherent about each. If you have only 2-3 papers total and they don't form a theme, return one cluster called "Notable single papers" — do not force 3 clusters of 1.
Step 3 — Assign papers
Each paper goes to exactly one cluster (or outliers). When a paper plausibly fits two, choose the cluster where the paper's contribution (read from the abstract's last 1-2 sentences) is the better fit — not just where its keywords match. Note the alternative in also_fits.
Outliers: a paper with no good cluster fit. Do not exceed 3-4 outliers; if you have more, your clustering is too narrow — go back to Step 2 and split a cluster.
Step 4 — Argument-shaped names
Bad cluster names:
Good cluster names (argument-shaped):
A good name is a one-line argument the cluster collectively makes. If you can't write that argument because the papers in the cluster disagree, that's actually fine — name it as a tension: "Disagreement on whether X requires Y."
Step 5 — Validate
Reject and redo if:
Step 6 — Return
{
"clusters": [
{
"name": "Protein design moves from sequence-only to sequence+structure conditioning",
"rationale": "Three of the kept papers (P1, P2, P5) all argue that adding structural context at training time outperforms sequence-only baselines. P5 disagrees on the magnitude.",
"papers": ["10.1101/2026.05.07.123456", "PMID:39000001", "10.1101/2026.05.06.654321"],
"tension": "P5 reports smaller gains than P1; worth noting in synthesis."
},
{
"name": "Single-cell foundation models start releasing benchmarks, not just weights",
"rationale": "Two papers (P3, P7) release benchmark suites alongside the model.",
"papers": ["PMID:39000002", "10.1101/2026.05.05.111111"],
"tension": null
}
],
"outliers": [
{
"id": "PMID:39111222",
"rationale": "Single paper on cryo-EM segmentation; doesn't fit either cluster but matches watchlist."
}
],
"summary": {
"input_papers": 17,
"cluster_count": 3,
"outlier_count": 2,
"largest_cluster_size": 6,
"smallest_cluster_size": 3
}
}
Pattern A — Focused watchlist, week with 5-15 papers: typically 2-3 strong clusters + 1-2 outliers. The default.
Pattern B — Broad watchlist, week with 20+ papers: 4-5 clusters; cluster names get more specific (one keyword's worth each). Risk: cluster names become topic labels rather than arguments. Push back on yourself.
Pattern C — Thin week (3-5 kept papers): skip clustering. Return one cluster "Notable single papers" with all of them. The synthesis layer will write per-paper rather than per-theme.
Pattern D — Disagreement-heavy week: when 2+ papers in a cluster directly contradict each other on a finding, name the cluster as the tension and call this out in tension. The synthesis layer treats this as a high-value 30K-ft observation.
also_fits as a note, not as a duplicate assignment.rationale field that names which papers anchor the theme and how. Without it the synthesis writer has to re-derive your reasoning.| Cluster count | When | | ------------- | -------------------------------------------------- | | 1 | Thin week (≤ 5 papers, no real grouping) | | 2-3 | Default for focused weekly digest | | 4-5 | Broad watchlist or unusually busy week | | 6+ | Reject — merge until ≤ 5 |
| Naming test | Pass? | | ---------------------------------------------------------------- | ----- | | Is the name a noun phrase that could be a topic in a textbook? | FAIL | | Does the name name an argument or a tension? | PASS | | Could a reader predict the cluster's content from the name? | PASS | | Could you swap two clusters' names and have it still make sense? | FAIL — names are too generic |
testing
Cluster a conference's event records into a small set of coarse themes with finer sub-clusters, an explicit outlier bucket, and soft (multi-membership) affinities — using the hybrid embed-then-label pipeline (embed abstracts, reduce, density-cluster, then LLM-label the clusters) when embedding libraries are available, and an LLM-reasoned hierarchical fallback when they are not. Embeddings do the grouping; the LLM only names the groups. Conference-agnostic. Use when turning structured event records into a navigable theme map for preference elicitation and scheduling, when you need 6-8 reasonable themes rather than 20 muddy ones, or when overlapping talks must belong to more than one theme. Trigger keywords - theme clustering, cluster talks, embed then label, soft membership, outlier talks, conference themes, topic map.
development
Build a personal conference schedule as a constraint-optimization problem — hard constraints (no time overlap, room-to-room travel time, capacity/registration, the attendee's own must-attends and blackouts) plus a user-owned weighted objective trading interest against breadth, pacing (maximize contiguous free time), and serendipity. Surfaces unbreakable conflicts (two high-value overlapping talks the model cannot rank) as decisions for the human rather than silently picking, and reports what each choice traded away. Conference-agnostic. Use to turn a preference profile plus a theme map into a day-by-day plan, to resolve overlapping sessions, or to balance a packed vs paced schedule. Trigger keywords - schedule optimization, conference schedule, constraint optimization, overlapping talks, contiguous free time, conflict surfacing, packed vs paced.
development
Parse a heterogeneous conference program (markdown, HTML, PDF-derived text, or JSON) into normalized event records with per-field confidence scores and independent classification axes (topic, depth, format, prerequisites, recorded, capacity). Detects the program's format before extracting, treats every inferred field as uncertain (present vs inferred vs missing), and flags thin or missing abstracts so downstream enrichment can target them. Conference-agnostic. Use when ingesting a conference or event schedule into a structured store, normalizing a talk/session list, or extracting per-session metadata with calibrated confidence. Trigger keywords - program ingestion, parse schedule, session extraction, event records, conference program, talk metadata, per-field confidence.
development
Build a personalized preference profile from a small number of well-chosen, cluster-grounded questions instead of a long survey. Represents the person's interests as an uncertainty region over the theme map, picks the single highest-information-gain choice-based question (contrasting real talks from different clusters), balances exploiting known interests against exploring uncertain ones, deliberately injects outlier probes to fight selection bias, and stops as soon as the schedule would be stable. Also elicits the user-owned objective weights and hard constraints. Interactive — runs where it can actually ask the person. Conference-agnostic. Use to turn a theme map into a preference profile, to decide what to ask a conference attendee, or to elicit scheduling priorities. Trigger keywords - preference elicitation, ask few questions, information gain, choice-based questions, selection bias probe, objective weights, attendee preferences.