Refresh local .tex/.bib files against Overleaf before AI edits, so the agent never edits a stale copy (default Overleaf-to-Dropbox sync lags 10-20 min). Refresh path: probe `/project/<id>/updates` (read-only), skip if nothing changed, skip if all changes were our own Dropbox round-trips, else download-zip and extract only the web-origin changed files. WHEN: (1) before editing .tex/.bib/.cls/.sty/.bst under Apps/Overleaf/<project>/ run `overleaf-sync-now sync`; (2) on user request to refresh; ...
Scanned 5/27/2026
Install via CLI
openskills install hanlulong/overleaf-sync-now---
name: overleaf
description: "Refresh local .tex/.bib files against Overleaf before AI edits, so the agent never edits a stale copy (default Overleaf-to-Dropbox sync lags 10-20 min). Refresh path: probe `/project/<id>/updates` (read-only), skip if nothing changed, skip if all changes were our own Dropbox round-trips, else download-zip and extract only the web-origin changed files. WHEN: (1) before editing .tex/.bib/.cls/.sty/.bst under Apps/Overleaf/<project>/ run `overleaf-sync-now sync`; (2) on user request to refresh; (3) for first-time auth run `overleaf-sync-now login`. Claude Code: a PreToolUse hook auto-runs sync; manual invocation rarely needed. Codex CLI: invoke sync explicitly. AUTH RECOVERY when sync/setup fails: run `overleaf-sync-now login` (browser-assisted, works on Chrome 130+). Do NOT tell the user to 'log into Overleaf' in their daily browser — on Chrome 130+ app-bound encryption blocks on-disk cookie extraction regardless of login state. See body for full recovery flow."
argument-hint: "setup | sync [folder] [--force] | status [folder] | link <project_id> [folder] | install | save-cookie <value> | doctor"
user-invocable: true
---
# overleaf-sync-now
## ⚠ STOP — read this before suggesting "log in to Overleaf"
If the user is on Windows with Chrome 130 or later, **logging into Overleaf in their daily browser will NOT fix auth failures.** Chrome 130 added App-Bound Encryption: the cookie database AES key is wrapped a second time with a key bound to `Chrome.exe` itself, brokered through Windows COM. Any process that isn't Chrome.exe (and isn't running as admin) can read the encrypted bytes but can't decrypt them. So `browser_cookie3` and `rookiepy` fail regardless of how recently the user logged in.
**The proper fix is `overleaf-sync-now login`.** It launches a controlled browser (patchright-managed Chromium since 0.3.2; vanilla Playwright fallback), the user logs in there once, and we read the cookie via Chrome DevTools Protocol — which returns plaintext because the request comes from inside the browser. The login persists in our profile for weeks.
## The problem
Overleaf's Dropbox bridge polls in one direction (Overleaf → Dropbox) every 10–20 minutes, so a local Dropbox-mirrored `.tex` file can be stale by that long. This skill fixes it by probing Overleaf's version history (`GET /project/{id}/updates`) and, on an actual web-origin change, downloading the project zip (`GET /project/{id}/download/zip`) and extracting only the files that changed — without changing the user's existing Dropbox-bridge setup, so cross-device Dropbox sync still works as before.
## How project lookup works
- **Auto-link** (zero-config, preferred): if a file lives under any `…/Apps/Overleaf/<project-name>/`, the skill looks up `<project-name>` in the user's Overleaf project list (cached 24 h, projects.json v2 since 0.3.0). The cached list keeps `trashed`/`archived`/`lastUpdated`/`ownerId`, so the resolver filters out trashed and archived projects by default and refuses to guess when two living projects share a name.
- **Marker auto-write** (since 0.3.0): on a successful auto-link the resolver writes a tiny `.overleaf-project` JSON marker into the project folder so future resolution skips the index lookup entirely. The marker carries `project_id` + provenance (`source`, `linked_at`, `name_at_link_time`).
- **Manual link** (override): if the user has two living projects with the same name (or the local folder name doesn't match), the resolver refuses to guess and prints all candidates with the exact `overleaf-sync-now link <id> <folder>` command to copy-paste. Run that command to write the marker explicitly. Old marker files containing only `{"project_id": "..."}` keep working.
### When `sync` warns or refuses
- **`auto-link: N non-trashed Overleaf projects named <name>. Refusing to guess.`** — Two or more live projects share the folder name. The skill lists candidates with IDs, last-updated timestamps, and any archived flag. Tell the user to pick one and run the printed `link` command. *Do NOT pick a project ID for them.*
- **`WARN: marker at <folder> -> <id> is trashed/archived on Overleaf`** — User explicitly linked a stale project. Sync proceeds but the user probably wants `overleaf-sync-now link <other_id> <folder>` to relink to the active project.
- **`WARN: project <id> has recent Dropbox-origin updates touching files not present in <folder>`** — Strong signal the link points at the wrong project entirely (a typo'd manual link, a fork, or a same-name duplicate that earlier defenses didn't catch). Have the user run `overleaf-sync-now status` and `overleaf-sync-now projects` to verify, then `link` to fix.
## Auth — DO NOT ask the user which method to use
The script handles auth itself. It tries (in this exact order, automatically): cached cookies → `rookiepy` (Chrome 127+ friendly) → `browser_cookie3` → Claude Code's Playwright profile → manual paste prompt.
**Just run `overleaf-sync-now setup` (or `install`).** Do not ask the user "do you want auto-detect or manual paste?" — the script picks the best available source.
## When auth fails (the recovery flow you should use)
When `setup` reports "AUTO-DETECT FAILED" or `sync` returns a "No valid Overleaf cookies" error, **the proper recovery is `overleaf-sync-now login`** (browser-assisted, works on every platform including Chrome 130+ Windows). Don't suggest the user "log in" in their daily browser — on Chrome 130+ Windows that doesn't help.
**Recovery flow:**
1. Run `overleaf-sync-now doctor` to confirm which automatic sources failed.
2. Tell the user: *"Run `overleaf-sync-now login` in your terminal. A browser window will open. Log into Overleaf there. We'll capture the cookie via the browser's API."*
3. (On first run, this auto-installs Playwright + Chromium, ~150MB, one-time.) The browser opens to overleaf.com, the user logs in, and the script captures the cookie via Chrome DevTools Protocol (no on-disk decryption needed). The login persists in the profile.
4. After they confirm login finished, run `overleaf-sync-now status` to verify, then retry the original sync.
**Fallback for environments where `login` can't run** (no display, server, etc.): `save-cookie <value>`. Ask the user to copy their `overleaf_session2` value from F12 → Application → Cookies → overleaf.com, then run `overleaf-sync-now save-cookie "<value>"`. Don't rely on this when `login` is available — `login` is more reliable.
### If Google blocks the `login` browser ("This browser or app may not be secure")
If the user signs into Overleaf via **"Sign in with Google"** and the managed `login` browser hits Google's *"This browser or app may not be secure"* page, that's Google's anti-automation gate (`disallowed_useragent`). The `login` command since 0.3.2 detects this and prints a tailored recovery message. The supported escape hatch is to give the user's Overleaf account an email+password alternate login:
1. Open https://www.overleaf.com/user/password/reset in any normal browser.
2. Enter the Overleaf account email; Overleaf emails a password-set link.
3. Set a password (their Google sign-in still works elsewhere; this just adds email+password).
4. Re-run `overleaf-sync-now login` and use **email+password** in the Overleaf form. Google never sees this flow.
Or fall back to `save-cookie` paste. **Do not** suggest fighting Google's detection further — patchright already does the best-available stealth, and Google iterates against bypasses.
## Subcommands
The CLI is `overleaf-sync-now` (installed globally via `uv tool install`).
### `setup`
Auth wizard. Walks the auto-detect chain; in interactive mode also prompts for manual paste. Run once; cached for weeks afterward.
### `login`
Browser-assisted login (Playwright + Chromium). The proper fix when `setup` can't auto-detect — including the Chrome 130+ app-bound encryption case on Windows. See the recovery flow above.
### `save-cookie <value>`
Last-resort: persist an `overleaf_session2` cookie value pasted from the browser's F12 → Application → Cookies pane. Use only when `login` can't run (no display / CI / server).
### `sync [folder] [--force]`
Refresh the project that owns `folder` (or current dir) against Overleaf.
- Probes `/project/<id>/updates`; skips if no change or if all new updates are Dropbox-origin round-trips of our own saves; otherwise downloads the zip and extracts only the files whose web-origin updates aren't yet on local.
- `--force`: always download the zip and re-extract. Hash-compare still skips files whose bytes already match local. Also disables the 30-second recent-mtime guard (see below).
Data-safety: by default, `sync` refuses to overwrite a local file modified within the last 30 seconds, and prints `SKIP <path>` to stderr. This protects an in-progress local save that hasn't yet propagated Dropbox → Overleaf. Pass `--force` to override.
When to invoke: manually when the user says "pull latest from Overleaf," or automatically before editing in Codex CLI (PreToolUse hooks aren't reliable on Windows in Codex).
### `status [folder]`
Reports data dir, cookie validity, linked project, last-sync time, and cached Overleaf version (`toV`). Distinguishes sandbox-blocked network from real auth failures.
### `projects [--refresh]`
List the user's Overleaf projects (name + ID). `--refresh` forces re-fetch of the index.
### `doctor [folder]`
Diagnostic dump: cookie cache state, per-browser cookie extraction, Playwright profile, auth-chain resolution, and a live `/updates` probe against the given folder's linked project.
### `link <project_id> [folder]`
Writes a `.overleaf-project` marker. Only needed for non-standard folder layouts (i.e., not `Apps/Overleaf/<name>/`).
### `hook`
PreToolUse hook entrypoint for Claude Code. Reads JSON from stdin. **Not for manual use.**
### `install`
Idempotent post-install setup: copies `SKILL.md` into `~/.claude/skills/overleaf/` and `~/.codex/skills/overleaf/` (whichever exists), installs / updates the Claude Code PreToolUse hook (matcher `Read|Edit|Write|MultiEdit`), runs the auth chain. Re-run after upgrading.
### `uninstall`
Removes skill installs and the hook. Cookies are preserved.
## Sandbox notes (Codex CLI, restricted shells)
If any network-using subcommand (`sync`, `status`, `login`, `doctor`, `setup`) fails with a socket-permission error — **Windows** `WinError 10013` / `forbidden by its access permissions`, **POSIX** `EACCES` / `EPERM` / "Permission denied" — the host shell is blocking the outbound HTTPS call. **This is not an auth problem.**
The tool detects this case specifically and prints:
> Outbound HTTPS to Overleaf was blocked by the host environment (likely a sandboxed shell — Codex CLI, some CI runners). Auth is probably fine; running setup/login/doctor will fail the same way. Approve the `overleaf-sync-now` command prefix in your sandbox policy, or re-run outside the sandbox.
When you see that message (or any of the above errno markers):
- Do **not** run `setup` / `login` / `doctor` — each hits the same blocked socket.
- Tell the user to approve the `overleaf-sync-now` command prefix in their sandbox (Codex CLI's always-approve list), or re-run from an unsandboxed shell.
- `status` will print `Cookie auth: UNKNOWN — outbound HTTPS is blocked ...` rather than `INVALID` in this case, so you don't have to guess.
## When to invoke this skill
- **In Claude Code**: rarely — the hook handles editing automatically. Invoke `sync` only on explicit user request, or `setup`/`link` for first-time configuration.
- **In Codex CLI on Windows**: every time you're about to Edit/Write a `.tex`/`.bib`/`.cls`/`.sty`/`.bst` file under `Apps/Overleaf/`, invoke `sync` first. (Codex hooks don't reliably fire pre-Edit on Windows.)
- **User mentions stale Overleaf content**: invoke `sync`.
- **User asks to set up Overleaf sync**: invoke `setup` (or full `install` if not yet linked into Claude/Codex skill dirs).
## Failure modes & recovery
- **"No valid Overleaf cookies found. Run setup"**: cookies expired or never set. Run `overleaf-sync-now setup`. The chain will try cached → browsers → Playwright; falls through to manual paste in interactive mode.
- **`setup` can't find browser cookies**: user may not be logged into overleaf.com in Chrome/Edge/Firefox. Either log in there, or paste cookie manually when prompted.
- **Auto-link can't find the project**: folder name doesn't match Overleaf project name. Use `link <project_id> .` inside the folder.
## Security note
Cached cookies grant full access to the user's Overleaf account. Stored at `~/.overleaf-sync/cookies.json` with default user permissions. Don't commit, don't share.
No comments yet. Be the first to comment!