scholarcli 1.23__tar.gz → 1.26__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 (88) hide show
  1. {scholarcli-1.23 → scholarcli-1.26}/PKG-INFO +93 -4
  2. {scholarcli-1.23 → scholarcli-1.26}/README.md +92 -3
  3. {scholarcli-1.23 → scholarcli-1.26}/pyproject.toml +1 -1
  4. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/__init__.py +3 -0
  5. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/cli.py +798 -100
  6. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/crossref.py +67 -11
  7. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/enrich.py +30 -5
  8. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/llm_review.py +202 -90
  9. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/notes.py +34 -0
  10. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/pdf.py +10 -41
  11. scholarcli-1.26/src/scholar/preprint.py +220 -0
  12. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/providers.py +1489 -286
  13. scholarcli-1.26/src/scholar/ratelimit.py +481 -0
  14. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/review.py +957 -240
  15. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/scholar.py +152 -15
  16. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/tui.py +15 -0
  17. scholarcli-1.26/src/scholar/unpaywall.py +203 -0
  18. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/utils.py +102 -0
  19. {scholarcli-1.23 → scholarcli-1.26}/src/scholarcli.egg-info/PKG-INFO +93 -4
  20. {scholarcli-1.23 → scholarcli-1.26}/src/scholarcli.egg-info/SOURCES.txt +6 -0
  21. {scholarcli-1.23 → scholarcli-1.26}/tests/test_cli.py +901 -0
  22. {scholarcli-1.23 → scholarcli-1.26}/tests/test_crossref.py +88 -1
  23. {scholarcli-1.23 → scholarcli-1.26}/tests/test_enrich.py +90 -0
  24. {scholarcli-1.23 → scholarcli-1.26}/tests/test_llm_review.py +311 -0
  25. {scholarcli-1.23 → scholarcli-1.26}/tests/test_notes.py +59 -0
  26. {scholarcli-1.23 → scholarcli-1.26}/tests/test_pdf.py +20 -24
  27. scholarcli-1.26/tests/test_preprint.py +302 -0
  28. {scholarcli-1.23 → scholarcli-1.26}/tests/test_providers.py +1354 -55
  29. scholarcli-1.26/tests/test_ratelimit.py +396 -0
  30. {scholarcli-1.23 → scholarcli-1.26}/tests/test_review.py +635 -0
  31. {scholarcli-1.23 → scholarcli-1.26}/tests/test_scholar.py +227 -0
  32. scholarcli-1.26/tests/test_unpaywall.py +265 -0
  33. {scholarcli-1.23 → scholarcli-1.26}/tests/test_utils.py +65 -0
  34. {scholarcli-1.23 → scholarcli-1.26}/LICENSE +0 -0
  35. {scholarcli-1.23 → scholarcli-1.26}/setup.cfg +0 -0
  36. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/__main__.py +0 -0
  37. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/cache.py +0 -0
  38. {scholarcli-1.23 → scholarcli-1.26}/src/scholar/questionary.py +0 -0
  39. {scholarcli-1.23 → scholarcli-1.26}/src/scholarcli.egg-info/dependency_links.txt +0 -0
  40. {scholarcli-1.23 → scholarcli-1.26}/src/scholarcli.egg-info/entry_points.txt +0 -0
  41. {scholarcli-1.23 → scholarcli-1.26}/src/scholarcli.egg-info/requires.txt +0 -0
  42. {scholarcli-1.23 → scholarcli-1.26}/src/scholarcli.egg-info/top_level.txt +0 -0
  43. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/__init__.py +0 -0
  44. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/__init__.py +0 -0
  45. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/aggregator.py +0 -0
  46. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/arxiv.py +0 -0
  47. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/base.py +0 -0
  48. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/crossref.py +0 -0
  49. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/google_scholar.py +0 -0
  50. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/openalex.py +0 -0
  51. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/opencitations.py +0 -0
  52. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/apis/semantic_scholar.py +0 -0
  53. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/cli.py +0 -0
  54. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/exporters/__init__.py +0 -0
  55. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/exporters/bibtex.py +0 -0
  56. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/exporters/csv_exporter.py +0 -0
  57. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/exporters/tikz.py +0 -0
  58. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/filters/__init__.py +0 -0
  59. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/filters/filter_engine.py +0 -0
  60. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/models.py +0 -0
  61. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/paper_utils.py +0 -0
  62. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/parsers/__init__.py +0 -0
  63. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/parsers/pdf_parser.py +0 -0
  64. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/scoring/__init__.py +0 -0
  65. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/scoring/base.py +0 -0
  66. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/scoring/llm_scorer.py +0 -0
  67. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/scoring/tfidf_scorer.py +0 -0
  68. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/services.py +0 -0
  69. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/snowballing.py +0 -0
  70. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/storage/__init__.py +0 -0
  71. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/storage/json_storage.py +0 -0
  72. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/tui/__init__.py +0 -0
  73. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/tui/app.py +0 -0
  74. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/tui/dialogs.py +0 -0
  75. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/tui/setup.py +0 -0
  76. {scholarcli-1.23 → scholarcli-1.26}/src/snowball/visualization.py +0 -0
  77. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/__init__.py +0 -0
  78. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/analysis.py +0 -0
  79. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/cli.py +0 -0
  80. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/clustering.py +0 -0
  81. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/database.py +0 -0
  82. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/grobid.py +0 -0
  83. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/logging.py +0 -0
  84. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/models.py +0 -0
  85. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/project.py +0 -0
  86. {scholarcli-1.23 → scholarcli-1.26}/src/tuxedo/tui.py +0 -0
  87. {scholarcli-1.23 → scholarcli-1.26}/tests/test_cache.py +0 -0
  88. {scholarcli-1.23 → scholarcli-1.26}/tests/test_tui.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scholarcli
3
- Version: 1.23
3
+ Version: 1.26
4
4
  Summary: A tool for structured literature searches across bibliographic databases
5
5
  Author-email: Daniel Bosk <dbosk@kth.se>, Ric Glassey <glassey@kth.se>
6
6
  License-Expression: MIT
@@ -46,19 +46,36 @@ A command-line tool for conducting structured literature searches across multipl
46
46
 
47
47
  ### Multi-Database Search
48
48
 
49
- Search across six academic databases with a single query:
49
+ Search across fifteen academic databases with a single query:
50
50
 
51
51
  - **Semantic Scholar** - AI-powered research database with 200M+ papers
52
52
  - **OpenAlex** - Open catalog of 250M+ scholarly works
53
53
  - **DBLP** - Computer science bibliography
54
54
  - **Web of Science** - Comprehensive citation index (requires API key)
55
55
  - **IEEE Xplore** - IEEE technical literature (requires API key)
56
- - **arXiv** - Preprints (no API key)
56
+ - **Scopus** - Elsevier's abstract and citation database (requires API key)
57
+ - **arXiv** - Preprints in physics, math, CS (no API key)
58
+ - **HAL** - The French national open archive (no API key)
59
+ - **Preprint servers** - SSRN, bioRxiv, medRxiv, ChemRxiv, Research
60
+ Square, Preprints.org, and the IACR Cryptology ePrint Archive, each
61
+ searched through OpenAlex pinned to that server (none of them offers
62
+ a usable search API of its own)
63
+
64
+ The preprint-server providers are opt-in: a default search already finds
65
+ their papers through OpenAlex, so they run only when you name them —
66
+ either individually (`-p ssrn` scopes a search to SSRN) or all at once
67
+ with the `preprints` group.
57
68
 
58
69
  ```bash
59
70
  # Search specific providers
60
71
  scholar search "federated learning" -p s2 -p openalex
61
72
 
73
+ # Scope a search to one preprint server
74
+ scholar search "corporate governance" -p ssrn
75
+
76
+ # All preprint servers at once (arXiv, HAL, SSRN, bioRxiv, medRxiv, ...)
77
+ scholar search "diffusion models" -p preprints
78
+
62
79
  # Start from a research question (LLM generates provider-specific queries)
63
80
  scholar rq "How can privacy-preserving ML be evaluated?" \
64
81
  --provider openalex --provider dblp \
@@ -109,6 +126,16 @@ scholar sessions resume "machine learning"
109
126
 
110
127
  # Export session to reports
111
128
  scholar sessions export "machine learning" -f all
129
+
130
+ # LaTeX report as an \input-able fragment (writes review.tex + review.bib)
131
+ scholar sessions export "machine learning" -f latex --no-standalone -o review
132
+
133
+ # Audit table for a backing appendix (one row per paper with the reason;
134
+ # always a fragment; --lang en|sv, --theme TAG=NAME gives themes readable names)
135
+ scholar sessions export "machine learning" -f table --lang sv --label sok-A \
136
+ --track "sökspår 1" --theme ml=maskininlärning -o review-full
137
+ # ... listing only the cited/supporting/qualifying rows, the rest as counts
138
+ scholar sessions export "machine learning" -f table --bearing-only -o review-bearing
112
139
  ```
113
140
 
114
141
  ### Paper Notes
@@ -139,6 +166,18 @@ scholar cache path # Print cache directory
139
166
 
140
167
  PDF downloads are also cached for offline viewing.
141
168
 
169
+ ### Rate-Limit and Quota Tracking
170
+
171
+ Provider rate limits and daily quotas (e.g. IEEE's 200 requests/day) are
172
+ tracked persistently across invocations: a provider whose budget is spent
173
+ is skipped with a warning naming the reset time instead of firing doomed
174
+ requests.
175
+
176
+ ```bash
177
+ scholar providers limits # Show usage, remaining budget, reset times
178
+ scholar providers limits --reset ieee # Clear tracked state for one provider
179
+ ```
180
+
142
181
  ## Quickstart
143
182
 
144
183
  ### Install
@@ -204,15 +243,34 @@ uv pip install scholarcli
204
243
 
205
244
  ## Configuration
206
245
 
246
+ Set `SCHOLAR_EMAIL` to a contact address: OpenAlex (and thus every
247
+ preprint-server provider), Crossref, and the polite pools use it for
248
+ faster responses, and Unpaywall (open-access lookup during
249
+ `scholar enrich` and `scholar pdf open <doi>`) requires it. `OPENALEX_EMAIL`
250
+ and `CROSSREF_MAILTO` are still honoured as per-service overrides.
251
+
252
+ OpenAlex meters requests against a daily budget (a search costs $0.001,
253
+ reset at midnight UTC). A free API key from
254
+ [openalex.org/settings/api](https://openalex.org/settings/api) raises the
255
+ budget tenfold; set it as `OPENALEX_API_KEY` and it is used by the
256
+ `openalex` provider and every preprint-server provider. `scholar
257
+ providers check` then shows how much of the day's budget is left, and a
258
+ search that hits the spent budget reports the reset time instead of a
259
+ bare 429.
260
+
207
261
  Some providers require API keys set as environment variables:
208
262
 
209
263
  | Provider | Environment Variable | Required | How to Get |
210
264
  |----------|---------------------|----------|------------|
211
265
  | Semantic Scholar | `S2_API_KEY` | No | [api.semanticscholar.org](https://api.semanticscholar.org) |
212
- | OpenAlex | `OPENALEX_EMAIL` | No | Any email (for polite pool) |
266
+ | OpenAlex | `OPENALEX_API_KEY`, `SCHOLAR_EMAIL` | No | [openalex.org/settings/api](https://openalex.org/settings/api) (10x daily budget); any email (polite pool) |
213
267
  | DBLP | - | No | No key needed |
268
+ | arXiv | - | No | No key needed |
269
+ | HAL | - | No | No key needed |
270
+ | SSRN, bioRxiv, medRxiv, ChemRxiv, Research Square, Preprints.org, IACR | `SCHOLAR_EMAIL` | No | Any email (they search via OpenAlex) |
214
271
  | Web of Science | `WOS_EXPANDED_API_KEY` or `WOS_STARTER_API_KEY` | Yes | [developer.clarivate.com](https://developer.clarivate.com) |
215
272
  | IEEE Xplore | `IEEE_API_KEY` | Yes | [developer.ieee.org](https://developer.ieee.org) |
273
+ | Scopus | `SCOPUS_API_KEY` | Yes | [dev.elsevier.com](https://dev.elsevier.com) |
216
274
 
217
275
  View provider status:
218
276
 
@@ -249,6 +307,15 @@ scholar sessions resume "privacy-ml-review"
249
307
 
250
308
  # 4. Generate reports
251
309
  scholar sessions export "privacy-ml-review" -f all
310
+
311
+ # 5. Synthesise the kept papers (needs a research context); the LaTeX
312
+ # document ends with the decision record as an appendix
313
+ scholar llm context "privacy-ml-review" "How is privacy preserved in ML?"
314
+ scholar llm synthesize "privacy-ml-review" -f latex -o synthesis.tex
315
+
316
+ # ... or as a fragment to \input into a thesis chapter (also writes
317
+ # synthesis.bib; add \addbibresource{synthesis.bib} to the preamble)
318
+ scholar llm synthesize "privacy-ml-review" -f latex --no-standalone -o synthesis.tex
252
319
  ```
253
320
 
254
321
  ### Enriching Results
@@ -263,6 +330,22 @@ scholar search "query" --enrich
263
330
  scholar enrich "session-name"
264
331
  ```
265
332
 
333
+ When no PDF can be found for a paper, enrichment falls back to preprint
334
+ versions: authoritative links (OpenAlex's alternate locations and
335
+ Crossref's `has-preprint` relation) are always followed, and with
336
+ `--preprint-search` the preprint servers are additionally searched by
337
+ title and authors (exact match only). An adopted preprint *replaces*
338
+ the entry — its DOI, venue, and PDF — so exported citations point at
339
+ the version you actually read; the published DOI is kept on the entry
340
+ for provenance, and `scholar verify` reports such entries as
341
+ `preprint of <doi>` rather than superseded.
342
+
343
+ ```bash
344
+ # Also search preprint servers for papers without a PDF
345
+ scholar enrich "session-name" --preprint-search
346
+ scholar search "query" --enrich --preprint-search
347
+ ```
348
+
266
349
  ### PDF Management
267
350
 
268
351
  ```bash
@@ -299,6 +382,12 @@ For large result sets, Scholar can use LLMs to assist with paper classification:
299
382
  # In the TUI, press 'L' to invoke LLM classification
300
383
  # Or use the CLI command directly
301
384
  scholar llm classify "session-name" --count 10
385
+
386
+ # Constrain the tags to a vocabulary (tags already in the session count too)
387
+ scholar llm classify "session-name" -t supports-claim -t qualifies-claim \
388
+ -t adjacent-subtopic -t off-topic-false-hit
389
+ # ... or let the model add tags of its own when none of them fits
390
+ scholar llm classify "session-name" --allow-new-tags
302
391
  ```
303
392
 
304
393
  ### How It Works
@@ -6,19 +6,36 @@ A command-line tool for conducting structured literature searches across multipl
6
6
 
7
7
  ### Multi-Database Search
8
8
 
9
- Search across six academic databases with a single query:
9
+ Search across fifteen academic databases with a single query:
10
10
 
11
11
  - **Semantic Scholar** - AI-powered research database with 200M+ papers
12
12
  - **OpenAlex** - Open catalog of 250M+ scholarly works
13
13
  - **DBLP** - Computer science bibliography
14
14
  - **Web of Science** - Comprehensive citation index (requires API key)
15
15
  - **IEEE Xplore** - IEEE technical literature (requires API key)
16
- - **arXiv** - Preprints (no API key)
16
+ - **Scopus** - Elsevier's abstract and citation database (requires API key)
17
+ - **arXiv** - Preprints in physics, math, CS (no API key)
18
+ - **HAL** - The French national open archive (no API key)
19
+ - **Preprint servers** - SSRN, bioRxiv, medRxiv, ChemRxiv, Research
20
+ Square, Preprints.org, and the IACR Cryptology ePrint Archive, each
21
+ searched through OpenAlex pinned to that server (none of them offers
22
+ a usable search API of its own)
23
+
24
+ The preprint-server providers are opt-in: a default search already finds
25
+ their papers through OpenAlex, so they run only when you name them —
26
+ either individually (`-p ssrn` scopes a search to SSRN) or all at once
27
+ with the `preprints` group.
17
28
 
18
29
  ```bash
19
30
  # Search specific providers
20
31
  scholar search "federated learning" -p s2 -p openalex
21
32
 
33
+ # Scope a search to one preprint server
34
+ scholar search "corporate governance" -p ssrn
35
+
36
+ # All preprint servers at once (arXiv, HAL, SSRN, bioRxiv, medRxiv, ...)
37
+ scholar search "diffusion models" -p preprints
38
+
22
39
  # Start from a research question (LLM generates provider-specific queries)
23
40
  scholar rq "How can privacy-preserving ML be evaluated?" \
24
41
  --provider openalex --provider dblp \
@@ -69,6 +86,16 @@ scholar sessions resume "machine learning"
69
86
 
70
87
  # Export session to reports
71
88
  scholar sessions export "machine learning" -f all
89
+
90
+ # LaTeX report as an \input-able fragment (writes review.tex + review.bib)
91
+ scholar sessions export "machine learning" -f latex --no-standalone -o review
92
+
93
+ # Audit table for a backing appendix (one row per paper with the reason;
94
+ # always a fragment; --lang en|sv, --theme TAG=NAME gives themes readable names)
95
+ scholar sessions export "machine learning" -f table --lang sv --label sok-A \
96
+ --track "sökspår 1" --theme ml=maskininlärning -o review-full
97
+ # ... listing only the cited/supporting/qualifying rows, the rest as counts
98
+ scholar sessions export "machine learning" -f table --bearing-only -o review-bearing
72
99
  ```
73
100
 
74
101
  ### Paper Notes
@@ -99,6 +126,18 @@ scholar cache path # Print cache directory
99
126
 
100
127
  PDF downloads are also cached for offline viewing.
101
128
 
129
+ ### Rate-Limit and Quota Tracking
130
+
131
+ Provider rate limits and daily quotas (e.g. IEEE's 200 requests/day) are
132
+ tracked persistently across invocations: a provider whose budget is spent
133
+ is skipped with a warning naming the reset time instead of firing doomed
134
+ requests.
135
+
136
+ ```bash
137
+ scholar providers limits # Show usage, remaining budget, reset times
138
+ scholar providers limits --reset ieee # Clear tracked state for one provider
139
+ ```
140
+
102
141
  ## Quickstart
103
142
 
104
143
  ### Install
@@ -164,15 +203,34 @@ uv pip install scholarcli
164
203
 
165
204
  ## Configuration
166
205
 
206
+ Set `SCHOLAR_EMAIL` to a contact address: OpenAlex (and thus every
207
+ preprint-server provider), Crossref, and the polite pools use it for
208
+ faster responses, and Unpaywall (open-access lookup during
209
+ `scholar enrich` and `scholar pdf open <doi>`) requires it. `OPENALEX_EMAIL`
210
+ and `CROSSREF_MAILTO` are still honoured as per-service overrides.
211
+
212
+ OpenAlex meters requests against a daily budget (a search costs $0.001,
213
+ reset at midnight UTC). A free API key from
214
+ [openalex.org/settings/api](https://openalex.org/settings/api) raises the
215
+ budget tenfold; set it as `OPENALEX_API_KEY` and it is used by the
216
+ `openalex` provider and every preprint-server provider. `scholar
217
+ providers check` then shows how much of the day's budget is left, and a
218
+ search that hits the spent budget reports the reset time instead of a
219
+ bare 429.
220
+
167
221
  Some providers require API keys set as environment variables:
168
222
 
169
223
  | Provider | Environment Variable | Required | How to Get |
170
224
  |----------|---------------------|----------|------------|
171
225
  | Semantic Scholar | `S2_API_KEY` | No | [api.semanticscholar.org](https://api.semanticscholar.org) |
172
- | OpenAlex | `OPENALEX_EMAIL` | No | Any email (for polite pool) |
226
+ | OpenAlex | `OPENALEX_API_KEY`, `SCHOLAR_EMAIL` | No | [openalex.org/settings/api](https://openalex.org/settings/api) (10x daily budget); any email (polite pool) |
173
227
  | DBLP | - | No | No key needed |
228
+ | arXiv | - | No | No key needed |
229
+ | HAL | - | No | No key needed |
230
+ | SSRN, bioRxiv, medRxiv, ChemRxiv, Research Square, Preprints.org, IACR | `SCHOLAR_EMAIL` | No | Any email (they search via OpenAlex) |
174
231
  | Web of Science | `WOS_EXPANDED_API_KEY` or `WOS_STARTER_API_KEY` | Yes | [developer.clarivate.com](https://developer.clarivate.com) |
175
232
  | IEEE Xplore | `IEEE_API_KEY` | Yes | [developer.ieee.org](https://developer.ieee.org) |
233
+ | Scopus | `SCOPUS_API_KEY` | Yes | [dev.elsevier.com](https://dev.elsevier.com) |
176
234
 
177
235
  View provider status:
178
236
 
@@ -209,6 +267,15 @@ scholar sessions resume "privacy-ml-review"
209
267
 
210
268
  # 4. Generate reports
211
269
  scholar sessions export "privacy-ml-review" -f all
270
+
271
+ # 5. Synthesise the kept papers (needs a research context); the LaTeX
272
+ # document ends with the decision record as an appendix
273
+ scholar llm context "privacy-ml-review" "How is privacy preserved in ML?"
274
+ scholar llm synthesize "privacy-ml-review" -f latex -o synthesis.tex
275
+
276
+ # ... or as a fragment to \input into a thesis chapter (also writes
277
+ # synthesis.bib; add \addbibresource{synthesis.bib} to the preamble)
278
+ scholar llm synthesize "privacy-ml-review" -f latex --no-standalone -o synthesis.tex
212
279
  ```
213
280
 
214
281
  ### Enriching Results
@@ -223,6 +290,22 @@ scholar search "query" --enrich
223
290
  scholar enrich "session-name"
224
291
  ```
225
292
 
293
+ When no PDF can be found for a paper, enrichment falls back to preprint
294
+ versions: authoritative links (OpenAlex's alternate locations and
295
+ Crossref's `has-preprint` relation) are always followed, and with
296
+ `--preprint-search` the preprint servers are additionally searched by
297
+ title and authors (exact match only). An adopted preprint *replaces*
298
+ the entry — its DOI, venue, and PDF — so exported citations point at
299
+ the version you actually read; the published DOI is kept on the entry
300
+ for provenance, and `scholar verify` reports such entries as
301
+ `preprint of <doi>` rather than superseded.
302
+
303
+ ```bash
304
+ # Also search preprint servers for papers without a PDF
305
+ scholar enrich "session-name" --preprint-search
306
+ scholar search "query" --enrich --preprint-search
307
+ ```
308
+
226
309
  ### PDF Management
227
310
 
228
311
  ```bash
@@ -259,6 +342,12 @@ For large result sets, Scholar can use LLMs to assist with paper classification:
259
342
  # In the TUI, press 'L' to invoke LLM classification
260
343
  # Or use the CLI command directly
261
344
  scholar llm classify "session-name" --count 10
345
+
346
+ # Constrain the tags to a vocabulary (tags already in the session count too)
347
+ scholar llm classify "session-name" -t supports-claim -t qualifies-claim \
348
+ -t adjacent-subtopic -t off-topic-false-hit
349
+ # ... or let the model add tags of its own when none of them fits
350
+ scholar llm classify "session-name" --allow-new-tags
262
351
  ```
263
352
 
264
353
  ### How It Works
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "scholarcli"
3
- version = "1.23"
3
+ version = "1.26"
4
4
  description = "A tool for structured literature searches across bibliographic databases"
5
5
  authors = [{ name = "Daniel Bosk", email = "dbosk@kth.se" },
6
6
  { name = "Ric Glassey", email = "glassey@kth.se" }]
@@ -4,6 +4,7 @@ Scholar package for structured literature searches.
4
4
 
5
5
  from .scholar import Search, SearchResult, Paper, SearchFilters
6
6
  from .scholar import search, filter_papers, deduplicate_papers
7
+ from .scholar import deduplicate_versions, merge_version_of
7
8
  from .scholar import get_registry, isolated_registry
8
9
  from .utils import safe_get_nested, ensure_list
9
10
 
@@ -15,6 +16,8 @@ __all__ = [
15
16
  "search",
16
17
  "filter_papers",
17
18
  "deduplicate_papers",
19
+ "deduplicate_versions",
20
+ "merge_version_of",
18
21
  "get_registry",
19
22
  "isolated_registry",
20
23
  "safe_get_nested",