syw-adopt-overleaf
Skill1 starsChanged 21 days agoMITView on GitHub
Runbook for moving an existing paper (a live Overleaf project, often with co-authors, plus a private git repository) into a fresh showyourwork (SYW) repository without losing or silently changing anything. Backs up first, rebuilds figures and numbers from code and compares the new PDF with the old one, keeps the old git history private, and stops for the author's yes before every irreversible step. Use this whenever the user wants to "adopt", "migrate", "convert" or "move" a paper to showyourwork, put an existing Overleaf paper under SYW, or make an older paper reproducible, even if they only say "set up showyourwork for this paper". Afterwards the paper is ready for syw-overleaf-dropbox (daily work) and syw-site init (paper site).
In this repository17 other files it gives its agents.
- AGENTS.mdAGENTS.md
- speckit-analyzeSkill
- speckit-checklistSkill
- speckit-clarifySkill
- speckit-constitutionSkill
- speckit-convergeSkill
- speckit-implementSkill
- speckit-planSkill
- speckit-specifySkill
- speckit-tasksSkill
- speckit-taskstoissuesSkill
- diataxisSkill
- engaging-hybrid-computeSkill
- quarto-revealjsSkill
- submit-hybrid-computeSkill
- syw-overleaf-dropboxSkill
- syw-zenodo-cacheSkill
The file
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 3 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 19
⛔ gates: Every step marked ⛔ below waits for the author's explicit yes in chat.
- Distinctive: line 30
Signing: never bypass commit signing.
- Very specific: line 49
Read the paper's build: main file, bibliography, class/bst files, preamble packages, submodules, any \variable-like macro, make variables / …
- Very specific: line 90
Place files per the inventory (references/mapping.md): text from the backup's Overleaf clone under its new names src/tex/ms.tex, …
- Very specific: line 97
Run the old tests. Point pytest's testpaths at the package, never at src/scripts: importing a figure script runs it.
- Very specific: line 134
Read the rule's cache key without letting any script run: build once with UV_CONFIG_FILE=/nonexistent (every uv run then exits at once.
- Distinctive: line 168
every write and every deletion, with where each deleted file lives afterwards (the repository by content hash, regenerated by a rule, or …
- Distinctive: line 203
Check the old GitHub repository against the backup before retiring it: a fresh git clone --mirror has the same refs as the bundle.
- Very specific: line 223
Run it once per bundle (repo.bundle, and github.bundle if there is one).
- Very specific: line 229
Every phase has restore steps in references/rollback.md.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Moving an existing Overleaf paper into showyourwork
The paper is real, often submitted, and other people edit it. Nothing may be lost, no number may change silently, and the old repository's history must never become public. So the migration is a runbook with checkpoints: the agent prepares, the author decides.
The result: a new private repository paper-<slug> whose history starts at
[showyourwork] first commit; the same Overleaf project (same co-authors, links and history)
with the text renamed to SYW's defaults ms.tex / bib.bib; figures and numbers built by code;
the old repository archived, untouched otherwise.
Hard rules
- ⛔ gates. Every step marked ⛔ below waits for the author's explicit yes in chat. Record
each answer in
MIGRATION.md(one line: phase, what was shown, answer, date). - The author acts, the agent prepares: sending the co-author freeze message, setting Overleaf's main document, setting repository secrets, changing repository visibility.
- Never
showyourwork setup --overleaf=<id>on an existing project: that code path is for an empty project and SYW also ships a function that wipes one. Set up without--overleaf; theoverleaf:section is added by hand in phase 6. - The new repository never fetches from the old one (no
git remote add old, nogit fetch <bundle>). Text comes from the Overleaf clone, code is copied as files. - Tokens are read inline (
op read) on the one command that needs them, never printed, written, logged or put in a URL. Redactaccess_token=when reading SYW logs. - Signing: never bypass commit signing. If signing fails, ask the author to unlock 1Password.
- Private until arXiv: the repository is created private; any docs site stays local.
- Never compile in the Dropbox mirror: aux files there sync into the co-authors' project. Compile a temporary copy.
- Touch nothing else of the author's: other repositories, branches, worktrees, uncommitted work.
Before starting
Find, and write into MIGRATION.md → Sources: the old repository (local clone and
owner/name), the Dropbox mirror (~/Library/CloudStorage/Dropbox/Apps/Overleaf/<Project>/),
the Overleaf project id (Overleaf → Menu → Git, or the project URL), the 1Password reference of
the Overleaf git token, and the SYW version to use (ask; e.g. a development install). Propose a
slug from the title (short, lowercase, hyphens) and get the author's confirmation of
paper-<slug>.
Phases
0. Survey (read-only)
- Read the paper's build: main file, bibliography, class/bst files, preamble packages,
submodules, any
\variable-like macro,make variables/variables.yml, figure scripts, data locations, lockfiles. - Compile the current Overleaf text in a temporary copy of the mirror (latexmk) — or, if the
local toolchain cannot build it, ask the author to download Overleaf's compiled PDF. That PDF
is
baseline.pdf. - Inventory every Overleaf file into
inventory.tsv(class 1–4, seereferences/mapping.md), using the post-rename names. Check that every file in the Overleaf project appears exactly once.
1. Backup ⛔
scripts/backup.sh --repo <old clone> --mirror "<mirror>" --overleaf-id <id> \
--op-ref 'op://<vault>/<item>/credential' --baseline baseline.pdf [--github <owner/name>] [--dest <backups root>]--github is needed when the old repository has no origin (for example when it is the
Dropbox mirror folder); if GitHub holds a different history (Overleaf's own GitHub sync), it is
bundled too, as github.bundle.
Writes <dest>/<old-repo>-<YYYY-MM-DD>/ (--dest defaults to ~/backups) (refuses Dropbox/iCloud and an
existing folder) with repo.bundle, mirror.tar.gz, overleaf/ (clone with Overleaf's
history), baseline.pdf, secrets.txt (names only) and a MIGRATION.md from
references/migration-template.md; every part verified. Move inventory.tsv there.
⛔ Show the ok lines; the author confirms before anything changes.
2. Freeze Overleaf
Draft a short message asking co-authors not to edit until the migration is done (expected
duration, who to contact). The author sends it. If the Overleaf project is linked to a GitHub
repository through Overleaf's own GitHub integration (Menu → GitHub), note it: Overleaf cannot
unlink a single project, so from now on nobody uses that menu, and phase 8 retires the repository.
Record Overleaf's HEAD (from the backup clone) in MIGRATION.md → Freeze.
3. Build the SYW layout locally
In a new folder <parent>/paper-<slug>/ (a new repository; nothing from the old one's .git):
showyourwork setup(no--overleaf) with the agreed SYW version → commit 1,[showyourwork] first commit.- Place files per the inventory (
references/mapping.md): text from the backup's Overleaf clone under its new namessrc/tex/ms.tex,src/tex/bib.bib(and\bibliography{bib}); class-3 files intosrc/tex/; code tosrc/scripts/, data tosrc/data/; Snakefile rules for every figure and cited number. Keep everyms.texchange in an exact-match edit script in the backup folder (ms_edits.py): phase 6 replays it on Overleaf so the first pull is byte-identical. The usual edits, and the other first-build failures, are inreferences/lessons.md. - Run the old tests. Point pytest's
testpathsat the package, never atsrc/scripts: importing a figure script runs it. Commit 2,[showyourwork] migrate paper sources. The prefix matters: SYW's pull refuses to overwrite a file whose last commit is not a[showyourwork]commit. showyourwork.ymlhas nooverleaf:section yet. Draft the push/pull lists inMIGRATION.mdand runscripts/check_lists.py <draft> inventory.tsvuntilok. Itsdeleted:lines are the class-4 files the first push removes from Overleaf (a pushed folder replaces the whole Overleaf folder); they are approved at the dry run.
4. Build and compare ⛔
Build locally (Zenodo token inline if the paper caches on Zenodo). Then:
scripts/pdf_diff.py baseline.pdf ms.pdf --out pdf-diff/Show every section that differs (numbers first, then images with the PNGs, then text,
pages). For each difference: find the cause (code, data, a hand-edited figure, a font), fix
what is a migration error, and leave what the author accepts. Repeat 3–4. ⛔ The author accepts
the remaining differences, one by one; record them in MIGRATION.md → PDF differences.
SYW compiles with tectonic and Overleaf with pdflatex, so ms.pdf differs from the baseline
everywhere (hyphenation, line numbers, the SYW stamp) and that diff hides real changes. Compare
the parts instead: each regenerated figure against the old one (pdf_diff.py), every generated
number file byte for byte, and the migrated src/tex/ compiled with pdflatex in a temporary
copy against the baseline (expect only \today). Then show the author the two PDFs side by side,
page by page: a figure moving to another page is layout work they will want to know about.
5. Create the new repository ⛔
If any rule is cache: True, seed the Zenodo cache before main reaches GitHub. With no
Sandbox DOI in zenodo.yml, CI does not treat those rules as cached and runs them (a 21-hour
rule once ran on a runner until cancelled). ⛔ With the author's yes, showyourwork cache create
(token inline) makes a private Sandbox draft and writes its DOI. To upload existing results
instead of recomputing:
- Read the rule's cache key without letting any script run: build once with
UV_CONFIG_FILE=/nonexistent(everyuv runthen exits at once; the key is not affected) and take the hash fromSearching for file \<rule>` with hash `<key>`in.showyourwork/logs/showyourwork.log`. - Copy the results to
.showyourwork/cache/<key>(a folder for a directory output, the file plus its extension otherwise). - Build normally (with any
local_cacheentry for that rule off for this one build): SYW restores from the local cache and uploads to the draft. The draft's notes list each rule's key.
Then ⛔ gh repo create <owner>/paper-<slug> --private --source . --push. The author sets the
secrets (OVERLEAF_TOKEN, and SANDBOX_TOKEN/ZENODO_TOKEN if used) in the GitHub UI or with
op read … | gh secret set NAME -R <owner>/paper-<slug> run themselves. Watch the first CI run:
it should restore cached rules (Restoring from Zenodo Sandbox cache), not run them. The old
repository is not touched.
6. Rename, then first sync
Still frozen; compare Overleaf's HEAD with the one recorded at the freeze, and stop to reconcile if a co-author edited.
- ⛔ In a fresh Overleaf clone (credential helper as in
backup.sh, in a temporary folder):git mv main.tex ms.tex,git mv main.bib bib.bib, runms_edits.py ms.tex, addshowyourwork.sty(the editedms.texloads it, so Overleaf cannot compile without it).cmpms.tex/bib.bibwithsrc/tex/: byte-identical. Show the diff, commit, push. - ⛔ The author sets Overleaf Menu → Main document to
ms.tex. - The author recompiles in Overleaf and downloads the PDF;
pdf_diff.py baseline.pdf <it>shows only\today(and, if Overleaf's pdfTeX differs from the local one, sub-pixel anti-aliasing in figures; zoom in to confirm). - Dry run. SYW pulls and pushes only on branch
main, and has no dry-run flag. So, on a branchoverleaf-sync(notmain): add theoverleaf:section (id,gh_actions_sync: true, the checked lists) and commit it, unpushed. Simulate the push on a copy of a fresh Overleaf clone: for eachpushentry, delete the Overleaf folder and copysrc/tex/<entry>in its place (files: copy over);git add -A; git status --short. Show the author:- every write and every deletion, with where each deleted file lives afterwards (the repository by content hash, regenerated by a rule, or the backup only). Files only in the backup are the author's call: keep them in the repository (gitignored if private) or not;
ms.tex/bib.bibin the clone byte-identical tosrc/tex/;check_lists.py showyourwork.yml inventory.tsv→ok, itsdeleted:count matching. ⛔ The author approves.
- Merge to
main. Read each token into a variable and check it is non-empty first (a timed-outop readgives an empty string and SYW then skips the sync quietly). Run the full SYW build (pull, build, push). SYW pushes from anonsuccesshandler that Snakemake skips when there is nothing to do: if the log has noPushing changes to Overleaf, deletems.pdfand build again. Compare Overleaf's new commit with the dry run (same files, same change types; pushed figures identical to the old ones). Push to GitHub. - The first CI run on
mainsyncs Overleaf with CI's build. Compare every figure it pushed with the local one:pdfinfopage size, thenpdf_diff.py. Two CI-only failures have come up here (cached outputs insrc/tex/crashing the cache restore; a figure whose size depended on the matplotlib backend); both are inreferences/lessons.md.
7. Prune ⛔
List every file in a fresh Overleaf clone that the sync lists do not cover, with its class and
its identical copy in the repository, if any. ⛔ The author approves the list (keeping a file is
an answer). Delete them in the clone, compile that exact tree with pdflatex in a temporary copy
(it must still build), then commit and push. Overleaf's git access does not export hidden
folders (.vscode/, .figure-baseline/): the author deletes those in Overleaf's file tree.
The author recompiles in Overleaf and tells co-authors the freeze is over.
The Dropbox mirror may still hold the old checkout (.git, .venv, notes) next to Overleaf's
files. ⛔ With the author's choice for it, delete only files whose content is in
mirror.tar.gz; afterwards the mirror's file set must equal Overleaf's exactly.
8. Hand off ⛔
sh <syw-overleaf-dropbox>/scripts/check_build.sh "<mirror>" build.login the new repository: push found, no missing variables, every figure (subfolders too) same as the mirror. Withgh_actions_sync, a figure CI rebuilt differs in bytes from the local one; compare content.- Check the old GitHub repository against the backup before retiring it: a fresh
git clone --mirrorhas the same refs as the bundle; list what lives only on GitHub (issues, PRs and comments, releases, wiki, secrets, Actions artifacts); and look up every blob in its history (git rev-list --objects --all) in the new repository,repo.bundle, the Overleaf backup,mirror.tar.gzand any submodule's repository. Report the blobs found only on GitHub. ⛔ Then archive (gh repo archive <owner>/<old> --yes) or, if the author asks, delete (gh repo delete; needsgh auth refresh -h github.com -s delete_repo, run by the author). Overleaf's GitHub link cannot be removed per project; an archived or deleted repository makes any accidental push from Overleaf's GitHub menu fail. - Point the author to
syw-overleaf-dropboxfor daily work andsyw-site initfor a paper site. - New gotchas go into
references/lessons.md.
Before the repository is ever made public
The author decides when (typically at arXiv). First run:
scripts/public_check.sh <new repo> <backup>/repo.bundle <backup>/inventory.tsvRun it once per bundle (repo.bundle, and github.bundle if there is one). It fails on any
commit shared with the old repository, a token-like string anywhere in history,
or a class-4 file marked private ever committed. Identical file contents are fine.
If something goes wrong
Every phase has restore steps in references/rollback.md. In short: the old repository is
unchanged until phase 8; Overleaf can be restored from the backup clone or Overleaf's history;
the new repository and folder can be deleted until the author has used them.
Files
references/mapping.md— the four classes, rules, inventory format, a worked example.references/rollback.md— restore commands per phase.references/lessons.md— what went wrong in earlier migrations, and why.references/migration-template.md— theMIGRATION.mdskeleton.scripts/backup.sh,scripts/pdf_diff.py,scripts/check_lists.py,scripts/public_check.sh— run each with no arguments for usage.pdf_diff.pyneeds poppler.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

