Overleaf Sync Skill
Bidirectional sync between local LaTeX projects and Overleaf without requiring Premium (Git access).
Quick Start
# Add to PATH (one-time setup)
export PATH="$PATH:/workspace/overleaf/bin"
# Link local directory to an Overleaf project
cd /workspace/overleaf/projects/my-project
overleaf link <project_id>
# Pull current state from Overleaf
overleaf pull
# Check what's changed locally
overleaf status
# Push local changes (generates Playwright steps)
overleaf push
Commands Reference
| Command | Description |
|---|---|
overleaf link <id> |
Link local directory to Overleaf project |
overleaf unlink |
Remove link (keeps local files) |
overleaf status |
Show added/modified/deleted files |
overleaf push |
Generate Playwright steps to upload changes |
overleaf push --dry-run |
Preview push plan without staging files |
overleaf push --no-delete |
Push but skip file deletions |
overleaf pull |
Download from Overleaf to local |
overleaf pull --force |
Overwrite local changes |
overleaf init <name> |
Initialize new project with template |
overleaf sync-complete |
Mark sync as complete after push |
overleaf cleanup |
Clean up staging directory |
overleaf list |
List all Overleaf projects (find IDs) |
Architecture
Local Project Sync Engine Overleaf
│ │ │
├── .overleaf/ │ │
│ ├── config.json │ │
│ └── sync_state.json │ │
│ │ │
└───────────────────────┼───────────────────────┤
PULL (API) │ PUSH (Playwright)
Download ZIP ←──────┤───────→ Upload files
Why Hybrid?
- Overleaf free plan has no Git access
- API handles reads (list, download)
- Playwright handles writes (upload, delete)
File Types Supported
.tex- LaTeX source files.bib- Bibliography files.cls,.sty- Style and class files.png,.jpg,.pdf- Images and figures- Any file type Overleaf accepts
Project Structure
Each synced project has a .overleaf/ metadata directory:
my-project/
├── main.tex
├── references.bib
├── figures/
│ └── diagram.png
└── .overleaf/ # Sync metadata (gitignored)
├── config.json # Project ID, URL, link timestamp
└── sync_state.json # File hashes from last sync
Workflow Examples
Scenario 1: Work on Existing Overleaf Project
# Find project ID
overleaf list --filter "thesis"
# Create local directory and link
cd ~/Workspace/overleaf-integration/projects
mkdir thesis && cd thesis
overleaf link 507f1f77bcf86cd799439011
overleaf pull
# Edit locally...
vim main.tex
mkdir figures && cp ~/image.png figures/
# Check status
overleaf status
# → M main.tex
# → A figures/image.png
# Push changes
overleaf push
# → Generates Playwright steps for agent to execute
Scenario 2: Check Sync Status
overleaf status
# Output:
# Project: My Thesis
# Overleaf ID: 507f1f77bcf86cd799439011
# URL: https://www.overleaf.com/project/507f1f77bcf86cd799439011
# Last sync: 2026-01-16T10:30:00 (pull)
#
# Added (2):
# + figures/diagram.png
# + appendix.tex
#
# Modified (1):
# M main.tex
Scenario 3: Push with Dry Run
overleaf push --dry-run
# Shows what would be synced without staging files
# Useful for previewing before actual push
Important Constraints
1. Playwright File Path Restriction
Files must be in the user's home directory ($HOME/) for Playwright MCP to access them.
The sync engine automatically stages files to $HOME/tmp/overleaf-staging/ before upload.
2. No Git Access (Free Plan)
- All reads via Overleaf API (download ZIP)
- All writes via Playwright browser automation
- No real-time collaboration sync
3. Deletions Require Confirmation
Deletions are dangerous - files removed from Overleaf cannot be recovered.
--no-deleteflag skips deletion operations- Push shows warnings before deleting
- Always confirm with user first
After Push: Executing Playwright Steps
When overleaf push runs, it:
- Calculates diff (added/modified/deleted)
- Stages files to
$HOME/tmp/overleaf-staging/ - Outputs Playwright MCP steps to execute
You (the agent) must execute these steps:
--- Operation 1: create_folder ---
Target: figures
Steps: 8
--- Operation 2: upload_file ---
Target: main.tex
Steps: 11
After successful execution:
overleaf sync-complete # Updates sync state
When the User Says...
| Request | Action |
|---|---|
| "Sync my Overleaf project" | overleaf pull then edit, then overleaf push |
| "Push my changes to Overleaf" | overleaf push (then execute Playwright steps) |
| "What files have I changed?" | overleaf status |
| "Download latest from Overleaf" | overleaf pull |
| "Link this folder to Overleaf" | overleaf link <project_id> |
| "What's the project ID for X?" | overleaf list --filter "X" |
| "Initialize a new LaTeX project" | overleaf init "Project Name" |
Python API
from overleaf_sync import OverleafProject, SyncEngine
from pathlib import Path
# Work with a project
project = OverleafProject(Path("/path/to/project"))
# Check if linked
if project.is_linked:
print(f"Linked to: {project.project_name}")
# Get status
status = project.get_status()
if status.has_changes:
print(f"Changes: {status.diff.summary()}")
# Create sync engine
engine = SyncEngine(project)
# Pull from Overleaf
result = engine.pull(force=False)
# Generate push plan
plan = engine.push(dry_run=False, skip_delete=True)
print(f"Operations: {len(plan.operations)}")
Related Skills
- overleaf-integration - Read-only API operations, list projects
- browser-automation - Playwright MCP reference for executing steps
- homework-workflow - Uses Overleaf for transcription output
- task-delegation - Complex syncs can be delegated to worker
File Locations
| Component | Path |
|---|---|
| CLI Script | /workspace/overleaf/scripts/overleaf_cli.py |
| Sync Engine | /workspace/overleaf/scripts/overleaf_sync.py |
| Diff Engine | /workspace/overleaf/scripts/overleaf_diff.py |
| CLI Wrapper | /workspace/overleaf/bin/overleaf |
| Projects | /workspace/overleaf/projects/ |
| Staging | $HOME/tmp/overleaf-staging/ |
Troubleshooting
"Not linked to Overleaf"
Run overleaf link <project_id> first. Find project IDs with overleaf list.
"Local changes would be overwritten"
Your local files have changes. Either:
- Push first:
overleaf push - Or force pull:
overleaf pull --force
"Session cookie expired"
Refresh cookie from browser DevTools and update .credentials file.
"File must be in $HOME/"
Playwright MCP restriction. The sync engine handles this automatically by staging files.
Playwright execution fails
- Take fresh snapshot:
browser_snapshot - Find correct element refs
- Retry the step