@aloth/olcli 0.6.0 → 0.7.0

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.
package/README.md CHANGED
@@ -3,7 +3,8 @@
3
3
  **Command-line interface for Overleaf** — Sync, manage, and compile LaTeX projects from your terminal.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@aloth/olcli.svg)](https://www.npmjs.com/package/@aloth/olcli)
6
- [![AUR Package](https://img.shields.io/aur/version/olcli)](https://aur.archlinux.org/packages/olcli)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@aloth/olcli.svg)](https://www.npmjs.com/package/@aloth/olcli)
7
+ [![GitHub stars](https://img.shields.io/github/stars/aloth/olcli)](https://github.com/aloth/olcli)
7
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
9
  [![AgentSkills](https://img.shields.io/badge/AgentSkills-compatible-blue)](https://agentskills.io)
9
10
 
@@ -15,31 +16,30 @@ Work with Overleaf projects directly from your command line. Edit locally with y
15
16
 
16
17
  ## Features
17
18
 
18
- **Full Overleaf command-line access:**
19
-
20
19
  - 📋 **List** all your Overleaf projects
21
20
  - ⬇️ **Pull** project files to local directory for offline editing
22
21
  - ⬆️ **Push** local changes back to Overleaf
23
22
  - 🔄 **Sync** bidirectionally with smart conflict detection
24
- - ✌️ **Two-way deletions** — files removed locally are deleted on Overleaf on the next sync (opt out with `--no-delete`)
23
+ - 🔀 **Git remote** — use Overleaf as a native git remote ([docs](docs/GIT-REMOTE.md))
24
+ - ✌️ **Two-way deletions** — files removed locally are deleted on Overleaf on next sync
25
25
  - 🗑️ **Delete** and ✏️ **rename** remote files by path
26
- - 🚫 **Smart ignore** — LaTeX build artifacts (`.aux`, `.bbl`, `.log`, `.synctex.gz`, …) and OS noise are filtered out automatically; extend with `.olignore` (gitignore-style)
26
+ - 🚫 **Smart ignore** — LaTeX build artifacts and OS noise filtered automatically; extend with `.olignore`
27
27
  - 📄 **Compile** PDFs using Overleaf's remote compiler
28
28
  - 📦 **Download** individual files or full project archives
29
29
  - 📤 **Upload** files to projects
30
- - 💬 **Review comments** — list comments with source locations, add, resolve, reopen, delete threads, and **reply** to existing threads
30
+ - 💬 **Review comments** — list, add, resolve, reopen, delete, and reply to threads
31
31
  - 🗂️ **Preserve folder structure** when pushing nested files
32
- - ⏱️ **Configurable timeout** — global `--timeout <ms>` flag, `OVERLEAF_TIMEOUT` env var, or `config set-timeout` for slow connections
33
- - 🔑 **Password login** — `olcli auth --email --password` for self-hosted instances (no browser required)
34
- - ⚙️ **Support self-hosted Overleaf/ShareLaTeX instances** via configurable base URL and session cookie name
32
+ - ⏱️ **Configurable timeout** for slow connections
33
+ - 🔑 **Password login** for self-hosted instances (no browser required)
34
+ - ⚙️ **Self-hosted Overleaf/ShareLaTeX** support
35
35
  - 📊 **Output** compile artifacts (`.bbl`, `.log`, `.aux` for arXiv submissions)
36
+ - 🤖 **MCP server** for AI assistants ([docs](docs/MCP.md))
36
37
 
37
38
  **Perfect for:**
38
39
  - Editing LaTeX in your preferred text editor (Vim, VS Code, Emacs, etc.)
39
40
  - Version control with Git while using Overleaf's compiler
40
41
  - Automating workflows and CI/CD pipelines
41
42
  - Offline work with periodic sync
42
- - Collaborative projects where some prefer CLI, others prefer web
43
43
 
44
44
  ## Installation
45
45
 
@@ -52,8 +52,6 @@ brew install olcli
52
52
 
53
53
  ### npm (all platforms)
54
54
 
55
- Install globally to use the `olcli` command anywhere:
56
-
57
55
  ```bash
58
56
  npm install -g @aloth/olcli
59
57
  ```
@@ -70,95 +68,53 @@ npx @aloth/olcli list
70
68
  npx skills add aloth/olcli
71
69
  ```
72
70
 
73
- ### Arch Linux
74
-
75
- The package is available on the [Arch User Repository (AUR)](https://aur.archlinux.org/packages/olcli).
76
-
77
- You can install it using your preferred AUR helper (such as `yay` or `paru`):
78
-
79
- ```bash
80
- yay -S olcli
81
- # or
82
- paru -S olcli
83
- ```
84
-
85
- #### Manual Installation:
86
- If you prefer not to use an AUR helper, you can build and install the package manually using makepkg:
87
- code Bash
88
-
89
- ```bash
90
- git clone https://aur.archlinux.org/olcli.git
91
- cd olcli
92
- makepkg -si
93
- ```
94
-
95
71
  ## Quick Start
96
72
 
97
- ### 1. Authenticate with Overleaf
73
+ ### 1. Authenticate
98
74
 
99
- **Option A: Session cookie** (overleaf.com and self-hosted)
100
-
101
- 1. Log into [overleaf.com](https://www.overleaf.com)
102
- 2. Open Developer Tools (F12 or Cmd+Option+I) → Application/Storage → Cookies
103
- 3. Copy the value of `overleaf_session2`
75
+ **Session cookie** (overleaf.com and self-hosted):
104
76
 
105
77
  ```bash
106
78
  olcli auth --cookie "your_session_cookie_value"
107
79
  ```
108
80
 
109
- **Option B: Email/password** (self-hosted instances without reCAPTCHA)
81
+ **Email/password** (self-hosted without reCAPTCHA):
110
82
 
111
83
  ```bash
112
84
  olcli auth --email "you@example.com" --password "your_password"
113
85
  ```
114
86
 
115
- Credentials are stored securely and the session auto-refreshes on expiry.
116
-
117
- **Tip:** The cookie stays valid for weeks. Just refresh it when authentication fails.
118
-
119
- ### 2. List Your Projects
87
+ ### 2. List Projects
120
88
 
121
89
  ```bash
122
90
  olcli list
123
91
  ```
124
92
 
125
- See all your Overleaf projects with IDs and last modified dates.
126
-
127
- ### 3. Pull a Project Locally
128
-
129
- Download any project to work on it locally:
93
+ ### 3. Pull, Edit, Push
130
94
 
131
95
  ```bash
132
96
  olcli pull "My Thesis"
133
97
  cd My_Thesis/
134
- ```
135
-
136
- Now you can edit `.tex` files with your preferred editor (Vim, VS Code, Emacs, etc.).
137
-
138
- ### 4. Edit Locally, Sync to Overleaf
139
-
140
- ```bash
141
- # Edit files locally with your favorite editor
142
98
  vim main.tex
143
-
144
- # Push changes back to Overleaf
145
99
  olcli push
146
-
147
- # Or sync bidirectionally (pull + push in one command)
148
- olcli sync
149
100
  ```
150
101
 
151
- Your collaborators can continue using the Overleaf web editor — changes sync seamlessly.
102
+ ### 4. Compile PDF
152
103
 
153
- ### 5. Compile and Download PDF
104
+ ```bash
105
+ olcli pdf
106
+ ```
154
107
 
155
- Use Overleaf's remote compiler from the command line:
108
+ ### 5. Or use native git commands
156
109
 
157
110
  ```bash
158
- olcli pdf
111
+ git clone overleaf::https://www.overleaf.com/project/<id>
112
+ cd <project>
113
+ # edit, commit, push — standard git workflow
114
+ git push
159
115
  ```
160
116
 
161
- The compiled PDF downloads automatically to your current directory.
117
+ See [Git Remote Helper docs](docs/GIT-REMOTE.md) for details.
162
118
 
163
119
  ## Commands
164
120
 
@@ -176,302 +132,142 @@ All commands auto-detect the project when run from a synced directory (contains
176
132
  | `olcli sync [dir]` | Bidirectional sync (pull + push) |
177
133
  | `olcli upload <file> [project]` | Upload a single file |
178
134
  | `olcli download <file> [project]` | Download a single file |
179
- | `olcli comments list [project]` | List comments with source text and file locations (`--status`, `--context`) |
180
- | `olcli comments add <file> <message> [project]` | Add a comment to selected text |
181
- | `olcli comments resolve <threadId> [project]` | Resolve a comment thread |
182
- | `olcli comments reply <threadId> <body> [project]` | Reply to a comment thread |
183
- | `olcli comments reopen <threadId> [project]` | Reopen a resolved comment thread |
184
- | `olcli comments delete <threadId> [project]` | Permanently delete a comment thread |
185
- | `olcli delete <file> [project]` | Delete a remote file or folder by path (alias: `rm`) |
186
- | `olcli rename <oldname> <newname> [project]` | Rename a remote file or folder by path (alias: `mv`) |
187
- | `olcli ignored [dir]` | List ignore patterns currently in effect |
188
- | `olcli zip [project]` | Download project as zip archive |
135
+ | `olcli delete <file> [project]` | Delete a remote file or folder (alias: `rm`) |
136
+ | `olcli rename <old> <new> [project]` | Rename a remote file or folder (alias: `mv`) |
189
137
  | `olcli compile [project]` | Trigger PDF compilation |
190
138
  | `olcli pdf [project]` | Compile and download PDF |
191
139
  | `olcli output [type]` | Download compile output files |
192
- | `olcli config set-url <url>` | Set a self-hosted Overleaf base URL |
193
- | `olcli config set-cookie-name <name>` | Set the session cookie name |
194
- | `olcli config set-timeout <ms>` | Set default HTTP request timeout |
195
- | `olcli config get-timeout` | Show current timeout setting |
140
+ | `olcli zip [project]` | Download project as zip archive |
141
+ | `olcli comments list [project]` | List comments (`--status`, `--context`) |
142
+ | `olcli comments add <file> <msg>` | Add a comment to selected text |
143
+ | `olcli comments reply <id> <body>` | Reply to a comment thread |
144
+ | `olcli comments resolve <id>` | Resolve a comment thread |
145
+ | `olcli comments reopen <id>` | Reopen a resolved thread |
146
+ | `olcli comments delete <id>` | Delete a comment thread |
147
+ | `olcli ignored [dir]` | List ignore patterns in effect |
148
+ | `olcli config set-url <url>` | Set self-hosted base URL |
149
+ | `olcli config set-cookie-name <name>` | Set session cookie name |
150
+ | `olcli config set-timeout <ms>` | Set default HTTP timeout |
196
151
  | `olcli check` | Show config paths and credential sources |
197
152
 
198
- ### Review comments
199
-
200
- ```bash
201
- olcli comments list "My Paper" --status open --context 2
202
- olcli comments list "My Paper" --status resolved --json
203
- olcli comments add main.tex "Please clarify this definition" "My Paper" --text "A Skill is"
204
- olcli comments add main.tex "Check this sentence" "My Paper" --line 42 --column 1 --length 20 --json
205
- olcli comments reply 6a1a5fedbf90b811e1000001 "Good point, I'll fix this" "My Paper"
206
- olcli comments resolve 6a1a5fedbf90b811e1000001 "My Paper" --json
207
- olcli comments reopen 6a1a5fedbf90b811e1000001 "My Paper"
208
- olcli comments delete 6a1a5fedbf90b811e1000001 "My Paper" --json
209
- ```
210
-
211
- ### Global options
212
-
213
- These flags work with **every** command and may be placed before or after the command name:
153
+ ### Global Options
214
154
 
215
155
  | Flag | Description |
216
156
  |------|-------------|
217
- | `--verbose` | Print every HTTP request, status, content-type, and (on errors) a response-body snippet to stderr. Useful for debugging failed compiles, 404s on `pdf`/`output`, auth issues, or unexpected upload behavior. |
218
- | `--base-url <url>` | Override the Overleaf instance base URL (also `OVERLEAF_BASE_URL` env var or `olcli config set-url`). |
219
- | `--cookie-name <name>` | Override the session cookie name (default `overleaf_session2`; older instances use `overleaf.sid`). |
220
- | `--timeout <ms>` | Override the HTTP request timeout in milliseconds (also `OVERLEAF_TIMEOUT` env var or `olcli config set-timeout`). Default: 10000. |
221
-
222
- Examples:
223
-
224
- ```bash
225
- olcli --verbose pdf # see every request the compile makes
226
- olcli pdf --verbose # same thing, flag after command
227
- olcli --verbose sync # debug a sync that's misbehaving
228
- olcli --verbose upload figures/a.png # confirm the file is placed in figures/
229
- ```
230
-
231
- ## Use Cases
232
-
233
- ### Local Editing with Overleaf Compilation
234
-
235
- Work offline in your favorite editor, push when ready, compile remotely:
236
-
237
- ```bash
238
- olcli pull "Research Paper"
239
- cd Research_Paper
240
- vim introduction.tex
241
- git commit -am "Update intro"
242
- olcli push
243
- olcli pdf
244
- ```
245
-
246
- ### Git Version Control + Overleaf
247
-
248
- Keep your LaTeX project in Git while using Overleaf's compiler:
249
-
250
- ```bash
251
- olcli pull "My Thesis" thesis
252
- cd thesis
253
- git init
254
- git add .
255
- git commit -m "Initial import from Overleaf"
256
-
257
- # Daily workflow
258
- vim chapters/methods.tex
259
- git commit -am "Draft methods section"
260
- olcli sync # Sync with Overleaf
261
- olcli pdf
262
- ```
263
-
264
- ### Automated Workflows
265
-
266
- Integrate Overleaf compilation into CI/CD:
267
-
268
- ```bash
269
- #!/bin/bash
270
- olcli auth --cookie "$OVERLEAF_SESSION"
271
- olcli pull "Automated Report"
272
- ./generate-data.py > tables/results.tex
273
- olcli push
274
- olcli pdf -o report-$(date +%Y-%m-%d).pdf
275
- ```
276
-
277
- ### arXiv Submissions
278
-
279
- Download the `.bbl` file for arXiv submissions:
280
-
281
- ```bash
282
- olcli output bbl --project "My Paper"
283
- # Downloads: bbl
284
- ```
285
-
286
- List all available compile output files:
287
-
288
- ```bash
289
- olcli output --list
290
- # Available output files:
291
- # aux output.aux
292
- # bbl output.bbl
293
- # blg output.blg
294
- # log output.log
295
- # ...
296
- ```
157
+ | `--verbose` | Print HTTP requests and responses to stderr |
158
+ | `--base-url <url>` | Override Overleaf instance URL |
159
+ | `--cookie-name <name>` | Override session cookie name |
160
+ | `--timeout <ms>` | Override HTTP timeout (default: 10000) |
297
161
 
298
162
  ## Sync Behavior
299
163
 
300
164
  ### Pull
301
165
  - Downloads all files from Overleaf
302
- - **Skips** local files modified after last pull (won't overwrite your changes)
166
+ - Skips local files modified after last pull (won't overwrite your changes)
303
167
  - Use `--force` to overwrite local changes
304
168
 
305
169
  ### Push
306
170
  - Uploads files modified after last pull
307
- - Preserves nested folder structure when uploading
308
- - Filters out LaTeX build artifacts and OS noise (see [Ignoring files](#ignoring-files))
309
- - Use `--all` to upload all files
310
- - Use `--dry-run` to preview changes
311
- - Use `--show-ignored` to see what was filtered out
171
+ - Preserves nested folder structure
172
+ - Filters out LaTeX build artifacts and OS noise
173
+ - Use `--all` to upload all files, `--dry-run` to preview
312
174
 
313
175
  ### Sync
314
- - Pulls remote changes
315
- - Preserves local modifications (local wins if newer)
316
- - Pushes local changes to remote
317
- - **Propagates local deletions to the remote** — if you delete a file locally, it's deleted on Overleaf on the next sync. Use `--no-delete` to opt out.
318
- - Filters out LaTeX build artifacts and OS noise
319
- - Use `--verbose` to see detailed file operations (see [Global options](#global-options))
176
+ - Pulls remote changes, then pushes local changes
177
+ - Local modifications win if newer
178
+ - **Propagates local deletions** — use `--no-delete` to opt out
320
179
  - Use `--dry-run` to preview without applying
321
180
 
322
181
  #### How deletion propagation works
323
182
 
324
- On every sync, `olcli` records a manifest of remote files in `.olcli.json`. The next sync compares the manifest against your local working tree:
183
+ `olcli` records a manifest of remote files in `.olcli.json`. On next sync:
325
184
 
326
- - File missing locally **and** still present on remote → deleted on Overleaf
185
+ - File missing locally + still on remote → deleted on Overleaf
327
186
  - File new locally → uploaded
328
- - File modified locally after last pull → uploaded (local wins)
187
+ - File modified locally → uploaded (local wins)
329
188
  - File only on remote → downloaded
330
189
 
331
- First-time syncs skip the deletion phase (no manifest exists yet to distinguish "never had it" from "deleted it").
332
-
333
- ## Ignoring files
190
+ First-time syncs skip the deletion phase (no prior manifest to compare).
334
191
 
335
- `olcli` automatically filters local files through a layered ignore list before uploading. This keeps LaTeX build artifacts (from local `pdflatex`/`latexmk` runs) and OS noise out of your Overleaf project.
192
+ ## Ignoring Files
336
193
 
337
194
  ### Three layers
338
195
 
339
- | Layer | File | Purpose |
196
+ | Layer | Source | Purpose |
340
197
  |---|---|---|
341
- | 1 | (built-in) | LaTeX intermediates (`.aux`, `.bbl`, `.log`, `.fls`, `.synctex.gz`, beamer/biber/glossaries/minted), OS noise (`.DS_Store`, `Thumbs.db`, `*.swp`), common build dirs (`build/`, `out/`, `_minted-*/`). Always on; opt out with `--no-default-ignore`. |
342
- | 2 | `.olignore` | Project-level patterns, gitignore syntax. Commit alongside your `.tex` sources. |
343
- | 3 | `.olignore.local` | Machine-specific patterns. Add to `.gitignore`. |
198
+ | 1 | Built-in | LaTeX intermediates, OS noise, build dirs. Always on. |
199
+ | 2 | `.olignore` | Project-level patterns (gitignore syntax). |
200
+ | 3 | `.olignore.local` | Machine-specific patterns. |
344
201
 
345
- Later layers override earlier ones, just like git. Negation (`!important.aux`) is supported.
202
+ Later layers override earlier ones. Negation (`!important.aux`) is supported.
346
203
 
347
204
  ### Special PDF rule
348
205
 
349
- `X.pdf` is ignored only if a same-named `X.tex` (or `.ltx`) exists in the same folder. So `thesis.pdf` next to `thesis.tex` is filtered, but a hand-uploaded `figures/diagram.pdf` still syncs.
350
-
351
- ### Example `.olignore`
352
-
353
- ```gitignore
354
- # Drafts that should never reach Overleaf
355
- *.draft.tex
356
- notes/
357
- chapters/scratch/
358
-
359
- # But keep this one auxiliary file
360
- !important.aux
361
- ```
206
+ `X.pdf` is ignored only if `X.tex` (or `.ltx`) exists in the same folder.
362
207
 
363
208
  ### Inspecting and overriding
364
209
 
365
210
  ```bash
366
- olcli ignored # list patterns currently in effect
367
- olcli push --show-ignored # see what was skipped on this run
211
+ olcli ignored # list patterns in effect
212
+ olcli push --show-ignored # see what was skipped
368
213
  olcli sync --no-default-ignore # only .olignore applies
369
- olcli sync --no-ignore # escape hatch — upload everything
214
+ olcli sync --no-ignore # upload everything
370
215
  ```
371
216
 
372
217
  ## Configuration
373
218
 
374
- Credentials are stored in (checked in order):
219
+ Credentials are checked in order:
375
220
 
376
221
  1. `OVERLEAF_SESSION` environment variable
377
222
  2. `.olauth` file in current directory
378
- 3. Global config: `~/.config/olcli-nodejs/config.json` (macOS/Linux)
379
-
380
- ### .olauth File
381
-
382
- For project-specific credentials, create `.olauth` in your project directory:
223
+ 3. Global config: `~/.config/olcli-nodejs/config.json`
383
224
 
384
- ```
385
- s%3AyourSessionCookieValue...
386
- ```
387
-
388
- ### Self-hosted Overleaf / ShareLaTeX
389
-
390
- You can point `olcli` at a self-hosted instance and override the session cookie name. Both flags are documented under [Global options](#global-options) and can be combined with any command.
391
-
392
- ```bash
393
- olcli --base-url https://latex.example.org list
394
- olcli --base-url https://latex.example.org --cookie-name overleaf.sid whoami
395
- ```
396
-
397
- Persist these settings in `olcli` config so you don't have to repeat them:
225
+ ### Self-hosted Overleaf
398
226
 
399
227
  ```bash
400
228
  olcli config set-url https://latex.example.org
401
229
  olcli config set-cookie-name overleaf.sid
402
230
  ```
403
231
 
404
- ### Timeout configuration
232
+ Or pass per-command: `olcli --base-url https://latex.example.org list`
405
233
 
406
- For slow connections or large projects, increase the HTTP request timeout:
234
+ ### Timeout
407
235
 
408
236
  ```bash
409
- # One-off: pass as a flag
410
- olcli --timeout 60000 pull "Large Thesis"
411
-
412
- # Persist as default
413
- olcli config set-timeout 60000
414
-
415
- # Or use environment variable
416
- export OVERLEAF_TIMEOUT=60000
417
- olcli pull "Large Thesis"
237
+ olcli config set-timeout 60000 # persist
238
+ olcli --timeout 60000 pull "Big Thesis" # one-off
239
+ export OVERLEAF_TIMEOUT=60000 # env var
418
240
  ```
419
241
 
420
- Precedence: `--timeout` flag > `OVERLEAF_TIMEOUT` env > `config set-timeout` > default (10000ms).
242
+ Precedence: `--timeout` > `OVERLEAF_TIMEOUT` > config > default (10000ms).
421
243
 
422
244
  ## Examples
423
245
 
424
- ### Work on a thesis
425
-
426
246
  ```bash
427
- # Initial setup
428
- olcli pull "PhD Thesis" thesis
429
- cd thesis
430
-
431
- # Daily workflow
432
- vim chapters/introduction.tex
433
- olcli sync
434
- olcli pdf -o draft.pdf
435
- ```
436
-
437
- ### Quick PDF download
247
+ # Daily thesis workflow
248
+ olcli pull "PhD Thesis" thesis && cd thesis
249
+ vim chapters/methods.tex
250
+ olcli sync && olcli pdf -o draft.pdf
438
251
 
439
- ```bash
252
+ # Quick PDF download
440
253
  olcli pdf "Conference Paper" -o paper.pdf
441
- ```
442
-
443
- ### Download a single file
444
254
 
445
- ```bash
446
- olcli download main.tex "My Project"
447
- ```
448
-
449
- ### Upload figures
450
-
451
- ```bash
452
- cd my-project
255
+ # Upload figures
453
256
  olcli upload figures/diagram.png
454
- ```
455
257
 
456
- ### Backup all projects
258
+ # arXiv submission prep
259
+ olcli output bbl -o main.bbl
260
+ olcli zip -o arxiv-submission.zip
457
261
 
458
- ```bash
262
+ # Backup all projects
459
263
  for proj in $(olcli list --json | jq -r '.[].name'); do
460
264
  olcli zip "$proj" -o "backups/${proj}.zip"
461
265
  done
462
266
  ```
463
267
 
464
- ### Prepare for arXiv
465
-
466
- ```bash
467
- cd my-paper
468
- olcli output bbl -o main.bbl
469
- olcli zip -o arxiv-submission.zip
470
- ```
471
-
472
268
  ## Programmatic Usage (Library API)
473
269
 
474
- `@aloth/olcli` exposes `OverleafClient` and all public interfaces as a proper library so you can use it in your own scripts, tools, and AI agents.
270
+ `@aloth/olcli` exposes `OverleafClient` and all public interfaces as a library.
475
271
 
476
272
  ### Install
477
273
 
@@ -484,27 +280,15 @@ npm install @aloth/olcli
484
280
  ```ts
485
281
  import { OverleafClient } from '@aloth/olcli';
486
282
 
487
- // Create a client from an Overleaf session cookie
488
283
  const client = await OverleafClient.fromSessionCookie(cookie);
489
284
 
490
- // List all projects
491
285
  const projects = await client.listProjects();
492
- console.log(projects);
493
-
494
- // Get detailed info (file tree) for a project
495
286
  const info = await client.getProjectInfo(projectId);
496
-
497
- // Download project as a zip buffer
498
287
  const zipBuf = await client.downloadProject(projectId);
499
-
500
- // Compile and download PDF
501
288
  const pdfBuf = await client.downloadPdf(projectId);
502
289
 
503
- // Upload a file
504
- import { readFileSync } from 'node:fs';
505
290
  await client.uploadFile(projectId, null, 'main.tex', readFileSync('main.tex'));
506
291
 
507
- // List review comments
508
292
  const comments = await client.listComments(projectId, { status: 'open' });
509
293
  ```
510
294
 
@@ -512,167 +296,33 @@ const comments = await client.listComments(projectId, { status: 'open' });
512
296
 
513
297
  ```ts
514
298
  import {
515
- // Core client
516
299
  OverleafClient,
517
-
518
- // Types / interfaces
300
+ // Types
519
301
  Project, ProjectInfo, FolderEntry, DocEntry, FileEntry,
520
302
  CommentMessage, ProjectComment, CommentContext, CommentStatus,
521
303
  ListCommentsOptions, AddCommentOptions, Credentials, SessionCookiePair,
522
-
523
- // Configuration utilities
304
+ // Config utilities
524
305
  getBaseUrl, setBaseUrl, getSessionCookie, setSessionCookie,
525
306
  getSessionCookieName, setSessionCookieName, getCsrf, setCsrf,
526
307
  getLastProject, setLastProject, clearConfig, getConfigPath, saveOlAuth,
527
308
  getTimeout, setTimeout, getPasswordCredentials, setPasswordCredentials,
528
309
  clearPasswordCredentials, type PasswordCredentials,
529
-
530
310
  // Ignore utilities
531
311
  DEFAULT_IGNORE_PATTERNS, loadIgnore, shouldIgnore, buildTexSiblingSet,
532
312
  IgnoreContext, LoadIgnoreOptions,
533
313
  } from '@aloth/olcli';
534
314
  ```
535
315
 
536
- ---
537
-
538
- ## MCP Server
316
+ ## Further Documentation
539
317
 
540
- `@aloth/olcli` ships an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server so AI assistants like **Claude Desktop**, **Cursor**, and **Windsurf** can interact with your Overleaf projects directly.
541
-
542
- ### MCP tools
543
-
544
- | Tool | Description |
545
- |------|-------------|
546
- | `list_projects` | List all Overleaf projects |
547
- | `get_project_info` | Get file tree and metadata for a project |
548
- | `pull_project` | Download and extract a project to a local directory |
549
- | `push_file` | Upload a local file to a project |
550
- | `compile` | Compile a project and get the PDF URL |
551
- | `download_pdf` | Compile a project and save the PDF locally |
552
- | `list_comments` | List review comments (filter: all / open / resolved) |
553
- | `get_entities` | Get a flat list of all files in a project |
554
- | `download_file` | Download a specific file by its remote path |
555
- | `add_comment` | Add a review comment to a document |
556
- | `reply_to_comment` | Reply to an existing comment thread |
557
- | `resolve_comment` | Mark a comment thread as resolved |
558
- | `delete_entity` | Delete a file or document by path |
559
- | `rename_entity` | Rename a file or document |
560
- | `compile_with_outputs` | Compile and return all output files (PDF, BBL, logs…) |
561
-
562
- ### Authentication
563
-
564
- The MCP server reads credentials in this order:
565
-
566
- 1. **`OVERLEAF_SESSION` environment variable** — set in your MCP config (recommended)
567
- 2. **`OVERLEAF_EMAIL` + `OVERLEAF_PASSWORD` environment variables** — for password login (self-hosted)
568
- 3. **`.olauth` file in cwd** — written by `olcli auth`
569
- 4. **Stored config** — written by `olcli auth` (including saved password credentials)
570
-
571
- When a session cookie expires and password credentials are available, the MCP server automatically re-authenticates.
572
-
573
- ### Claude Desktop
574
-
575
- Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
576
-
577
- ```json
578
- {
579
- "mcpServers": {
580
- "overleaf": {
581
- "command": "npx",
582
- "args": ["-y", "@aloth/olcli-mcp"],
583
- "env": {
584
- "OVERLEAF_SESSION": "<your-overleaf-session-cookie>"
585
- }
586
- }
587
- }
588
- }
589
- ```
590
-
591
- Or if you have olcli installed globally (`npm install -g @aloth/olcli`):
592
-
593
- ```json
594
- {
595
- "mcpServers": {
596
- "overleaf": {
597
- "command": "olcli-mcp",
598
- "env": {
599
- "OVERLEAF_SESSION": "<your-overleaf-session-cookie>"
600
- }
601
- }
602
- }
603
- }
604
- ```
605
-
606
- ### Cursor
607
-
608
- Add to your Cursor MCP settings (`~/.cursor/mcp.json` or project `.cursor/mcp.json`):
609
-
610
- ```json
611
- {
612
- "mcpServers": {
613
- "overleaf": {
614
- "command": "npx",
615
- "args": ["-y", "@aloth/olcli-mcp"],
616
- "env": {
617
- "OVERLEAF_SESSION": "<your-overleaf-session-cookie>"
618
- }
619
- }
620
- }
621
- }
622
- ```
623
-
624
- ### Windsurf
625
-
626
- Add to `~/.codeium/windsurf/mcp_config.json`:
627
-
628
- ```json
629
- {
630
- "mcpServers": {
631
- "overleaf": {
632
- "command": "npx",
633
- "args": ["-y", "@aloth/olcli-mcp"],
634
- "env": {
635
- "OVERLEAF_SESSION": "<your-overleaf-session-cookie>"
636
- }
637
- }
638
- }
639
- }
640
- ```
641
-
642
- ### Getting your session cookie
643
-
644
- 1. Open Overleaf in your browser and log in
645
- 2. Open DevTools → Application (Chrome) or Storage (Firefox) → Cookies
646
- 3. Find `overleaf_session2` (or `sharelatex.sid` for self-hosted)
647
- 4. Copy the value — that's your `OVERLEAF_SESSION`
648
-
649
- Or run `olcli auth` and then the MCP server will pick it up automatically.
650
-
651
- ### Self-hosted Overleaf
652
-
653
- Set `OVERLEAF_BASE_URL` in your MCP env:
654
-
655
- ```json
656
- "env": {
657
- "OVERLEAF_SESSION": "<cookie>",
658
- "OVERLEAF_BASE_URL": "https://overleaf.yourcompany.com"
659
- }
660
- ```
661
-
662
- ---
318
+ - [MCP Server](docs/MCP.md) — AI assistant integration (Claude, Cursor, Windsurf)
319
+ - [Git Remote Helper](docs/GIT-REMOTE.md) — use Overleaf as a native git remote
663
320
 
664
321
  ## Troubleshooting
665
322
 
666
- ### Session expired
667
-
668
- If you get authentication errors, your session cookie may have expired. Get a fresh one from the browser and run `olcli auth` again.
669
-
670
- ### Compilation fails
323
+ **Session expired** — Get a fresh cookie from the browser and run `olcli auth` again.
671
324
 
672
- Check the Overleaf web editor for detailed error logs. Common issues:
673
- - Missing packages
674
- - Syntax errors in `.tex` files
675
- - Missing bibliography files
325
+ **Compilation fails** — Check the Overleaf web editor for detailed error logs (missing packages, syntax errors, missing bibliography files).
676
326
 
677
327
  ## Contributing
678
328
 
package/dist/mcp.js CHANGED
@@ -84,7 +84,7 @@ async function getClient() {
84
84
  // ---------------------------------------------------------------------------
85
85
  const server = new McpServer({
86
86
  name: 'olcli',
87
- version: '0.6.0',
87
+ version: '0.7.0',
88
88
  }, {
89
89
  capabilities: { tools: {} },
90
90
  });
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * git-remote-overleaf — Git remote helper for Overleaf projects.
4
+ *
5
+ * Allows native git commands against Overleaf:
6
+ * git clone overleaf::https://www.overleaf.com/project/<id>
7
+ * git pull
8
+ * git push
9
+ *
10
+ * Protocol reference: gitremote-helpers(7)
11
+ *
12
+ * Capabilities: import + export with refspec.
13
+ * State stored in .git/overleaf/ (manifest).
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=remote-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-helper.d.ts","sourceRoot":"","sources":["../src/remote-helper.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,431 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * git-remote-overleaf — Git remote helper for Overleaf projects.
4
+ *
5
+ * Allows native git commands against Overleaf:
6
+ * git clone overleaf::https://www.overleaf.com/project/<id>
7
+ * git pull
8
+ * git push
9
+ *
10
+ * Protocol reference: gitremote-helpers(7)
11
+ *
12
+ * Capabilities: import + export with refspec.
13
+ * State stored in .git/overleaf/ (manifest).
14
+ */
15
+ import { createInterface } from 'node:readline';
16
+ import { execSync } from 'node:child_process';
17
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
18
+ import { join, resolve } from 'node:path';
19
+ import { OverleafClient } from './client.js';
20
+ import { getSessionCookie, getBaseUrl, getSessionCookieName, getTimeout, getPasswordCredentials, } from './config.js';
21
+ import { loadIgnore, shouldIgnore } from './ignore.js';
22
+ // ─── Logging (stderr only — stdout is the git protocol channel) ───
23
+ function debug(msg) {
24
+ if (process.env.GIT_REMOTE_OVERLEAF_DEBUG) {
25
+ process.stderr.write(`[git-remote-overleaf] ${msg}\n`);
26
+ }
27
+ }
28
+ function fatal(msg) {
29
+ process.stderr.write(`fatal: ${msg}\n`);
30
+ process.exit(1);
31
+ }
32
+ /**
33
+ * Parse an Overleaf project URL into base URL and project ID.
34
+ *
35
+ * Supported formats:
36
+ * https://www.overleaf.com/project/abc123
37
+ * overleaf::https://www.overleaf.com/project/abc123
38
+ * https://custom.overleaf.example.com/project/abc123
39
+ * abc123 (bare project ID, uses configured base URL)
40
+ */
41
+ function parseRemoteUrl(url) {
42
+ // Strip the overleaf:: prefix if present (git passes the raw URL part)
43
+ const cleaned = url.replace(/^overleaf::/, '');
44
+ // Try parsing as URL with /project/<id> path
45
+ const projectPathMatch = cleaned.match(/^(https?:\/\/[^/]+)\/project\/([a-f0-9]{24})$/i);
46
+ if (projectPathMatch) {
47
+ return { baseUrl: projectPathMatch[1], projectId: projectPathMatch[2] };
48
+ }
49
+ // Bare 24-char hex ID
50
+ if (/^[a-f0-9]{24}$/i.test(cleaned)) {
51
+ return { baseUrl: getBaseUrl(), projectId: cleaned };
52
+ }
53
+ fatal(`Cannot parse Overleaf URL: ${url}\n Expected: https://<host>/project/<24-char-id>`);
54
+ }
55
+ function getGitDir() {
56
+ const gitDir = process.env.GIT_DIR;
57
+ if (!gitDir)
58
+ fatal('GIT_DIR not set — are you running inside git?');
59
+ return resolve(gitDir); // Always return absolute path
60
+ }
61
+ function stateDir() {
62
+ return join(getGitDir(), 'overleaf');
63
+ }
64
+ function ensureStateDir() {
65
+ const dir = stateDir();
66
+ if (!existsSync(dir))
67
+ mkdirSync(dir, { recursive: true });
68
+ }
69
+ function loadState() {
70
+ const path = join(stateDir(), 'state.json');
71
+ if (!existsSync(path))
72
+ return { manifest: [], lastMark: 0 };
73
+ try {
74
+ return JSON.parse(readFileSync(path, 'utf-8'));
75
+ }
76
+ catch {
77
+ return { manifest: [], lastMark: 0 };
78
+ }
79
+ }
80
+ function saveState(state) {
81
+ ensureStateDir();
82
+ writeFileSync(join(stateDir(), 'state.json'), JSON.stringify(state, null, 2));
83
+ }
84
+ // ─── Authentication (reuses olcli's config chain) ───
85
+ async function getClient(baseUrl) {
86
+ const cookieName = getSessionCookieName();
87
+ const cookie = getSessionCookie();
88
+ const passwordCredentials = getPasswordCredentials();
89
+ if (cookie) {
90
+ try {
91
+ const client = await OverleafClient.fromSessionCookie(cookie, baseUrl, cookieName);
92
+ client.setGlobalTimeout(getTimeout());
93
+ return client;
94
+ }
95
+ catch (err) {
96
+ if (!passwordCredentials) {
97
+ fatal(`Authentication failed: ${err.message}\nRun 'olcli login' first.`);
98
+ }
99
+ }
100
+ }
101
+ if (passwordCredentials) {
102
+ const client = await OverleafClient.fromPasswordLogin(passwordCredentials.email, passwordCredentials.password, baseUrl);
103
+ client.setGlobalTimeout(getTimeout());
104
+ return client;
105
+ }
106
+ fatal('No Overleaf credentials found. Run \'olcli login\' or set OVERLEAF_SESSION.');
107
+ }
108
+ /**
109
+ * Read fast-export stream from stdin and extract file modifications/deletions.
110
+ *
111
+ * The stream comes after we respond to the "export" command. Git sends
112
+ * fast-export data terminated by "done\n".
113
+ */
114
+ async function parseFastExport(rl) {
115
+ const files = [];
116
+ const deletes = [];
117
+ const blobData = new Map(); // mark → data
118
+ let currentMark = '';
119
+ let dataBuffer = Buffer.alloc(0);
120
+ // State machine for parsing the fast-export stream.
121
+ // readline gives us lines; for binary `data <N>` sections we accumulate bytes.
122
+ let state = 'command';
123
+ let pendingDataBytes = 0;
124
+ let pendingMark = '';
125
+ let commitSection = false;
126
+ for await (const line of rl) {
127
+ if (state === 'data') {
128
+ // Accumulate data — readline splits on \n so we rejoin
129
+ const lineBytes = Buffer.from(line + '\n', 'binary');
130
+ dataBuffer = Buffer.concat([dataBuffer, lineBytes]);
131
+ if (dataBuffer.length >= pendingDataBytes) {
132
+ // Trim to exact length
133
+ const finalData = dataBuffer.subarray(0, pendingDataBytes);
134
+ if (pendingMark) {
135
+ blobData.set(pendingMark, finalData);
136
+ }
137
+ state = 'command';
138
+ dataBuffer = Buffer.alloc(0);
139
+ pendingMark = '';
140
+ }
141
+ continue;
142
+ }
143
+ // Command mode
144
+ if (line === 'done' || line === '') {
145
+ if (line === 'done')
146
+ break;
147
+ continue;
148
+ }
149
+ if (line.startsWith('blob')) {
150
+ commitSection = false;
151
+ continue;
152
+ }
153
+ if (line.startsWith('mark :')) {
154
+ currentMark = line.slice(6);
155
+ continue;
156
+ }
157
+ if (line.startsWith('data ')) {
158
+ pendingDataBytes = parseInt(line.slice(5), 10);
159
+ pendingMark = commitSection ? '' : currentMark;
160
+ state = 'data';
161
+ dataBuffer = Buffer.alloc(0);
162
+ continue;
163
+ }
164
+ if (line.startsWith('commit ')) {
165
+ commitSection = true;
166
+ continue;
167
+ }
168
+ if (line.startsWith('committer ') || line.startsWith('author ')) {
169
+ continue;
170
+ }
171
+ if (line.startsWith('from ') || line.startsWith('merge ')) {
172
+ continue;
173
+ }
174
+ // File modification: M <mode> <dataref> <path>
175
+ const mMatch = line.match(/^M \d+ :(\S+) (.+)$/);
176
+ if (mMatch) {
177
+ const [, markRef, path] = mMatch;
178
+ const content = blobData.get(markRef);
179
+ if (content) {
180
+ files.push({ path, content });
181
+ }
182
+ continue;
183
+ }
184
+ // Inline modification: M <mode> inline <path>
185
+ const mInline = line.match(/^M \d+ inline (.+)$/);
186
+ if (mInline) {
187
+ // Next will be a data line
188
+ currentMark = `__inline_${mInline[1]}`;
189
+ continue;
190
+ }
191
+ // Deletion: D <path>
192
+ const dMatch = line.match(/^D (.+)$/);
193
+ if (dMatch) {
194
+ deletes.push({ path: dMatch[1] });
195
+ continue;
196
+ }
197
+ }
198
+ // Resolve any inline blobs
199
+ for (const [mark, data] of blobData) {
200
+ if (mark.startsWith('__inline_')) {
201
+ const path = mark.slice(9);
202
+ files.push({ path, content: data });
203
+ }
204
+ }
205
+ return { files, deletes };
206
+ }
207
+ // ─── Push logic ───
208
+ async function pushChanges(client, projectId, parsed, _state) {
209
+ const ignoreCtx = loadIgnore(process.cwd(), {});
210
+ // Upload modified/new files
211
+ for (const file of parsed.files) {
212
+ if (shouldIgnore(file.path, ignoreCtx)) {
213
+ debug(`Skipping ignored file: ${file.path}`);
214
+ continue;
215
+ }
216
+ debug(`Uploading: ${file.path}`);
217
+ await client.uploadFile(projectId, null, file.path, file.content);
218
+ }
219
+ // Delete removed files
220
+ for (const del of parsed.deletes) {
221
+ debug(`Deleting: ${del.path}`);
222
+ try {
223
+ await client.deleteByPath(projectId, del.path);
224
+ }
225
+ catch (err) {
226
+ // File might already be gone on remote
227
+ debug(`Warning: Could not delete ${del.path}: ${err.message}`);
228
+ }
229
+ }
230
+ }
231
+ // ─── Protocol handler ───
232
+ async function main() {
233
+ // Args: git-remote-overleaf <remote-name> <url>
234
+ const args = process.argv.slice(2);
235
+ if (args.length < 1) {
236
+ fatal('Usage: git-remote-overleaf <remote> [<url>]');
237
+ }
238
+ // The URL is usually the second arg; if only one arg, it IS the URL
239
+ const rawUrl = args[1] || args[0];
240
+ const { projectId, baseUrl } = parseRemoteUrl(rawUrl);
241
+ debug(`Project ID: ${projectId}, Base URL: ${baseUrl}`);
242
+ ensureStateDir();
243
+ let state = loadState();
244
+ const rl = createInterface({
245
+ input: process.stdin,
246
+ terminal: false,
247
+ });
248
+ const iterator = rl[Symbol.asyncIterator]();
249
+ for await (const line of rl) {
250
+ const trimmed = line.trim();
251
+ debug(`< ${trimmed}`);
252
+ if (trimmed === '') {
253
+ // Empty line = end of command batch (for list/import/export batches)
254
+ continue;
255
+ }
256
+ if (trimmed === 'capabilities') {
257
+ // Declare what we support.
258
+ ensureStateDir();
259
+ // Create empty marks file if it doesn't exist (fast-export --import-marks
260
+ // fails if file is missing; empty file = nothing previously exported).
261
+ const marks = join(stateDir(), 'marks');
262
+ if (!existsSync(marks)) {
263
+ writeFileSync(marks, '');
264
+ }
265
+ const caps = [
266
+ 'import',
267
+ 'export',
268
+ // Map remote refs/heads/* to a private namespace refs/overleaf/<remote>/*
269
+ // This is critical: git uses the private namespace to track what the remote has.
270
+ // Without a separate namespace, git can't compute the push delta.
271
+ 'refspec refs/heads/*:refs/overleaf/*',
272
+ // import-marks/export-marks = passed to fast-export on push.
273
+ `import-marks ${marks}`,
274
+ `export-marks ${marks}`,
275
+ '', // blank line terminates capabilities
276
+ ].join('\n');
277
+ process.stdout.write(caps + '\n');
278
+ debug(`> capabilities response sent (marks=${marks})`);
279
+ continue;
280
+ }
281
+ if (trimmed === 'list' || trimmed === 'list for-push') {
282
+ // Report what SHA the remote currently has.
283
+ // Read from refs/overleaf/main (our private namespace ref updated by
284
+ // git after import/export via the refspec mapping).
285
+ let remoteSha;
286
+ try {
287
+ const sha = execSync('git rev-parse --verify refs/overleaf/main 2>/dev/null', { encoding: 'utf-8', env: { ...process.env, GIT_DIR: getGitDir() } }).trim();
288
+ if (/^[a-f0-9]{40}$/.test(sha))
289
+ remoteSha = sha;
290
+ }
291
+ catch { /* not yet created */ }
292
+ if (remoteSha) {
293
+ process.stdout.write(`${remoteSha} refs/heads/main\n`);
294
+ }
295
+ else {
296
+ process.stdout.write('? refs/heads/main\n');
297
+ }
298
+ process.stdout.write('@refs/heads/main HEAD\n');
299
+ process.stdout.write('\n'); // blank line terminates
300
+ debug(`> list response sent (sha=${remoteSha || '?'})`);
301
+ continue;
302
+ }
303
+ if (trimmed.startsWith('import ')) {
304
+ // import refs/heads/main
305
+ // May be followed by more "import" lines, terminated by blank line
306
+ const refs = [trimmed.slice(7)];
307
+ // Consume additional import lines until blank
308
+ for await (const nextLine of rl) {
309
+ const next = nextLine.trim();
310
+ if (next === '')
311
+ break;
312
+ if (next.startsWith('import ')) {
313
+ refs.push(next.slice(7));
314
+ }
315
+ }
316
+ debug(`Import requested for: ${refs.join(', ')}`);
317
+ // Authenticate and fetch
318
+ const client = await getClient(baseUrl);
319
+ debug('Generating fast-import stream...');
320
+ const zipBuffer = await client.downloadProject(projectId);
321
+ const AdmZip = (await import('adm-zip')).default;
322
+ const zip = new AdmZip(zipBuffer);
323
+ const entries = zip.getEntries();
324
+ let mark = state.lastMark;
325
+ const newManifest = [];
326
+ const fileMarks = [];
327
+ // Emit feature lines so fast-import writes/reads marks.
328
+ // This enables incremental import and allows fast-export to know
329
+ // which objects were already imported.
330
+ const marks = join(stateDir(), 'marks');
331
+ process.stdout.write(`feature import-marks-if-exists=${marks}\n`);
332
+ process.stdout.write(`feature export-marks=${marks}\n`);
333
+ // feature done tells fast-import to expect "done" as terminator
334
+ process.stdout.write('feature done\n');
335
+ // Write blobs
336
+ for (const entry of entries) {
337
+ if (entry.isDirectory)
338
+ continue;
339
+ const path = entry.entryName;
340
+ newManifest.push(path);
341
+ mark++;
342
+ const data = entry.getData();
343
+ process.stdout.write(`blob\nmark :${mark}\ndata ${data.length}\n`);
344
+ process.stdout.write(data);
345
+ process.stdout.write('\n');
346
+ fileMarks.push({ path, mark });
347
+ }
348
+ // Write commit
349
+ mark++;
350
+ const now = Math.floor(Date.now() / 1000);
351
+ // Write to private namespace per refspec: refs/heads/* → refs/overleaf/*
352
+ process.stdout.write(`commit refs/overleaf/main\n`);
353
+ process.stdout.write(`mark :${mark}\n`);
354
+ process.stdout.write(`committer Overleaf <overleaf@localhost> ${now} +0000\n`);
355
+ const msg = 'Import from Overleaf';
356
+ process.stdout.write(`data ${Buffer.byteLength(msg)}\n`);
357
+ process.stdout.write(`${msg}\n`);
358
+ // Parent: reference previous state if any
359
+ if (state.manifest.length > 0) {
360
+ process.stdout.write(`from refs/overleaf/main^0\n`);
361
+ }
362
+ // Deletions (files removed on Overleaf since last import)
363
+ const removedFiles = state.manifest.filter(f => !newManifest.includes(f));
364
+ for (const f of removedFiles) {
365
+ process.stdout.write(`D ${f}\n`);
366
+ }
367
+ // Modifications (all current files)
368
+ for (const fm of fileMarks) {
369
+ process.stdout.write(`M 100644 :${fm.mark} ${fm.path}\n`);
370
+ }
371
+ process.stdout.write('\n'); // end of commit
372
+ process.stdout.write('done\n');
373
+ // Update state
374
+ state.manifest = newManifest;
375
+ state.lastMark = mark;
376
+ saveState(state);
377
+ debug(`Import complete: ${fileMarks.length} files, ${removedFiles.length} deletions`);
378
+ continue;
379
+ }
380
+ if (trimmed.startsWith('export')) {
381
+ // Push: git sends a fast-export stream on stdin
382
+ debug('Export (push) starting — reading fast-export stream...');
383
+ const client = await getClient(baseUrl);
384
+ const parsed = await parseFastExport(iterator);
385
+ debug(`Parsed export: ${parsed.files.length} modifications, ${parsed.deletes.length} deletions`);
386
+ if (parsed.files.length === 0 && parsed.deletes.length === 0) {
387
+ debug('Nothing to push.');
388
+ // Don't report ok — nothing was actually pushed.
389
+ // This prevents git from advancing the remote tracking ref.
390
+ process.stdout.write('\n');
391
+ }
392
+ else {
393
+ await pushChanges(client, projectId, parsed, state);
394
+ // Report success for each ref that was pushed
395
+ process.stdout.write('ok refs/heads/main\n');
396
+ process.stdout.write('\n');
397
+ // Update state with new manifest
398
+ const currentManifest = new Set(state.manifest);
399
+ for (const del of parsed.deletes) {
400
+ currentManifest.delete(del.path);
401
+ }
402
+ for (const file of parsed.files) {
403
+ currentManifest.add(file.path);
404
+ }
405
+ state.manifest = [...currentManifest];
406
+ saveState(state);
407
+ }
408
+ debug('Export complete.');
409
+ continue;
410
+ }
411
+ if (trimmed.startsWith('option ')) {
412
+ // We don't support any options currently
413
+ process.stdout.write('unsupported\n');
414
+ continue;
415
+ }
416
+ // Unknown command
417
+ debug(`Unknown command: ${trimmed}`);
418
+ fatal(`Unsupported command: ${trimmed}`);
419
+ }
420
+ rl.close();
421
+ }
422
+ // Gracefully handle EPIPE (git closed the pipe before we finished writing)
423
+ process.stdout.on('error', (err) => {
424
+ if (err.code === 'EPIPE')
425
+ process.exit(0);
426
+ throw err;
427
+ });
428
+ main().catch((err) => {
429
+ fatal(err.message || String(err));
430
+ });
431
+ //# sourceMappingURL=remote-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-helper.js","sourceRoot":"","sources":["../src/remote-helper.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aloth/olcli",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Command-line interface for Overleaf — Sync, manage, and compile LaTeX projects from your terminal",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "bin": {
16
16
  "olcli": "dist/cli.js",
17
- "olcli-mcp": "dist/mcp.js"
17
+ "olcli-mcp": "dist/mcp.js",
18
+ "git-remote-overleaf": "dist/remote-helper.js"
18
19
  },
19
20
  "scripts": {
20
21
  "build": "tsc",