Project-Level IPython Startup Scripts
Every time I open IPython in a project directory, I want to hit the ground running. Not type imports. Not remember which random seed I used last time. Just work.
That's where project-level startup scripts come in.
How It Works
IPython startup files live in ~/.ipython/profile_default/startup/. Any .py or .ipy files in this directory are executed when IPython starts, in alphabetical order, so you can control execution order with prefixes like 00-, 01-, etc.
I symlink my dotfiles to keep them in sync:
This way, my startup scripts live in my dotfiles repo and travel with me across machines. My setup includes:
00-basic-imports.py- global imports I want everywhere01-custom-startup.py- the project-level import trick
It tries to import from a local startup.py in the current directory, and silently fails if one doesn't exist. No errors, no fuss.
The Magic: It Differs by Project
Here's where it gets useful. Each project can have its own startup.py with exactly what that project needs.
For a data analysis project, you might have:
"""Startup script to initialize data and random number generator."""
import myproject.data as md
import numpy as np
df = md.load_main_dataset()
seed = sum(map(ord, "analysis-2026"))
rng = np.random.default_rng(seed)
When I'm in that directory, IPython loads the dataset and sets up a reproducible RNG. I'm ready to analyze immediately.
For a different project, I might have:
import numpy as np
import polars as pl
from sklearn.model_selection import train_test_split
rng = np.random.default_rng(42)
Or maybe a project that needs API clients, database connections, or ML experiment trackers.
Why This Beats Global Startup Scripts
Global startup scripts are great for always-available imports like pandas or numpy. But project-level scripts give you something they can't: context-specific setup.
The data project startup.py knows about your dataset and uses a seed based on the project name. A generic data science starter can't provide that.
And because the import is wrapped in a try/except, there's no error when you're in a directory without a startup.py. It just falls back to your global imports.
Tip
The numbered prefix controls execution order. Files run in alphabetical order, so use 00- for global imports, 10- for project-specific imports, etc.
Further Inspiration
If you want to see how someone else sets theirs up, check out Cam Davidson-Pilon's startup files. He uses a similar numbered prefix system with files like 00-imports.py, 01-plotting.py, 05-data_analysis.py, and more. Great ideas if you're building out your own setup.
What imports do you find yourself typing at the start of every IPython session? Drop them in a startup.py and never type them again.