The Pain
There is a person in every good lab whom nobody quite knows how to replace. She is the one who decides that a taxi doing 78 miles an hour through Midtown is a GPS error and not a fast cab, and who can tell you why the cutoff is 65 and not 70 — it was 70 once, until the winter the tunnel data came in clean and proved otherwise. She reads a paper and, in four minutes, can say what identifies the effect and what would overturn it. When she critiques your design she asks the same three questions she always asks, and they are always the right three.
None of this is written down. It lives in her judgment, accreted over years, and it transfers exactly one way: by sitting next to her for a semester and absorbing it. When she graduates, the lab does not lose a pair of hands. It loses its method — the accumulated rulings about how this group reads, cleans, and argues. The next student rediscovers the 65-mph cutoff the hard way, by shipping an elasticity estimate inflated by phantom speed demons, and the adviser sighs the sigh of a man who has explained this before to people who are no longer here.
You are, this term, both the methodologist and her only apprentice. Every decision you make about this project is a small piece of method, and right now all of it lives in your head and your shell history, which is to say nowhere your future self can find it.
Why / When
The temptation is to read what follows as a macro system — a way to alias a long command to a short name. It is not, and the distinction is the whole lesson. The Goldsmith-Pinkham insight is that a skill is codified methodology, not a saved command. Writing one means teaching the agent your lab’s decision-making process: the thresholds together with the reasons they hold, the structure your group imposes on a paper, the questions your adviser cannot stop himself from asking. The numbers are the easy part; the rationales are the method, and the rationales are what a macro throws away.
Place the skill in the unit’s taxonomy — two of the three rows you now know, the third completed in C2:
| Mechanism | Nature | Runs |
|---|---|---|
| instruction file | always-on context | every session, as advice |
| skill | on-demand procedure | when invoked |
| hook | enforced rule | always, mechanically (C2) |
An instruction file is what the agent always knows; a skill is what it knows how to do when you ask. The cost model is the point of the middle row: a skill is invisible until invoked — its procedure does not crowd the context window every session, only when its moment comes. In the research pipeline, skills sit across the whole workflow — cleaning, reading, critiquing — wherever a decision recurs with a reason behind it. The role they absorb is the methodologist: her judgment, written down once, applied identically whether you invoke it on week three or hand the repo to a student in two years.
The three rows are a decision, not a hierarchy. Before the syntax, walk the choice on a piece of knowledge you actually have — the navigator returns the ruling the situation earns, including the honest “just run it” when codifying would cost more than rerunning:
You have a piece of lab knowledge to give the agent. Which of the three mechanisms should carry it? Answer for the knowledge in front of you — the taxonomy turns on how it runs, not how important it is.
Contrary winds
Not for: a one-off transformation you will run once and never explain to anyone — codifying it costs more than rerunning it; a skill is for judgment you will reuse, not a command you will forget.
Mechanics
A skill is a Markdown file with frontmatter. The shared anatomy first, then the two dialects, then the three skills the project actually needs.
Anatomy of a skill
Every skill is one file with two parts. The frontmatter carries a
name and — load-bearing — a description. The body is the
procedure: prose, steps, code, the rationales. The description is not a
label; it is the trigger the agent matches your request against to
decide whether this skill applies. Write it as the answer to “when
should you reach for this,” not as a title.
---name: clean-tripsdescription: >- Apply the lab's taxi-trip cleaning SOP — documented filters with rationales, emitting a filter-cascade table. Use whenever raw TLC trip data is loaded and needs to become an analysis-ready table.---
## When to useRaw monthly TLC parquet has been ingested and must be filtered toanalysis-ready trips, with every dropped row counted and justified.
## Procedure1. … (the steps, with thresholds AND the reason each holds)The key property is progressive disclosure: the body costs nothing until the description matches and the skill is invoked. You can keep a shelf of twenty skills and pay for none of them until their moment arrives — which is exactly why a skill, not the instruction file, is where a long procedure belongs.
Where skills live and how you invoke them
The file format is identical across both tools; the directory and the invocation token differ.
Claude Code
A skill is a SKILL.md under .claude/skills/<name>/, committed with
the repo so it arrives with the clone. You invoke it by its name as a
slash command — authoring clean-trips gives you /clean-trips:
.claude/skills/├── clean-trips/SKILL.md → invoke /clean-trips├── paper-summary/SKILL.md → invoke /paper-summary└── demanding-adviser/SKILL.md → invoke /demanding-adviserBecause the directory is committed, the method travels with the project: a collaborator who clones the repo inherits your cleaning SOP, your reading template, and your adviser’s three questions, with no hand-off conversation. The skill is the hand-off conversation, frozen.
Codex
A skill is a SKILL.md under .agents/skills/<name>/, committed with
the repo. You invoke it by name with a leading sigil — authoring
clean-trips gives you $clean-trips:
.agents/skills/├── clean-trips/SKILL.md → invoke $clean-trips├── paper-summary/SKILL.md → invoke $paper-summary└── demanding-adviser/SKILL.md → invoke $demanding-adviserThe directory follows the agentskills.io open standard — the same
on-disk shape other agent runners read, so a skill you author here is
not locked to one vendor. If you would rather not hand-write the
frontmatter, the bundled $skill-creator interviews you about the
procedure and scaffolds a conforming SKILL.md; treat its output as a
first draft of method, not the method itself.
Three skills, one per archetype
The project needs exactly three skills to start, and they are deliberately different kinds of method: a procedure, a piece of scholarship, a unit of judgment. Author all three in both dialects from the same policy notes; the bodies are identical, only the directory and invocation differ.
/clean-trips — a procedure with rationales
The cleaning SOP is where the methodologist’s judgment is densest. It
runs on the raw monthly trip parquet — the fixed course slice you fetched
with the kit’s python3 get_data.py (Get the data). The
SKILL.md does not say “drop fast trips”; it says which speed, why
that number, and demands the dropped count be reported — so the filter
cascade becomes the report’s data appendix instead of a forgotten
command. The filters are statistics, so the body’s reference
implementation comes in both of the lab’s languages:
Python
import duckdb
# Each filter is a (predicate, rationale) pair. The rationale is the# method; the predicate is just how the method is spelled in SQL.FILTERS = [ ("fare_amount >= 0", "negative fares are voided transactions, not trips — drop and count"), ("trip_distance > 0 AND tpep_dropoff_datetime > tpep_pickup_datetime", "zero-distance / non-positive-duration rows are meter glitches"), ("trip_distance / (epoch(tpep_dropoff_datetime - tpep_pickup_datetime)/3600.0) " "< 65 OR borough <> 'Manhattan'", "speed > 65 mph in Manhattan is a GPS error, not a fast cab — " "the cutoff was 70 until the clean-tunnel winter proved 65"),]
con = duckdb.connect("warehouse.duckdb")cascade, surviving = [], "trips_raw"for i, (pred, why) in enumerate(FILTERS): n = con.sql(f"SELECT count(*) FROM ({surviving}) t WHERE {pred}").fetchone()[0] cascade.append((i, why, n)) # the audit trail, row by row surviving = f"SELECT * FROM ({surviving}) t WHERE {pred}"
con.sql(f"CREATE OR REPLACE TABLE trips_clean AS {surviving}")for i, why, n in cascade: print(f" filter {i}: {n:>12,} survive — {why}")This block is orchestration, not statistics — it’s the same in R. Ask the agent to translate (Lesson A1).
R
library(duckdb)
# Each filter is a (predicate, rationale) pair. The rationale is the# method; the predicate is just how the method is spelled in SQL.filters <- list( c("fare_amount >= 0", "negative fares are voided transactions, not trips — drop and count"), c("trip_distance > 0 AND tpep_dropoff_datetime > tpep_pickup_datetime", "zero-distance / non-positive-duration rows are meter glitches"), c(paste("trip_distance / (epoch(tpep_dropoff_datetime - tpep_pickup_datetime)", "/3600.0) < 65 OR borough <> 'Manhattan'"), paste("speed > 65 mph in Manhattan is a GPS error, not a fast cab —", "the cutoff was 70 until the clean-tunnel winter proved 65")))
con <- dbConnect(duckdb(), "warehouse.duckdb")surviving <- "trips_raw"for (i in seq_along(filters)) { pred <- filters[[i]][1]; why <- filters[[i]][2] n <- dbGetQuery(con, sprintf( "SELECT count(*) FROM (SELECT * FROM %s) t WHERE %s", surviving, pred))[[1]] cat(sprintf(" filter %d: %12s survive — %s\n", i, format(n, big.mark = ","), why)) # the audit trail surviving <- sprintf("SELECT * FROM (%s) t WHERE %s", surviving, pred)}dbExecute(con, sprintf("CREATE OR REPLACE TABLE trips_clean AS %s", surviving))Read the comments, not the SQL: a new RA who runs this learns why 65, not merely that 65. That is the difference between a skill and an alias. In C2 this exact procedure runs under an enforced contract — the skill encodes the method, the hook removes the option of skipping it.
/paper-summary — scholarship with a fixed shape
The lit-review workhorse for D1 and F1. Its method is a structure: the six things your group reads every paper for, in the same order, so two summaries are comparable and a related-work section assembles itself. The skill’s body is mostly the template and the rule that every field cite a page.
## ProcedureRead the paper and emit exactly these six fields, one page total.Cite a page or section for every empirical claim — no field may befilled from the abstract alone.
1. **Question** — what causal or descriptive question, stated in one sentence.2. **Identification** — what variation identifies the effect; the key assumption.3. **Data** — source, unit, period, sample size, notable construction choices.4. **Findings** — the headline estimate with its sign, magnitude, and precision.5. **Limitations** — what the authors concede, plus one they don't.6. **Relation to ours** — does it support, complicate, or supersede our design./demanding-adviser — judgment, written as questions
The hardest archetype to codify and the most valuable. It carries no procedure to run; it carries your adviser’s stance — the skeptical questions a good critique always asks of a research design. Used on your own design in D1, and the seed that becomes the adversarial referee in D4 and F1.
## ProcedureCritique the supplied research design as a demanding but fair adviser.Be specific to THIS design — never generic. For each issue, name thethreat and what evidence would resolve it. Always ask, at minimum:
- **What is the identifying variation?** Name it. If it is "weather," what makes it as-good-as-random conditional on the controls?- **What would falsify this?** State the result that, if found, would sink the claim — and whether the design can produce it.- **Where does leakage hide?** Post-treatment controls, full-series rolling statistics, random CV where the data are temporal.
Rank the three most serious objections. Do not soften them.Writing skills that work
Four rules, learned the hard way, that separate a skill from a wish:
- The description is an interface. A vague description never triggers, or triggers always; either way the agent’s judgment about when to use the skill is only as good as the sentence you wrote. Describe the situation, not the skill.
- Checkable steps over vibes. “Clean the data sensibly” is not a
method. “Drop
fare_amount < 0, report the count” is. If a step cannot be checked, it cannot be transferred. - Demand evidence in the output. A skill that emits a cascade table, a cited summary, a ranked objection list produces something you can audit. One that emits a paragraph of reassurance produces compliance without judgment.
- Version skills like code; review them like protocols. They drift from actual lab practice the same way a lab manual does. Re-read them quarterly, and test a skill the way you test a function — run it on a known input and check the output is the method you meant.
Field Assignment
Artifact make check-c1 passes
Build the methodologist into the repo. Author all three skills in both
dialects from one set of policy notes, then put two of them to work —
/paper-summary on real papers, the adviser on your own brief.
Claude Code
- Author
clean-trips,paper-summary, anddemanding-adviserunder.claude/skills/<name>/SKILL.md, each with a description written as a trigger and a body carrying thresholds with rationales. - Run
/clean-tripson one month and confirm the filter cascade table prints a count and a reason per filter. - Run
/paper-summaryon two related papers from the project’s reading list; check every field cites a page, none from the abstract. - Run
/demanding-adviseronreport/brief.mdand log its three hardest questions — verbatim — injournal/c1-adviser.md, marking the one you cannot yet answer. make check-c1.
Codex
- Author
clean-trips,paper-summary, anddemanding-adviserunder.agents/skills/<name>/SKILL.md, each with a description written as a trigger and a body carrying thresholds with rationales. - Run
$clean-tripson one month and confirm the filter cascade table prints a count and a reason per filter. - Run
$paper-summaryon two related papers from the project’s reading list; check every field cites a page, none from the abstract. - Run
$demanding-adviseronreport/brief.mdand log its three hardest questions — verbatim — injournal/c1-adviser.md, marking the one you cannot yet answer. make check-c1.
make check-c1 verifies the three skills exist with non-empty
descriptions, that /clean-trips emits a cascade with one rationale per
filter, and that journal/c1-adviser.md records three adviser
questions. The cleaning skill feeds straight into C2, where it runs
under contract; the adviser feeds D1 and is sharpened into D4’s referee.
make check-c1advances C1/clean-trips (procedure), /paper-summary (scholarship), /demanding-adviser (judgment).
speed > 65 mph in Manhattan = GPS error; negative fare = voided transaction — drop and count.
The description is the interface the agent matches against; vague descriptions never fire.
Question, identification, data, findings, limitations, relation to our project.
What is the identifying variation? What would falsify this? Where does leakage hide?
Check each item only once it is true of YOUR repo — the gate is self-certified, like the rest of your methodology.
Pitfalls & Gotchas
- [both]
〜〜
Skills without rationales produce compliance without judgment. An RA who runs a
/clean-tripsthat only says “drop speed > 65” learns a number; one who reads “the cutoff was 70 until the clean-tunnel winter proved 65” learns the method, and knows when to revisit it. The rationale lines are the only part that transfers — strip them and you have written an alias, not a skill. - [both]
Vague descriptions never trigger, or always do — the description is the interface, not a label. “Helps with data” matches everything and nothing; “apply the TLC cleaning SOP when raw trip parquet is loaded” matches exactly its moment. Write the description for the agent’s matching decision, not for a human skimming a list.
- [both]
〜〜
Un-reviewed skills drift from actual lab practice. The cutoff moves, a new schema arrives, the adviser starts asking a fourth question — and the SKILL.md still encodes last year’s method, applied at machine speed and machine confidence. Review them quarterly, like a protocol, and re-run them on a known input to confirm the output is still the method you meant.
- [CX]
Legacy
~/.codex/promptsstill work, but they are superseded by the.agents/skills/standard. A prompt is per-user and invisible to the repo; a skill is committed and travels with the clone. Migrate old prompts into skills so the method ships with the project, not with your laptop.
Check Your Bearings
- Question 1Choose one
Your
/clean-tripsskill drops Manhattan trips faster than 65 mph. A new RA clones the repo and runs it. What does a well-written skill transfer that a saved command would not? - Question 2Match the dialects
Match each mechanism to when it runs. This is the unit's taxonomy — two rows now, the third in C2.
instruction fileskillhook - Question 3Choose onedialect check — Claude Code
You author
.claude/skills/clean-trips/SKILL.mdbut itsdescriptionreadsHelps with data cleaning. You run/clean-tripsand it fires fine — yet later the agent never reaches for it on its own. Why? - Question 4Choose onedialect check — Codex
You have the cleaning SOP as a
~/.codex/promptsentry from last term. A collaborator clones the repo and cannot find it. What is the fix?
Field journal
Parity note
Skills are a clean parity feature: both tools read an identical
SKILL.md (frontmatter name + description-as-trigger, Markdown body)
and offer progressive disclosure, differing only in directory and
invocation token — .claude/skills/ with /name on one side,
.agents/skills/ with $name on the other. Codex’s directory follows
the agentskills.io open standard and ships a $skill-creator
scaffolder; Claude Code has no first-party scaffolder but the format is
the same, so a hand-authored skill is portable either direction. The
real asymmetry is upstream of the file: Codex still honors legacy
~/.codex/prompts, a per-user surface with no Claude Code analogue and
no reason to prefer it over a committed skill.