overleaf-comments-export 0.3.0__tar.gz → 0.5.0__tar.gz

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 (31) hide show
  1. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/LICENSE +1 -1
  2. overleaf_comments_export-0.5.0/PKG-INFO +241 -0
  3. overleaf_comments_export-0.5.0/README.md +204 -0
  4. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/__main__.py +85 -2
  5. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/export.py +25 -5
  6. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/gui.py +21 -0
  7. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/render.py +115 -3
  8. overleaf_comments_export-0.5.0/overleaf_comments_export.egg-info/PKG-INFO +241 -0
  9. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export.egg-info/SOURCES.txt +3 -1
  10. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/pyproject.toml +7 -3
  11. overleaf_comments_export-0.5.0/tests/test_response_letter.py +111 -0
  12. overleaf_comments_export-0.5.0/tests/test_stable_output.py +122 -0
  13. overleaf_comments_export-0.3.0/PKG-INFO +0 -176
  14. overleaf_comments_export-0.3.0/README.md +0 -140
  15. overleaf_comments_export-0.3.0/overleaf_comments_export.egg-info/PKG-INFO +0 -176
  16. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/__init__.py +0 -0
  17. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/anchors.py +0 -0
  18. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/client.py +0 -0
  19. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/model.py +0 -0
  20. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export/sections.py +0 -0
  21. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export.egg-info/dependency_links.txt +0 -0
  22. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export.egg-info/entry_points.txt +0 -0
  23. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export.egg-info/requires.txt +0 -0
  24. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/overleaf_comments_export.egg-info/top_level.txt +0 -0
  25. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/setup.cfg +0 -0
  26. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/tests/test_anchors_sections.py +0 -0
  27. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/tests/test_client.py +0 -0
  28. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/tests/test_errors_and_auth.py +0 -0
  29. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/tests/test_export.py +0 -0
  30. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/tests/test_render.py +0 -0
  31. {overleaf_comments_export-0.3.0 → overleaf_comments_export-0.5.0}/tests/test_replies_and_changes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Shivang (https://github.com/Mangluu)
3
+ Copyright (c) 2026 Shivang Gupta <https://github.com/Mangluu>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,241 @@
1
+ Metadata-Version: 2.4
2
+ Name: overleaf-comments-export
3
+ Version: 0.5.0
4
+ Summary: Export comment threads and tracked changes from an Overleaf project to Markdown + JSON, optimized for AI-agent consumption.
5
+ Author-email: Shivang Gupta <47645533+Mangluu@users.noreply.github.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Mangluu/overleaf-comments-export
8
+ Project-URL: Issues, https://github.com/Mangluu/overleaf-comments-export/issues
9
+ Project-URL: Source, https://github.com/Mangluu/overleaf-comments-export
10
+ Keywords: overleaf,latex,research,comments,review,academic,tracked-changes,ai-agents
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Text Processing :: Markup :: LaTeX
24
+ Classifier: Topic :: Scientific/Engineering
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: pyoverleaf>=0.1.7
29
+ Requires-Dist: browser-cookie3>=0.19
30
+ Requires-Dist: requests>=2.31
31
+ Requires-Dist: platformdirs>=4.0
32
+ Provides-Extra: gui
33
+ Requires-Dist: sv-ttk>=2.6; extra == "gui"
34
+ Provides-Extra: test
35
+ Requires-Dist: pytest>=8.0; extra == "test"
36
+ Dynamic: license-file
37
+
38
+ # overleaf-comments-export
39
+
40
+ Get the review comments out of an Overleaf paper, into Markdown and JSON you
41
+ can read, keep, commit, and hand to an AI assistant.
42
+
43
+ [![CI](https://github.com/Mangluu/overleaf-comments-export/actions/workflows/ci.yml/badge.svg)](https://github.com/Mangluu/overleaf-comments-export/actions/workflows/ci.yml)
44
+ [![PyPI](https://img.shields.io/pypi/v/overleaf-comments-export.svg)](https://pypi.org/project/overleaf-comments-export/)
45
+ [![Downloads](https://img.shields.io/pypi/dm/overleaf-comments-export.svg)](https://pypi.org/project/overleaf-comments-export/)
46
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
47
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%20to%203.14-blue.svg)](https://www.python.org/)
48
+
49
+ Overleaf leaves comments out of both the source download and the Git sync, so
50
+ the only way to work through them is inside the editor, one at a time. On a
51
+ paper with ninety comments from three co-authors that stops being workable.
52
+
53
+ ## What the output looks like
54
+
55
+ ```markdown
56
+ ## Summary
57
+
58
+ - **Threads:** 2 (2 open, 0 resolved)
59
+ - **Tracked changes:** 0
60
+ - **Most active reviewers:** A. Reviewer (2), Co Author (1)
61
+
62
+ ### § Method
63
+
64
+ **Line 142** — 2 comments
65
+
66
+ > …We propose **▸a novel framework◂** for measuring perceived quality across conditions.
67
+
68
+ **C014** _open · 1 reply_ — "a novel framework"
69
+ - **A. Reviewer** · 2026-02-25 06:13 UTC: Needs a citation. Which studies show this?
70
+ - ↳ **Co Author** · 2026-02-26 10:00 UTC: Agree, Smith 2023 would work here.
71
+
72
+ **C015** _open_ — "coherent"
73
+ - **A. Reviewer** · 2026-02-27 13:46 UTC: This word is doing a lot of work. Define it.
74
+ ```
75
+
76
+ Every comment sits in its section, next to the words it was attached to, with
77
+ its replies underneath and a stable id you can point at.
78
+
79
+ ## Install and run
80
+
81
+ ```bash
82
+ pip install overleaf-comments-export
83
+ overleaf-comments-export --gui
84
+ ```
85
+
86
+ That opens a small window. Paste your project link, choose a folder, press the
87
+ button. If you prefer the terminal:
88
+
89
+ ```bash
90
+ overleaf-comments-export \
91
+ --project-url https://www.overleaf.com/project/YOUR_PROJECT_ID \
92
+ --out ./paper-comments
93
+ ```
94
+
95
+ Python 3.10 or newer, tested up to 3.14, on macOS, Windows, and Linux.
96
+
97
+ ## What you get
98
+
99
+ | File | What it is |
100
+ |---|---|
101
+ | `comments-<date>.md` | The readable export, or `comments.md` with `--stable`. Grouped by file, then section, then line. Stable ids `C001`, `T001`. |
102
+ | `comments.json` | The same data, structured. Threads, anchors, tracked changes, source context. |
103
+ | `comments.jsonl` | One self-contained record per comment, for pipelines. |
104
+ | `agents.md` | A short brief telling an AI assistant how to read the other two. |
105
+ | `response-letter.md` | Optional. A point-by-point reply document with a blank slot under every open comment. |
106
+ | `by-reviewer/<name>.md` | Optional. One file per reviewer, so you can work through them one person at a time. |
107
+
108
+ ## Working through comments with an AI
109
+
110
+ This is what the export is shaped for. Hand an assistant the folder and it can
111
+ work on any comment by id, because it already knows the quoted passage, the
112
+ section it lives in, and what the replies said.
113
+
114
+ Some things that work well.
115
+
116
+ - Draft a reply to C014 that answers the reviewer and says what we changed.
117
+ - Which comments are asking for the same thing? Group them.
118
+ - Fill in the response letter for every comment from A. Reviewer.
119
+
120
+ Tracked changes come through too, as insertions and deletions with the
121
+ surrounding text, so a deletion reads as `before ~~removed~~ after`.
122
+
123
+ ## Useful options
124
+
125
+ ```bash
126
+ --response-letter # draft a point-by-point reply document
127
+ --per-reviewer # one report per reviewer
128
+ --reviewer "Emma" # only threads this person touched
129
+ --no-resolved # only what is still open
130
+ --render-mode detailed # more source context around each comment
131
+ --stable # output that only changes when the comments change
132
+ ```
133
+
134
+ Run `overleaf-comments-export --help` for the full list.
135
+
136
+ ## Keeping the comments in git
137
+
138
+ By default each run writes `comments-<date>.md`, so you end up with one file per
139
+ run. That is fine for a one-off export and useless for version control.
140
+
141
+ `--stable` writes a single `comments.md` with no timestamps in it. Re-run it and
142
+ the file does not move unless the comments actually moved.
143
+
144
+ ```bash
145
+ overleaf-comments-export --project-url <link> --out ./review --stable
146
+ git add review/comments.md
147
+ git commit -m "reviewer comments as of today"
148
+ ```
149
+
150
+ Next time you pull the comments, `git diff` shows the new ones and nothing else.
151
+
152
+ ```diff
153
+ thread_count: 41
154
+ +thread_count: 42
155
+
156
+ +**C042** _open_ — "the axis labels"
157
+ +- **A. Reviewer** · 2026-08-14 09:12 UTC: units are missing here
158
+ ```
159
+
160
+ ## Signing in
161
+
162
+ The tool needs the session your browser already has. It reads that session and
163
+ nothing else, and it only ever reads.
164
+
165
+ | How | Notes |
166
+ |---|---|
167
+ | Safari or Firefox | Reads the cookie file directly. No password prompt. |
168
+ | Paste it yourself | Works on every computer and browser. The window shows you how, step by step. |
169
+ | Chrome, Edge, Brave | Works on macOS but asks for your Keychain password every run. Chrome 127 and newer on Windows cannot be read at all, so use the paste option there. |
170
+
171
+ To paste it, open Overleaf, press F12, go to Application or Storage, then
172
+ Cookies, then `https://www.overleaf.com`, and copy the value of
173
+ `overleaf_session2`. Treat it like a password. It stops working when you sign
174
+ out. Nothing is stored unless you tick the box that says so.
175
+
176
+ ```bash
177
+ overleaf-comments-export --project-url <link> --out ./out --cookie "PASTE_HERE"
178
+ ```
179
+
180
+ ## When something goes wrong
181
+
182
+ | What you see | What it means |
183
+ |---|---|
184
+ | Could not look up www.overleaf.com | This computer is offline, or a VPN is in the way. Nothing to do with your project. |
185
+ | Overleaf refused the request | The session expired. Sign in again in your browser and re-run. |
186
+ | Could not read Overleaf cookies | Use the paste method above. |
187
+ | The window cannot open | Python's Tk toolkit is missing. The message tells you what to install for your system. |
188
+
189
+ Anything else, please [open an issue](https://github.com/Mangluu/overleaf-comments-export/issues/new/choose).
190
+ Never paste your session cookie into an issue.
191
+
192
+ ## Related projects
193
+
194
+ Several people hit this same wall independently. Different approaches suit
195
+ different people, so here are the others.
196
+
197
+ - [adakite/extract-overleaf-comments](https://github.com/adakite/extract-overleaf-comments)
198
+ works from a saved copy of the page, and can put comments in the PDF margins.
199
+ - [salokr/overleaf-comment-exporter](https://github.com/salokr/overleaf-comment-exporter)
200
+ is a browser extension, so there is nothing to install on the command line.
201
+ - [IcarusLemon/overleaf-comments-cli](https://github.com/IcarusLemon/overleaf-comments-cli)
202
+ is another command line exporter, driving a real browser under the hood.
203
+
204
+ All of them exist because of
205
+ [this three year old request](https://github.com/overleaf/overleaf/issues/1126).
206
+ An official export would make every one of us unnecessary, which would be the
207
+ better outcome.
208
+
209
+ ## Honest limitations
210
+
211
+ This is an unofficial tool. It uses Overleaf's internal endpoints, which are
212
+ undocumented and can change with any release. It identifies itself honestly in
213
+ every request, backs off when asked to, and cannot modify your project. Even
214
+ so, it may stop working one day without warning. If that happens, please say so
215
+ in an issue, because you may be the first to notice.
216
+
217
+ It is not affiliated with or endorsed by Overleaf. Use it on projects you have
218
+ access to, in line with
219
+ [Overleaf's terms](https://www.overleaf.com/legal).
220
+
221
+ ## Feedback and contributing
222
+
223
+ Feedback shapes what gets built next.
224
+
225
+ - Something broke, or the output was wrong. [Open an issue.](https://github.com/Mangluu/overleaf-comments-export/issues/new/choose)
226
+ You do not need to be a programmer. Paste what the tool said and that is plenty.
227
+ - Want it to do something it does not. [Suggest a feature.](https://github.com/Mangluu/overleaf-comments-export/issues/new/choose)
228
+ Describe the task, not only the feature. The real task usually leads somewhere better.
229
+ - A question, or something you built with it. [Discussions.](https://github.com/Mangluu/overleaf-comments-export/discussions)
230
+ - Code. See [CONTRIBUTING.md](CONTRIBUTING.md). Two minutes to get the tests
231
+ running, and there are items marked *help wanted* in [ROADMAP.md](ROADMAP.md).
232
+
233
+ What is coming next is in [ROADMAP.md](ROADMAP.md). What already changed is in
234
+ [CHANGELOG.md](CHANGELOG.md).
235
+
236
+ Maintained by [Shivang Gupta](https://github.com/Mangluu), who wrote it to
237
+ handle the review comments on his own papers.
238
+
239
+ ## License
240
+
241
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,204 @@
1
+ # overleaf-comments-export
2
+
3
+ Get the review comments out of an Overleaf paper, into Markdown and JSON you
4
+ can read, keep, commit, and hand to an AI assistant.
5
+
6
+ [![CI](https://github.com/Mangluu/overleaf-comments-export/actions/workflows/ci.yml/badge.svg)](https://github.com/Mangluu/overleaf-comments-export/actions/workflows/ci.yml)
7
+ [![PyPI](https://img.shields.io/pypi/v/overleaf-comments-export.svg)](https://pypi.org/project/overleaf-comments-export/)
8
+ [![Downloads](https://img.shields.io/pypi/dm/overleaf-comments-export.svg)](https://pypi.org/project/overleaf-comments-export/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%20to%203.14-blue.svg)](https://www.python.org/)
11
+
12
+ Overleaf leaves comments out of both the source download and the Git sync, so
13
+ the only way to work through them is inside the editor, one at a time. On a
14
+ paper with ninety comments from three co-authors that stops being workable.
15
+
16
+ ## What the output looks like
17
+
18
+ ```markdown
19
+ ## Summary
20
+
21
+ - **Threads:** 2 (2 open, 0 resolved)
22
+ - **Tracked changes:** 0
23
+ - **Most active reviewers:** A. Reviewer (2), Co Author (1)
24
+
25
+ ### § Method
26
+
27
+ **Line 142** — 2 comments
28
+
29
+ > …We propose **▸a novel framework◂** for measuring perceived quality across conditions.
30
+
31
+ **C014** _open · 1 reply_ — "a novel framework"
32
+ - **A. Reviewer** · 2026-02-25 06:13 UTC: Needs a citation. Which studies show this?
33
+ - ↳ **Co Author** · 2026-02-26 10:00 UTC: Agree, Smith 2023 would work here.
34
+
35
+ **C015** _open_ — "coherent"
36
+ - **A. Reviewer** · 2026-02-27 13:46 UTC: This word is doing a lot of work. Define it.
37
+ ```
38
+
39
+ Every comment sits in its section, next to the words it was attached to, with
40
+ its replies underneath and a stable id you can point at.
41
+
42
+ ## Install and run
43
+
44
+ ```bash
45
+ pip install overleaf-comments-export
46
+ overleaf-comments-export --gui
47
+ ```
48
+
49
+ That opens a small window. Paste your project link, choose a folder, press the
50
+ button. If you prefer the terminal:
51
+
52
+ ```bash
53
+ overleaf-comments-export \
54
+ --project-url https://www.overleaf.com/project/YOUR_PROJECT_ID \
55
+ --out ./paper-comments
56
+ ```
57
+
58
+ Python 3.10 or newer, tested up to 3.14, on macOS, Windows, and Linux.
59
+
60
+ ## What you get
61
+
62
+ | File | What it is |
63
+ |---|---|
64
+ | `comments-<date>.md` | The readable export, or `comments.md` with `--stable`. Grouped by file, then section, then line. Stable ids `C001`, `T001`. |
65
+ | `comments.json` | The same data, structured. Threads, anchors, tracked changes, source context. |
66
+ | `comments.jsonl` | One self-contained record per comment, for pipelines. |
67
+ | `agents.md` | A short brief telling an AI assistant how to read the other two. |
68
+ | `response-letter.md` | Optional. A point-by-point reply document with a blank slot under every open comment. |
69
+ | `by-reviewer/<name>.md` | Optional. One file per reviewer, so you can work through them one person at a time. |
70
+
71
+ ## Working through comments with an AI
72
+
73
+ This is what the export is shaped for. Hand an assistant the folder and it can
74
+ work on any comment by id, because it already knows the quoted passage, the
75
+ section it lives in, and what the replies said.
76
+
77
+ Some things that work well.
78
+
79
+ - Draft a reply to C014 that answers the reviewer and says what we changed.
80
+ - Which comments are asking for the same thing? Group them.
81
+ - Fill in the response letter for every comment from A. Reviewer.
82
+
83
+ Tracked changes come through too, as insertions and deletions with the
84
+ surrounding text, so a deletion reads as `before ~~removed~~ after`.
85
+
86
+ ## Useful options
87
+
88
+ ```bash
89
+ --response-letter # draft a point-by-point reply document
90
+ --per-reviewer # one report per reviewer
91
+ --reviewer "Emma" # only threads this person touched
92
+ --no-resolved # only what is still open
93
+ --render-mode detailed # more source context around each comment
94
+ --stable # output that only changes when the comments change
95
+ ```
96
+
97
+ Run `overleaf-comments-export --help` for the full list.
98
+
99
+ ## Keeping the comments in git
100
+
101
+ By default each run writes `comments-<date>.md`, so you end up with one file per
102
+ run. That is fine for a one-off export and useless for version control.
103
+
104
+ `--stable` writes a single `comments.md` with no timestamps in it. Re-run it and
105
+ the file does not move unless the comments actually moved.
106
+
107
+ ```bash
108
+ overleaf-comments-export --project-url <link> --out ./review --stable
109
+ git add review/comments.md
110
+ git commit -m "reviewer comments as of today"
111
+ ```
112
+
113
+ Next time you pull the comments, `git diff` shows the new ones and nothing else.
114
+
115
+ ```diff
116
+ thread_count: 41
117
+ +thread_count: 42
118
+
119
+ +**C042** _open_ — "the axis labels"
120
+ +- **A. Reviewer** · 2026-08-14 09:12 UTC: units are missing here
121
+ ```
122
+
123
+ ## Signing in
124
+
125
+ The tool needs the session your browser already has. It reads that session and
126
+ nothing else, and it only ever reads.
127
+
128
+ | How | Notes |
129
+ |---|---|
130
+ | Safari or Firefox | Reads the cookie file directly. No password prompt. |
131
+ | Paste it yourself | Works on every computer and browser. The window shows you how, step by step. |
132
+ | Chrome, Edge, Brave | Works on macOS but asks for your Keychain password every run. Chrome 127 and newer on Windows cannot be read at all, so use the paste option there. |
133
+
134
+ To paste it, open Overleaf, press F12, go to Application or Storage, then
135
+ Cookies, then `https://www.overleaf.com`, and copy the value of
136
+ `overleaf_session2`. Treat it like a password. It stops working when you sign
137
+ out. Nothing is stored unless you tick the box that says so.
138
+
139
+ ```bash
140
+ overleaf-comments-export --project-url <link> --out ./out --cookie "PASTE_HERE"
141
+ ```
142
+
143
+ ## When something goes wrong
144
+
145
+ | What you see | What it means |
146
+ |---|---|
147
+ | Could not look up www.overleaf.com | This computer is offline, or a VPN is in the way. Nothing to do with your project. |
148
+ | Overleaf refused the request | The session expired. Sign in again in your browser and re-run. |
149
+ | Could not read Overleaf cookies | Use the paste method above. |
150
+ | The window cannot open | Python's Tk toolkit is missing. The message tells you what to install for your system. |
151
+
152
+ Anything else, please [open an issue](https://github.com/Mangluu/overleaf-comments-export/issues/new/choose).
153
+ Never paste your session cookie into an issue.
154
+
155
+ ## Related projects
156
+
157
+ Several people hit this same wall independently. Different approaches suit
158
+ different people, so here are the others.
159
+
160
+ - [adakite/extract-overleaf-comments](https://github.com/adakite/extract-overleaf-comments)
161
+ works from a saved copy of the page, and can put comments in the PDF margins.
162
+ - [salokr/overleaf-comment-exporter](https://github.com/salokr/overleaf-comment-exporter)
163
+ is a browser extension, so there is nothing to install on the command line.
164
+ - [IcarusLemon/overleaf-comments-cli](https://github.com/IcarusLemon/overleaf-comments-cli)
165
+ is another command line exporter, driving a real browser under the hood.
166
+
167
+ All of them exist because of
168
+ [this three year old request](https://github.com/overleaf/overleaf/issues/1126).
169
+ An official export would make every one of us unnecessary, which would be the
170
+ better outcome.
171
+
172
+ ## Honest limitations
173
+
174
+ This is an unofficial tool. It uses Overleaf's internal endpoints, which are
175
+ undocumented and can change with any release. It identifies itself honestly in
176
+ every request, backs off when asked to, and cannot modify your project. Even
177
+ so, it may stop working one day without warning. If that happens, please say so
178
+ in an issue, because you may be the first to notice.
179
+
180
+ It is not affiliated with or endorsed by Overleaf. Use it on projects you have
181
+ access to, in line with
182
+ [Overleaf's terms](https://www.overleaf.com/legal).
183
+
184
+ ## Feedback and contributing
185
+
186
+ Feedback shapes what gets built next.
187
+
188
+ - Something broke, or the output was wrong. [Open an issue.](https://github.com/Mangluu/overleaf-comments-export/issues/new/choose)
189
+ You do not need to be a programmer. Paste what the tool said and that is plenty.
190
+ - Want it to do something it does not. [Suggest a feature.](https://github.com/Mangluu/overleaf-comments-export/issues/new/choose)
191
+ Describe the task, not only the feature. The real task usually leads somewhere better.
192
+ - A question, or something you built with it. [Discussions.](https://github.com/Mangluu/overleaf-comments-export/discussions)
193
+ - Code. See [CONTRIBUTING.md](CONTRIBUTING.md). Two minutes to get the tests
194
+ running, and there are items marked *help wanted* in [ROADMAP.md](ROADMAP.md).
195
+
196
+ What is coming next is in [ROADMAP.md](ROADMAP.md). What already changed is in
197
+ [CHANGELOG.md](CHANGELOG.md).
198
+
199
+ Maintained by [Shivang Gupta](https://github.com/Mangluu), who wrote it to
200
+ handle the review comments on his own papers.
201
+
202
+ ## License
203
+
204
+ MIT. See [LICENSE](LICENSE).
@@ -4,6 +4,7 @@ import argparse
4
4
  import logging
5
5
  import os
6
6
  import sys
7
+ import traceback
7
8
  from pathlib import Path
8
9
 
9
10
  from . import __version__
@@ -11,6 +12,35 @@ from .client import OverleafClient, UserFacingError
11
12
  from .export import ExportResult, run_export
12
13
 
13
14
 
15
+ def _no_tkinter_message() -> str:
16
+ """Platform-specific instructions for installing Python's GUI toolkit."""
17
+ if sys.platform == "darwin":
18
+ fix = (
19
+ "Install Python from python.org (it includes the GUI toolkit), or\n"
20
+ "with Homebrew run:\n\n"
21
+ " brew install python-tk"
22
+ )
23
+ elif sys.platform.startswith("win"):
24
+ fix = (
25
+ "Re-run the Python installer from python.org, choose \"Modify\", and\n"
26
+ "tick \"tcl/tk and IDLE\"."
27
+ )
28
+ else:
29
+ fix = (
30
+ "Install it with your package manager, for example:\n\n"
31
+ " Debian/Ubuntu : sudo apt install python3-tk\n"
32
+ " Fedora : sudo dnf install python3-tkinter\n"
33
+ " Arch : sudo pacman -S tk"
34
+ )
35
+ return (
36
+ "The window cannot open because this Python has no GUI toolkit "
37
+ "installed.\n\n"
38
+ f"{fix}\n\n"
39
+ "Or skip the window entirely and use the command line:\n\n"
40
+ " overleaf-comments-export --project-url <your project link> --out ./comments"
41
+ )
42
+
43
+
14
44
  def main(argv: list[str] | None = None) -> int:
15
45
  parser = argparse.ArgumentParser(
16
46
  prog="overleaf-comments-export",
@@ -106,6 +136,21 @@ def main(argv: list[str] | None = None) -> int:
106
136
  action="store_false",
107
137
  help="Skip writing comments.jsonl (the streaming-friendly companion).",
108
138
  )
139
+ parser.add_argument(
140
+ "--response-letter",
141
+ action="store_true",
142
+ help="Also write response-letter.md: a point-by-point reply document "
143
+ "pre-filled with every open comment, grouped by who raised it, with "
144
+ "blanks for your response.",
145
+ )
146
+ parser.add_argument(
147
+ "--stable",
148
+ action="store_true",
149
+ help="Write output that only changes when the comments change: one "
150
+ "comments.md instead of a dated filename, and no timestamps. Use this "
151
+ "when you keep the export in a git repository, so a diff shows the new "
152
+ "comments and nothing else.",
153
+ )
109
154
  parser.add_argument(
110
155
  "--per-reviewer",
111
156
  action="store_true",
@@ -120,8 +165,31 @@ def main(argv: list[str] | None = None) -> int:
120
165
  args = parser.parse_args(argv)
121
166
 
122
167
  if args.gui or (not args.project_url and not args.out):
123
- from .gui import launch_gui
124
- return launch_gui()
168
+ try:
169
+ from .gui import launch_gui
170
+ except ImportError:
171
+ # tkinter is NOT bundled with Python everywhere — most Linux
172
+ # distributions ship it as a separate system package, and it is
173
+ # missing from some minimal/conda builds.
174
+ print(_no_tkinter_message(), file=sys.stderr)
175
+ return 1
176
+ try:
177
+ return launch_gui()
178
+ except Exception as e:
179
+ # Typically TclError on a headless machine (SSH, server, container).
180
+ if "display" in str(e).lower() or type(e).__name__ == "TclError":
181
+ print(
182
+ "There is no screen to open a window on.\n\n"
183
+ "This looks like a computer without a desktop (a server, or "
184
+ "a remote session). Use the command line instead, for "
185
+ "example:\n\n"
186
+ " overleaf-comments-export --project-url <your project link> "
187
+ "--out ./comments\n\n"
188
+ "Run with --help to see every option.",
189
+ file=sys.stderr,
190
+ )
191
+ return 1
192
+ raise
125
193
 
126
194
  if not args.project_url or not args.out:
127
195
  parser.error("--project-url and --out are required in CLI mode (or pass --gui).")
@@ -151,12 +219,27 @@ def main(argv: list[str] | None = None) -> int:
151
219
  render_mode=args.render_mode,
152
220
  write_jsonl=args.write_jsonl,
153
221
  per_reviewer_reports=args.per_reviewer,
222
+ response_letter=args.response_letter,
223
+ stable=args.stable,
154
224
  progress=lambda msg: print(msg, file=sys.stderr),
155
225
  )
156
226
  except UserFacingError as e:
157
227
  # Expected, explainable failures: no traceback, just what to do next.
158
228
  print(f"\n{e}", file=sys.stderr)
159
229
  return 1
230
+ except Exception:
231
+ # Unexpected: show the traceback, but also tell people where to send it.
232
+ # The moment something breaks is the only moment we have their attention.
233
+ traceback.print_exc()
234
+ print(
235
+ f"\nThat looks like a bug in overleaf-comments-export {__version__}.\n"
236
+ "Please report it (copy the lines above) at\n"
237
+ " https://github.com/Mangluu/overleaf-comments-export/issues/new/choose\n"
238
+ "It probably affects other people too, and it cannot be fixed if "
239
+ "nobody says anything.",
240
+ file=sys.stderr,
241
+ )
242
+ return 2
160
243
  print(f"\nDone. Open: {result.markdown_path}")
161
244
  return 0
162
245