Overleaf — Read & Write workflow
There are two channels for working with Overleaf, but only the first is required:
- Overleaf git bridge (read AND write) — every Overleaf project can be
cloned as a git repo. Editing locally +
git pushsyncs changes back to Overleaf. This is the only path for writes, and it works on any machine with git + a personal Overleaf token. Prefer this for everything. - Overleaf MCP server (read-only, optional) — a Node.js server that
exposes structured browsing of registered projects. Tools:
mcp__overleaf__list_projects,list_files,read_file,get_sections,get_section_content,status_summary. If those tools aren't visible in this session, the MCP isn't installed here — skip it and use the git bridge. Install instructions in the appendix.
First-run setup (do this automatically, don't pre-ask the user)
Resolve the user's Overleaf git token (format olp_…) on every Overleaf
task in this order, stopping at the first hit. Never echo the token to
chat output — refer to it only via env var or file path.
TOKEN=""
[ -n "$OVERLEAF_GIT_TOKEN" ] && TOKEN="$OVERLEAF_GIT_TOKEN"
[ -z "$TOKEN" ] && [ -r "$HOME/.overleaf-token" ] && TOKEN=$(tr -d '\n' < "$HOME/.overleaf-token")
If $TOKEN is still empty after both checks, the user has no token
configured on this machine. Ask them once for it, with this message:
I need an Overleaf personal git token to talk to your project. Get one from: Overleaf web → top-right account menu → Account Settings → Git Integration → Create Token. Paste it here (format
olp_…) and I'll save it to~/.overleaf-token(mode 600).
Once they paste it, save it without further questions:
printf '%s\n' "<token>" > "$HOME/.overleaf-token" && chmod 600 "$HOME/.overleaf-token"
Do not ask the user where to store the token, which storage method to
use, etc. — ~/.overleaf-token chmod 600 is the convention. If they have
a strong preference for env var or keychain, they'll bring it up; default
to the file.
The git URL pattern is always:
https://git:<token>@git.overleaf.com/<24-char-projectId>
The token ends up embedded in .git/config of each clone — that's how the
bridge works. Don't paste full remote URLs into chat output (use the
local clone path instead).
Cloning a project
When the user gives you an Overleaf project URL like
https://www.overleaf.com/project/<projectId>:
- Extract the project ID — the 24-char hex segment after
/project/. - Pick a clone path automatically:
- if the user invoked the skill from an empty cwd that's clearly named for this project (e.g. cwd contains "overleaf" or matches the paper), use that cwd,
- else default to
~/projects/overleaf-<short-name>, - else if they have explicit per-machine conventions in their personal setup, follow those (don't ask — just pick the most plausible).
- Clone:
Auth errors usually mean the token is for a different account or the user lacks access to that specific project — ask the user.target="<chosen-path>" if [ -d "$target" ] && [ -z "$(ls -A "$target" 2>/dev/null)" ]; then # target exists and is empty — clone via temp dir + rsync (git refuses # to clone into existing dirs, even empty ones, on some platforms) tmp=$(mktemp -d) git clone "https://git:${TOKEN}@git.overleaf.com/<projectId>" "$tmp" rsync -a "$tmp"/ "$target"/ && rm -rf "$tmp" else mkdir -p "$(dirname "$target")" git clone "https://git:${TOKEN}@git.overleaf.com/<projectId>" "$target" fi - (MCP-only, optional) If the MCP is installed and its
projects.jsonis reachable, register the new project for convenience. See the appendix for the MCP file layout — theprojects.jsonpath is wherever the user installed the server. Use Read + Edit (not Write) to preserve formatting:
MCP access to the new alias only activates after a Claude Code restart (or"<alias>": { "name": "<Human-readable name>", "projectId": "<projectId>", "gitToken": "<same-token-as-default>" }/mcpreconnect). The git clone path works immediately.
Reading
- MCP path (only if
mcp__overleaf__*tools are available in this session): quick section lookup on a registered project viamcp__overleaf__get_sections/get_section_contentwith the alias asprojectName. - Default path (always works): read directly from the clone with the
standard
Readtool. Rungit pull --rebasefirst if the user might have edited in the Overleaf web UI in the meantime.
Writing (the actual workflow)
Overleaf merges anything you push, but it does not rebase your local branch — so always pull first.
git -C <clone-path> pull --rebase- Edit / add files locally with
Edit/Write. Image/figure files go in the project's existingfigures/(or wherever the project's convention places them — check the tree first). git -C <clone-path> add <files>thengit -C <clone-path> commit -m "<message>".git -C <clone-path> push.- Confirm the new commit hash to the user. The change appears in the Overleaf web editor on next refresh.
If the push is rejected because Overleaf has newer commits, git pull --rebase again, resolve any conflicts, then push.
Common task: adding a conference rebuttal
Most ECCV/CVPR/etc. main-paper templates do not include the rebuttal
LaTeX scaffolding. A widely-used source is
https://github.com/paolo-favaro/rebuttal-template (ECCV 2026 rebuttal
template — adapt to other years/conferences as appropriate, or use the
template the user prefers).
Standard procedure:
- Check the project tree for any existing
rebuttal*file. If one exists, ask whether to edit it instead. - Clone the template into a temp dir (shallow clone is fine):
git clone --depth 1 https://github.com/paolo-favaro/rebuttal-template "$(mktemp -d)/rebuttal-template". - Compare overlapping files (
eccvabbrv.sty,splncs04.bst,main.bib) withdiff -q. Do not overwrite the project'smain.bib— it is the user's bibliography. Only copy in files that don't already exist or that genuinely differ in a way the user wants. - Typically only
rebuttal.texandcvpr.styneed to be added. - Inside
rebuttal.tex: set\paperID(look forTODO REBUTTALmarkers). The boilerplate body needs to be replaced with the actual response. - Commit + push as usual.
Things to avoid
- Do not call
git push --forceagainst an Overleaf remote — it can destroy collaborator edits made through the web UI. - Do not put the git token into shell history, log files, or any committed file. The remote URL has the token embedded; don't paste that URL into chat output. Refer to clones by their local path.
- Do not commit Overleaf-built PDFs (
*.pdfartifacts of the user's own paper) unless they were already tracked. Overleaf rebuilds the PDF on its side; pushed PDFs aren't used by the web compiler. ~/.overleaf-tokenand any MCPprojects.jsonfile live outside any git repo; do not move them into one without scrubbing the token first.
Appendix: installing the optional MCP server
The MCP is a quality-of-life addition — everything still works without it. Only set it up if the user explicitly wants structured project browsing or if multiple papers are in play and an alias map helps.
A working MCP install consists of three pieces:
1. The server source — a Node.js script (overleaf-mcp-server.js).
Source repo: <MCP_REPO_URL> (maintainer fills this in before
sharing). Conventional install location: ~/OverleafMCP/.
git clone <MCP_REPO_URL> ~/OverleafMCP
cd ~/OverleafMCP && npm install # if there's a package.json
2. A projects.json registry next to the server, listing each
project the user wants the MCP to expose:
{
"projects": {
"default": {
"name": "Default",
"projectId": "<24-char-id>",
"gitToken": "<olp_…>"
},
"<alias>": {
"name": "<Human-readable name>",
"projectId": "<24-char-id>",
"gitToken": "<olp_…>"
}
}
}
chmod 600 it — it contains tokens. The MCP caches this file at
startup, so newly added entries only show up after a Claude Code
restart (or /mcp reconnect).
3. A Claude Code MCP entry in the user's MCP config (typically
~/.claude/.mcp.json):
{
"mcpServers": {
"overleaf": {
"command": "node",
"args": ["<absolute-path-to>/overleaf-mcp-server.js"]
}
}
}
Restart Claude Code. The mcp__overleaf__* tools should now be visible.
If any of those three pieces is missing, the MCP simply won't expose its tools — Claude will fall through to the git-bridge path automatically.