A standardized folder structure, environment setup, and AI-assisted workflow for turning research projects into journal-ready replication packages. It ships with a Claude skill (create-replication-package) and a Codex (ChatGPT) agent that do most of the conversion work: they find the code that actually produces your paper, migrate it into notebooks, standardize figure and table names, rewrite the LaTeX, build index.ipynb, the README and the submission zips, and check that every number in your tables is reproduced.
Based on the replication packages for "Is Secessionism Mostly About Income or Identity? A Global Analysis of 3,153 Subnational Regions" (Zenodo) and "Roots of Cultural and Linguistic Traits".
- Quick Start
- Repository Layout
- Use Case 1: Start a New Project from Scratch
- Use Case 2: Convert an Existing Project with the Claude Skill
- Use Case 3: Convert an Existing Project with Codex (ChatGPT)
- Installing the Skills
- Paper and Author Information
- Running the Analysis
- Creating the Replication Zip
- Troubleshooting
You only install the skill. You do not clone this repository or edit any configuration file:
the skill carries its own copy of the template and creates the package folder. Paper and author
information (all co-authors) is read from your paper's LaTeX, completed with web searches, and
confirmed with you; it is stored in the package itself (replication-info.json).
- Install the skill once — download
create-replication-package.skilland- Claude desktop app / claude.ai: add it as a custom skill in Claude's skills settings;
- Claude Code:
unzip create-replication-package.skill -d ~/.claude/skills/; - Codex:
unzip create-replication-package.skill -d ~/.agents/skills/.
- Ask: "Create a replication package for my paper."
- Answer the three opening questions:
- Where is the original project folder? (e.g.
~/Dropbox/Papers/MyProject) - Do you have a manuscript ID? (e.g.
MS20230792— or "not yet") - Where should the replication package go? Accept the default —
MyProject-shared/<ID>-replicationin your other synced drive (e.g. Google Drive) at the same relative path — or give another location.
- Where is the original project folder? (e.g.
- Confirm the authors the skill found (names, order, affiliations, e-mails, ORCIDs, websites) and say which computer ran the analysis.
- Confirm the decisions at each checkpoint (final
.tex, figure/table names, migration plan, licensed data). - When it finishes: create the environment, run
index.ipynb, check the table comparison, runreplication-zip.ipynb, upload the zips.
Starting a new paper? Ask "Set up a new paper project with the replication template" — the skill creates the folder structure for you (see Use Case 1).
replication-folder-template/
├── 1-paper/ # LaTeX source for the main paper
├── 2-appendix/ # LaTeX source for the appendix
├── replication-package/ # Self-contained, submittable replication package
│ ├── index.ipynb # Master notebook — runs the full analysis
│ ├── README.md # Social Science Data Editors README template
│ ├── environment.yml # Minimal Python environment (what the code imports; no R)
│ ├── environment-R.yml # Separate R environment (only if R is used)
│ ├── environment.R # R packages at the authors' versions, checked
│ ├── create_env.sh # Creates the environments and kernels (unattended; EDIT HERE block)
│ ├── setup.do # Stata package installer
│ ├── progs/Python/ # Python notebooks (incl. Renaming.ipynb, Copy-Final.ipynb) + run_notebooks.py (runner)
│ ├── progs/Stata/ # Stata notebooks (pystata: python3 kernel + %%stata)
│ └── progs/R/ # R notebooks (IRkernel)
├── replication-zip.ipynb # Creates distributable zips for journal submission
├── .claude/skills/ # Claude skill (instructions, scripts, bundled template copy) + packaged .skill file
├── .agents/skills/ # Codex / ChatGPT agent (create-replication-package)
Use the template as your project folder from day one so you are always ready to produce a replication package.
Ask the skill: "Set up a new paper project with the replication template." It asks where the folder should go, the project name, the working title and the co-authors' names; looks up each author's affiliation, e-mail, website and ORCID on the web; asks you to confirm them; and creates the structure (no cloning).
Without the skill: git clone https://github.com/ozak/replication-folder-template my-paper, delete .git, .claude/, .agents/, CLAUDE.md, and replace the {{title}}, {{authors_...}} placeholders yourself.
cd replication-package
bash create_env.shThis creates a Mamba/Conda environment with Python 3.11, Jupyter, pystata support, R and IRkernel. On macOS it applies Apple Silicon optimizations automatically.
- Python notebooks in
replication-package/progs/Python/, Stata inprogs/Stata/(pystata notebooks: first cellimport stata_init, then%%statacells), R inprogs/R/ - Raw/input data in
replication-package/raw-data/<Source>/(one folder per provider); data created by code indata/<Step>/ - All paths relative to the notebook's folder:
../../raw-data/...,../../data/... - LaTeX in
1-paper/and2-appendix/; final figures/tables inreplication-package/graphs|tables/(paper|appendix)/, copied into flatgraphs/andtables/folders next to each.tex, namedFigure-1-a,Table-D3, … (see the naming rules in.claude/skills/create-replication-package/references/naming-conventions.md) - In the paper, keep each table's caption, column headers and notes in the
.texand\inputonly the body produced by the code
Add one step per notebook to replication-package/index.ipynb (the template shows the pattern). Header colors:
| Color | Meaning |
|---|---|
| Blue | Normal step |
| Red | Computationally expensive (guarded with should_I_run = False) |
| Green | Test / robustness check |
When you're ready to submit, run replication-zip.ipynb. You can also run the skill on the project at any time to check and finish it.
The create-replication-package skill turns a working (usually messy) research folder into a journal-ready package. It works in Claude Code (terminal) and in Claude's desktop app (Cowork) with your folders connected.
- The original project folder (code, data, paper sources). Co-author copies, external data drives or a journal-submission folder can be added as extra sources.
- The final version of the paper's LaTeX (the skill shows the candidates it finds and asks which one is final).
- Your manuscript ID, if you have one.
- Nothing about your software setup: the skill finds the conda/mamba environment, R, Stata and Julia setup your code used and asks you to confirm.
- Which datasets are licensed or confidential.
- Nothing to install or configure beyond the skill itself: the template comes with the skill, and the authors are taken from your paper (and the web) and confirmed with you.
Claude Code:
cd /path/to/your/research/project
claudethen type /create-replication-package, or just "Create a replication package for my paper".
Claude desktop app (Cowork): connect the original folder (and the destination's parent folder, e.g. your Google Drive) and ask "Create a replication package for my paper". The skill asks for access to exactly the folders it needs.
- Where is the original project folder? (plus any other folders with material for this paper)
- Do you have a manuscript ID? (if not, it uses the project name and later looks for an ID in file names such as editor letters)
- Where should the replication package go? The default follows this layout:
<synced drive A, e.g. Dropbox>/<path>/<Project>/ original — never modified
<synced drive B, e.g. Google Drive>/<path>/<Project>-shared/ shared with co-authors
<synced drive B, e.g. Google Drive>/<path>/<Project>-shared/<ID>-replication/ ← the package
You can choose "next to the original" or any other path. The skill refuses destinations inside the original folder and never writes into a non-empty folder.
| Phase | What happens | Your checkpoint |
|---|---|---|
| 0 — Locations | The three questions above; validates the destination | — |
| 1 — Discover | Surveys the project (and extra sources): candidate .tex versions, code by language, data sizes, absolute paths, earlier replication attempts, online-only cloud files (downloaded automatically). Extracts title and all authors from the final .tex and completes missing affiliations, e-mails, ORCIDs and websites by web search. Detects the software environment used: kernelspecs and mamba activate lines in the code, environment/requirements/renv files, and the environments on your machine ranked by how many of the code's imports they provide |
Final .tex; the author list and details; which mamba/conda environment (and R/Stata/Julia setup) was used; journal, licensed data, slow/cluster steps |
| 2 — Map & trace | Names every figure and table as LaTeX prints them; finds the files behind tables pasted into the .tex; traces each output back to the code and raw data that produce it, so only what the paper needs is migrated |
Rename map and migration plan |
| 3 — Scaffold | Creates the package from the template bundled with the skill, stores the confirmed paper/author info in replication-info.json and fills the README, notebooks and paper templates from it. Builds a minimal environment.yml from the environment you used (only what the code imports; result-computing packages pinned exactly, system libraries left free), a separate R environment with environment.R (your installed versions, core packages last, checked), and setup.do installing each Stata package from the source you installed it from; checks that the environments resolve on Linux and macOS without installing anything |
Packages the code imports but your environment lacks; computer used |
| 4 — Migrate | Copies raw data into raw-data/<Source>/; converts each script to a notebook (same code, same order; Stata via pystata); makes every path relative |
— |
| 5 — Names & LaTeX | Writes 1-paper/ and 2-appendix/ .tex files pointing at the standardized outputs; builds Renaming.ipynb; compares tables |
Any table whose numbers differ |
| 6 — index.ipynb | One step per notebook in dependency order, run by run_notebooks.py (saves failed notebooks, Stata licence limit, retries when Stata cannot start, dependencies, optional parallel mode); slow steps guarded, with cluster/local options and tests against shipped data |
— |
| 7 — README & zips | Fills the Data Editors README; sets zip exclusions for licensed data and the files derived from it | Exclusion list |
| 8 — Verify | Static package check, environment check, table comparison, run-twice checks for nondeterministic steps, consistency checks for errors in the original | Final report; decisions that change results |
| 9 — Clean-up (optional) | Removes code and loop iterations that produce nothing used; verifies used outputs are identical | What to remove |
- Your original folders are never modified. Nothing is created, edited, moved or deleted there; code is never run in place. The bundled scripts refuse to write anywhere except the destination.
- Only the code the paper needs. Source folders often mix papers, versions and experiments; the skill traces from the final figures and tables back to code and data.
- Code stays as close to the original as possible. One script becomes one notebook with the same code; only paths, plumbing and output file names change (every change is logged). Code is consolidated only if you ask.
- Numbers from the code, presentation from the final paper. Each table's caption, column headers and notes stay in the paper's
.texexactly as in your final version; the code produces only the body, which the paper\inputs. This applies both to tables pasted into the.texand to hand-edited table files the paper included — their header/footer are moved into the paper. Rows you removed or labels you edited in the paper are reapplied, and a comparison checks that every printed number is reproduced. - Online-only Dropbox/Google Drive files are downloaded as needed; you don't have to do anything.
- Nothing is installed without asking.
<ID>-replication/
├── _migration/ # how the package was built: inventory, rename map, lineage report,
│ # plan, migration log, original table bodies (not zipped)
├── 1-paper/ # <ID>-main-<date>.tex + graphs/ tables/ it references
├── 2-appendix/ # <ID>-appendix-<date>.tex + graphs/ tables/
├── replication-package/ # index.ipynb, README.md, environment, progs/, raw-data/, data/, outputs
└── replication-zip.ipynb
cd replication-package && bash create_env.sh(once).- In Stata:
do setup.do(once). - Open
index.ipynb, setSTATA_location/versionin the first cell, restart and run all (slow steps stay off unless you switch them on). - Check tables: ask the skill to "compare the tables" (it runs
compare_tables.py) — all tables should show ✅. - Compile
1-paper/and2-appendix/and compare with your submitted PDF. - Run
replication-zip.ipynb, then upload3-replication-package.zip(public) to Zenodo / the journal's repository and send4-confidential-data-not-for-publication.zipto the data editor if required.
The same workflow is available in Codex via the .agents/ copy of the skill (identical instructions and scripts).
- Install the skill (see below) — no need to clone this repo.
- Say:
Use $create-replication-package to turn this research project into a journal-ready replication package.— or describe the goal;allow_implicit_invocation: truelets it trigger on natural requests. - Answer the same three opening questions and checkpoints as above.
The packaged skill .claude/skills/create-replication-package.skill is a zip of the skill folder, which contains the instructions, the helper scripts and a bundled copy of this template (assets/template/). That single file is all a user needs.
| Where | How |
|---|---|
| Claude desktop app / claude.ai | Add create-replication-package.skill as a custom skill in Claude's skills settings |
| Claude Code (any project) | unzip create-replication-package.skill -d ~/.claude/skills/ — check with /skills |
| Claude Code (inside this repo) | Nothing: .claude/skills/ is picked up automatically |
| Codex | unzip create-replication-package.skill -d ~/.agents/skills/ (the repo's .agents/ copy also includes agents/openai.yaml) |
To follow the repository instead of a downloaded copy, symlink the folder:
ln -s "/path/to/replication-folder-template/.claude/skills/create-replication-package" ~/.claude/skills/Requirements: Python ≥ 3.9 (the scripts use only the standard library). Running a finished package needs Mamba/Conda, Jupyter, and Stata/R if the paper uses them.
For template maintainers: after editing 1-paper/, 2-appendix/, replication-package/ or replication-zip.ipynb, refresh the copy bundled with the skill and rebuild the .skill file:
python3 .claude/skills/create-replication-package/scripts/sync_template.py
python3 .agents/skills/create-replication-package/scripts/sync_template.py
(cd .claude/skills && rm -f create-replication-package.skill && zip -r create-replication-package.skill create-replication-package -x '*.DS_Store' '*__pycache__*')There is no personal profile to set up: papers have different co-authors, so the information belongs to each package. The skill builds replication-info.json in the replication folder:
- Extract the title and every author (with affiliation, e-mail and ORCID where printed) from the final
.tex—\author/\and,\thanks,\footnote,authblk's\affilare all handled. - Complete missing affiliations, websites, ORCIDs and e-mails with web searches (faculty pages, ORCID, RePEc/IDEAS), recording each source.
- Confirm with you: the skill shows the list and only uses it once you confirm that these are the authors, in this order, with these details.
For a new project, it asks for the working title and your co-authors' names, then does steps 2–3.
The README (title block, contributors, suggested citation, computational requirements), index.ipynb and the paper/appendix templates are filled from this file. To change something later, ask the skill (it edits the file with project_info.py set, asks you to confirm, and refills the templates).
From replication-package/index.ipynb:
- Edit the first cell:
STATA_location(e.g./Applications/Stata) andversion(e.g.mp). - Run it — it writes
progs/Stata/stata_init.py, which every Stata notebook imports. - Launch JupyterLab in the environment:
mamba activate <env-name> jupyter lab
- Open
index.ipynb, restart the kernel, run all cells. Each step executes a notebook with the runner and shows its HTML output (setPARALLEL = Truein the runner cell to run independent notebooks at once).
Run a single notebook (Python or Stata/pystata):
cd replication-package/progs/Python # or progs/Stata
jupyter nbconvert "Analysis.ipynb" --to notebook \
--ExecutePreprocessor.kernel_name=python3 --execute --output "Analysis.ipynb"or, with the runner (saves the notebook and its HTML even when it fails), from replication-package/:
python progs/Python/run_notebooks.py progs/Python/A.ipynb progs/Stata/B.ipynb:after=A --parallel 2Run replication-zip.ipynb from the folder that contains replication-package/. It produces:
3-replication-package.zip— public files only4-confidential-data-not-for-publication.zip— the excluded (licensed/confidential) filesfull-replication.zip— both zips plus the journal checklist, for the editor
Exclusions go in the designated cells, one per licensed source and its derived data:
df_files.loc[df_files['file_path'].str.contains('raw-data/LicensedSource'), 'include'] = False
df_files.loc[df_files['file_path'].str.contains('data/DerivedFromLicensedSource'), 'include'] = FalseThe notebook also writes directory_structure.{txt,html,md} (shown in the README's file list).
| Problem | What to do |
|---|---|
| "Resource deadlock avoided" when reading Dropbox/Google Drive files | Those are online-only files. The skill downloads them through the host automatically; on your own Mac, opening them downloads them. |
A table shows ❌ in compare_tables.py |
The code does not reproduce the printed numbers: check the script version, data vintage, sample or seed — never edit the numbers. Suggested drop_rows / replace fixes are only for presentation differences. |
REFUSED: … read-only source folder |
Working as intended — a script tried to write into an original folder. Write to the replication folder instead. |
A Stata notebook fails with No module named stata_init |
Run the first cell of index.ipynb (it writes progs/Stata/stata_init.py). |
Figure/table missing when compiling 1-paper/ |
Run Renaming.ipynb then Copy-Final.ipynb (or the last part of index.ipynb). |
© Ömer Özak (2024)
This code and data is provided under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License and GPLv3.
