Skip to main content

claude-to-overleaf

CI Docs Python License

📖 Full documentation: https://srezaeeucr.github.io/claude-to-overleaf/

One prompt to push your LaTeX repo to Overleaf. No web-UI tab-juggling. No copy-paste. No "wait, did I save that?"

A tiny, zero-dependency Python package that ships with a Claude Code skill. Edit locally in your editor of choice, commit, then tell Claude:

"sync to overleaf"

Claude invokes the skill, runs the tool, handles the safety checks, and your Overleaf project reflects the changes within seconds. (No Claude Code? It's also a normal CLI — claude-to-overleaf sync.)


Why this exists

Overleaf gives every project a git URL — but actually using it day-to-day means:

  • remembering to add a remote
  • juggling a token you saw exactly once
  • knowing the magic incantation (commit-tree, HEAD^{tree}, fast-forward push) because Overleaf rejects normal pushes
  • not blowing away edits made in the Overleaf web editor

This script does all of that for you, and refuses to push when it would silently destroy work.


Features

  • Ships a Claude Code skill — one command (claude-to-overleaf install-skill) drops a skill file into ~/.claude/skills/ so Claude reliably knows when and how to invoke it
  • Prompt-driven by default — say "sync to overleaf" and Claude does the rest, including handling the "Overleaf is ahead" cherry-pick flow
  • Standalone CLI for anyone — claude-to-overleaf sync works without Claude Code
  • Installable as a real package — pipx install it once and the command lives on your PATH
  • Five subcommands — setup, status, sync, pull, install-skill
  • Zero runtime dependencies — pure Python 3 stdlib (3.9+)
  • Safe by default — refuses to push when Overleaf is ahead, or when the working tree is dirty
  • .env-driven config — your token never lives in shell history or the LaTeX repo
  • Idempotent setup — re-run anytime; only updates the remote URL if the token rotated
  • Works from anywhere — point REPO_PATH at any LaTeX repo on disk

Quick start

1. Install

The recommended way — using pipx so the tool gets its own isolated environment:

pipx install claude-to-overleaf

Or with regular pip:

pip install --user claude-to-overleaf

Either way, you should now have a claude-to-overleaf command on your PATH:

claude-to-overleaf --help

(For development: git clone the repo and pip install -e . from inside it.)

1a. Install the Claude Code skill (optional, recommended)

If you use Claude Code, run this once:

claude-to-overleaf install-skill

It drops a skill file at ~/.claude/skills/claude-to-overleaf/SKILL.md. Restart Claude Code and from then on Claude knows to use this tool whenever you say things like "sync to overleaf" or "push my latex to overleaf" — including the right way to handle "Overleaf has commits ahead" warnings (cherry-pick first, never --force without asking).

2. Grab your Overleaf credentials

Two things from Overleaf:

What Where to find it
Project ID Open your project → Menu (top left) → Sync → Git. The URL looks like https://git.overleaf.com/<long-hex-id>. The hex string is the project id.
Access token Account Settings → Git Integration → "Generate token". Starts with olp_. Overleaf only shows it once — copy immediately.

Treat the token like a password. Anyone with it can read and write your project. Never paste it into chat, screenshots, or a tracked file. If it leaks, revoke it on Overleaf and generate a new one.

3. Make a .env

The tool reads config from two .env files (CWD wins per-key, global is the base layer) plus environment variables. For a single-project setup, just put everything in one file. For a global setup:

mkdir -p ~/.config/claude-to-overleaf
curl -fsSL https://raw.githubusercontent.com/srezaeeucr/claude-to-overleaf/main/.env.example \
  > ~/.config/claude-to-overleaf/.env

Then open it and fill in:

OVERLEAF_TOKEN=olp_your_real_token
OVERLEAF_PROJECT_ID=abcdef1234567890...
REPO_PATH=/absolute/path/to/your/latex/repo

The repo at REPO_PATH should have your .tex file at the root (e.g. thesis.tex, not thesis/main.tex). For per-project configs, drop a .env next to where you run the command instead.

4. Wire it up

claude-to-overleaf setup

Adds an overleaf remote to your LaTeX repo and runs a test fetch. OK — 'overleaf' is reachable. means you're done.

5. Sync

Edit. Commit. Push to GitHub as usual. Then either:

With Claude Code:

"sync to overleaf"

Claude runs the tool, handles the safety checks, and reports back.

Or run it directly:

claude-to-overleaf sync

Refresh Overleaf in the browser — the changes are there.


Commands

Command What it does
setup Adds (or updates) the overleaf git remote and verifies auth. Idempotent — safe to re-run.
status Shows whether local HEAD matches Overleaf. Lists Overleaf-only commits if any.
sync Pushes local HEAD's tree to Overleaf. Refuses if Overleaf is ahead, or the working tree is dirty.
sync --force Push anyway, overwriting Overleaf-side commits. Use deliberately.
pull Lists Overleaf-only commits so you can git cherry-pick them.
install-skill Installs the bundled Claude Code skill to ~/.claude/skills/claude-to-overleaf/.

Run claude-to-overleaf --help for the same info from the CLI. (Or python -m claude_to_overleaf --help if you'd rather not rely on the entry-point shim.)


Config reference

Settings are resolved in this order, highest precedence first:

  1. Environment variables
  2. ./.env (current working directory)
  3. ~/.config/claude-to-overleaf/.env (global)

The two .env files are merged — values in CWD .env override only the keys they define. The global file is the base layer. So you can keep one shared OVERLEAF_TOKEN in the global file and just put OVERLEAF_PROJECT_ID in each repo's local .env for multi-project setups.

Variable Required Default Purpose
OVERLEAF_TOKEN yes — Personal access token (starts with olp_)
OVERLEAF_PROJECT_ID yes — Hex id from the Overleaf git URL
REPO_PATH yes — Absolute path to the local git repo
OVERLEAF_BRANCH no master Branch name on the Overleaf side
OVERLEAF_REMOTE no overleaf What to call the remote in your repo

Day-to-day workflow

Case 1 — you only edited locally

git add .
git commit -m "..."
git push origin main                  # GitHub

Then ask Claude "sync to overleaf" — or run claude-to-overleaf sync directly.

Case 2 — someone (or you) edited on Overleaf

sync will refuse and tell you exactly what's there. Bring those edits home first:

claude-to-overleaf pull               # see what's on Overleaf only
cd $REPO_PATH
git cherry-pick <hash>                # bring each one onto local main
claude-to-overleaf sync               # now safe

Case 3 — both sides edited the same file

Same as Case 2, but expect conflicts during cherry-pick. Resolve by hand, then:

git add <files>
git cherry-pick --continue

Multiple Overleaf projects

Put your shared token once in ~/.config/claude-to-overleaf/.env:

OVERLEAF_TOKEN=olp_your_real_token

Then drop a per-repo .env in each LaTeX project directory with just the bits that differ:

# inside ~/repos/thesis/.env
OVERLEAF_PROJECT_ID=thesis_hex_id

# inside ~/repos/conference-paper/.env
OVERLEAF_PROJECT_ID=paper_hex_id

CWD overrides global per key, so the token is inherited from the global file and the project id comes from the local one. cd to whichever repo you want to sync, run claude-to-overleaf sync. Don't forget to add .env to each repo's .gitignore.


The one rule

Don't edit the same file in Overleaf and locally between syncs.

Pick one editor per file per session, sync, then switch sides. The safety check catches the common version of this mistake, but discipline beats tooling.


Safety nets baked in

  • Refuses to push when the working tree has uncommitted changes (Overleaf only sees committed state — uncommitted edits would silently not sync, leaving you confused later)
  • Refuses to push when Overleaf has commits the local repo doesn't have (no silent overwrites of web-editor work)
  • .env is in .gitignore so your token can't accidentally land on GitHub
  • Token is URL-encoded before being embedded in the remote URL (handles weird characters cleanly)

Troubleshooting

error: missing required config: OVERLEAF_TOKEN The tool can't find a .env (it looks in CWD then ~/.config/claude-to-overleaf/) or the key isn't in it. Re-do Step 3.

Authentication failed during setup Token is wrong, expired, or revoked. Generate a new one in Overleaf, update .env, re-run setup. Sanity-check the token directly:

curl -u git:$OVERLEAF_TOKEN -I \
  "https://git.overleaf.com/$OVERLEAF_PROJECT_ID/info/refs?service=git-upload-pack"

HTTP/2 200 = token is valid. HTTP/2 401 = bad token.

error: ... is not a git repo REPO_PATH points somewhere without a .git directory. Fix the path or git init there.

WARNING: overleaf/master has N commit(s) not in your local repo Working as designed. Run pull, cherry-pick what you want, then sync again.


What it does under the hood

sync is the textbook Overleaf-git recipe in Python:

  1. git fetch overleaf master
  2. Compare HEAD^{tree} to overleaf/master^{tree} — exit early if equal
  3. git commit-tree HEAD^{tree} -p overleaf/master -m "Sync from GitHub @<short>"
  4. git push overleaf <new-commit>:master

The trick is step 3. Overleaf rejects non-fast-forward pushes, so the script grafts your local tree onto Overleaf's history as a brand-new commit. From Overleaf's perspective, it's a normal forward step — even though your local branch and Overleaf's branch share no recent history.


Limitations

  • Assumes your LaTeX project is at the root of the repo. If it lives in a subfolder, you'd need git subtree split instead — open an issue and we'll add it.
  • One Overleaf project per .env. To sync multiple, drop a .env in each repo's directory (CWD takes precedence over the global one in ~/.config/claude-to-overleaf/).
  • Tested on macOS. Should work on Linux. Windows is unverified.

Metadata

Release files for claude-to-overleaf 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for claude-to-overleaf 0.3.0
File Size Uploaded
claude_to_overleaf-0.3.0.tar.gz 16.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for claude-to-overleaf 0.3.0
File Interpreter ABI Platform
claude_to_overleaf-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 29.7 kB

Release files / claude_to_overleaf-0.3.0.tar.gz

Download URL claude_to_overleaf-0.3.0.tar.gz
Size 16.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e9f88fda9b0bd7239b15773899b737481be4f7bc5fce16524b6a501ab27b392c
BLAKE2b-256 checksum
How to use checksums
e067e8cd6932dcfd876097fd35b42e039fb4d6133f65b8f90b20c78be7266c29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release files / claude_to_overleaf-0.3.0-py3-none-any.whl

Download URL claude_to_overleaf-0.3.0-py3-none-any.whl
Size 12.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a58a9cf1d3e981ac6236c79a53f4ede137cdc2e756a3dc9ec62757e61e960952
BLAKE2b-256 checksum
How to use checksums
43d83ba9770432f2e568ce1747b86365af6661d5d53b88158d51976431cece74
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page