Holubar Lab — Research Toolkit
Vibe Coding — A Primer for Clinicians
A working definition + the lab's workflow for letting LLMs write your analysis code while keeping your fingerprints on every result. Companion to the Python Biostats Cheatsheet.
Working definition. Vibe coding is a coding workflow in which you describe what you want in natural language and let an LLM write the code, while you stay in the driver's seat — reading every line, running it, and iterating in conversation. It's not "the AI did it for me." It's "I directed the AI; I own the result." The clinician supplies the question, the domain judgment, and the QC. The LLM supplies the syntax and the boilerplate.
TL;DR for the impatient. Vibe coding is fastest when (a) you can describe the analysis in clinical language, (b) you can read code well enough to spot wrong answers, and (c) you treat the LLM as a junior coauthor whose draft you redline. The lab's default stack is Python (see the cheatsheet) — LLMs are dramatically more fluent in Python than R, and the gap matters in practice.
Why this works for biostats specifically
- Clinical analyses are mostly boilerplate. Cox regression, GEE with site clustering, propensity-score IPTW, Kaplan-Meier with at-risk counts, AMA-style Table 1 — these are repeatable patterns. LLMs have seen them all. The LLM is a vastly better typist than you; your value is in the design and interpretation.
- The output is verifiable. A regression coefficient is either right or wrong. You spot-check it against known reference cases (Leeds 2022 ICER, a published HR, Drummond textbook examples). If the LLM hallucinates a function, the script throws. If it picks the wrong family or link, the coefficient looks bizarre and you catch it.
- The LLM scales your boilerplate skill, not your judgment. Choosing whether to use a competing-risks model or a cause-specific Cox model is a clinical-statistical decision. The LLM can recommend, but you decide. Vibe coding compresses the implementation time so you spend more cycles on the choice and less on the typing.
The lab loop — 5 steps
- Describe the analysis in plain English. Be specific about cohort, exposure, outcome, covariates, clustering, sensitivity analyses. "Cox model for time-to-pouch-failure, stratified by IBD diagnosis, clustering by surgeon, with age + BMI + ASA as covariates. Report HR with 95% CI."
- Hand the LLM the data shape. Paste
df.head().to_string()+df.dtypes. The LLM needs column names + types to write working code. (Privacy note: schema only, never PHI.) - Read the generated code before you run it. Every line. If a line is opaque, ask the LLM to explain it. If it picks an idiom you don't recognize, ask why it chose that over the alternative. Vibe coding is not blind execution; it's fast paired programming with a junior coauthor who never sleeps.
- Run, eyeball the output, iterate in conversation. "The HRs look directionally right but the CI is wide for the pediatric subgroup — is the model converging? Show me the model summary." → LLM revises. Five rounds of this beats 30 minutes of solo debugging.
- Cascade through the deliverables. Once the analysis is right, ask the LLM to: regenerate the Table 1, update the manuscript's Results paragraph, produce a TIFF figure. The lab's cascade rule (CORS Research SOP) treats Code → JSON → Notebook → Memo → Manuscript → Figures as one update pass.
Tooling — what the lab actually uses
- Claude Code (CLI) — the lab's daily driver. Runs locally, edits files in place, executes Python. Best for analyses where you want the model to actually run the code, see the output, and iterate. claude.com/claude-code
- Claude Desktop — for chat-style exploration, RAG queries (Odin/Pouchology), one-off analyses. Same model family; different surface.
- Cursor — for fellows who prefer a VS Code interface with inline AI. Same vibe-coding pattern; different UX.
- Anthropic API direct — for production pipelines (Acceptance Calc, CORS RAG, Pouchology RAG). The lab's tools use Sonnet 4.6 for structured judgment and Opus 4.8 for prose/heavy-judgment work.
Do / Don't
✓ Do
- Describe the analysis in clinical terms first; let the LLM translate to code
- Paste the data schema (columns + dtypes) — schema only
- Read every generated line before running
- Spot-check against a known reference case (Leeds 2022, a published HR, etc.)
- Ask "why this choice over the alternative?" when an idiom is unfamiliar
- Use Python by default; reach for R only via
rpy2fornetmeta/BCEA - Re-prompt with the actual error message — the model debugs faster than you
- Save the prompt as well as the code (a script + a
.prompt.mdbeside it)
✗ Don't
- Paste PHI into a prompt — schema only, never patient-level data unless the tool is HIPAA-cleared (it isn't, yet)
- Run code you haven't read
- Trust the LLM's clinical judgment on study design — that's your job
- Accept a "this works" without spot-checking a number against a known truth
- Let the LLM pick the statistical framework alone (causal? hierarchical? Bayesian?) — describe the constraints, you decide
- Ship code with comments like
# LLM-generated, didn't read - Use R for new analyses unless you have a specific reason (legacy code, netmeta, BCEA, biostatistician preference)
Pitfalls — where vibe coding fails
- Hallucinated functions. LLM invents
statsmodels.api.cox()(doesn't exist). The script crashes — you catch it fast. The cost is one extra round-trip, not a wrong answer. - Wrong default link / family. Logistic where you wanted Poisson; Gaussian where you wanted log-link. The coefficient looks weird — you catch it on spot-check. If you don't spot-check, you ship a wrong number. This is the highest-risk failure mode.
- Subtly wrong filtering. LLM applies a filter you didn't ask for ("excluding emergencies" implied from the abstract you pasted). The N changes; you don't notice. Always print
df.shapeand the filter steps. - Drift from canonical conventions. LLM produces a table with comma-as-decimal or 4-decimal p-values. Push back with the
statistical-output.mdconventions or a one-liner prompt suffix: "format per Holubar Lab conventions: 2-sig-non-zero-decimal p-values, en-dash CIs." - "Looks plausible, isn't." The cardinal sin. The script runs, the numbers are reasonable, the figure looks like a paper, but the math is subtly wrong. Defense: always run the same analysis with a fully-different method as a sanity check. If the IPTW result and the GEE result are within rounding, you're good. If they diverge by 30%, one of them is wrong — investigate.
What to read for the fellow's first week
- Python Biostats Cheatsheet — the lab's stack + idiomatic patterns
- CORS Research SOP — the cascade rule and deliverables structure
- R Cheatsheets — for the legacy R scripts you'll encounter
- Research Methods & Epidemiology — methods papers (propensity scores, cluster RCTs, EHR re-use)
- Anthropic — Agentic safety research — read once, so you understand the tradeoffs in trusting an LLM
Lab opinion — codified
Vibe coding is a multiplier on clinical and statistical thinking, not a replacement for it. The fellow who reads their generated code carefully and spot-checks against reference cases ships better analyses faster than the fellow who hand-writes everything. The fellow who runs LLM output without reading it ships wrong answers faster. The difference is judgment, and judgment is what we hire for.
This page will evolve. If you find an LLM pattern that works well — or one that fails subtly — flag it to Stefan and we'll add it.
Suggestions, war stories, lessons learned:
webmaster@holubarlab.org