@aloth/olcli 0.15.3 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +140 -437
  2. package/dist/browser-auth.d.ts +144 -0
  3. package/dist/browser-auth.d.ts.map +1 -0
  4. package/dist/browser-auth.js +442 -0
  5. package/dist/browser-auth.js.map +1 -0
  6. package/dist/cli.js +429 -174
  7. package/dist/cli.js.map +1 -1
  8. package/dist/client.d.ts +20 -0
  9. package/dist/client.d.ts.map +1 -1
  10. package/dist/client.js +103 -37
  11. package/dist/client.js.map +1 -1
  12. package/dist/config.d.ts +25 -0
  13. package/dist/config.d.ts.map +1 -1
  14. package/dist/config.js +40 -7
  15. package/dist/config.js.map +1 -1
  16. package/dist/errors.d.ts +50 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +115 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/fast-export.d.ts +2 -0
  21. package/dist/fast-export.d.ts.map +1 -1
  22. package/dist/fast-export.js +5 -1
  23. package/dist/fast-export.js.map +1 -1
  24. package/dist/mcp-server.d.ts.map +1 -1
  25. package/dist/mcp-server.js +4 -1
  26. package/dist/mcp-server.js.map +1 -1
  27. package/dist/mcp.js +1 -1
  28. package/dist/mcp.js.map +1 -1
  29. package/dist/paths.d.ts +18 -0
  30. package/dist/paths.d.ts.map +1 -1
  31. package/dist/paths.js +45 -0
  32. package/dist/paths.js.map +1 -1
  33. package/dist/project-match.d.ts +37 -0
  34. package/dist/project-match.d.ts.map +1 -0
  35. package/dist/project-match.js +97 -0
  36. package/dist/project-match.js.map +1 -0
  37. package/dist/proxy.d.ts +52 -0
  38. package/dist/proxy.d.ts.map +1 -0
  39. package/dist/proxy.js +189 -0
  40. package/dist/proxy.js.map +1 -0
  41. package/dist/remote-helper.d.ts +3 -2
  42. package/dist/remote-helper.d.ts.map +1 -1
  43. package/dist/remote-helper.js +130 -37
  44. package/dist/remote-helper.js.map +1 -1
  45. package/dist/term.d.ts +25 -0
  46. package/dist/term.d.ts.map +1 -0
  47. package/dist/term.js +42 -0
  48. package/dist/term.js.map +1 -0
  49. package/package.json +9 -4
package/README.md CHANGED
@@ -1,530 +1,233 @@
1
- # olcli — Overleaf CLI
1
+ # olcli: Overleaf CLI
2
2
 
3
- **Command-line interface for Overleaf** — Sync, manage, and compile LaTeX projects from your terminal.
3
+ **Work on Overleaf projects from your terminal while your coauthors keep using the Overleaf web editor.** Pull, push, sync, diff and compile LaTeX projects; read and answer review comments; use Overleaf as a git remote; give AI agents an MCP server that asks you before it writes.
4
4
 
5
5
  [![CI](https://github.com/aloth/olcli/actions/workflows/ci.yml/badge.svg)](https://github.com/aloth/olcli/actions/workflows/ci.yml)
6
6
  [![npm version](https://img.shields.io/npm/v/@aloth/olcli.svg)](https://www.npmjs.com/package/@aloth/olcli)
7
7
  [![npm downloads](https://img.shields.io/npm/dm/@aloth/olcli.svg)](https://www.npmjs.com/package/@aloth/olcli)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
- [![AgentSkills](https://img.shields.io/badge/AgentSkills-compatible-blue)](https://agentskills.io)
9
+
10
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23896243.svg)](https://doi.org/10.5281/zenodo.23896243)
10
11
  [![Glama MCP server](https://glama.ai/mcp/servers/aloth/olcli/badges/score.svg)](https://glama.ai/mcp/servers/aloth/olcli)
12
+ [![AgentSkills](https://img.shields.io/badge/AgentSkills-compatible-blue)](https://agentskills.io)
11
13
 
12
- Work with Overleaf projects directly from your command line. Edit locally with your favorite editor, version control with Git, and sync seamlessly with Overleaf's cloud compilation.
14
+ - **Coauthors change nothing.** They keep editing, commenting and compiling in the browser; you work in Vim, VS Code, Emacs or an agent and sync with the same project.
15
+ - **Works on the free Overleaf plan.** Pull, push, sync, diff, latexdiff, compile, PDF and output downloads, file operations, zip, comment listing and the git remote helper were checked on a free overleaf.com account. Tracked changes are the exception: Overleaf itself only offers them in premium projects.
16
+ - **Works on self-hosted Overleaf Community Edition** with the same commands.
17
+ - **No git token, no paid plan.** olcli signs in with your normal Overleaf session. Overleaf's own Git integration is a premium feature; olcli's git remote helper is not tied to it.
18
+ - **One package:** command-line tool, git remote helper, MCP server and TypeScript library.
13
19
 
14
20
  <p align="center">
15
21
  <img src="screenshots/demo.gif" alt="olcli demo" width="600">
16
22
  </p>
17
23
 
18
- ## Features
24
+ <p align="center">
25
+ <img src="screenshots/latexdiff.gif" alt="olcli diff --latexdiff --pdf turns a local edit into a marked-up PDF" width="600">
26
+ </p>
19
27
 
20
- - 📋 **List** all your Overleaf projects
21
- - ✨ **Create** blank or example projects
22
- - ⬇️ **Pull** project files to local directory for offline editing
23
- - ⬆️ **Push** local changes back to Overleaf
24
- - 🔄 **Sync** bidirectionally with smart conflict detection
25
- - 🔍 **Diff** local files against the live remote before pushing
26
- - 📝 **Marked-up revisions** — `diff --latexdiff` produces the struck-through/underlined PDF advisors and journals ask for
27
- - 🔀 **Git remote** — use Overleaf as a native git remote ([docs](docs/GIT-REMOTE.md))
28
- - ✌️ **Two-way deletions** — files removed locally are deleted on Overleaf on next sync
29
- - 🗑️ **Delete** and ✏️ **rename** remote files by path
30
- - 🚫 **Smart ignore** — LaTeX build artifacts and OS noise filtered automatically; extend with `.olignore`
31
- - 📄 **Compile** PDFs using Overleaf's remote compiler
32
- - 📦 **Download** individual files or full project archives
33
- - 📤 **Upload** files to projects
34
- - 💬 **Review comments** — list, add, resolve, reopen, delete, and reply to threads
35
- - 🗂️ **Preserve folder structure** when pushing nested files
36
- - ⏱️ **Configurable timeout** for slow connections
37
- - 🔑 **Password login** for self-hosted instances (no browser required)
38
- - ⚙️ **Self-hosted Overleaf/ShareLaTeX** support
39
- - 📊 **Output** compile artifacts (`.bbl`, `.log`, `.aux` for arXiv submissions)
40
- - 🤖 **MCP server** for AI assistants ([docs](docs/MCP.md))
41
-
42
- **Perfect for:**
43
- - Editing LaTeX in your preferred text editor (Vim, VS Code, Emacs, etc.)
44
- - Version control with Git while using Overleaf's compiler
45
- - Automating workflows and CI/CD pipelines
46
- - Offline work with periodic sync
47
-
48
- ## Installation
49
-
50
- ### Homebrew (macOS/Linux)
28
+ ## Install
51
29
 
52
30
  ```bash
53
- brew tap aloth/tap
54
- brew install olcli
31
+ brew install aloth/tap/olcli # Homebrew (macOS, Linux)
32
+ npm install -g @aloth/olcli # npm (any platform, Node 20.18.1 or newer)
55
33
  ```
56
34
 
57
- ### npm (all platforms)
35
+ On Linux with Nix: `nix run github:aloth/olcli -- --help`. Without installing: `npx @aloth/olcli list`. For AI agents through AgentSkills: `npx skills add aloth/olcli`.
36
+
37
+ ## Quick start
58
38
 
59
39
  ```bash
60
- npm install -g @aloth/olcli
40
+ olcli auth --browser # sign in through a browser window
41
+ olcli list # your projects
42
+ olcli pull "My Thesis" # download into ./My_Thesis
43
+ cd My_Thesis
44
+ vim main.tex
45
+ olcli diff # what would change on Overleaf
46
+ olcli push # upload your edits
47
+ olcli pdf # compile on Overleaf and download the PDF
61
48
  ```
62
49
 
63
- Or use with `npx` without installation:
50
+ `olcli auth --browser` opens the login page in Chrome, Edge, Chromium or Brave with a new temporary profile (never your own), waits until you have signed in, and keeps only the session cookie. It works with SSO, Google, ORCID and two-factor logins, and olcli never sees your password. It needs Node 22 or newer; set `OLCLI_BROWSER` when your browser is not found.
64
51
 
65
- ```bash
66
- npx @aloth/olcli list
67
- ```
52
+ ### Sign in with a session cookie
68
53
 
69
- ### For AI agents (via AgentSkills)
54
+ No supported browser, or a server without a display? Paste the cookie instead:
70
55
 
71
56
  ```bash
72
- npx skills add aloth/olcli
57
+ olcli auth --cookie # prompts, input stays hidden
58
+ pbpaste | olcli auth --cookie - # or read it from stdin
59
+ olcli auth status # instance, account, where the credential comes from
73
60
  ```
74
61
 
75
- ## Quick Start
62
+ **Get your session cookie:** sign in to Overleaf in a browser, open the developer tools (F12), then Application (Chrome, Edge) or Storage (Firefox), Cookies, and copy the value of `overleaf_session2` (`overleaf.sid` on most self-hosted instances). A value on the command line also works but lands in your shell history.
76
63
 
77
- ### 1. Authenticate
64
+ Self-hosted instances without reCAPTCHA also accept `olcli auth --email you@example.com`, which prompts for the password. Scripts can set `OVERLEAF_SESSION`, or `OVERLEAF_EMAIL` and `OVERLEAF_PASSWORD`, and skip `olcli auth` entirely.
78
65
 
79
- **Session cookie** (overleaf.com and self-hosted):
66
+ ### Self-hosted Overleaf
80
67
 
81
68
  ```bash
82
- olcli auth --cookie "your_session_cookie_value"
69
+ olcli config set-url https://latex.example.org
70
+ olcli config set-cookie-name overleaf.sid
71
+ olcli auth --browser
83
72
  ```
84
73
 
85
- **Email/password** (self-hosted without reCAPTCHA):
86
-
87
- ```bash
88
- olcli auth --email "you@example.com"
89
- # prompts for the password, so it stays out of your shell history
90
- ```
74
+ Or per command: `olcli --base-url https://latex.example.org list`. The MCP server and the git remote helper read `OVERLEAF_BASE_URL` and `OVERLEAF_COOKIE_NAME`.
91
75
 
92
- The password is **not stored** unless you pass `--save-password`. A session
93
- cookie is saved either way and is what later commands use; the password only
94
- buys an automatic re-login once that cookie expires. For scripts, set
95
- `OVERLEAF_EMAIL` and `OVERLEAF_PASSWORD` — every command reads them, so a
96
- scripted run never needs `olcli auth` at all.
76
+ ## Features
97
77
 
98
- ### 2. List Projects
78
+ - **Pull, push, sync** with nested folders, local deletions propagated on `sync`, and LaTeX build artifacts ignored ([ignore rules](docs/CONFIGURATION.md#ignoring-files))
79
+ - **Diff** local files against the live project before you push, with `--exit-code` for CI ([docs/DIFF.md](docs/DIFF.md))
80
+ - **Marked-up revisions:** `olcli diff --latexdiff --pdf` builds the struck-through and underlined PDF advisors and journals ask for, compiled on Overleaf, no local TeX needed (needs `latexdiff` on PATH)
81
+ - **Compile and download** the PDF, a single root document (`-r appendix.tex`), or compile outputs such as `.bbl` for arXiv
82
+ - **Files:** upload, download, delete, rename and move by path; download the project as a zip
83
+ - **Review comments:** list, add, reply, resolve, reopen and delete comment threads
84
+ - **Tracked changes:** list suggested insertions and deletions, accept or reject them. Track changes is an Overleaf premium feature: it is only available in projects whose owner has a premium plan, and invited collaborators on any plan can then use it. In other projects there are no tracked changes to list
85
+ - **Projects:** create, rename, and bulk-rename by pattern (dry run unless `--apply`)
86
+ - **Git remote:** `git clone overleaf::https://www.overleaf.com/project/<id>` ([docs/GIT-REMOTE.md](docs/GIT-REMOTE.md))
87
+ - **MCP server** for AI agents; every tool that writes asks you first ([docs/MCP.md](docs/MCP.md))
88
+ - **Forgiving project names:** case-insensitive, unique prefixes, "Did you mean" suggestions
89
+ - **Scriptable:** `--json` on listings, plain output when piped, `NO_COLOR`, exit codes that mean something
99
90
 
100
- ```bash
101
- olcli list
102
- ```
91
+ ## Use with Claude Code, Codex and Cursor
103
92
 
104
- ### 3. Pull, Edit, Push
93
+ olcli ships an MCP server, `olcli-mcp`. Add it to `.mcp.json` (Claude Code), `.cursor/mcp.json` (Cursor) or your client's MCP settings:
105
94
 
106
- ```bash
107
- olcli pull "My Thesis"
108
- cd My_Thesis/
109
- vim main.tex
110
- olcli push
95
+ ```json
96
+ {
97
+ "mcpServers": {
98
+ "overleaf": {
99
+ "command": "npx",
100
+ "args": ["-y", "--package", "@aloth/olcli", "olcli-mcp"]
101
+ }
102
+ }
103
+ }
111
104
  ```
112
105
 
113
- ### 4. Compile PDF
106
+ Codex uses TOML in `~/.codex/config.toml` (or `.codex/config.toml` in a trusted project):
114
107
 
115
- ```bash
116
- olcli pdf
117
- # Compile a specific .tex file (for multi-doc projects):
118
- olcli pdf -r appendix.tex
108
+ ```toml
109
+ [mcp_servers.overleaf]
110
+ command = "npx"
111
+ args = ["-y", "--package", "@aloth/olcli", "olcli-mcp"]
119
112
  ```
120
113
 
121
- ### 5. Or use native git commands
122
-
123
- ```bash
124
- git clone overleaf::https://www.overleaf.com/project/<id>
125
- cd <project>
126
- # edit, commit, push — standard git workflow
127
- git push
128
- ```
129
-
130
- See [Git Remote Helper docs](docs/GIT-REMOTE.md) for details.
114
+ The server uses the session stored by `olcli auth`; set `OVERLEAF_SESSION` in `env` instead if you prefer. Every tool that changes a project (push a file, delete, rename, comment, accept or reject tracked changes, create a project) shows you what it will do and writes only after you confirm it in the client. The server tells the agent that project content, such as comments and document text, is data and not instructions. Details, the full tool list and clients without confirmation support: [docs/MCP.md](docs/MCP.md).
131
115
 
132
116
  ## Commands
133
117
 
134
- All commands auto-detect the project when run from a synced directory (contains `.olcli.json`).
118
+ Inside a pulled directory (it contains `.olcli.json`), the project argument can be left out. `olcli <command> --help` shows every option with examples.
135
119
 
136
120
  | Command | Description |
137
121
  |---------|-------------|
138
- | `olcli auth` | Set session cookie or login with email/password |
139
- | `olcli whoami` | Check authentication status |
140
- | `olcli logout` | Clear the global config and the local `.olauth`, reporting each |
141
- | `olcli list` | List all projects |
142
- | `olcli info [project]` | Show project details and file list |
143
- | `olcli pull [project] [dir]` | Download project files to local directory |
144
- | `olcli push [dir]` | Upload local changes to Overleaf (`--delete` also removes files deleted locally) |
145
- | `olcli sync [dir]` | Bidirectional sync (pull + push) |
146
- | `olcli diff [project] [dir]` | Show content-level changes between local files and the remote |
147
- | `olcli upload <file> [project]` | Upload a single file (`--to <path>` sets the remote destination) |
148
- | `olcli download <file> [project]` | Download a single file |
149
- | `olcli delete <file> [project]` | Delete a remote file or folder (alias: `rm`) |
150
- | `olcli rename <old> <new> [project]` | Rename or move a remote file or folder (alias: `mv`); `<new>` with a folder part moves, a trailing `/` moves and keeps the name |
151
- | `olcli project create <name>` | Create a blank or example project (`--template blank\|example`) |
152
- | `olcli project rename <new> [project]` | Rename the project itself (`--dry-run`) |
153
- | `olcli project rename-bulk` | Rename many projects by pattern (dry-run unless `--apply`) |
154
- | `olcli compile [project]` | Trigger PDF compilation |
155
- | `olcli pdf [project]` | Compile and download PDF |
156
- | `olcli output [type]` | Download compile output files |
157
- | `olcli zip [project]` | Download project as zip archive |
158
- | `olcli comments list [project]` | List comments (`--status`, `--context`, `--concurrency`); `--changes` also lists tracked changes (with `--json` the output becomes `{ comments, changes }`) |
159
- | `olcli changes accept <ids...>` | Accept tracked changes by id (`--project`, `--json`) |
160
- | `olcli changes reject <ids...>` | Reject tracked changes by id; preview only unless `--yes` (`--project`, `--json`) |
161
- | `olcli comments add <file> <msg>` | Add a comment to selected text |
162
- | `olcli comments reply <id> <body>` | Reply to a comment thread |
163
- | `olcli comments resolve <id>` | Resolve a comment thread |
164
- | `olcli comments reopen <id>` | Reopen a resolved thread |
165
- | `olcli comments delete <id>` | Delete a comment thread |
166
- | `olcli ignored [dir]` | List ignore patterns in effect |
167
- | `olcli config set-url <url>` | Set self-hosted base URL |
168
- | `olcli config get-url` | Show the configured base URL |
169
- | `olcli config set-cookie-name <name>` | Set session cookie name |
170
- | `olcli config get-cookie-name` | Show the configured session cookie name |
171
- | `olcli config set-timeout <ms>` | Set default HTTP timeout |
172
- | `olcli config get-timeout` | Show the configured HTTP timeout |
173
- | `olcli check` | Show config paths and credential sources |
174
-
175
- > **Tracked changes are an Overleaf premium feature.** They are only available in projects whose owner has a premium plan; invited collaborators can then use them regardless of their own plan. In other projects there are no tracked changes, so `--changes` returns an empty list and `changes accept`/`changes reject` report the ids as not found. See the [Overleaf documentation](https://docs.overleaf.com/collaborating/track-changes) for details.
176
-
177
- ### Compile Options
178
-
179
- The compile-related commands (`compile`, `pdf`, `output`) accept:
180
-
181
- | Flag | Description |
182
- |------|-------------|
183
- | `-r, --resource <path>` | Compile a specific `.tex` file as the root document (e.g. `appendix.tex`, `folder/test.tex`) |
184
-
185
- Useful in multi-doc projects: each `-r` run compiles the file as if it were the main document.
186
-
187
- ### Global Options
188
-
189
- | Flag | Description |
190
- |------|-------------|
191
- | `--verbose` | Print HTTP requests and responses to stderr |
192
- | `--base-url <url>` | Override Overleaf instance URL |
193
- | `--cookie-name <name>` | Override session cookie name |
194
- | `--timeout <ms>` | Override HTTP timeout (default: 10000) |
195
-
196
- ## Sync Behavior
197
-
198
- ### Pull
199
- - Downloads all files from Overleaf
200
- - Skips local files modified after last pull (won't overwrite your changes)
201
- - Use `--force` to overwrite local changes
202
-
203
- ### Push
204
- - Uploads files modified after last pull
205
- - Preserves nested folder structure
206
- - Filters out LaTeX build artifacts and OS noise
207
- - Use `--all` to upload all files, `--dry-run` to preview
208
-
209
- ### Sync
210
- - Pulls remote changes, then pushes local changes
211
- - Local modifications win if newer
212
- - **Propagates local deletions** — use `--no-delete` to opt out
213
- - Use `--dry-run` to preview without applying
214
-
215
- ### Diff
216
-
217
- `olcli diff` compares the bytes of your local files against the project's
218
- current contents and prints a unified diff.
219
-
220
- ```bash
221
- olcli diff # every changed file, as patches
222
- olcli diff --name-only # just the changed paths
223
- olcli diff --file main.tex # one file
224
- olcli diff -U 8 # wider context
225
- olcli diff --exit-code # exit 1 if anything differs, for CI
226
- ```
227
-
228
- **The remote side is fetched fresh on every run.** The diff describes the
229
- project as it is at that moment — which is what a subsequent `push` would
230
- overwrite — not a comparison against your last `pull`. `.olcli.json` records
231
- remote *paths*, never remote *contents*, so there is no stored snapshot to
232
- compare against; and the whole project arrives in a single request, the same
233
- one `pull` makes, so fetching fresh costs one round trip rather than one per
234
- file. A collaborator editing between `diff` and `push` can still change the
235
- outcome, which is why the fetch time is printed.
236
-
237
- In the output, `a/` is the remote and `b/` is local: a `+` line is content
238
- `push` would upload, a `-` line is content it would overwrite. Files that
239
- differ only in bytes that are not text (PDFs, images) are reported as
240
- `Binary files ... differ`. Both sides pass through the same ignore layers, so
241
- build artifacts sitting on Overleaf are not reported as locally deleted.
242
-
243
- `diff --name-only` and `push --dry-run` answer different questions and will
244
- disagree. `push --dry-run` lists files whose **modification time** is newer
245
- than the last pull, because that is what `push` uploads; `diff` lists files
246
- whose **contents** actually differ. A file you touched without editing appears
247
- in the first and not the second.
248
-
249
- #### Marked-up revisions with latexdiff
250
-
251
- A unified diff is the right artifact for a developer and the wrong one for a
252
- thesis advisor. `--latexdiff` marks the same revision up inside the document
253
- instead — deletions struck through, additions underlined — which is what
254
- advisors and journals ask for.
255
-
256
- ```bash
257
- olcli diff --latexdiff # write .olcli-diff/main-diff.tex
258
- olcli diff --latexdiff --pdf # ...and compile it, download .olcli-diff/main-diff.pdf
259
- ```
260
-
261
- Requires `latexdiff` on your PATH. It ships with TeX Live and MacTeX; nothing
262
- else in `olcli diff` needs an external tool.
263
-
264
- **`--pdf` compiles on Overleaf, so you do not need a local TeX installation.**
265
- The compile endpoint can only build a file that is in the project, so the
266
- marked-up document is uploaded as `olcli-latexdiff.tex` next to your root
267
- document, compiled, downloaded, and then removed. The command says so before it
268
- does it, refuses to overwrite a file of that name if one already exists, and
269
- prints the exact `olcli rm` command if the cleanup itself fails.
270
-
271
- `\input` and `\include` are inlined before comparing (`--no-flatten` to opt
272
- out). Without that, a remote compile would resolve those against the files
273
- sitting in the project — the old content — and quietly produce a PDF showing
274
- every input file as unchanged.
275
-
276
- Output goes to `.olcli-diff/`, which is dotted so that `push` and `sync` never
277
- pick it up; `-o <path>` puts it elsewhere. The root document is the `.tex` file
278
- declaring `\documentclass`; if several do, `--main <path>` picks one rather
279
- than the command guessing. `--latexdiff-opt` passes anything else straight
280
- through, e.g. `--latexdiff-opt --math-markup=0`.
281
-
282
- One limit worth knowing: `--pdf` compiles against the project, not against your
283
- working directory, so anything the markup needs must already be on Overleaf. A
284
- `.sty` or `.cls` you added locally fails the compile — the compiler log is
285
- written next to the marked-up source when that happens. A *figure* you added
286
- locally does not fail it; Overleaf draws a placeholder box naming the missing
287
- file and the rest of the PDF is fine.
288
-
289
- #### Using `diff` as a CI gate
290
-
291
- `--exit-code` turns the command into a check, with the statuses `diff(1)` uses:
292
-
293
- | Status | Meaning |
294
- |--------|---------|
295
- | `0` | Nothing differs |
296
- | `1` | Something differs |
297
- | `2` | The run failed — bad flags, no session, project unreachable |
298
-
299
- ```yaml
300
- - name: Fail if the paper on Overleaf has drifted from the repo
301
- run: olcli diff --exit-code --name-only
302
- env:
303
- OVERLEAF_SESSION: ${{ secrets.OVERLEAF_SESSION }}
304
- ```
305
-
306
- **The `1` versus `2` split is the point of the flag.** Without it a pipeline
307
- cannot tell a changed file from an expired session cookie, and a job that goes
308
- red for the second reason sends whoever reads the log hunting for a diff that
309
- was never computed. Every other olcli command reports failure as `1`, and
310
- `olcli diff` still does when `--exit-code` is absent, so adding the flag does
311
- not change what existing scripts see.
312
-
313
- The gate covers whatever was compared: `--file main.tex` narrows it to one
314
- file, the way a `git diff --exit-code` pathspec does, and a `--file` that
315
- matches nothing is `0` rather than an error. Under `--latexdiff` it still
316
- reports on the project as a whole — a changed figure is a real difference even
317
- though a marked-up root document cannot show it.
318
-
319
- Note that this compares against Overleaf **now**, not against your last pull,
320
- so the check is "has anyone drifted from what is committed here", which is what
321
- makes it worth running on a schedule as well as on a push.
322
-
323
- #### How deletion propagation works
324
-
325
- `olcli` records a manifest of remote files in `.olcli.json`. On next sync:
326
-
327
- - File missing locally + still on remote → deleted on Overleaf
328
- - File new locally → uploaded
329
- - File modified locally → uploaded (local wins)
330
- - File only on remote → downloaded
331
-
332
- First-time syncs skip the deletion phase (no prior manifest to compare).
333
-
334
- ## Ignoring Files
335
-
336
- ### Three layers
337
-
338
- | Layer | Source | Purpose |
339
- |---|---|---|
340
- | 1 | Built-in | LaTeX intermediates, OS noise, build dirs. Always on. |
341
- | 2 | `.olignore` | Project-level patterns (gitignore syntax). |
342
- | 3 | `.olignore.local` | Machine-specific patterns. |
343
-
344
- Later layers override earlier ones. Negation (`!important.aux`) is supported.
345
-
346
- ### Special PDF rule
347
-
348
- `X.pdf` is ignored only if `X.tex` (or `.ltx`) exists in the same folder.
349
-
350
- ### Inspecting and overriding
351
-
352
- ```bash
353
- olcli ignored # list patterns in effect
354
- olcli push --show-ignored # see what was skipped
355
- olcli sync --no-default-ignore # only .olignore applies
356
- olcli sync --no-ignore # upload everything
357
- ```
358
-
359
- ## Configuration
360
-
361
- Credentials are checked in order:
362
-
363
- 1. `OVERLEAF_SESSION` environment variable
364
- 2. `.olauth` file in current directory
365
- 3. Global config — run `olcli check` to see the exact path
366
-
367
- The global config path is platform-dependent (`conf` resolves it), so it is not
368
- hardcoded here: on macOS it lands under `~/Library/Preferences/`, on Linux under
369
- `~/.config/`. `olcli auth` prints the path it wrote to.
370
-
371
- ⚠️ `olcli auth --save-local` writes `.olauth` into the **current directory**,
372
- which is usually your LaTeX project. Add it to that project's `.gitignore`
373
- before committing.
374
-
375
- ### What is stored, and how to clear it
376
-
377
- Everything is stored in plaintext, so it is worth knowing what is on disk:
378
-
379
- | Credential | Stored by default | Where |
380
- |---|---|---|
381
- | Session cookie | yes | global config, or `.olauth` with `--save-local` |
382
- | Email + password | **no** — only with `--save-password` | global config |
383
-
384
- `olcli check` reports what exists without printing any secret.
385
-
386
- `olcli logout` clears the global config **and** the `.olauth` file in the
387
- current directory, then lists what it removed. It cannot unset environment
388
- variables, so if `OVERLEAF_SESSION` or `OVERLEAF_EMAIL`/`OVERLEAF_PASSWORD` are
389
- set, it says so instead of implying you are logged out — those take precedence
390
- over anything on disk.
391
-
392
- ### Self-hosted Overleaf
393
-
394
- ```bash
395
- olcli config set-url https://latex.example.org
396
- olcli config set-cookie-name overleaf.sid
397
- ```
398
-
399
- Or pass per-command: `olcli --base-url https://latex.example.org list`
400
-
401
- ### Timeout
402
-
403
- ```bash
404
- olcli config set-timeout 60000 # persist
405
- olcli --timeout 60000 pull "Big Thesis" # one-off
406
- export OVERLEAF_TIMEOUT=60000 # env var
407
- ```
408
-
409
- Precedence: `--timeout` > `OVERLEAF_TIMEOUT` > config > default (10000ms).
410
-
411
- ### Environment variables
412
-
413
- olcli reads these. The MCP server and the git remote helper read the same session, password and cookie name variables. Where a flag exists, the flag takes precedence over the variable, and the variable over the stored config.
414
-
415
- | Variable | Purpose |
416
- |---|---|
417
- | `OVERLEAF_SESSION` | Session cookie value |
418
- | `OVERLEAF_EMAIL`, `OVERLEAF_PASSWORD` | Password login, used when no session cookie is set or it is rejected |
419
- | `OVERLEAF_BASE_URL` | Instance URL, like `--base-url` (default: `https://www.overleaf.com`) |
420
- | `OVERLEAF_COOKIE_NAME` | Session cookie name, like `--cookie-name` (default: `overleaf_session2`; self-hosted instances often use `overleaf.sid`) |
421
- | `OVERLEAF_TIMEOUT` | HTTP timeout in milliseconds, like `--timeout` |
422
- | `OLCLI_CONCURRENCY` | Documents fetched in parallel by `comments list`, 1 to 8 (default: 4); `--concurrency` takes precedence |
423
- | `OLCLI_MCP_UNCONFIRMED_WRITES` | MCP server only: `1` turns off write confirmation, see [docs/MCP.md](docs/MCP.md#write-confirmation) |
424
- | `GIT_REMOTE_OVERLEAF_DEBUG` | Git remote helper only: `1` prints protocol debug output, see [docs/GIT-REMOTE.md](docs/GIT-REMOTE.md#debugging) |
122
+ | `olcli auth` | Sign in: `--browser`, `--cookie`, or `--email` |
123
+ | `olcli auth status` | Instance, account, credential source; exits 1 when not signed in |
124
+ | `olcli logout` | Clear stored credentials |
125
+ | `olcli list` | List projects (`--json`, `-n`) |
126
+ | `olcli info [project]` | Project details and file list |
127
+ | `olcli project create <name>` | Create a blank or example project (`--template`) |
128
+ | `olcli project rename <new> [project]` | Rename the project itself |
129
+ | `olcli project rename-bulk` | Rename many projects by pattern (dry run unless `--apply`) |
130
+ | `olcli pull [project] [dir]` | Download project files |
131
+ | `olcli push [dir]` | Upload local changes (`--dry-run`, `--all`, `--delete`) |
132
+ | `olcli sync [dir]` | Pull then push, propagating local deletions (`--no-delete`, `--dry-run`) |
133
+ | `olcli diff [project] [dir]` | Content diff against the live project (`--name-only`, `--exit-code`, `--latexdiff`, `--pdf`) |
134
+ | `olcli upload <file> [project]` | Upload one file (`--to <path>`) |
135
+ | `olcli download <file> [project]` | Download one file (`-o`) |
136
+ | `olcli delete <file> [project]` | Delete a file or folder (alias `rm`) |
137
+ | `olcli rename <old> <new> [project]` | Rename or move a file or folder (alias `mv`) |
138
+ | `olcli zip [project]` | Download the project as a zip archive |
139
+ | `olcli compile [project]` | Compile on Overleaf (`-r <root.tex>`) |
140
+ | `olcli pdf [project]` | Compile and download the PDF (`-o`, `-r`) |
141
+ | `olcli output [type]` | Download compile outputs such as `bbl` or `log` (`--list`) |
142
+ | `olcli comments list [project]` | List comments (`--status`, `--context`, `--changes`, `--json`) |
143
+ | `olcli comments add <file> <message>` | Comment on selected text |
144
+ | `olcli comments reply <id> <body>` | Reply to a thread |
145
+ | `olcli comments resolve <id>` | Resolve a thread (`reopen` and `delete` too) |
146
+ | `olcli changes accept <ids...>` | Accept tracked changes (premium projects) |
147
+ | `olcli changes reject <ids...>` | Reject tracked changes; preview unless `--yes` |
148
+ | `olcli config set-url <url>` | Set the instance URL (`get-url`, `set-cookie-name`, `set-timeout`) |
149
+ | `olcli ignored [dir]` | Show the ignore patterns in effect |
150
+
151
+ Global options: `--base-url <url>`, `--cookie-name <name>`, `--timeout <ms>`, `--verbose` (print every HTTP request), `--no-color`.
152
+
153
+ ## How sync works
154
+
155
+ - `pull` downloads every file and skips local files changed since the last pull; `--force` overwrites them.
156
+ - `push` uploads files changed since the last pull and keeps the folder structure. `push --dry-run` lists them; `olcli diff` shows what actually differs.
157
+ - `sync` pulls, then pushes. Local edits win when they are newer, and a file you deleted locally is deleted on Overleaf (`--no-delete` to opt out; `sync --dry-run --verbose` to preview).
158
+ - Before a push, `olcli diff` compares against the project as it is on Overleaf right now, so you see a coauthor's newer edit before you overwrite it.
425
159
 
426
160
  ## Examples
427
161
 
428
162
  ```bash
429
163
  # Daily thesis workflow
430
164
  olcli pull "PhD Thesis" thesis && cd thesis
431
- vim chapters/methods.tex
432
165
  olcli sync && olcli pdf -o draft.pdf
433
166
 
434
- # Quick PDF download
435
- olcli pdf "Conference Paper" -o paper.pdf
167
+ # Marked-up PDF of your local revision for your advisor
168
+ olcli diff --latexdiff --pdf
436
169
 
437
- # Compile a specific root document
438
- olcli pdf "Conference Paper" -r appendix.tex -o appendix.pdf
439
- olcli compile "Conference Paper" -r folder/test.tex
170
+ # Fail a CI job when the paper on Overleaf drifted from the repository
171
+ olcli diff --exit-code --name-only
440
172
 
441
- # Upload figures
442
- olcli upload figures/diagram.png # relative path is preserved
443
- olcli upload /tmp/build/diagram.png # absolute path lands in the project root
444
- olcli upload /tmp/build/diagram.png --to figures/diagram.png # explicit destination
173
+ # Review comments, with two lines of context
174
+ olcli comments list --status open --context 2
445
175
 
446
176
  # arXiv submission prep
447
177
  olcli output bbl -o main.bbl
448
- olcli output bbl -r folder/test.tex -o main.bbl # compile artifacts from a specific root doc
449
178
  olcli zip -o arxiv-submission.zip
450
179
 
451
- # Backup all projects
180
+ # Back up every project
452
181
  for proj in $(olcli list --json | jq -r '.[].name'); do
453
182
  olcli zip "$proj" -o "backups/${proj}.zip"
454
183
  done
455
184
  ```
456
185
 
457
- ## Programmatic Usage (Library API)
458
-
459
- `@aloth/olcli` exposes `OverleafClient` and all public interfaces as a library.
186
+ ## Proxy
460
187
 
461
- ### Install
188
+ olcli honors `HTTPS_PROXY`, `HTTP_PROXY`, `ALL_PROXY` and `NO_PROXY` (lower-case names take precedence) for every request. https:// instances are reached through a CONNECT tunnel, so the proxy never sees the session cookie. `localhost` and loopback addresses are always reached directly. `--verbose` names the proxy used for each request.
462
189
 
463
190
  ```bash
464
- npm install @aloth/olcli
191
+ HTTPS_PROXY=http://proxy.example.org:3128 olcli list
465
192
  ```
466
193
 
467
- ### Basic example
194
+ ## Configuration and credentials
195
+
196
+ Credentials are read in this order: `OVERLEAF_SESSION`, then `.olauth` in the current directory (written by `olcli auth --save-local`), then the global config. `olcli auth status` shows which one is used and where it lives. The session cookie is stored in plaintext; a password only when you pass `--save-password`. `olcli logout` clears the global config and `.olauth`.
197
+
198
+ Every environment variable, the timeout setting and the ignore rules (`.olignore`, `.olignore.local`) are described in [docs/CONFIGURATION.md](docs/CONFIGURATION.md). `olcli --help` lists the variables too.
199
+
200
+ ## Library
468
201
 
469
202
  ```ts
470
203
  import { OverleafClient } from '@aloth/olcli';
471
204
 
472
205
  const client = await OverleafClient.fromSessionCookie(cookie);
473
-
474
- const created = await client.createProject('My Paper');
475
206
  const projects = await client.listProjects();
476
- const info = await client.getProjectInfo(projectId);
477
- const zipBuf = await client.downloadProject(projectId);
478
- const pdfBuf = await client.downloadPdf(projectId);
479
-
480
- await client.uploadFile(projectId, null, 'main.tex', readFileSync('main.tex'));
481
-
482
- const comments = await client.listComments(projectId, { status: 'open' });
207
+ const pdf = await client.downloadPdf(projects[0].id);
483
208
  ```
484
209
 
485
- ### Available exports
486
-
487
- ```ts
488
- import {
489
- OverleafClient,
490
- // Types
491
- Project, ProjectInfo, ProjectTemplate, CreateProjectOptions, CreatedProject,
492
- FolderEntry, DocEntry, FileEntry,
493
- CommentMessage, ProjectComment, CommentContext, CommentStatus,
494
- ListCommentsOptions, AddCommentOptions, Credentials, SessionCookiePair,
495
- // Config utilities
496
- getBaseUrl, setBaseUrl, getSessionCookie, setSessionCookie,
497
- getSessionCookieName, setSessionCookieName, getCsrf, setCsrf,
498
- getLastProject, setLastProject, clearConfig, getConfigPath, saveOlAuth,
499
- getTimeout, setTimeout, getPasswordCredentials, setPasswordCredentials,
500
- clearPasswordCredentials, type PasswordCredentials,
501
- // Ignore utilities
502
- DEFAULT_IGNORE_PATTERNS, loadIgnore, shouldIgnore, buildTexSiblingSet,
503
- IgnoreContext, LoadIgnoreOptions,
504
- } from '@aloth/olcli';
505
- ```
506
-
507
- ## Further Documentation
508
-
509
- - [MCP Server](docs/MCP.md) — AI assistant integration (Claude, Cursor, Windsurf)
510
- - Tools that change a project ask you to confirm through MCP elicitation and write nothing without it; clients without elicitation get a preview and the `olcli` command to run instead. `OLCLI_MCP_UNCONFIRMED_WRITES=1` turns this off. See [Write confirmation](docs/MCP.md#write-confirmation)
511
- - [Git Remote Helper](docs/GIT-REMOTE.md) — use Overleaf as a native git remote
210
+ All exports: [docs/LIBRARY.md](docs/LIBRARY.md).
512
211
 
513
212
  ## Troubleshooting
514
213
 
515
- **Session expired** — Get a fresh cookie from the browser and run `olcli auth` again.
214
+ - **"Session expired or invalid. Run: olcli auth"**: sessions expire; sign in again. `olcli auth status` tells you which credential was used.
215
+ - **Timeouts on large projects:** `olcli config set-timeout 60000`, or `--timeout 60000` once.
216
+ - **Compilation fails:** the Overleaf web editor shows the full log; `olcli output log` downloads it.
217
+ - **Anything else:** run the command with `--verbose` and include the output (without the cookie) in an issue.
516
218
 
517
- **Compilation fails** — Check the Overleaf web editor for detailed error logs (missing packages, syntax errors, missing bibliography files).
219
+ ## Documentation
518
220
 
519
- ## Contributing
221
+ - [docs/DIFF.md](docs/DIFF.md): diff, latexdiff and the CI gate
222
+ - [docs/MCP.md](docs/MCP.md): MCP server, tools and write confirmation
223
+ - [docs/GIT-REMOTE.md](docs/GIT-REMOTE.md): Overleaf as a git remote
224
+ - [docs/CONFIGURATION.md](docs/CONFIGURATION.md): credentials, environment variables, timeout, ignore rules
225
+ - [docs/LIBRARY.md](docs/LIBRARY.md): TypeScript library
226
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md): how the client talks to Overleaf (there is no public Overleaf API, so it uses a browser session)
520
227
 
521
- Contributions are welcome! Please open an issue or submit a pull request.
522
-
523
- See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, which tests need a real
524
- Overleaf account, and what to expect from CI on a pull request.
228
+ ## Contributing
525
229
 
526
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) explains how the client works —
527
- there is no public Overleaf API, so it authenticates as a browser session.
230
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, which tests need a real Overleaf account, and what CI checks on a pull request.
528
231
 
529
232
  ## License
530
233