Migrating an existing repo
20th Jun 2026
A runbook for bringing an existing research repo or codebase into this structure — so your real experiments produce artifacts and publish posts like everything else. Run it with a coding agent: say “migrate my code” and point it at the repo (a local path or a clone). It can also be followed by hand.
Do the Getting started doc (ar004.md) first so the loop is familiar. The contract you’re migrating into is in CONTRIBUTORS.md — keep it open.
Three principles, and the whole guide follows from them:
- Incremental, not lift-and-shift. Bring experiments across one at a time. A research repo doesn’t map onto this structure wholesale; each experiment becomes its own CLI command + notebook + post.
- Wrap, don’t rewrite. Keep the user’s code where it is. The new
cli.pyis a thin adapter that imports and calls their existing functions — you’re not reimplementing their science. - One environment. Their dependencies fold into this repo’s root
pyproject.toml, not a parallel env.
Agent: work in small, verified steps. The failure mode here is trying to move everything at once or rewriting the user’s computation — don’t. Get one experiment publishing end to end before touching the next.
1. Inventory the existing repo
Agent: get the path (or URL) to the user’s repo and read its structure. Produce a short list of candidate experiments — each script or function that computes a result, ideally one that ends in a figure or a few numbers. Then, with the user, pick the single simplest one to migrate first. Don’t try to catalogue or move everything; just find the easiest end-to-end win.
2. Bring their code in — wrap, don’t rewrite
The aim is for their computation to stay in their modules; the CLI just calls it. Two cases:
- It’s an installable package (has a
pyproject.toml/setup.py): add it as a dependency so you can import it without copying —uv add <name>for a PyPI package, or a git/local-path dependency for an unpublished repo — thenuv sync. Nowimport their_packageworks from the CLI. - It’s loose scripts/modules: copy only the modules the chosen experiment needs into the new tool directory (next to
cli.py), or a sharedsrc/<their_pkg>/. When a CLI runs viauv run python src/clis/<tool>_cli/cli.py, that directory is on the import path, sofrom their_module import run_experimentresolves.
Agent: prefer the dependency route when the repo is installable — zero copying, easiest to keep in sync. Only copy modules when there’s no package to depend on.
3. Merge dependencies
Agent: read the existing repo’s
requirements.txt/pyproject.toml. Add the dependencies the migrated experiment actually needs to this repo’s rootpyproject.tomlwithuv add …(neverpip install), thenuv sync. Surface any version conflicts to the user and resolve them together. Add only what the chosen experiment uses — not the whole list.
4. Wrap the first experiment as a CLI command
Agent: create
src/clis/<tool>_cli/cli.py(or add a subcommand to an existing tool), modeled onsrc/clis/neuron_cli/cli.py:
- Copy the
setup_run_dirandwrite_outputhelpers fromneuron_cli/cli.pyverbatim, adjusting the tool name inARTIFACTS_DIRand the logger.- Add an
argparsesubcommand whose arguments are the experiment’s parameters (with the defaults from their code).- In the handler: call
setup_run_dir, call the user’s existing function to do the computation, save the figure to the run dir, build a flatmetricsdict, andwrite_output(run_dir, metrics, manifest)with amanifestdeclaringheadline_figureandheadline_metrics.The handler should be thin — parse args, call their code, write the contract files. If you find yourself porting their math, stop and import it instead. Run
uv run python src/clis/<tool>_cli/cli.py <command>and confirmsrc/artifacts/<tool>_cli/<command>/has the full set (config.json,output.json,manifest.json, the figure,run.sh).
5. Runner and post
Agent: create the runner
src/notebooks/nbNNN.py(modeled onnb000.py, ornb002.pyfor a tool mix) with itsCOMMANDS, and run it. Then create the postsrc/docs/content/notebooks/nbNNN.mdx—title+datefrontmatter (optionaldescription/collection/status), with values inlined from the generatednumbers.json, the figure, and a parameter table. Start the site (cd src/docs && bun run dev) and open the new post with the user athttp://localhost:4321. Confirm the figure and numbers match their original code’s output.
6. Repeat for the next experiment
Agent: once one experiment publishes end to end, bring the next across the same way — each becomes its own command (and usually its own notebook). Stop when the experiments that matter are migrated; there’s no need to move everything.
Notes
- Don’t fork their science into the contract — wrap it. The CLI is glue; their code is the source of truth.
- Determinism: if an experiment uses randomness, thread a
--seedargument through (seeneuron_cli’snetcommand) so runs reproduce. - Keep their tests. If the repo has tests, bring the relevant ones and run them with
uv run.