Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ title: Craig T. Russell, PhD
theme: minima
markdown: kramdown

# Header nav: only these pages (index.md keeps its long job title for the page and the PDF)
header_pages:
- vibe.md
- vibe-coding.md

# Minima settings
minima:
skin: auto # Automatically switches between light and dark mode
Expand Down
9 changes: 5 additions & 4 deletions assets/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

@import "minima";

/* The CV's job title, a paragraph marked <p class="jobtitle"> at the top of index.md */
.jobtitle { font-size: 1.125em; color: #555; margin-bottom: 0.5em; }

/* Print: a compact A4 CV when the page is printed or saved as PDF from the browser */
@page { size: A4; margin: 10mm 13mm; }

Expand All @@ -16,10 +19,8 @@
.site-header { border: 0; min-height: 0; margin-bottom: 2mm; }
.site-title { float: none; display: block; font-size: 17pt; font-weight: 700;
line-height: 1.2; color: #111; letter-spacing: 0; }
.site-nav { float: none; position: static; border: 0; background: none; line-height: 1.3; }
.site-nav label, .site-nav .nav-trigger { display: none; }
.site-nav .trigger { display: block; }
.site-nav .page-link { display: block; font-size: 10.5pt; color: #444; margin: 0; }
.site-nav { display: none; }
.jobtitle { font-size: 10.5pt; color: #444; margin: 0 0 1.5mm; }
.site-footer { display: none; }

.page-content { padding: 0; }
Expand Down
2 changes: 2 additions & 0 deletions cv-print.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ h1.title { font-size: 17pt; margin: 0 0 1mm; text-align: left; }
p.subtitle { font-size: 10.5pt; color: #444; margin: 0; text-align: left; }
/* Keep a role heading (the paragraph before its bullets) on the same page as them. */
p:has(+ ul) { break-after: avoid; }
/* pandoc already prints the job title as the document subtitle */
.jobtitle { display: none; }
2 changes: 2 additions & 0 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: Senior Machine Learning Scientist, generative and agentic models for biol
layout: default
---

<p class="jobtitle">Senior Machine Learning Scientist, generative and agentic models for biology</p>

London, UK • [linkedin.com/in/ctr26](https://linkedin.com/in/ctr26) • [github.com/ctr26](https://github.com/ctr26) • [Google Scholar](https://scholar.google.com/citations?user=XVt7BYQAAAAJ&hl=en)
Generative and agentic models for biology • LLM post-training • out-of-distribution modelling • virtual cells

Expand Down
113 changes: 57 additions & 56 deletions vibe-coding.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,71 @@
---
layout: page
title: Vibe Coding for Scientists
layout: default
permalink: /vibe-coding/
description: A practical guide to coding with Claude Code as a research scientist; setup, CLAUDE.md, workflows for ML, data analysis, and pipelines, and the pitfalls.
---

You're a scientist, not a software engineer — but you write a lot of code. Data pipelines, analysis scripts, ML experiments, plotting, glue code between tools that were never meant to talk to each other. Most of it is means to an end: you care about the *result*, not the code itself.
# Vibe Coding for Scientists

**Vibe coding** is the practice of using AI to write code by describing what you want in natural language, iterating conversationally, and staying in the driver's seat on the science while the AI handles implementation details. Think of it as pair programming with a colleague who types fast, knows every API, and never gets annoyed when you change your mind.
You're a scientist, not a software engineer, but you write a lot of code. Data pipelines, analysis scripts, glue between tools that were never meant to talk to each other. Most of it is a means to an end; you care about the result, not the code.

I've been using [Claude Code](https://docs.anthropic.com/en/docs/claude-code) — Anthropic's CLI coding agent — as my primary vibe coding tool. This page is a practical guide to getting started, shaped by my experience building ML pipelines, bioimage analysis tools, and foundation models.
Vibe coding, in the sense I mean here, is using an AI to write code by describing what you want in plain language, iterating conversationally, and staying in the driver's seat on the science while the AI handles implementation. Karpathy's original sense was closer to "forget the code exists"; for science I mean something more careful, and the pitfalls below say why. Think of it as pair programming with a colleague who types fast and never minds when you change your mind.

## Why This Matters for Scientists
I've been using [Claude Code](https://code.claude.com/docs), Anthropic's CLI coding agent, as my main tool for this. This page is a practical guide to getting started, shaped by building ML pipelines, bioimage analysis tools, and foundation models with it. How I run a repository more generally is on [How I Work](/vibe/).

Most scientists I've worked with (myself included) fall into a gap: we know enough to code, but not enough to be *fast*. We lose hours to:
## Why this matters for scientists

- Debugging environment issues and dependency conflicts
- Remembering the right pandas/numpy/scipy incantation
- Writing boilerplate (argparse, logging, config files, plotting)
- Translating a method from a paper into working code
- Refactoring a Jupyter notebook into something reproducible
Most scientists I've worked with, myself included, know enough to code but not enough to be fast. We lose hours to

These are exactly the tasks where AI assistants excel. The science — experimental design, hypothesis formation, interpreting results, knowing what to compute and why — that's still entirely you. Vibe coding lets you spend more time on the parts that require your domain expertise.
- debugging environment issues and dependency conflicts,
- remembering the right pandas, numpy, or scipy incantation,
- writing boilerplate (argparse, logging, config files, plotting),
- translating a method from a paper into working code, and
- refactoring a Jupyter notebook into something reproducible.

## Getting Started with Claude Code
These are exactly the tasks an AI assistant is good at. The science, which is to say the experimental design and knowing what to compute and why, is still entirely you. Vibe coding lets you spend more of your time there.

## Getting started with Claude Code

### Install

```bash
# Install Claude Code CLI
npm install -g @anthropic-ai/claude-code
# Native installer (or: brew install claude-code, or npm install -g @anthropic-ai/claude-code)
curl -fsSL https://claude.ai/install.sh | bash

# Start a session in your project directory
cd my-research-project/
claude
```

### Basic Patterns
### Basic patterns

Once you're in a session, you just talk:
Once you're in a session, you just talk.

- *"Read the CSV in data/results.csv and plot a violin plot of column 'expression' grouped by 'treatment'"*
- *"This script is too slow — profile it and suggest optimisations"*
- *"This script is too slow; profile it and suggest optimisations"*
- *"Write a Snakemake rule that runs this analysis for each sample in the manifest"*
- *"Refactor this notebook into a CLI script with proper argument parsing"*

Claude reads your files, understands your project structure, writes code, runs it, and iterates based on errors or your feedback. You stay in the loop at every step — approving changes, correcting course, adding constraints.
Claude reads your files, understands your project structure, writes code, runs it, and iterates on the errors or your feedback. You stay in the loop at every step, approving changes, correcting course, and adding constraints.

### The Conversational Loop
### The conversational loop

The power is in the iteration. A typical flow looks like:
The power is in the iteration. A typical flow runs

1. **Describe** what you want at a high level
2. **Review** the proposed code — does it match your scientific intent?
3. **Run** it — Claude can execute code and see the output
4. **Refine** — "actually, use log scale on the y-axis" or "filter out controls first"
5. **Commit** when you're happy
1. **Describe** what you want at a high level.
2. **Review** the proposed code. Does it match your scientific intent?
3. **Run** it. Claude can execute code and see the output.
4. **Refine** with "actually, use log scale on the y-axis" or "filter out controls first".
5. **Commit** when you're happy.

This is faster than writing code from scratch *and* faster than searching Stack Overflow, because the AI has full context of your project.
This is faster than writing from scratch and faster than searching Stack Overflow, because the AI reads the parts of your project it needs as it goes.

## The CLAUDE.md File: Teaching Claude Your Project
## Teaching Claude your project with CLAUDE.md

The single most impactful thing you can do is add a `CLAUDE.md` file to your repo root. This is a plain Markdown file that Claude reads at the start of every session. Think of it as onboarding notes for a new lab member.
The single most useful thing you can do is add a `CLAUDE.md` file to your repository root. It is a plain Markdown file that Claude reads at the start of every session. Think of it as onboarding notes for a new lab member.

A good scientific `CLAUDE.md` includes:
A good scientific `CLAUDE.md` looks something like this.

```markdown
# CLAUDE.md
Expand Down Expand Up @@ -91,62 +94,60 @@ The main analysis pipeline is in `src/pipeline.py`.
- Don't modify anything in `src/legacy/` — it's kept for reproducibility
```

This context makes Claude dramatically more useful. Instead of generic Python, it writes code that fits *your* project.
With that context Claude writes code that fits your project instead of generic Python.

## Workflows That Work
## Workflows that work

### Prototyping ML Experiments
### Prototyping ML experiments

This is where I get the most value. Instead of writing training loops from scratch:
This is where I get the most value. Instead of writing a training loop from scratch, I ask for it.

*"Set up a PyTorch Lightning module for a VAE with a ResNet18 encoder. The input is 3-channel 224x224 cell images. Use the same latent dim as the config. Add wandb logging for reconstruction loss and KL divergence."*

Claude writes it, you review the architecture, tweak the loss weighting, and you're training in minutes instead of an hour.
Claude writes it, you review the architecture and tweak the loss weighting, and you're training in minutes rather than an hour.

### Data Analysis and Exploration
### Data analysis and exploration

For the kind of exploratory analysis that fills a scientist's day:
For the exploratory analysis that fills a scientist's day, the same applies.

*"Load the AnnData object in data/processed/adata.h5ad. Show me the top 20 differentially expressed genes between clusters 3 and 7, and make a volcano plot."*

You get the plot, stare at it, and follow up: *"Interesting — now run GO enrichment on the upregulated genes and show me the top biological process terms."*
You get the plot, stare at it, and follow up. *"Interesting; now run GO enrichment on the upregulated genes and show me the top biological process terms."*

### Debugging Legacy Code
### Debugging legacy code

Every lab has *that* script — the one a former postdoc wrote, nobody fully understands, but it still runs the key analysis. Claude can read it, explain what it does, and help you carefully refactor it:
Every lab has that script, the one a former postdoc wrote, nobody fully understands, and the key analysis still depends on. Claude can read it, explain it, and help you refactor it carefully.

*"Read src/legacy/process_images.py. Explain what it does step by step, then refactor it to use pathlib instead of os.path and add type hints. Don't change the logic."*

### Writing Reproducible Pipelines
### Reproducible pipelines

Moving from notebooks to proper pipelines:
Moving from a notebook to a proper pipeline is a one-line ask.

*"Convert this Jupyter notebook into a Snakemake workflow. Each section header should be a separate rule. Keep the same parameters but read them from a config.yaml."*

## Tips and Pitfalls

**Verify numerical code.** AI is excellent at writing syntactically correct code that does the wrong maths. Always sanity-check statistical tests, loss functions, and data transformations against known results or toy examples.
## Tips and pitfalls

**Don't trust unfamiliar libraries blindly.** Claude occasionally suggests functions that don't exist or have different signatures than expected. If it uses an API you haven't seen before, check the docs.
**Verify numerical code.** AI is excellent at writing syntactically correct code that does the wrong maths. Sanity-check statistical tests, loss functions, and data transformations against known results or toy examples.

**Keep the science in your head.** The AI doesn't know your biological system, your experimental design, or why that specific normalisation step matters. Provide that context explicitly — don't assume it will infer scientific intent from code alone.
**Don't trust unfamiliar libraries blindly.** Claude occasionally suggests functions that don't exist or have different signatures than expected. If it uses an API you haven't seen, check the docs.

**Commit often.** Vibe coding moves fast. Commit working states frequently so you can roll back when an iteration goes sideways.
**Keep the science in your head.** The AI doesn't know your biological system, your experimental design, or why that normalisation step matters. Say so explicitly; it won't infer scientific intent from code alone.

**Start small.** Don't ask Claude to write your entire pipeline in one go. Break it into components: data loading, preprocessing, model, training, evaluation. Review each piece before moving on.
**Commit often.** Vibe coding moves fast. Commit working states so you can roll back when an iteration goes sideways.

**Use headless mode for batch jobs.** Claude Code supports non-interactive usage (`claude -p "your prompt"`) which is useful for running standardised analysis steps or code generation as part of CI.
**Start small.** Don't ask for the whole pipeline in one go. Data loading, preprocessing, model, training, evaluation, one at a time, reviewed before moving on.

## My Take
**Use headless mode for batch jobs.** Claude Code runs non-interactively with `claude -p "your prompt"`, which suits standardised analysis steps or code generation in CI.

Vibe coding isn't a replacement for understanding your code. It's a force multiplier. The scientists who will get the most out of it are the ones who already think clearly about their problems — the AI just removes the friction between "I know what I want to compute" and "I have working code that computes it."
## My take

The biggest mindset shift: treat code as *disposable infrastructure* for your scientific questions, not as a precious artefact. If Claude can regenerate a plotting script in 30 seconds, you don't need to spend 20 minutes making it perfect. Spend that time thinking about what the plot is telling you.
Vibe coding isn't a replacement for understanding your code. The scientists who get the most from it are the ones who already think clearly about their problems; the AI removes the friction between "I know what I want to compute" and "I have working code that computes it".

For scientists building ML models specifically, vibe coding is transformative. The gap between reading a paper and having a working implementation of the method used to be days. Now it's hours, sometimes minutes — if you can clearly articulate what you want.
The biggest shift is treating code as disposable infrastructure for your scientific questions rather than a precious artefact. If Claude can regenerate a plotting script in 30 seconds, you don't need to spend 20 minutes making it perfect. Spend that time thinking about what the plot is telling you. Disposable doesn't mean sloppy, and [How I Work](/vibe/) says where I draw that line.

That's the key skill: **clear articulation of scientific intent.** Turns out, the same thing that makes you good at writing papers makes you good at vibe coding.
For scientists building ML models, in my experience the gap between reading a paper and having a working implementation of the method has gone from days to hours, if you can articulate what you want. That articulation is the key skill, and the thing that makes you good at writing papers makes you good at this.

---

*I'm Craig Russell, an ML Scientist working on virtual cell foundation models at [Recursion](https://www.recursion.com/). I use Claude Code daily for ML research, pipeline development, and open-source tool building. Find me on [GitHub](https://github.com/ctr26) or [LinkedIn](https://linkedin.com/in/ctr26).*
*I'm Craig Russell, a Senior Machine Learning Scientist at Valence Labs, [Recursion](https://www.recursion.com/), working on generative and agentic models for biology. I use Claude Code daily for ML research, pipelines, and open-source tools. Find me on [GitHub](https://github.com/ctr26) or [LinkedIn](https://linkedin.com/in/ctr26).*
Loading
Loading