Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generate a citable data dictionary / codebook from a tabular dataset (CSV/TSV/Excel/Parquet/Stata/SAS). Profiles every variable — role, type, units placeholder, level frequencies, range/quantiles, missingness — and emits codebook.md + codebook.json. Flags coded variables whose level meanings are unknown as [NEEDS DICTIONARY] rather than guessing them, feeding /define-variables and the dictionary-first workflow.
.claude/skills/aperivue-generate-codebook/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 69% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 75% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 34% | 0% |
You help a medical researcher turn a raw tabular dataset into a structured, citable data dictionary (codebook). This is the generator side of the dictionary-first workflow: it produces the artifact that /define-variables and dictionary-first QC later consume. You generate code and review output — you do not invent the meaning of coded values.
A codebook describes what is in the data, not what the codes mean. Column distributions, types, and missingness are observable and safe to profile. The meaning of a coded value (fatty_liver_grade = 0) is NOT observable from the data — it lives in the authoritative data dictionary. This skill profiles the former deterministically and explicitly flags the latter as [NEEDS DICTIONARY] so a human fills it from the source. This is the generator counterpart to the dictionary-first rule that /define-variables enforces on consumption.
${CLAUDE_SKILL_DIR}/references/codebook_schema.md — thecodebook.json schema, the role-inference heuristics, and how the output threads into /define-variables and dictionary-first QC. Read this before interpreting output.
Run the bundled profiler rather than describing columns from memory:
bashpython "${CLAUDE_SKILL_DIR}/scripts/generate_codebook.py" data.csv --out-dir .
Supports .csv/.tsv/.xlsx/.parquet/.dta/.sas7bdat. Flags: --max-levels N (categorical cutoff, default 20), --json-only, --md-only. The script is pandas-only, runs locally, and never sends data anywhere.
Run generate_codebook.py on the dataset. It writes codebook.json (machine- readable) and codebook.md (review table), reporting per variable: role (id / continuous / categorical / binary / date / text), dtype, missingness, unique count, level frequencies or quantile summary, and a needs_dictionary flag.
Present codebook.md and walk the user through it. Gate: the user confirms the inferred roles (e.g., an integer-coded scale mis-read as continuous, or an id column). Do not proceed to definition work until the user approves the role assignments.
For every variable flagged needs_dictionary: true, the level codes are uninterpretable without the authoritative source. Gate: ask the user to supply the meaning of each code from the real data dictionary (file/sheet/row), or to confirm none exists. Fill label, units, and per-level meanings into the codebook only from that source — never from inference. If the user cannot supply it, leave the [NEEDS DICTIONARY] marker in place; do not erase it.
The completed codebook.json becomes the input dictionary for /define-variables (operationalization) and the citation source for dictionary-first QC. Gate: confirm with the user that no needs_dictionary flags remain unresolved before the codebook is treated as authoritative for downstream analysis.
.dta), SAS (.sas7bdat).[NEEDS DICTIONARY])./clean-data./deidentify before sharing./define-variables (this skill feeds it).codebook.json as its data dictionary input.codebook.json (schema in references) and codebook.md (review table with a "Columns requiring dictionary lookup" section). Summarize the counts (rows, columns, needs_dictionary_count) in chat; do not paste the full JSON.
Input cohort.csv:
textpatient_id,age,sex,fatty_liver_grade,smoking_status,visit_date 1001,54,1,0,never,2023-01-15 1002,61,2,2,former,2023-02-03
Run:
bashpython "${CLAUDE_SKILL_DIR}/scripts/generate_codebook.py" cohort.csv --out-dir . # -> {"n_rows": ..., "n_columns": 6, "needs_dictionary_count": 2, "outputs": [...]}
codebook.md (excerpt):
text| Variable | Role | Missing % | Unique | Needs dictionary | | `patient_id` | id | 0.0 | N | | | `age` | continuous | 0.0 | ... | | | `sex` | binary | 0.0 | 2 | ⚠️ YES | | `fatty_liver_grade` | categorical | 0.0 | 5 | ⚠️ YES | | `smoking_status` | categorical | 0.0 | 3 | | | `visit_date` | date | 0.0 | ... | |
sex and fatty_liver_grade are flagged because their levels are bare codes (1/2, 0..4). smoking_status is not flagged — its levels are already human-readable. The reviewer then:
sex: 1 = male, 2 = female and fatty_liver_grade: 0 = none … 4 = suspectedinto the codebook from that source (citing file > sheet > row).
[NEEDS DICTIONARY] flags remain, then hands codebook.json to/define-variables.
What the skill must never do: write sex: 1 = male because "that is the usual coding." If the dictionary is unavailable, the flag stays.
[NEEDS DICTIONARY];the meaning is filled only from the authoritative data dictionary, then cited.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 25,956 | 14,334 | -45% | 1 | 1 | 0% | 6,232 | 2,029 | -67% | 0 | 0 | — |
case-02 | fail→fail | 9,544 | 5,557 | -42% | 1 | 1 | 0% | 1,874 | 1,999 | +7% | 0 | 0 | — |
case-03 | fail→fail | 29,618 | 3,238 | -89% | 1 | 1 | 0% | 6,223 | 2,096 | -66% | 0 | 0 | — |
case-04 | fail→pass | 7,144 | 2,743 | -62% | 1 | 1 | 0% | 1,333 | 2,251 | +69% | 0 | 0 | — |
case-05 | fail→pass | 12,801 | 4,130 | -68% | 1 | 1 | 0% | 1,988 | 2,416 | +22% | 0 | 0 | — |
case-06 | fail→fail | 11,589 | 8,404 | -27% | 1 | 1 | 0% | 2,298 | 2,121 | -8% | 0 | 0 | — |
case-07 | fail→pass | 8,512 | 6,341 | -26% | 1 | 1 | 0% | 1,649 | 2,887 | +75% | 0 | 0 | — |
case-08 | pass→pass | 4,185 | 5,247 | +25% | 1 | 1 | 0% | 829 | 2,674 | +223% | 0 | 0 | — |
case-09 | fail→pass | 7,077 | 4,102 | -42% | 1 | 1 | 0% | 1,301 | 2,424 | +86% | 0 | 0 | — |
case-10 | fail→pass | 9,226 | 1,969 | -79% | 1 | 1 | 0% | 1,568 | 2,094 | +34% | 0 | 0 | — |
case-11 | fail→pass | 6,935 | 2,183 | -69% | 1 | 1 | 0% | 1,093 | 2,052 | +88% | 0 | 0 | — |
case-12 | pass→pass | 5,179 | 5,450 | +5% | 1 | 1 | 0% | 1,010 | 2,751 | +172% | 0 | 0 | — |
case-13 | fail→pass | 11,567 | 7,387 | -36% | 1 | 1 | 0% | 1,783 | 2,799 | +57% | 0 | 0 | — |
case-14 | fail→pass | 9,889 | 6,010 | -39% | 1 | 1 | 0% | 1,626 | 2,689 | +65% | 0 | 0 | — |
case-15 | pass→pass | 10,865 | 5,985 | -45% | 1 | 1 | 0% | 1,718 | 2,744 | +60% | 0 | 0 | — |
case-16 | fail→pass | 10,784 | 1,799 | -83% | 1 | 1 | 0% | 1,635 | 1,995 | +22% | 0 | 0 | — |
case-17 | fail→pass | 12,027 | 3,945 | -67% | 1 | 1 | 0% | 1,870 | 2,333 | +25% | 0 | 0 | — |
case-18 | fail→pass | 9,228 | 1,978 | -79% | 1 | 1 | 0% | 1,520 | 2,078 | +37% | 0 | 0 | — |
case-19 | fail→pass | 11,370 | 8,300 | -27% | 1 | 1 | 0% | 1,796 | 2,955 | +65% | 0 | 0 | — |
case-20 | fail→pass | 8,156 | 6,668 | -18% | 1 | 1 | 0% | 1,341 | 2,927 | +118% | 0 | 0 | — |
case-21 | pass→pass | 12,993 | 5,984 | -54% | 1 | 1 | 0% | 2,112 | 2,626 | +24% | 0 | 0 | — |
case-22 | fail→pass | 9,062 | 8,816 | -3% | 1 | 1 | 0% | 1,377 | 2,724 | +98% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +64 percentage points is the difference between those two pass rates over the 20 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.