papers-app 0.2.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.
- papers_app-0.2.0/.gitignore +10 -0
- papers_app-0.2.0/CONTRIBUTING.md +126 -0
- papers_app-0.2.0/LICENSE +21 -0
- papers_app-0.2.0/PKG-INFO +138 -0
- papers_app-0.2.0/README.md +109 -0
- papers_app-0.2.0/papers/__init__.py +2 -0
- papers_app-0.2.0/papers/__main__.py +3 -0
- papers_app-0.2.0/papers/agent/__init__.py +2 -0
- papers_app-0.2.0/papers/agent/loop.py +295 -0
- papers_app-0.2.0/papers/agent/mcp_server.py +65 -0
- papers_app-0.2.0/papers/agent/tools.py +329 -0
- papers_app-0.2.0/papers/ai/__init__.py +67 -0
- papers_app-0.2.0/papers/ai/anthropic_api.py +53 -0
- papers_app-0.2.0/papers/ai/claude_code.py +126 -0
- papers_app-0.2.0/papers/ai/codex.py +66 -0
- papers_app-0.2.0/papers/ai/errors.py +13 -0
- papers_app-0.2.0/papers/ai/openai_compat.py +124 -0
- papers_app-0.2.0/papers/ai/providers.py +112 -0
- papers_app-0.2.0/papers/ai/streaming.py +111 -0
- papers_app-0.2.0/papers/bibtex.py +28 -0
- papers_app-0.2.0/papers/chat/__init__.py +1 -0
- papers_app-0.2.0/papers/chat/answer.py +92 -0
- papers_app-0.2.0/papers/chat/store.py +178 -0
- papers_app-0.2.0/papers/cli.py +50 -0
- papers_app-0.2.0/papers/config.py +52 -0
- papers_app-0.2.0/papers/db.py +120 -0
- papers_app-0.2.0/papers/figures.py +234 -0
- papers_app-0.2.0/papers/folders.py +56 -0
- papers_app-0.2.0/papers/index.py +96 -0
- papers_app-0.2.0/papers/ingest.py +128 -0
- papers_app-0.2.0/papers/keys.py +103 -0
- papers_app-0.2.0/papers/library.py +208 -0
- papers_app-0.2.0/papers/llm.py +428 -0
- papers_app-0.2.0/papers/main.py +73 -0
- papers_app-0.2.0/papers/notes.py +73 -0
- papers_app-0.2.0/papers/pdf.py +116 -0
- papers_app-0.2.0/papers/routes/__init__.py +4 -0
- papers_app-0.2.0/papers/routes/chat.py +166 -0
- papers_app-0.2.0/papers/routes/goals.py +65 -0
- papers_app-0.2.0/papers/routes/learning.py +195 -0
- papers_app-0.2.0/papers/routes/notes.py +92 -0
- papers_app-0.2.0/papers/routes/papers.py +213 -0
- papers_app-0.2.0/papers/routes/reading.py +114 -0
- papers_app-0.2.0/papers/routes/recall.py +34 -0
- papers_app-0.2.0/papers/routes/settings.py +133 -0
- papers_app-0.2.0/papers/scholar.py +128 -0
- papers_app-0.2.0/papers/static/css/base.css +109 -0
- papers_app-0.2.0/papers/static/css/chat.css +241 -0
- papers_app-0.2.0/papers/static/css/components.css +285 -0
- papers_app-0.2.0/papers/static/css/goals.css +85 -0
- papers_app-0.2.0/papers/static/css/library.css +142 -0
- papers_app-0.2.0/papers/static/css/map.css +182 -0
- papers_app-0.2.0/papers/static/css/paper.css +138 -0
- papers_app-0.2.0/papers/static/css/reader.css +256 -0
- papers_app-0.2.0/papers/static/css/recall.css +69 -0
- papers_app-0.2.0/papers/static/css/settings.css +36 -0
- papers_app-0.2.0/papers/static/css/tokens.css +129 -0
- papers_app-0.2.0/papers/static/index.html +44 -0
- papers_app-0.2.0/papers/static/js/chat/answer.js +130 -0
- papers_app-0.2.0/papers/static/js/chat/canvas.js +24 -0
- papers_app-0.2.0/papers/static/js/chat/conversation.js +345 -0
- papers_app-0.2.0/papers/static/js/chat/render.js +230 -0
- papers_app-0.2.0/papers/static/js/chat/stream.js +39 -0
- papers_app-0.2.0/papers/static/js/chat/widgets.js +161 -0
- papers_app-0.2.0/papers/static/js/components/combobox.js +91 -0
- papers_app-0.2.0/papers/static/js/components/folderpicker.js +95 -0
- papers_app-0.2.0/papers/static/js/core.js +358 -0
- papers_app-0.2.0/papers/static/js/covers.js +74 -0
- papers_app-0.2.0/papers/static/js/highlights.js +181 -0
- papers_app-0.2.0/papers/static/js/main.js +115 -0
- papers_app-0.2.0/papers/static/js/notes.js +160 -0
- papers_app-0.2.0/papers/static/js/pages/goals.js +149 -0
- papers_app-0.2.0/papers/static/js/pages/library.js +144 -0
- papers_app-0.2.0/papers/static/js/pages/map.js +84 -0
- papers_app-0.2.0/papers/static/js/pages/recall.js +70 -0
- papers_app-0.2.0/papers/static/js/pages/settings.js +225 -0
- papers_app-0.2.0/papers/static/js/pages/shared.js +46 -0
- papers_app-0.2.0/papers/static/js/paper/figures.js +62 -0
- papers_app-0.2.0/papers/static/js/paper/overview.js +291 -0
- papers_app-0.2.0/papers/static/js/paper/reader/bar.js +50 -0
- papers_app-0.2.0/papers/static/js/paper/reader/cite.js +36 -0
- papers_app-0.2.0/papers/static/js/paper/reader/finish.js +54 -0
- papers_app-0.2.0/papers/static/js/paper/reader/highlighter.js +132 -0
- papers_app-0.2.0/papers/static/js/paper/reader/keys.js +30 -0
- papers_app-0.2.0/papers/static/js/paper/reader/layout.js +69 -0
- papers_app-0.2.0/papers/static/js/paper/reader/panel.js +105 -0
- papers_app-0.2.0/papers/static/js/paper/reader/progress.js +71 -0
- papers_app-0.2.0/papers/static/js/paper/reader/route.js +17 -0
- papers_app-0.2.0/papers/static/js/paper/reader/selection.js +113 -0
- papers_app-0.2.0/papers/static/js/paper/reader/state.js +22 -0
- papers_app-0.2.0/papers/static/js/paper/reader/terms.js +85 -0
- papers_app-0.2.0/papers/static/js/paper/reader/views.js +126 -0
- papers_app-0.2.0/papers/static/js/paper/reader/vocab.js +122 -0
- papers_app-0.2.0/papers/static/js/paper/reader/zoom.js +29 -0
- papers_app-0.2.0/papers/static/js/paper/reader.js +92 -0
- papers_app-0.2.0/papers/static/js/paper/review.js +109 -0
- papers_app-0.2.0/papers/static/js/paper/shared.js +23 -0
- papers_app-0.2.0/papers/static/js/pdfview.js +128 -0
- papers_app-0.2.0/papers/static/js/readprefs.js +123 -0
- papers_app-0.2.0/papers/static/js/speech.js +39 -0
- papers_app-0.2.0/papers/static/js/textview.js +52 -0
- papers_app-0.2.0/papers/static/js/theme.js +52 -0
- papers_app-0.2.0/papers/static/js/tracker.js +97 -0
- papers_app-0.2.0/papers/store.py +100 -0
- papers_app-0.2.0/pyproject.toml +65 -0
- papers_app-0.2.0/tests/__init__.py +0 -0
- papers_app-0.2.0/tests/conftest.py +54 -0
- papers_app-0.2.0/tests/test_abstract_figures.py +88 -0
- papers_app-0.2.0/tests/test_add_link.py +65 -0
- papers_app-0.2.0/tests/test_agent.py +164 -0
- papers_app-0.2.0/tests/test_agent_actions.py +104 -0
- papers_app-0.2.0/tests/test_ai.py +75 -0
- papers_app-0.2.0/tests/test_capture.py +50 -0
- papers_app-0.2.0/tests/test_claude_code.py +119 -0
- papers_app-0.2.0/tests/test_conversations.py +178 -0
- papers_app-0.2.0/tests/test_folders.py +44 -0
- papers_app-0.2.0/tests/test_frontend.py +14 -0
- papers_app-0.2.0/tests/test_highlights_notes.py +99 -0
- papers_app-0.2.0/tests/test_keys.py +72 -0
- papers_app-0.2.0/tests/test_learning.py +47 -0
- papers_app-0.2.0/tests/test_library_covers.py +18 -0
- papers_app-0.2.0/tests/test_library_folder.py +107 -0
- papers_app-0.2.0/tests/test_metadata.py +74 -0
- papers_app-0.2.0/tests/test_never_stuck.py +113 -0
- papers_app-0.2.0/tests/test_notes_ask.py +38 -0
- papers_app-0.2.0/tests/test_papers.py +166 -0
- papers_app-0.2.0/tests/test_prepare.py +80 -0
- papers_app-0.2.0/tests/test_progress.py +35 -0
- papers_app-0.2.0/tests/test_prompts.py +61 -0
- papers_app-0.2.0/tests/test_provider_list.py +102 -0
- papers_app-0.2.0/tests/test_providers.py +104 -0
- papers_app-0.2.0/tests/test_recall_refs.py +56 -0
- papers_app-0.2.0/tests/test_review.py +50 -0
- papers_app-0.2.0/tests/test_scaffold.py +11 -0
- papers_app-0.2.0/tests/test_search.py +49 -0
- papers_app-0.2.0/tests/test_streaming.py +90 -0
- papers_app-0.2.0/tests/test_tracker.py +66 -0
- papers_app-0.2.0/tests/test_triage.py +59 -0
- papers_app-0.2.0/tests/test_upload.py +64 -0
- papers_app-0.2.0/tests/test_vocabulary.py +80 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Contributing to Papers
|
|
2
|
+
|
|
3
|
+
Thanks for helping. Papers is a small app on purpose: a Python server (FastAPI) and a web page made of plain
|
|
4
|
+
JavaScript modules, with no build step. If you can read Python and JavaScript, you can change any part of it.
|
|
5
|
+
|
|
6
|
+
## Set up
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/hBouanane/papers && cd papers
|
|
10
|
+
python -m venv .venv
|
|
11
|
+
.venv/Scripts/pip install -e ".[dev]" # macOS/Linux: .venv/bin/pip
|
|
12
|
+
.venv/Scripts/uvicorn papers.main:app --reload # http://localhost:8000; restarts when Python changes
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The web files are served as they are: edit them and reload the page. To try things without touching your own
|
|
16
|
+
library, point the app at another folder: `PAPERS_DATA=./scratch` (or `papers --data ./scratch`).
|
|
17
|
+
|
|
18
|
+
Before sending a pull request:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
.venv/Scripts/ruff check papers tests # style and common mistakes (`--fix` repairs most)
|
|
22
|
+
.venv/Scripts/pytest -q # all AI and network calls are faked; no keys needed
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
CI runs both on Python 3.11 to 3.13 and checks that the Docker image starts.
|
|
26
|
+
|
|
27
|
+
## How the code is laid out
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
papers/
|
|
31
|
+
cli.py the `papers` command: options, then starts the server and opens the browser
|
|
32
|
+
config.py where data lives and every environment variable
|
|
33
|
+
main.py builds the app: the routers below, error handling, the web files, the Inbox watcher
|
|
34
|
+
|
|
35
|
+
routes/ the HTTP API, one file per part of the app
|
|
36
|
+
papers.py add (search result, link, PDF), list, edit, delete, the PDF file, prepare
|
|
37
|
+
goals.py goals (stored as "topics"), finding papers for them, BibTeX export
|
|
38
|
+
reading.py progress, finishing, figures and tables, references, the chain a paper is in
|
|
39
|
+
learning.py key points, vocabulary, explain/translate/ask (streamed), quiz and spaced review
|
|
40
|
+
notes.py notes and highlights
|
|
41
|
+
recall.py full-text search and "which paper had this idea?"
|
|
42
|
+
settings.py name, language, AI provider, library folder and the folder picker
|
|
43
|
+
|
|
44
|
+
store.py reading and writing papers; every change also updates the search index and the folder
|
|
45
|
+
ingest.py turning a PDF into a paper, the Inbox, and preparing papers ahead of time with the AI
|
|
46
|
+
llm.py every prompt: one function per task (skim, explain, glossary, quiz, grade, recall, ...), and the
|
|
47
|
+
tutor's rules for conversations (TUTOR, TASKS: how Explain, Simplify, Translate and questions answer)
|
|
48
|
+
ai/ getting a prompt to the chosen model and its answer back; streaming.py: thinking vs answer, Stop,
|
|
49
|
+
and giving up on a silent model
|
|
50
|
+
chat/ conversations: store.py (conversations and messages), answer.py (streams an answer and saves it)
|
|
51
|
+
agent/ Deep mode: tools.py (what the AI can look up and do), loop.py (the tool loop for each provider),
|
|
52
|
+
mcp_server.py (the same tools for Claude Code)
|
|
53
|
+
providers.py the provider list and which one is chosen, with its key, model and address
|
|
54
|
+
anthropic_api.py claude_code.py codex.py openai_compat.py one file per way of reaching a model
|
|
55
|
+
|
|
56
|
+
db.py SQLite schema, migrations and settings index.py full-text search (SQLite FTS5)
|
|
57
|
+
pdf.py text, titles and abstracts out of PDFs figures.py figures and tables cut out of PDFs
|
|
58
|
+
scholar.py Semantic Scholar and arXiv library.py the library folder (PDFs + Markdown notes)
|
|
59
|
+
notes.py notes and highlights storage folders.py the folder picker
|
|
60
|
+
bibtex.py BibTeX entries
|
|
61
|
+
|
|
62
|
+
static/ the web app (no build step; ES modules loaded by the browser)
|
|
63
|
+
index.html the page shell; links the stylesheets below in order
|
|
64
|
+
css/ styles by area, each file building on the ones before it:
|
|
65
|
+
tokens (colours, shadows, fonts for light, dim and dark), base (type, page, top bar,
|
|
66
|
+
theme switch, toast), components (buttons, cards, menus, covers, notes, vocabulary,
|
|
67
|
+
combobox, folder picker), then one per screen: library, goals, recall, map, paper
|
|
68
|
+
(overview, figures, review), reader, settings
|
|
69
|
+
js/main.js routes each #/address to a page; paste and drop anywhere to add papers
|
|
70
|
+
js/core.js shared helpers: api(), toast(), paper rows, markdown, the top bar
|
|
71
|
+
js/pages/ one file per screen: library, goals, recall, map, settings (+ shared.js)
|
|
72
|
+
js/paper/ a paper's screens: overview, reader, review, figures (+ shared.js)
|
|
73
|
+
js/paper/reader/ the reader's parts, wired together by readerPage() in reader.js; they share one
|
|
74
|
+
state object (state.js: the paper, the page's elements, the open view):
|
|
75
|
+
layout (markup), bar (one-row bar and its ⋯ menu), route (the pill at the bottom),
|
|
76
|
+
views (PDF or Text, Go to…, back to where you stopped), progress (what you've read,
|
|
77
|
+
skimming), selection (the bar on selected text), highlighter, panel (Ask, Words,
|
|
78
|
+
Notes; streamed answers), finish, zoom, keys (shortcuts), terms + vocab (the Words switch:
|
|
79
|
+
hard words marked in the page, with a card for each)
|
|
80
|
+
js/components/ reusable widgets: combobox (searchable dropdown), folderpicker
|
|
81
|
+
js/chat/ the conversation panel: conversation.js (History, composer, Quick/Deep), answer.js (an answer
|
|
82
|
+
being written), stream.js, render.js (Markdown, math, citations, visuals), widgets.js,
|
|
83
|
+
canvas.js (a visual opened large)
|
|
84
|
+
js/*.js shared by the paper screens: pdfview (PDF.js), textview, highlights, notes, tracker,
|
|
85
|
+
speech, readprefs (font, size, page tone), covers (first-page thumbnails), theme
|
|
86
|
+
|
|
87
|
+
tests/ one file per feature, using FastAPI's test client against a temporary database
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Two rules keep it easy to follow:
|
|
91
|
+
|
|
92
|
+
- **Routes stay thin.** A route checks its input (the pydantic `...In` classes), calls `store`, `ingest` or
|
|
93
|
+
`llm`, and returns JSON. Logic that isn't about HTTP goes in a module next to them.
|
|
94
|
+
- **The AI is only reached through `llm.py`.** Pages and routes never build prompts; tests replace the `llm`
|
|
95
|
+
functions with fakes (see `tests/conftest.py`, which also blocks any real AI call).
|
|
96
|
+
|
|
97
|
+
## Common changes
|
|
98
|
+
|
|
99
|
+
| You want to | Look at |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| Change what the AI writes (key points, quiz, ...) | the prompt in `papers/llm.py` |
|
|
102
|
+
| Change how Explain or Simplify answer | `TASKS` in `papers/llm.py` (the rules all answers follow are `TUTOR`) |
|
|
103
|
+
| Give the AI a new tool in Deep mode | a function and an entry in `TOOLS`, `papers/agent/tools.py` (`"act": True` if it changes the library, with `data` for Undo) |
|
|
104
|
+
| Add a kind of visual | a fenced block in `papers/static/js/chat/render.js` (or a widget in `widgets.js`), and a line in `TUTOR` |
|
|
105
|
+
| Add a provider that speaks the OpenAI chat API | one line in `PROVIDERS`, `papers/ai/providers.py` |
|
|
106
|
+
| Add a provider with its own API | a module in `papers/ai/` with `parse()` and `stream()`, and a branch in `ai/__init__.py` |
|
|
107
|
+
| Add an API endpoint | the matching file in `papers/routes/` (a new area gets a new file, added to `routes/__init__.py`) |
|
|
108
|
+
| Add a column or table | `SCHEMA` and the migrations in `papers/db.py` |
|
|
109
|
+
| Add a screen | a file in `static/js/pages/` and a line in the `routes` list of `static/js/main.js` |
|
|
110
|
+
| Change colours or spacing | `static/css/tokens.css` (see [DESIGN.md](DESIGN.md)) |
|
|
111
|
+
| Change how a screen looks | its file in `static/css/`; shared pieces are in `components.css` |
|
|
112
|
+
| Change something in the reader | its part in `static/js/paper/reader/` (each file says what it does at the top) |
|
|
113
|
+
|
|
114
|
+
## Style
|
|
115
|
+
|
|
116
|
+
- Python: `ruff` settings in `pyproject.toml` (120 columns). Type hints on public functions; a docstring when
|
|
117
|
+
the name doesn't say it all.
|
|
118
|
+
- JavaScript: ES modules, no framework, no build. Keep markup in template strings next to the code that
|
|
119
|
+
wires it up, and escape anything from the server or the user with `esc()`.
|
|
120
|
+
- Text the user reads: short, plain sentences; say what to do, not what went wrong inside.
|
|
121
|
+
- Light, dim and dark themes all need to look right, and motion respects `prefers-reduced-motion`.
|
|
122
|
+
|
|
123
|
+
## Releasing
|
|
124
|
+
|
|
125
|
+
Bump `__version__` in `papers/__init__.py` and push a tag like `v0.2.0`. The release workflow publishes to PyPI
|
|
126
|
+
and pushes the Docker image to `ghcr.io`.
|
papers_app-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hBouanane
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: papers-app
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: An AI reading companion for research papers: skim, read, ask, recall. Runs on your computer.
|
|
5
|
+
Project-URL: Homepage, https://github.com/hBouanane/papers
|
|
6
|
+
Project-URL: Issues, https://github.com/hBouanane/papers/issues
|
|
7
|
+
Author: hBouanane
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: ai,llm,papers,pdf,reading,research
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Web Environment
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: anthropic>=0.40
|
|
18
|
+
Requires-Dist: fastapi>=0.115
|
|
19
|
+
Requires-Dist: httpx>=0.27
|
|
20
|
+
Requires-Dist: keyring>=24
|
|
21
|
+
Requires-Dist: pdfplumber>=0.11
|
|
22
|
+
Requires-Dist: pypdf>=5
|
|
23
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
24
|
+
Requires-Dist: uvicorn>=0.30
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# Papers
|
|
31
|
+
|
|
32
|
+
An AI reading companion for research papers. Define what you are working on, get relevant
|
|
33
|
+
papers, skim them Andrew Ng–style, read with an explainer that knows the whole paper, track
|
|
34
|
+
where you stopped, quiz yourself when you finish, ask "where did I read this idea?", and follow
|
|
35
|
+
reference chains. It runs on your computer; your papers and notes stay there.
|
|
36
|
+
See [SPEC.md](SPEC.md) for the design.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
With Python 3.11 or newer, one command (like `npx` for Node):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uvx papers-app
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
or install it to keep it around, then start it with `papers`:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pipx install papers-app
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`papers` opens http://localhost:8000 in your browser. Options: `--port 9000`, `--data D:\Papers` (where the
|
|
53
|
+
database and PDFs live), `--no-browser`, `--host 0.0.0.0` (reach it from other devices on your network; there
|
|
54
|
+
is no login, so only on networks you trust).
|
|
55
|
+
|
|
56
|
+
### With Docker
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
docker compose up -d
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Then open http://localhost:8000. Your library is kept in the `papers-data` volume. See
|
|
63
|
+
[docker-compose.yml](docker-compose.yml) to use a folder on your computer for the library folder, or a model
|
|
64
|
+
running on your computer (Ollama, LM Studio). Subscriptions (Claude, ChatGPT) need their app on the same
|
|
65
|
+
computer, so in Docker use an API key or a local model.
|
|
66
|
+
|
|
67
|
+
### From the source
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git clone https://github.com/hBouanane/papers && cd papers
|
|
71
|
+
python -m venv .venv
|
|
72
|
+
.venv/Scripts/pip install -e ".[dev]" # macOS/Linux: .venv/bin/pip
|
|
73
|
+
.venv/Scripts/papers
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Choosing an AI model
|
|
77
|
+
|
|
78
|
+
Settings > AI model has one list of providers; each is set up the same way (key if it needs one, then
|
|
79
|
+
**List models** and pick one). Each provider keeps its own key and model, so you can switch freely.
|
|
80
|
+
|
|
81
|
+
- **Use your subscription**: Claude (Pro, Max) through [Claude Code](https://claude.com/claude-code), or
|
|
82
|
+
ChatGPT (Plus, Pro) through OpenAI's [Codex CLI](https://developers.openai.com/codex/cli/reference)
|
|
83
|
+
(`npm install -g @openai/codex`, then `codex login`). Both run on your computer with your own account,
|
|
84
|
+
for your own use: don't host the app for others on your subscription.
|
|
85
|
+
- **Pay per use with an API key**: Anthropic, OpenAI, Google Gemini (has a free tier), Mistral, Groq, or
|
|
86
|
+
OpenRouter (hundreds of models).
|
|
87
|
+
- **On this computer**: [Ollama](https://ollama.com) or [LM Studio](https://lmstudio.ai). Free, and nothing
|
|
88
|
+
leaves your machine.
|
|
89
|
+
- **Other**: any OpenAI-compatible server (vLLM, llama.cpp, a company gateway), by its address.
|
|
90
|
+
|
|
91
|
+
Small local models can't read a whole paper; *More options* can send just its beginning.
|
|
92
|
+
Keys are kept in your system's keychain (Windows Credential Manager, macOS Keychain, or the Secret Service on Linux),
|
|
93
|
+
so you paste each one once; Settings shows which provider has a key saved (its last four characters) and can forget
|
|
94
|
+
it. Where there's no keychain (Docker, servers) they stay in the app's database. Keys are never sent back to the page.
|
|
95
|
+
|
|
96
|
+
With a subscription the app runs the official CLI on your computer (`claude -p` or `codex exec`, with no
|
|
97
|
+
tools), which signs in with your own account; usage counts toward your plan. The app never reads or stores
|
|
98
|
+
those credentials. `PAPERS_CLAUDE_BIN` and `PAPERS_CODEX_BIN` point at a specific binary if needed.
|
|
99
|
+
|
|
100
|
+
## Asking the AI
|
|
101
|
+
|
|
102
|
+
Select text in a paper and press **Explain** (a short lesson: the problem, the idea, the formula read slowly, a worked
|
|
103
|
+
example, why it works, where it connects in the paper), **Simplify** (the same passage in plain English) or
|
|
104
|
+
**Translate**. Each starts a conversation you can keep going; **History** keeps them per paper, and **Add to chat**
|
|
105
|
+
attaches more passages.
|
|
106
|
+
|
|
107
|
+
Answers can contain formulas, clickable citations ([§3.4], [Fig. 1]), charts, diagrams, the paper's own figures with
|
|
108
|
+
"look here" boxes, and interactive widgets. Switch the chat to **Deep** and the AI first reads the sections, looks at
|
|
109
|
+
the figures and checks your notes and library before it answers; ask it to and it saves notes, words and
|
|
110
|
+
highlights, or adds a paper from the references (each with Undo). Deep mode works with Claude (subscription or API
|
|
111
|
+
key) and with models that support tool calling; in **More options**, tick *This model can see images* if yours does,
|
|
112
|
+
and *Interactive pages* to let the AI write small demos that run in a sealed frame.
|
|
113
|
+
|
|
114
|
+
## Library folder
|
|
115
|
+
|
|
116
|
+
In Settings, choose a folder (**Choose…** opens a folder browser with your usual folders and drives) and the app keeps a copy of your
|
|
117
|
+
library there: one folder per goal (`Unsorted` for the rest), each paper as `Author et al. Year - Title.pdf`
|
|
118
|
+
with a `.md` notes file next to it (key points, explanations, quiz, `[[links]]` to related papers, so
|
|
119
|
+
Obsidian shows them as a graph). PDFs dropped into its `Inbox` folder are imported within about 10 seconds.
|
|
120
|
+
|
|
121
|
+
## Settings from the environment
|
|
122
|
+
|
|
123
|
+
| Variable | What it does |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| `PAPERS_DATA` | Folder for the database, PDFs and figures (same as `--data`). Default: `%APPDATA%\Papers`, `~/Library/Application Support/Papers` or `~/.local/share/papers` |
|
|
126
|
+
| `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` | API keys, if you'd rather not type them in Settings |
|
|
127
|
+
| `S2_API_KEY` | A Semantic Scholar key; without one, search often falls back to arXiv because of rate limits |
|
|
128
|
+
| `PAPERS_MODEL` | The Claude model used by default (`claude-opus-5-5`) |
|
|
129
|
+
| `PAPERS_INBOX_POLL` | Seconds between Inbox checks (`0` turns it off) |
|
|
130
|
+
|
|
131
|
+
## Contributing
|
|
132
|
+
|
|
133
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md): how the code is laid out, how to run it and the tests, and where to
|
|
134
|
+
start for common changes.
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Papers
|
|
2
|
+
|
|
3
|
+
An AI reading companion for research papers. Define what you are working on, get relevant
|
|
4
|
+
papers, skim them Andrew Ng–style, read with an explainer that knows the whole paper, track
|
|
5
|
+
where you stopped, quiz yourself when you finish, ask "where did I read this idea?", and follow
|
|
6
|
+
reference chains. It runs on your computer; your papers and notes stay there.
|
|
7
|
+
See [SPEC.md](SPEC.md) for the design.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
With Python 3.11 or newer, one command (like `npx` for Node):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uvx papers-app
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
or install it to keep it around, then start it with `papers`:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pipx install papers-app
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`papers` opens http://localhost:8000 in your browser. Options: `--port 9000`, `--data D:\Papers` (where the
|
|
24
|
+
database and PDFs live), `--no-browser`, `--host 0.0.0.0` (reach it from other devices on your network; there
|
|
25
|
+
is no login, so only on networks you trust).
|
|
26
|
+
|
|
27
|
+
### With Docker
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
docker compose up -d
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Then open http://localhost:8000. Your library is kept in the `papers-data` volume. See
|
|
34
|
+
[docker-compose.yml](docker-compose.yml) to use a folder on your computer for the library folder, or a model
|
|
35
|
+
running on your computer (Ollama, LM Studio). Subscriptions (Claude, ChatGPT) need their app on the same
|
|
36
|
+
computer, so in Docker use an API key or a local model.
|
|
37
|
+
|
|
38
|
+
### From the source
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
git clone https://github.com/hBouanane/papers && cd papers
|
|
42
|
+
python -m venv .venv
|
|
43
|
+
.venv/Scripts/pip install -e ".[dev]" # macOS/Linux: .venv/bin/pip
|
|
44
|
+
.venv/Scripts/papers
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Choosing an AI model
|
|
48
|
+
|
|
49
|
+
Settings > AI model has one list of providers; each is set up the same way (key if it needs one, then
|
|
50
|
+
**List models** and pick one). Each provider keeps its own key and model, so you can switch freely.
|
|
51
|
+
|
|
52
|
+
- **Use your subscription**: Claude (Pro, Max) through [Claude Code](https://claude.com/claude-code), or
|
|
53
|
+
ChatGPT (Plus, Pro) through OpenAI's [Codex CLI](https://developers.openai.com/codex/cli/reference)
|
|
54
|
+
(`npm install -g @openai/codex`, then `codex login`). Both run on your computer with your own account,
|
|
55
|
+
for your own use: don't host the app for others on your subscription.
|
|
56
|
+
- **Pay per use with an API key**: Anthropic, OpenAI, Google Gemini (has a free tier), Mistral, Groq, or
|
|
57
|
+
OpenRouter (hundreds of models).
|
|
58
|
+
- **On this computer**: [Ollama](https://ollama.com) or [LM Studio](https://lmstudio.ai). Free, and nothing
|
|
59
|
+
leaves your machine.
|
|
60
|
+
- **Other**: any OpenAI-compatible server (vLLM, llama.cpp, a company gateway), by its address.
|
|
61
|
+
|
|
62
|
+
Small local models can't read a whole paper; *More options* can send just its beginning.
|
|
63
|
+
Keys are kept in your system's keychain (Windows Credential Manager, macOS Keychain, or the Secret Service on Linux),
|
|
64
|
+
so you paste each one once; Settings shows which provider has a key saved (its last four characters) and can forget
|
|
65
|
+
it. Where there's no keychain (Docker, servers) they stay in the app's database. Keys are never sent back to the page.
|
|
66
|
+
|
|
67
|
+
With a subscription the app runs the official CLI on your computer (`claude -p` or `codex exec`, with no
|
|
68
|
+
tools), which signs in with your own account; usage counts toward your plan. The app never reads or stores
|
|
69
|
+
those credentials. `PAPERS_CLAUDE_BIN` and `PAPERS_CODEX_BIN` point at a specific binary if needed.
|
|
70
|
+
|
|
71
|
+
## Asking the AI
|
|
72
|
+
|
|
73
|
+
Select text in a paper and press **Explain** (a short lesson: the problem, the idea, the formula read slowly, a worked
|
|
74
|
+
example, why it works, where it connects in the paper), **Simplify** (the same passage in plain English) or
|
|
75
|
+
**Translate**. Each starts a conversation you can keep going; **History** keeps them per paper, and **Add to chat**
|
|
76
|
+
attaches more passages.
|
|
77
|
+
|
|
78
|
+
Answers can contain formulas, clickable citations ([§3.4], [Fig. 1]), charts, diagrams, the paper's own figures with
|
|
79
|
+
"look here" boxes, and interactive widgets. Switch the chat to **Deep** and the AI first reads the sections, looks at
|
|
80
|
+
the figures and checks your notes and library before it answers; ask it to and it saves notes, words and
|
|
81
|
+
highlights, or adds a paper from the references (each with Undo). Deep mode works with Claude (subscription or API
|
|
82
|
+
key) and with models that support tool calling; in **More options**, tick *This model can see images* if yours does,
|
|
83
|
+
and *Interactive pages* to let the AI write small demos that run in a sealed frame.
|
|
84
|
+
|
|
85
|
+
## Library folder
|
|
86
|
+
|
|
87
|
+
In Settings, choose a folder (**Choose…** opens a folder browser with your usual folders and drives) and the app keeps a copy of your
|
|
88
|
+
library there: one folder per goal (`Unsorted` for the rest), each paper as `Author et al. Year - Title.pdf`
|
|
89
|
+
with a `.md` notes file next to it (key points, explanations, quiz, `[[links]]` to related papers, so
|
|
90
|
+
Obsidian shows them as a graph). PDFs dropped into its `Inbox` folder are imported within about 10 seconds.
|
|
91
|
+
|
|
92
|
+
## Settings from the environment
|
|
93
|
+
|
|
94
|
+
| Variable | What it does |
|
|
95
|
+
| --- | --- |
|
|
96
|
+
| `PAPERS_DATA` | Folder for the database, PDFs and figures (same as `--data`). Default: `%APPDATA%\Papers`, `~/Library/Application Support/Papers` or `~/.local/share/papers` |
|
|
97
|
+
| `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` | API keys, if you'd rather not type them in Settings |
|
|
98
|
+
| `S2_API_KEY` | A Semantic Scholar key; without one, search often falls back to arXiv because of rate limits |
|
|
99
|
+
| `PAPERS_MODEL` | The Claude model used by default (`claude-opus-5-5`) |
|
|
100
|
+
| `PAPERS_INBOX_POLL` | Seconds between Inbox checks (`0` turns it off) |
|
|
101
|
+
|
|
102
|
+
## Contributing
|
|
103
|
+
|
|
104
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md): how the code is laid out, how to run it and the tests, and where to
|
|
105
|
+
start for common changes.
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
[MIT](LICENSE)
|