Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Noesis

noesis — the act of understanding; the exercise of the intellect.

A local-first research desk for arXiv papers. It collects paper metadata, downloads the PDFs to your own disk, and gives you a browser-based reader with a table of contents, persistent highlights, sticky notes, and Markdown export — plus a LaTeX editor that compiles to PDF in the same window.

Everything lives on your machine: SQLite for structured data, plain files for the PDFs and exports. Nothing is sent anywhere except to arXiv itself.

HTML + CSS + vanilla JS   ─┐
PDF.js                     ├──  FastAPI (single process)  ──  SQLite + data/pdfs + data/exports
mermaid.js                ─┘

Setup

Requires Python 3.9 or newer.

Mermaid and KaTeX are bundled in static/vendor/, so diagrams and mathematics render with no network connection at all. Only pdf.js is still fetched from a CDN.

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python run.py

Open http://127.0.0.1:8000. That is the homepage, which explains what the project is for and links to the documentation; press Open the workspace for the desk itself at /app. Clicking Noesis anywhere returns to the homepage.

Route Page
/ Homepage and philosophy
/docs-guide Full documentation
/app The workspace

The database and folders are created on first run.

Interactive API docs are at /docs.

Projects: casual and committed

A project groups everything done for one piece of work — the papers read, the videos watched, the LaTeX written, the diagrams drawn.

The pill in the masthead switches between them:

  • All work — everything is visible, and anything new stays unfiled. This is casual mode: open the app, collect a paper, read it, no ceremony.
  • A project — the view filters to it, and anything you collect or create while it is selected is filed there automatically.

Nothing is lost by not choosing. Unfiled work can be assigned to a project later from a paper's menu, and deleting a project leaves its contents as unfiled work unless you explicitly ask to purge them.

The choice is stored on the server rather than the browser, so every tab and every mode agrees about what is being worked on.

Four modes

The masthead switches between them, and the switch beside it toggles the theme.

  • Read & explore — collect papers, download PDFs, read, highlight, annotate
  • Write — LaTeX projects, compiled to PDF beside the editor
  • Draw — a Mermaid workbench with a live canvas and AI diagram generation
  • Watch — lectures and talks, with transcripts that join the search index

The hamburger collapses the left rail and the pencil collapses the right panel, in whichever mode you are in.

A dark theme is available from the toggle. It is a brushed-metal grey rather than flat black: panels carry a shallow gradient and a lit top edge. PDF pages stay white, because a document is white and inverting it would misrepresent the source. Your choice is remembered, and a first visit follows the system setting.

Collecting papers

Open the Collect tab in the left rail. There are two modes, and both end in the same normalised record, so everything downstream behaves identically.

Keyword search goes through the official arXiv API. You can search everything, titles or abstracts, narrow by author, category and submission date, choose a sort order, and set a result cap. Paging happens automatically via start / max_results, and requests are paced to one every three seconds to stay inside arXiv's guidance.

Listing URL takes any arXiv listing page and parses every visible entry:

https://arxiv.org/list/math.AP/recent
https://arxiv.org/list/cs.LG/recent
https://arxiv.org/list/stat.ML/recent

From each entry it pulls the arXiv ID, title, author names, abstract page URL and PDF URL. Titles containing inline TeX come back as readable LaTeX rather than MathJax debris. Leave Fill in abstracts from the arXiv API checked and each entry is then enriched by an id_list call, so listing-mode papers end up with abstracts, dates and affiliations too.

Tick Download PDFs after collecting to fetch everything in one pass, or download papers individually from the library card.

Reading

Click any downloaded paper to open it.

  • Contents in the left rail shows the PDF's embedded bookmarks; click one to jump to that section. Files with no bookmarks fall back to page shortcuts.
  • Pages render lazily as you approach them, so a 90-page paper opens immediately.
  • Navigate by page field, arrow keys, or the previous/next buttons. Zoom with the + / controls, or use Fit width / Fit page.

Highlighting

Select any text in a page and pick one of five colours. The highlight appears immediately and is saved to SQLite straight away.

Geometry is stored as fractions of the page box rather than pixels, so a highlight lands in exactly the same place after a zoom change, a window resize, a page refresh, a backend restart, or a move to a different screen.

From the Highlights tab you can add or edit a comment, recolour, attach a sticky note, delete, or click through to jump back to the passage in the page.

Sticky notes

Notes are written in Markdown and can be attached to three things:

  • the whole paperNew sticky note in the Notes tab
  • a pageNote on current page in the Paper tab
  • a highlightAdd note on any row in the Highlights tab

Notes support a title, a Markdown body and comma-separated tags, and they are editable at any time. They are laid out on a masonry board so long and short notes sit together without gaps.

Markdown export

Export Markdown in the reader bar builds a research note for the open paper. You get a preview, a clipboard copy, and a file download; a copy is also written to data/exports/, alongside a JSON bundle of the same content.

# Paper Title

- arXiv ID: 1234.5678
- Authors: A, B, C
- arXiv: https://arxiv.org/abs/1234.5678
- Local PDF: data/pdfs/1234.5678.pdf

## Summary Notes
Overall interpretation here.

## Highlights

### Page 2
> highlighted passage

Comment: important observation

## Sticky Notes

### Numerical idea
This may connect to operator-learning formulations.

The research assistant

A chat panel that answers questions about the papers you have collected, using models running on your own machine. Nothing is sent anywhere: retrieval, image description and generation all happen over localhost.

Open it from the Chat tab on the right, beside Notes and Highlights.

Setting up Ollama

Install the server:

# macOS
brew install ollama
# Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows: installer at https://ollama.com/download/windows

Start it and leave it running:

ollama serve

Pull the four models. Together they are about 11 GB:

ollama pull exaone-deep          # 4.8 GB  reasoning and answering
ollama pull llava                # 4.7 GB  reads figures out of PDFs
ollama pull nomic-embed-text     # 274 MB  builds the search index
ollama pull qwen2.5-coder:1.5b   # 986 MB  inline LaTeX edits

Each has a distinct job, and any of them can be swapped for something else in Chat → ⚙ settings:

Role Default What it does
Chat exaone-deep Answers questions, compares papers, explains passages
Vision llava Describes figures found in PDFs, and images you attach
Embedding nomic-embed-text Turns text into vectors so passages can be searched
LaTeX qwen2.5-coder:1.5b Small and fast; rewrites selected LaTeX in the editor

If a model is missing, the panel says which one and gives you the exact ollama pull command rather than failing quietly.

Memory. The chat and vision models are roughly 5 GB each. On 8 GB of RAM, run one at a time, or substitute smaller models (phi3, qwen2.5:3b). Ollama loads a model on first use and unloads it after a few idle minutes, so having four installed does not mean four in memory.

Indexing your papers

Retrieval only sees papers that have been indexed. Download some PDFs, then press Index papers in the chat panel.

For each paper: text is extracted per page, split into overlapping chunks on paragraph boundaries, and embedded. Figures are lifted out, described by the vision model, and those descriptions are embedded too — so asking about a plot finds the plot. The abstract gets its own chunk, because it is often the best match for a broad question.

Indexing a paper takes a few seconds for text, longer with figures, since each image is a separate vision-model call. Everything is stored in the same SQLite file as your notes and highlights.

Asking

Type in the box and press Enter (Shift+Enter for a newline). Two toggles control scope:

  • Use my library — retrieve passages before answering. Off makes it an ordinary chat with no document grounding.
  • This paper only — restrict retrieval to the paper open in the reader.

Every answer carries the passages it used, collapsed under the reply. Click one to open that paper at that page. The assistant is instructed to say when the passages do not contain an answer rather than filling the gap from training data — in research, an admission of not knowing beats a plausible invention.

You can attach images (click the clip, or paste straight into the box) and text files. Attaching an image routes the question to the vision model automatically.

Attaching files, and adding papers

Two different buttons in the compose row, because these are different intentions:

  • 📎 Attach — an image, PDF or text file used for this question only. A PDF is parsed server-side, its text handed to the model, and nothing is stored. Use it for a paper someone just sent you, a referee report, a page of notes.
  • 📥 Import — adds a PDF to your library permanently. Title, authors and abstract are read from the file's metadata and first page; it then behaves like any arXiv paper — readable, highlightable, indexable. Local imports get an ID beginning local/ so they never collide with real arXiv identifiers.

Images can also be pasted straight into the box.

Reading the replies

Reasoning models (exaone-deep, deepseek-r1, qwen3) emit their working in <thought> tags. Noesis folds that into a collapsible block above the answer — open it when you want to see the model's process, ignore it otherwise.

Mathematics is typeset with KaTeX, so $\sigma^2$ renders properly instead of appearing as source. If KaTeX cannot load, the LaTeX source is shown verbatim rather than mangled. Markdown headings, lists, tables, quotes and code blocks all render.

Maths is deliberately protected from the markdown pass: underscores and asterisks are subscripts and multiplication inside $…$, and italicising them would silently corrupt the formula.

Keeping part of an answer

Select any text in a reply and a small bar offers Save as note or Copy. Saving attaches it to the paper open in the reader, so it lands beside your highlights rather than in a separate pile.

Resizing

Drag the divider between the reading area and the right column. Double-click it to restore the default width. The width is remembered across restarts.

Managing models

Chat → ⚙ lists everything installed with its size, lets you remove any of them, and pulls new ones by name with live progress — llama3.2, qwen2.5:7b, mistral, whatever you want to try. Any model can be assigned to any of the four roles.

Answering as somebody

The dropdown beside the scope toggles chooses how the assistant approaches your question. The same passages read very differently depending on what you want from them, and one neutral prompt serves none of these well:

Role For
Researcher Synthesis across several papers — agreements, contradictions, gaps
Peer reviewer Adversarial reading: assumptions, evidence, threats to validity
Author Sharpening your own prose, framing and structure
Explainer Careful technical teaching for someone new to the subfield
Plain language No jargon, no equations — for talks, abstracts, explaining to family

The role layers on top of the grounding rules rather than replacing them, so a peer reviewer still cites real passages and still refuses to invent them. Your choice is remembered.

The cat

A small chibi cat shows what the assistant is doing:

Pose Meaning
Nose in a book, pages turning reading — retrieving passages, or taking in an attachment
Looking up, thought bubbles rising thinking — the model has the prompt and is working
Pen moving, ink appearing writing — tokens are arriving

These track the real pipeline rather than a timer. Ollama reports prompt evaluation separately from generation, so the change from thinking to writing is the actual moment the first token appears.

The cat is inline SVG with CSS animation, not a GIF. That keeps the app properly offline, lets it take the theme's colours, and keeps it sharp at any size. Animation is suppressed under prefers-reduced-motion; the pose still changes, so the stage stays readable without movement.

Rewriting LaTeX while you write

In the writing view, select a fragment and press AI edit (or Ctrl+K). Describe the change — "add a label", "convert this to an align environment", "tighten this sentence" — and the small coder model returns a rewrite.

The suggestion is shown for approval and only replaces your selection when you press the button. A model that silently rewrites your equations is not something to trust blindly.

Where the assistant is weak

Worth knowing before you rely on it:

  • A 5 GB model is not a frontier model. It will summarise and locate things reliably; it will be less dependable on subtle technical judgement. Check anything that matters against the cited passage — which is why every answer ships with its sources.
  • Retrieval is only as good as the chunk. If an argument spans several pages, the retrieved passage may hold only part of it.
  • Scanned PDFs yield nothing. Text extraction needs a text layer; image-only scans need OCR first, which is not included.
  • Uncensored models. The settings catalogue includes a group of models with their refusal training removed. They are not more accurate for it — an uncensored model invents citations as readily as any other — and everything you generate with one remains your responsibility.
  • Small talk. Greetings and acknowledgements skip retrieval entirely. Told to cite passages, a model answering "hello" will otherwise complain that the passages contain no greeting — which is what the first version did.
  • Changing the embedding model invalidates the index. Vectors from different models are not comparable, so re-index after switching. Mismatched vectors are skipped rather than silently compared against nonsense.

Writing LaTeX

Switch to Write in the masthead. The layout is editor on the left, typeset PDF on the right, problems behind a tab.

You need a TeX engine

Compilation is real: an actual TeX engine runs on your machine. The app detects what you have and says so in the Projects pane.

Engine Install Packages
Tectonic (recommended) cargo install tectonic, or a release binary Downloads whatever a document needs, on demand, then caches it
TeX Live apt install texlive-latex-extra latexmk (Debian/Ubuntu), MacTeX, or MiKTeX Installed on request via tlmgr from the Problems panel

Tectonic is the closest thing to Overleaf's behaviour: you never think about packages. It is one binary with no system dependencies. TeX Live works equally well for compiling and is what most people already have.

Without either, projects and files still work — nothing can be typeset.

Tectonic — the closest thing to Overleaf

Overleaf's defining convenience is that you never think about packages: you use \usepackage{whatever} and it works. Tectonic reproduces that. It ships as one binary, carries no TeX tree, and downloads exactly the files a document needs from a curated bundle the first time it needs them, caching them afterwards.

A full TeX Live install is about 7 GB and needs tlmgr babysitting. Tectonic is roughly 30 MB and needs nothing.

macOS

brew install tectonic

Linux (Debian / Ubuntu)

# runtime libraries Tectonic links against
sudo apt install -y libfontconfig1 libgraphite2-3 libharfbuzz0b libicu-dev libssl3

curl --proto '=https' --tlsv1.2 -fsSL https://drop-sh.fullyjustified.net | sh
sudo mv tectonic /usr/local/bin/

Linux (Fedora / RHEL)

sudo dnf install -y fontconfig graphite2 harfbuzz libicu openssl
curl --proto '=https' --tlsv1.2 -fsSL https://drop-sh.fullyjustified.net | sh
sudo mv tectonic /usr/local/bin/

Windows

winget install TectonicProject.Tectonic
# or: scoop install tectonic

From source, any platform (needs Rust):

cargo install tectonic

Where the cache lives. Noesis points Tectonic at data/texcache/tectonic and keeps it there permanently, shared by every project. An earlier version put this inside each project's build directory, which meant every compile in a new project re-fetched bundle files it had already downloaded — that is what made Tectonic seem to hang while latexmk stayed fast. If you have hit that, delete data/texcache once and let it rebuild cleanly.

Confirm it works. The first run downloads the parts of the bundle your document needs, so it is slower than the ones that follow:

tectonic --version
echo '\documentclass{article}\usepackage{amsmath}\begin{document}$e^{i\pi}+1=0$\end{document}' > t.tex
tectonic t.tex        # first run fetches; later runs are fast and offline

Restart Noesis afterwards. The Projects pane will report Tectonic as the engine, and the Problems panel will stop offering to install packages, because nothing will be missing.

One caveat. The initial bundle fetch needs an internet connection, and each new package a document introduces triggers a small download. After a few documents the cache (~/.cache/Tectonic) covers most of what you write, and compilation is fully offline. If you need guaranteed offline from the start, install TeX Live instead and accept the 7 GB.

Projects

New project offers five starting points:

  • Article — amsmath, natbib, a working bibliography, theorem environments
  • Preprint — title block with affiliations, keywords, reproducibility section
  • Slides — Beamer, 16:9
  • Reading notes from a paper — seeded with a paper's highlights and notes
  • Empty — bare document

The reading-notes template is the reason this lives in the same app: pick a paper you have already highlighted and you get a document containing its title, authors, abstract, every highlighted passage as a displayquote grouped by page, your comments as italics, and your sticky notes as paragraphs. A literature review that starts from what you actually marked while reading.

Editing

Files are listed in the Files tab; the compiled one is marked · main. Add more with New file — subfolders work, so sections/method.tex pulled in with \input{sections/method} is fine. Upload adds figures and other binary assets.

The editor gives you line numbers, LaTeX syntax colouring, two-space indent on Tab, indent-preserving newlines, and \begin{...} completing its own \end{...} when you press Enter. Text autosaves about a second after you stop typing; the state indicator next to the project name tells you where things stand.

Ctrl+S or Ctrl+Enter compiles. So does the Compile button.

Folders and assets

New folder creates one (nested paths like figures/experiments work). The + beside a folder uploads straight into it; the plain Upload button targets the project root. Multiple files at once are fine. After an upload you are told the exact \includegraphics{...} path to use.

Compiling before the figures exist

Three options sit under the file list:

  • Compile without missing figures (on by default) — any \includegraphics, \input or \bibliography pointing at a file that is not there yet draws a labelled grey box instead of stopping the build. Float numbering, captions and cross-references are unaffected, because the figure environment still runs; only its contents are substituted. The Problems panel lists exactly what was stood in for, and entries disappear as you supply the real files. Turn it off for a final build, when a missing figure should be an error.
  • Download the PDF after each build — saves the compiled PDF automatically on every successful compile.
  • Heavy document — forces extra passes. The driver normally works out how many runs a document needs, but deeply cross-referenced documents whose floats shift between passes occasionally settle one run late.

Compilation allows up to ten minutes, which is enough for book-length documents with TikZ and large bibliographies. A 25-page test with 40 floats, a table of contents, lists of figures and tables, 120 cross-references and a 40-entry bibliography builds in about three seconds with every reference resolved.

Finding the command you want

Commands in the toolbar (or Ctrl+/) searches a catalogue of about thirty LaTeX constructions by intent rather than by name. Searching LaTeX by name only works when you already know the name — someone who wants "a matrix with square brackets" does not know to look for bmatrix. Each entry carries the words a person would actually use, so that search finds it.

Click a result and the snippet is inserted at your caret, with the cursor placed in the first slot. If it needs a package, you are told which.

Problems

Errors and warnings are parsed out of the TeX log into a list, each with its file and line. Click one and the editor jumps there with the line selected. The raw engine log is underneath, collapsed.

When a document asks for a package you do not have, the missing files are collected into their own box with an Install these button. On TeX Live that resolves each file to its package with tlmgr search and installs it, preferring a user tree so it does not need root; if that is not possible it shows you the exact sudo tlmgr install command. Tectonic needs none of this.

Clicking between the PDF and the source

Compilation writes a SyncTeX position map recording, for every box TeX set, the source file and line it came from. Both directions are wired up:

  • Click anywhere in the compiled PDF and the editor opens that file, scrolls to the line, selects it, and marks it with a band that fades after a moment.
  • Move the caret in the editor and the matching region of the PDF is outlined. The preview only scrolls when the marker is off screen, so typing does not yank it around.

Resolution is the smallest box containing the click, which is the most specific attribution SyncTeX offers. On prose, headings and ordinary lines this lands exactly. Inside display-math environments it can be a line or two out — clicking an equation tends to give you \end{equation} rather than \begin{equation}, because that is where TeX attributes the assembled box. Established SyncTeX viewers behave the same way.

Clicking a region that came from a class or package file says so rather than failing silently, since those files are not part of your project.

Getting work out

PDF opens the compiled file. Zip downloads the whole project including sources, assets and the built PDF — ready to upload to a journal or to Overleaf.

A note on safety

Shell escape is disabled on every compilation path (-no-shell-escape, and --untrusted for Tectonic). A .tex file can otherwise execute arbitrary shell commands through \write18, which matters as soon as you paste in a template from somewhere else.

Draw

A Mermaid workbench. Source on the left, live render on the right.

The canvas behaves like a diagram tool. Drag to pan, wheel to zoom about the cursor, Fit to frame the whole diagram, Reset to return to 1:1. The graph paper background makes panning legible.

Mermaid is served from static/vendor/mermaid.min.js inside the project rather than a CDN. If a network filter or an offline machine blocks jsDelivr — which was the original cause of the canvas staying blank — nothing breaks now.

AI generation uses your configured chat model — exaone-deep by default. Reasoning models are handled properly: their deliberation is stripped, whether or not they remembered to close the <thought> tag, fences are removed, a lead-in like "Sure! flowchart TD" is trimmed, and trailing commentary after the diagram is dropped without mistaking a node label that ends in a full stop for prose. If the model reasons but never produces a diagram, you are told so and the editor is left untouched rather than wiped.

Describe what you want — "the pipeline from arXiv ingestion through indexing to a cited answer" — and the local chat model writes the Mermaid. It can also modify what is already there rather than starting over, so you can iterate by describing changes. The generated source lands in the editor, so nothing is a black box: correct it by hand whenever the model gets it wrong.

Seven diagram types come with working starters: flowchart, sequence, class, state, ER, mindmap and Gantt.

Export. Three buttons:

  • PNG — rasterised at 2× with the theme's paper colour behind it
  • PNG · clear — the same at 2×, transparent background, for dropping onto a slide or into a paper
  • SVG — vector, for editing elsewhere

Four details make export reliable, each fixing a real failure:

  • Mermaid runs with htmlLabels: false. With labels on, it wraps each one in a <foreignObject> containing HTML — and a canvas that has had a foreignObject drawn onto it is marked tainted, so toBlob throws "Tainted canvases may not be exported" and nothing is produced. Plain <text> labels export cleanly.
  • The SVG is passed to the rasteriser as a data URL, not a blob URL. Blob-backed SVG images are treated as cross-origin by some browsers and taint the canvas too.
  • The SVG is given explicit width and height, because some browsers refuse to rasterise one sized only by its viewBox and silently produce a blank image.
  • Every CSS custom property is resolved to a literal colour first — a serialised SVG has no access to the page's stylesheet, so a themed diagram would otherwise export as solid black.

If you had a diagram on screen from before this fix, re-render it once (edit a character, or press Fit) so it is redrawn without foreignObject.

Diagrams are saved automatically and kept in the same SQLite file as everything else. Changing the theme redraws them, because Mermaid bakes its palette into the rendered SVG rather than reading it from CSS.

Organising the library

Tags and reading status sit on every paper. The small ring beside each card cycles to-read → reading → read in place, because that changes often enough that a dropdown would be friction. Tags, citation and project assignment live behind the button.

The filter row narrows by status and tag; clicking a tag on a card filters to it.

Searching inside papers

The filter box matches titles. Full text searches the actual text of every indexed paper and transcript — and needs no model running, because the text is kept in a SQLite FTS5 index separate from the assistant's vector store.

Quoted phrases work ("nonlinear eigenvalue"), and hyphenated terms behave sensibly: sonic-point is split into two tokens rather than mashed into one, which is how the text was stored.

Papers are text-indexed when you index them for chat, or individually from the menu.

Citing what you have read

Every paper can produce a BibTeX entry, in the form arXiv itself recommends (@article with eprint and archivePrefix). Cite keys are built as surname-year-keyword, so bahja2026hybrid rather than something opaque.

From a paper's menu, choose a LaTeX project and press Add to bibliography: the entry is appended to references.bib, duplicates are skipped, and \cite{key} is copied to your clipboard ready to paste. This is the bridge between the two halves of the app — reading and writing were previously separate.

Watching lectures

Paste a YouTube link or a whole playlist. Nothing downloads until you ask.

Get transcript is the important one. Subtitles are a few tens of kilobytes against hundreds of megabytes of video, and they are the only part the assistant can read. A fetched transcript becomes keyword-searchable immediately, and Index for chat embeds it so the assistant can cite a talk alongside a paper.

Auto-generated captions repeat each line as the next scrolls in; those duplicates are stripped, or a transcript reads as a stutter at twice its true length.

Download video and Audio only fetch the media itself. Audio extraction needs ffmpeg; without it, video downloads still work but cap at 720p, because yt-dlp cannot merge YouTube's separate video and audio streams. The interface says so rather than failing obscurely.

Downloaded files play locally with no network access at all; until then, playback uses YouTube's privacy-preserving embed.

Exporting and backing up

Export in the library produces one Markdown document covering every paper in scope — optionally just a project, or just a tag. That is a literature review's first draft.

Chat → ⚙ → Your data downloads a zip of the whole desk: database, PDFs, documents, diagrams and transcripts. Restoring replaces the current data and keeps the old database alongside as library.db.replaced, so a restore from a damaged archive is recoverable.

Project layout

run.py                    start the server
requirements.txt
app/
  main.py                 FastAPI routes, static mount
  latex.py                engine detection, compilation, log parsing, tlmgr
  projects.py             LaTeX projects, files, templates, zip export
  synctex.py              position map parsing for two-way PDF/editor sync
  ollama_client.py        local model calls: chat, streaming, embeddings, vision
  rag.py                  PDF parsing, chunking, vector store, retrieval
  assistant.py            conversations, prompting, staged streaming
  draft_assets.py         placeholder package for missing figures
  roles.py                assistant roles and the LaTeX command catalogue
  library.py              projects, tags, full-text search, BibTeX, backup
  videos.py               yt-dlp ingestion, subtitles, transcripts
  migrations.py           additive schema upgrades for existing databases
  arxiv_client.py         Atom API: paging, retries, throttling, normalisation
  list_parser.py          listing-page parser (handles MathJax titles)
  models.py               request schemas
  database.py             SQLite schema and connection handling
  storage.py              paper upsert, queries, papers.json cache
  downloader.py           PDF fetch, skip-if-present, force refresh
  annotations.py          highlight persistence
  notes.py                sticky note persistence
  exporter.py             Markdown and JSON export
static/
  home.html               homepage and philosophy
  docs.html               documentation
  site.css · site.js      styles and theme toggle for both pages
  app.html                the workspace itself
  styles.css              warm-paper desk plus a dark metallic theme
  api.js                  backend client and shared helpers
  pdf-reader.js           PDF.js rendering, outline, highlight overlays
  notes.js                notes board, highlight list, modal
  latex.js                editor, compile, preview, problems panel
  chat.js                 assistant panel, streaming answers, attachments
  rich.js                 collapsible reasoning, markdown, KaTeX rendering
  draw.js                 Mermaid workbench: canvas, pan/zoom, PNG and SVG export
  cat.js                  the three-pose working indicator
  watch.js                the Watch view and the project selector
  app.js                  ingestion, library rail, export
data/
  library.db              SQLite: papers, authors, paper_authors, annotations,
                          notes, exports, ingestion_runs, latex_projects,
                          latex_files, latex_compiles, rag_chunks, rag_status,
                          chat_threads, chat_messages, settings
  papers.json             normalised metadata cache and export
  pdfs/                   downloaded PDFs, named {arxiv_id}.pdf
  exports/                generated Markdown and JSON
  latex/{id}/             one directory per LaTeX project; .build/ holds output
tests/
  fixture_listing.html    real arXiv listing markup used to check the parser

data/papers.json ships with three entries collected from a arxiv.org/list/math.AP/recent page, as a sample of the normalised schema.

API

Method Path Purpose
POST /api/search keyword/API ingestion
POST /api/ingest-url listing-URL ingestion
GET /api/papers library, with search and downloaded filters
GET /api/papers/{id} one paper
POST /api/papers/{id}/download fetch the PDF; {"force": true} to refetch
GET /api/papers/{id}/pdf serve the local PDF
DELETE /api/papers/{id} remove from the library
GET · POST /api/papers/{id}/annotations list · create highlights
PATCH · DELETE /api/annotations/{id} edit · delete a highlight
GET · POST /api/papers/{id}/notes list · create notes
PATCH · DELETE /api/notes/{id} edit · delete a note
POST /api/papers/{id}/export-markdown build the Markdown export
GET /api/stats library counters
GET /api/latex/environment detected engines and templates
GET · POST /api/latex/projects list · create projects
GET · PATCH · DELETE /api/latex/projects/{id} one project
GET · POST · DELETE /api/latex/projects/{id}/file read · write · delete a file
POST /api/latex/projects/{id}/upload add a binary asset
POST /api/latex/projects/{id}/compile build, with parsed diagnostics
GET /api/latex/projects/{id}/synctex position map, both directions
GET /api/assistant/environment Ollama status and model roles
POST /api/assistant/ask streamed answer with stages and sources
POST /api/assistant/index streamed indexing progress
POST /api/assistant/latex-edit rewrite a LaTeX fragment
POST /api/assistant/extract read an uploaded file without storing it
POST /api/papers/import add a local PDF to the library
POST /api/assistant/pull download an Ollama model, streamed
GET · POST /api/workspaces list · create projects
POST /api/workspaces/active switch the working project
GET /api/search full-text search, no model needed
GET /api/papers/{id}/bibtex BibTeX for a paper
POST /api/papers/{id}/cite/{project} add it to a project's bibliography
GET · POST /api/videos list · add videos or playlists
POST /api/videos/{id}/subtitles fetch and flatten the transcript
GET · POST /api/backup · /api/restore whole-desk archive
GET /api/assistant/roles available assistant roles
GET /api/latex/commands search the LaTeX catalogue
GET · POST /api/diagrams list · create diagrams
POST /api/diagrams/generate describe a diagram, get Mermaid back
GET /api/latex/projects/{id}/pdf the compiled PDF
GET /api/latex/projects/{id}/zip sources plus PDF
POST /api/latex/projects/{id}/install-packages resolve and install missing packages

Notes on behaviour

  • Duplicates. Papers are keyed on arXiv ID with the version suffix stripped, so re-running the same collection updates rather than duplicates.
  • Downloads. Existing files are skipped unless you force a refresh. Responses that are not actually PDFs are rejected rather than written to disk.
  • Rate limits. If arXiv starts refusing requests, wait a minute and retry; the client already backs off between attempts.
  • Reduced motion. All animation is disabled automatically when your system asks for reduced motion.
  • Bitmap fonts. Templates request T1 encoding only when lmodern is present. Asking for T1 without a scalable font makes TeX generate bitmap pk fonts, which look wrong in a PDF and can fail outright on minimal installs.
  • Build caching. latexmk's .fdb_latexmk database is cleared before each build. It otherwise refuses to retry after a failure, reporting that all targets are up to date.

What this is not

Overleaf's defining feature is several people editing one document at once. This has no collaboration, no accounts and no server: it is a single-user local workspace. Forward and reverse SyncTeX are implemented, but there is no continuous preview: you compile when you want to, with Ctrl+S.

About

Tired of Overleaf and regarding it's BS issues...A better integrated all in one version over past projects : tex4U, Kairos and noma

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages