lsyour
literature.

LabShelf is a local-first reference manager that lives where you write: VS Code, the terminal and the browser. It knows what you read, what you marked, and what your thesis cites.

>git clone https://github.com/labshelf/labshelf
Build from source · free and open source · no account · your library is a folder
~/thesiszsh
> labshelf search status:readingreading 2023  veen2023adapted          Adapted Large Language Models Can Outperform Medical…reading 2022  bai2022constitutional    Constitutional AI: Harmlessness from AI Feedbackreading 2022  wang2022selfconsistency  Self-Consistency Improves Chain of Thought Reasoning…> 

~/thesis$ labshelf sponsor

LabShelf is free, open source and built by one person. Funding pays for the hours that go into it and keeps it free for everyone who reads papers for a living.

~/thesis$ ls ~/Research/library

Your library is a folder.

One paper, one folder named by its cite key: the PDF and a small YAML file with its metadata and your note. No database to export, no account to lose.

Open it in Finder or put it in git. To use it on several machines, sync the folder with your own sync tool.

  • Plain files. PDF, YAML and a generated .bib
  • Unread, Reading, Done. One click on the mark cycles it
  • Search. status:reading, year:>2018, author:, has:pdf
Figure 1. The library in VS Code: folders on the left, papers in the middle, details on the right.
Try it. The same library view, running here on a demo library: filter, search, open a paper's details.
# ~/Research/library/papers/Language models/Reasoning
wei2022chainofthought/ # one paper = one folder, named by cite key
paper.pdf
metadata.yaml # title, authors, year, status, tags, note
bib.bib # generated from metadata.yaml

~/thesis$ ls --read# highlight and cite

Read, highlight, cite the page.

Select a passage and highlight it in yellow, green, blue, red or pink, or copy it with a citation that carries its page.

Months later, typing \cite[ in your thesis lists that paper's highlights and inserts \cite[p.~4]{key}.

  • Copy with citation Cmd/Ctrl+Shift+C, in pandoc, LaTeX, author-year or cite-key style
  • Hover a reference and its card opens in place
  • Notes tab inserts your highlights into the note
Figure 2. The reader in VS Code: select a passage, pick a colour or copy it with its page.
Try it. The same reader, running here on a real paper: select text, highlight it, hover a reference.

~/thesis$ ls --write thesis.tex# your citations, checked

It checks your citations against your library.

The PDF preview reads every \cite against your library. A mistyped key offers Replace with the key on your shelf. A cited preprint that has since been published offers Update to its venue. F8 walks every problem.

Try it on the right. One citation is on your shelf; the other is a typo.

  • Page and word limits in the preview footer
  • One chapter builds through \includeonly
  • arXiv bundle exported from the project
chapters/intro.texCompiled
42The Transformer removed recurrence altogether43\cite{vaswani2017attention}. Its cost grows with the44square of the sequence length \cite{vaswani2018attention}.
thesis.pdf · preview

1.1  Making attention cheaper

The Transformer removed recurrence altogether [1]. Its cost grows with the square of the sequence length [?].

>hover or tap the two citations

Figure 3. The preview next to the source: a citation's card, its fix, and the rebuilt page.
Figure 4. Typing \cite[ lists the paper's highlights and inserts the page.

~/thesis$ ls --cli# we would have called it ls. it was taken.

The same shelf, from a terminal.

Run labshelf with no arguments for folders, papers and a preview side by side, driven from the keyboard. Or run one command: add, search, status, tag, bib. ls, search and show speak --json.

Edits made in the terminal show up live in VS Code.

  • labshelf add DOI, arXiv ID, PMID, URL or PDF
  • labshelf search the same syntax as VS Code
  • labshelf bib writes a .bib of the papers you name
Figure 5. The terminal app with no arguments, then single commands in a shell.

~/thesis$ ls --web# save from the browser

One click from a paper page to your shelf.

The browser extension reads the paper you are looking at, finds its PDF and saves both to your library.

  • Works on arXiv, publisher pages, DOIs, PubMed
  • Google Scholar marks what is already in LabShelf
  • Chrome and Firefox
Figure 6. Saving a paper from its page with the toolbar button.

~/thesis$ labshelf open manual.pdf# the docs, in the reader

labshelf-manual.pdfLabShelf Reader yellowgreenblueredpink §1

LabShelf: a local-first reference manager for reading and writing

L. Nasser

User manual · labshelf 0.x · October 2026

AbstractThis manual describes LabShelf, a reference manager that keeps your library as a folder of plain files and works inside VS Code, a terminal and the browser. Each section is a set of tasks: numbered steps, the result to expect after each one, and what to check if it goes wrong. Select any passage to highlight it, as you would in the reader.

1Getting started

LabShelf is three apps over one library: a VS Code extension, a terminal app and a browser extension. None of them is published yet, so you build them from the repository. VS Code and the terminal read the same folder on your disk; the browser keeps its own copy in IndexedDB. To use the library on several computers, sync the folder with your own sync tool; LabShelf calls no cloud service.

1.1Build the apps

Each app builds from a clone of github.com/labshelf/labshelf with pnpm. Build only the apps you use; Table 1 lists the command and how to load each one.

  1. Clone the repository and run pnpm install at its root.The install ends without errors. The terminal app needs Node 22.6 or later; the extension needs VS Code 1.98 or later.
  2. Run the build command for your app from Table 1.The build writes the app into its package: out/ and dist/ for VS Code, dist/labshelf.mjs for the terminal, dist/chrome and dist/firefox for the browser.
  3. Load it as Table 1 says.VS Code opens an Extension Development Host with LabShelf in the activity bar; labshelf --help prints the commands; the browser shows the LabShelf toolbar button.

Table 1. Building and loading each app.

AppBuildLoad
VS Codepnpm --filter @labshelf/vscode buildOpen the repository in VS Code and press F5
terminalpnpm --filter @labshelf/terminal buildLink dist/labshelf.mjs as labshelf on your PATH (Listing 1)
Chrome 125+pnpm --filter @labshelf/browser buildchrome://extensions, Developer mode, Load unpacked, dist/chrome
Firefox 128+pnpm --filter @labshelf/browser buildabout:debugging, Load Temporary Add-on, dist/firefox/manifest.json
Listing 1. Building and linking the terminal app.
pnpm --filter @labshelf/terminal build
ln -s "$PWD/packages/terminal/dist/labshelf.mjs" /usr/local/bin/labshelf
labshelf doctor   # checks the library, config and image support
If it goes wronglabshelf: command not found means the link is not on your PATH: link it into a directory that echo $PATH lists. For anything else, labshelf doctor names the part that fails.

1.2Choose a library folder

The library is a folder you pick, empty or not. VS Code and the terminal share one library setting, so choosing it in one app sets it for the other.

The terminal looks at --library, then LABSHELF_LIBRARY, then the shared setting.
  1. In VS Code, open LabShelf in the activity bar.The sidebar reads No library configured with a Configure Library button.
  2. Click Configure Library, or run LabShelf: Configure Library, and pick a folder.The sidebar shows the Library and Projects sections, and the folder gets the layout of Listing 2.
  3. In a terminal, run labshelf where.It prints the same library folder, with the config and log paths. Without VS Code, labshelf init ~/Research/library creates the library and remembers it.
Listing 2. What LabShelf keeps in the library folder.
papers/<folders>/<paper id>/   # paper.pdf, metadata.yaml, bib.bib
projects/<project id>/       # your LaTeX or Typst project, labshelf.yaml
.research/                   # highlights, search index, logs
If it goes wrongIf VS Code and the terminal list different papers, they read different folders: compare labshelf where with the folder VS Code shows, and check that LABSHELF_LIBRARY is not set in your shell.

2Adding papers

A paper enters the library from an identifier, a PDF on your disk, a browser tab or the terminal. Its id is its cite key, such as vaswani2017attention. Metadata comes from Crossref, arXiv and OpenAlex, and each field takes the value of the source trusted most for it.

Figure 7. Adding a paper in VS Code.

2.1Add a paper by DOI, arXiv id, PMID or link

Any identifier works: a DOI, an arXiv id, a PMID written as PMID: 12345678, a PMCID such as PMC1234567, or the link to an article page. LabShelf looks it up and files the paper under its cite key.

  1. Run Research: Add Paper by DOI or Link….An input asks for a DOI, arXiv id, PubMed id or link.
  2. Paste 1706.03762 or 10.48550/arXiv.1706.03762 and press Enter.A message reads LabShelf: Added "Attention Is All You Need", and the paper is in the list.
  3. Paste the same identifier again.Nothing is added; the message reads LabShelf: Already in the library as vaswani2017attention.
If it goes wrongIf a title, author or year is missing, run Research: Fetch Metadata for Paper on that paper, or Research: Resolve Missing Metadata for every paper that lacks some.

2.2Drag a PDF into the library

A PDF on your disk becomes a paper when you drop it on the LabShelf sidebar. LabShelf copies it into the library and fills in the metadata it can find.

  1. Drag one or more PDFs from Finder or Explorer onto the Library section of the sidebar.Each PDF becomes a paper folder named by its cite key.
  2. Or run Research: Add Paper and pick the files.A message counts the result, such as LabShelf: 3 added, 1 already in the library.
If it goes wrongA paper whose text you cannot select or find is a scan: make it searchable as in §2.5.

2.3Save a paper from the browser

The browser extension saves the paper in the current tab, or any result on Google Scholar.

  1. On an article page, click the LabShelf toolbar button.The popup shows the paper with a folder, a Tags field, a note field and a Save to LabShelf button. For a paper you have, it reads Already in your library.
  2. Click Save to LabShelf.The paper is in the browser library.
  3. On Google Scholar, click Save to LabShelf under a result.The button turns into In LabShelf.
If it goes wrongWhen the page offers no PDF, choose Save without PDF. When you download the PDF later, the popup offers to attach it to the paper.

2.4Add papers from the terminal

labshelf add takes PDFs, folders, links, DOIs, arXiv ids, labelled PMIDs and PMCIDs, several at a time, and --to files them in a folder (Listing 3).

Every app refuses a paper the library already has.
Listing 3. Adding papers from a shell.
labshelf add 1706.03762                    # arXiv id
labshelf add 10.1038/nature14539 --to Vision
labshelf add ~/Downloads/*.pdf
  1. Run labshelf add 1706.03762.It prints added vaswani2017attention Attention Is All You Need.
  2. Run the same command again.It prints exists vaswani2017attention (1706.03762) and adds nothing.
If it goes wrongA line that ends in (metadata unconfirmed) means no source confirmed the record. Check the fields in the detail pane, or fetch them again in VS Code as in §2.1.

2.5Make a scanned paper searchable

A scanned PDF holds pictures of pages, so you cannot search or quote it until OCR adds a text layer. OCR runs on your computer.

  1. Select the paper and run Research: Make Scanned Paper Searchable (OCR).When it finishes, the PDF carries an invisible text layer, so find (Cmd/Ctrl F) in the reader matches words on the scanned pages.
  2. For every scan at once, run Research: Make All Scanned Papers Searchable (OCR).Each scanned paper gets its text layer.
If it goes wrongOCR reads English and skips a scan of more than 150 pages by default. For other papers, set labshelf.ocr.languages and labshelf.ocr.maxPages.
page 2

3Organizing

Folders give each paper one place, the status tracks what you have read, and tags and search cut across both. Every change is a plain file edit, so it shows up in every app.

3.1Sort papers into folders

Folders are real folders under papers/ in the library, so a paper keeps its place in every app.

  1. In the VS Code sidebar, use New Folder on a folder, or New Folder at Library Root.The folder appears in the Library section.
  2. In the TUI, press x on a paper, open the folder and press p; or press M to pick the folder.The paper moves; VS Code shows it in its folder at once.
  3. From a shell, run labshelf mv vaswani2017attention Vision, then labshelf ls Vision.The paper is listed under Vision.
If it goes wrongA change made in the terminal that VS Code does not show means the two read different libraries: see §1.2.

3.2Mark the status and add tags

Every paper is Unread, Reading or Done, and carries any number of tags.

TUI keys: mu, mr and md set the status; t edits the tags.
  1. In the VS Code list, click a paper's status mark.It cycles through Unread, Reading and Done.
  2. Select a paper, click the plus button (Add tag) in the detail pane, type a tag and press Enter.The tag is saved to the paper's metadata.yaml.
  3. From a shell, run labshelf status vaswani2017attention done and labshelf tag vaswani2017attention +nlp -todo.VS Code shows the new status and tags.

3.3Search the library

One query language works in VS Code, in the TUI (s) and in labshelf search. Every word must match, a quoted phrase matches as a whole, and the fields of Table 2 narrow the result.

  1. In VS Code, run Research: Search Library and type attention status:reading year:>2016.Only papers that match every term remain.
  2. From a shell, run labshelf search tag:nlp has:pdf.One line per paper: status, year, id and title, or No match. Add --json for the full records.

Table 2. Search syntax.

QueryFinds papers that
word "a phrase"contain every word and the phrase
-worddo not contain the word
tag:nlp #nlphave the tag
status:reading is:rhave the status: unread, reading or done
year:2015..2020were published in the range; also year:2017, year:>2018, year:<2000
author:vaswanihave a matching author
kw:graphshave a matching keyword
note:todohave a matching note
venue: key: abstract:match in the venue, the cite key or the abstract
has:pdf no:pdfhave or lack a PDF; also has:note, has:doi, has:tags, has:abstract
If it goes wrongEvery term must match, so one wrong year or tag empties the result. Drop terms one at a time to find the one that excludes the paper.

3.4Find what the library is missing

The Citation Map lists the works that at least three of your papers cite and that the library does not have yet: the reading your field assumes.

  1. In VS Code, run Show Citation Map; in the browser, open it from the library page.The map lists the missing works.
  2. Click Import on a work you want.The paper joins the library and its row leaves the map.
If it goes wrongAn empty map means no work is cited by three or more of your papers yet. Only papers with a DOI are looked up, and a work without a DOI has a disabled Import.
page 3

4Reading

LabShelf opens every paper in its own reader, in VS Code and in the browser. You mark passages in five colours, copy quotes with their citation, and keep a note for each paper.

4.1Highlight a passage

Highlights have five colours: yellow, green, blue, red and pink. What each colour means is up to you.

  1. Run Research: Open Paper and pick a paper.The paper opens in the reader.
  2. Select a passage.A bubble appears above the selection, with five buttons titled Highlight yellow to Highlight pink and a Copy with citation button.
  3. Click a colour.The passage keeps that colour.
If it goes wrongNo bubble on a scanned paper means the PDF has no text layer. Make it searchable first, as in §2.5.

4.2Copy a quote with its citation

Copy with citation (Cmd/Ctrl Shift C) copies the selected text together with the paper's cite key and page. The format follows labshelf.reader.citationStyle (Table 3).

  1. Select a passage in the reader and press Cmd/Ctrl Shift C.The quote and its citation are on the clipboard.
  2. Paste it into your draft.With the default style, a Markdown quote followed by [@key, p. 4].

Table 3. What Copy with citation writes for each citationStyle.

citationStyleCopied text
pandoc (default)> quote, a blank line, then [@key, p. 4]
latex``quote'' \cite[p.~4]{key}
author-year"quote" (Vaswani 2017, p. 4)
citekeyquote @key
If it goes wrongA quote in the wrong format means the setting is set for another workspace. Check labshelf.reader.citationStyle in both User and Workspace settings.

4.3Preview a reference

Resting the pointer on a reference in the paper shows a card for the cited work, so you do not lose your place to look it up.

  1. Hold the pointer over a citation in the text.After 250 ms a card shows the work it points to.
If it goes wrongNo card means labshelf.reader.hoverPreviews is off. Change the wait with labshelf.reader.hoverDelayMs.

4.4Keep notes and export highlights

Each paper has a note in the Notes tab of the detail pane, and its annotations can leave LabShelf as Markdown.

  1. Select the paper in the list, open the Notes tab of the detail pane and write.The note belongs to the paper and searches with note: (§3.3).
  2. Click Insert highlights.The paper's highlights are added to the note as quotes.
  3. Click Copy note, or run Research: Export Annotations to Markdown.The note is on the clipboard, or you choose to copy the annotations or save them as a Markdown file. The export lists highlights, notes and comments by page.
If it goes wrongNo Insert highlights button means the paper has no highlights yet: add one as in §4.1.

4.5Reader keys

Table 4 lists the keys the reader answers to. On a Mac, Cmd replaces Ctrl.

Table 4. Reader keys.

KeyDoes
Cmd/Ctrl+= Cmd/Ctrl+-zoom in, zoom out
Cmd/Ctrl+0reset the zoom
Cmd/Ctrl+Ffind in the paper
Alt+Left Alt+Rightgo back, go forward; Cmd+[ and Cmd+] on a Mac
F4show or hide the sidebar
Cmd/Ctrl+Shift+Ccopy the selection with its citation

5Writing

LabShelf writes LaTeX and Typst projects next to your library: a preview beside the source, citations taken from your highlights, and checks that catch a wrong citation before a reviewer does.

5.1Start a project

A project is a folder with a main .tex or .typ. Start one from a template, from a blank project or from a folder you already have.

  1. Run Research: Browse Templates… and pick one, or run Research: New Blank Project….The project opens and appears in the Projects section.
  2. For a folder you already have, run Research: Add Existing Folder as Project….The folder joins the Projects section.
  3. If a shared project lists papers you lack, run Install Project Papers.The papers it lists join your library.
If it goes wrongA project that is in the library folder or was added before, but is missing from the list, shows up after Research: Refresh Projects, which reads the project list again. A folder you never added needs Research: Add Existing Folder as Project….

5.2Build and preview

The preview shows the compiled PDF beside the source. Typst compiles inside VS Code; LaTeX uses the compiler you choose.

  1. Open the main file and run Research: Show Preview.The PDF opens beside the source.
  2. Press Cmd/Ctrl Enter.The project builds and the preview updates; the footer shows the build status.
  3. In a LaTeX source, press Cmd/Ctrl Alt J.The preview scrolls to the output of the line under the cursor and marks it. With no build yet, the project builds first.
If it goes wrongA LaTeX build that fails at once often means the wrong compiler. Run Research: Choose LaTeX Compiler and pick another.

5.3Cite from your highlights

Typing \cite[ lists the highlights of your papers, and choosing one inserts the citation with its page (Listing 4).

  1. In a LaTeX source, type \cite[.A list shows highlighted passages with their papers.
  2. Pick a passage.The citation is inserted with the page of the highlight.
  3. To pick a paper instead, run Research: Cite from Library.The citation for the chosen paper is inserted.
Listing 4. A citation inserted from a highlight on page 4.
Attention alone suffices~\cite[p.~4]{vaswani2017attention}.
If it goes wrongAn empty list means no paper has highlights yet; highlight a passage first (§4.1).

5.4Fix citations

LabShelf checks every citation in the build against your .bib and your library, and offers a fix on each card.

F8 and Shift+F8 walk the problems in the preview.
  1. Press F8 in the preview.The preview scrolls to the next problem and flashes its mark; Shift F8 goes back.
  2. For a key that is not in your .bib, choose Replace with ….The key becomes the suggested one from your library.
  3. For a preprint that has been published, choose Update to …; in the .bib, Replace with the published version.The entry points to the published venue.
  4. For a work that is not in your library, choose Add to library.The paper joins the library.
If it goes wrongA card without a suggestion means no paper in your library matches the key. Add the paper (§2.1), then build again.

5.5Set page and word limits

The preview footer shows the page and word count against your limits. The limits live in labshelf.yaml in the project (Listing 5).

  1. Add the limits of your venue to labshelf.yaml.The footer shows each count against its limit.
  2. Set countUpTo to references or end.Counting stops at the references, or runs to the end of the PDF.
Listing 5. Limits in labshelf.yaml.
check:
  pages: 8
  words: 6000
  countUpTo: references   # or end
If it goes wrongCounts that include the bibliography mean countUpTo is end; set it to references.

5.6Link to a page of a paper

A labshelf: link in any file opens a library paper in the reader, at the page you name.

  1. Write labshelf:vaswani2017attention#p5 in a source file or a note.Hovering the link shows the paper, or that no paper has the key.
  2. Follow the link.The paper opens in the reader at page 5.
If it goes wrong"No paper" on hover means the key is not a cite key in your library; check it with key: in a search.

5.7Build one chapter

In a project that uses \include, the preview can build only the chapter you are writing, through \includeonly.

  1. Open a chapter file and click the <file> only toggle in the preview header.Builds compile that chapter alone.
  2. Click the toggle again.Builds compile the whole project.
If it goes wrongNo toggle in the header means the project has no \included files; the toggle appears only when there is a chapter to build alone.

5.8Check before submitting

Research: Check Before Submitting reads the built PDF for what a venue rejects: the page limit, anything that reveals the authors, Type 3 fonts and low-resolution images (Figure 8).

  1. Run Research: Check Before Submitting.LabShelf saves your files, builds the project and checks the PDF and the sources. Each finding appears in the Problems panel: a finding in the PDF names its page when it has one, and a finding in a source sits on its line.
  2. Fix each finding and run the check again.The list empties.
Figure 8. Check Before Submitting lists an unresolved citation and a link that reveals the authors.
If it goes wrongThe check needs a successful build. When the build fails, a message says so and the build problems are listed in Problems.

5.9Bundle for arXiv

The arXiv bundle is a .zip of the files arXiv needs, with each .bib cut down to the entries the project cites.

  1. With the project open in the sidebar, open its title menu and choose Download for arXiv (.zip).A save dialog opens in the project folder, named <project id>-arxiv.zip. LabShelf writes the .zip where you choose and shows no other message.
  2. Upload the .zip to arXiv.arXiv builds the paper from the bundle.
If it goes wrongIf arXiv cannot build the bundle, check that every file the source needs is in the project folder. The bundle holds the folder's files except build output, such as .aux and .log files and the PDF built from a source.

5.10Install LabShelf Helper on macOS

LabShelf Helper is a small program that builds LaTeX projects for the browser extension, which cannot run a TeX compiler by itself. The extension sends the helper a project's files; the helper runs latexmk, using a TeX it installs for you or the one on your computer, and sends back the problems and the PDF. It runs as you, writes only to ~/Library/Application Support/LabShelf Helper and needs no administrator rights. The steps below are for macOS 15 or later. The installer is not signed by Apple, so macOS blocks it the first time (why).

  1. Download labshelf-helper-macos.pkg (Apple silicon) or labshelf-helper-macos-x64.pkg (Intel) from the releases page, and open it.macOS says the installer cannot be opened because Apple cannot check it for malicious software. Click Done; do not move it to the Bin.
  2. Open System Settings and choose Privacy & Security.Under Security, a line says the installer was blocked to protect your Mac.
  3. Click Open Anyway.macOS asks for your password or Touch ID.
  4. Enter your password, then confirm with Open Anyway in the dialog that follows.The installer opens. Click Continue and Install; it ends with The installation was successful.
  5. Open a LaTeX project in the LabShelf extension and build it.The extension finds the helper and builds the project. The first build may ask to install a TeX.
Figure 10. The Open Anyway button in Privacy & Security.
If it goes wrongWhen Privacy & Security shows no Open Anyway button, open the .pkg again; the button stays for about an hour after the block. When the extension still says the helper is missing, quit the browser completely and open it again.

5.11Why the macOS helper is unsigned

LabShelf is free and open source. A Developer ID certificate, which lets Apple vouch for a program, costs US$ 99 a year, so the macOS helper is not signed by Apple. What you can check instead is where the file came from. The public release workflow builds every helper binary and installer from the repository, attaches a build attestation that ties each file to that workflow run, and publishes the SHA-256 of every file in SHA256SUMS. The Windows helper is signed through the SignPath Foundation; see the code signing policy.

  1. Install the GitHub CLI and run the command in Listing 9 on the file you downloaded.It prints Verification succeeded! with the workflow that built the file.
  2. Compare the file with its published SHA-256: run shasum -a 256 labshelf-helper-macos.pkg and look for the same value in SHA256SUMS on the release.The two values are equal.
Listing 9. Verifying a downloaded installer.
gh attestation verify labshelf-helper-macos.pkg --repo labshelf/labshelf
If it goes wrongWhen verification fails or the SHA-256 differs, do not open the file. Download it again from the releases page, and report it in an issue if it fails again.

5.12Uninstall LabShelf Helper on macOS

Removing the helper takes two steps: unregister it from the browsers, then delete its folder. The folder holds the helper, the TeX it installed, a copy of your project files and its logs; your projects and library are elsewhere and stay.

  1. In Terminal, run the command in Listing 10.The helper removes its registration from every browser it was registered with and exits without output.
  2. Move the folder ~/Library/Application Support/LabShelf Helper to the Bin.The helper is gone. The extension shows that no helper is installed.
Listing 10. Unregistering the helper.
"$HOME/Library/Application Support/LabShelf Helper/bin/labshelf-helper" --unregister
page 4

6Sync across devices

LabShelf has no sync of its own and calls no cloud service. The library is a folder, so a sync tool you already use (Dropbox, iCloud Drive, Syncthing, the Google Drive desktop app) carries it between computers. Point VS Code and the terminal app at the synced folder on each computer. If a sync tool reports a conflict, keep the content you want in the original file and delete the conflict copy.

7Terminal

The terminal app reads and writes the same library as VS Code; edits made in the terminal show up live in VS Code. labshelf with no arguments opens the TUI; with a command, it runs that command and exits.

7.1Browse in the TUI

The TUI shows three panes: folders, papers and a preview with the tabs Info, Abstract, Notes and BibTeX (Figure 9). Press ? for every key; Table 5 lists the common ones.

Figure 9. The TUI with folders, papers and the preview.

Table 5. TUI keys.

KeyDoes
j k h lMove down, up, and between panes
gg GGo to the first or last item
tabSwitch the preview tab
f / sFilter the list, find in it, search the library
z ZJump to a folder or a paper
mu mr mdMark Unread, Reading or Done
oOpen the PDF
a t eAdd a paper, edit tags, edit the note in $EDITOR
x p MCut a paper, paste it into this folder, move it to a folder
yk yc yb ymCopy the key, \cite{}, BibTeX, or the highlights as Markdown
,t ,y ,a ,s ,mSort by title, year, author, status or last modified; a capital letter reverses
B SExport a .bib
:Command line: :export, :mkdir, :help
?Show every key
If it goes wrongNo thumbnails in the preview means the terminal cannot draw images; thumbnails need kitty, Ghostty, iTerm2 or WezTerm.

7.2Run a command

Each command works on the library and exits, so it fits in scripts (Table 6). --json prints machine-readable output for ls, search and show.

Table 6. Commands.

CommandDoes
labshelf init [path]Choose the library folder
labshelf wherePrint the library, config, log and manifest paths
labshelf doctorCheck Node, the library, thumbnails and the clipboard
labshelf add <input>… [--to <folder>]Add from a PDF, a folder, a link (including a PubMed link), a DOI, an arXiv id, PMID: … or a PMCID
labshelf ls [folder] [-r] [--sort key[!]]List a folder; -r lists the papers below it too, ! reverses the sort (keys: title, year, author, status, modified)
labshelf search <query…>Search the library with the syntax of §3.3
labshelf show <id>Show a paper's details, highlight count and reading position
labshelf open <id|key|labshelf:key#pN>Open a paper, at a page if the link names one
labshelf status <id…> unread|reading|doneSet Unread, Reading or Done
labshelf tag <id…> +tag -tagAdd and remove tags
labshelf mv <id…> <folder>Move papers to another folder
labshelf bib [id…] [-c folder] [-o file.bib]Print BibTeX for papers or a folder; -o writes it to a file
labshelf install [project-dir]Add the papers a project lists

7.3Read the output

add prints one line per input: added with the new cite key and title, or exists with the key the library already has (Listing 6). (metadata unconfirmed) marks a paper whose metadata needs a look.

Listing 6. Adding a paper twice.
$ labshelf add 10.48550/arXiv.1706.03762
added  vaswani2017attention  Attention Is All You Need
$ labshelf add 1706.03762
exists vaswani2017attention  (1706.03762)

search and ls print one paper per line: a status mark (○ Unread, ◐ Reading, ● Done), the year, the cite key and the title (Listing 7). A search without results prints No match.

Listing 7. Searching the library.
$ labshelf search attention year:2017
◐ 2017  vaswani2017attention  Attention Is All You Need
If it goes wrong(metadata unconfirmed) means no source confirmed the title and authors. Check them in the detail pane or with labshelf show.

7.4Set environment variables

Three environment variables change how the terminal app runs (Table 7).

Table 7. Environment variables.

VariableDoes
LABSHELF_LIBRARYUse this library folder (the -L flag wins over it)
LABSHELF_PDF_VIEWEROpen PDFs with this program
LABSHELF_IMAGES=itermDraw thumbnails with the iTerm2 image protocol
page 5

8Settings

These are VS Code settings; User and Workspace scopes work as usual (Table 8). Writing limits are not settings: they live in each project's labshelf.yaml (§5.5).

Table 8. Settings.

SettingDefaultMeaning
labshelf.ai.enabledtrueIndex paper text so the Related tab can list similar papers
labshelf.ocr.enabledtrueRead a PDF optically when its text layer is missing or unreadable
labshelf.ocr.makeSearchabletrueMake scanned PDFs searchable
labshelf.ocr.maxPages150Scans with more pages than this get no automatic text layer
labshelf.ocr.languages["eng"]Languages OCR reads
labshelf.reader.vimKeysfalseVim keys in the reader
labshelf.reader.defaultZoompage-widthZoom a paper opens at when it has no saved position: page-width, page-fit, page-actual or auto
labshelf.reader.toolbarAutoHidetrueHide the reader toolbar while you scroll down
labshelf.reader.restorePositiontrueReopen a paper at the page, zoom and sidebar state you left
labshelf.reader.hoverPreviewstrueShow a preview when you hover a citation, figure, equation, table or section link
labshelf.reader.hoverDelayMs250Milliseconds before the card shows
labshelf.reader.citationStylepandocFormat of Copy with citation: pandoc, latex, author-year or citekey
labshelf.reader.openBesidefalseOpen the reader beside the current editor; off opens it full-width
labshelf.writing.autoCompiletrueCompile the PDF preview when you save a project source

9Privacy

LabShelf has no account and no server of its own. Your library stays on your disk, and any sync tool you use on it is your own. Table 9 lists every host the apps contact.

Table 9. Network hosts.

HostWhen
api.crossref.orgLooking up a paper's metadata
export.arxiv.orgLooking up an arXiv paper
api.openalex.orgLooking up metadata and the citations behind the Citation Map
api.semanticscholar.orgMatching a title or a DOI to metadata, and finding an open-access PDF by DOI, arXiv id or PMID
www.ebi.ac.uk (Europe PMC), eutils.ncbi.nlm.nih.gov, www.ncbi.nlm.nih.govLooking up a PMID or PMCID, and finding a full-text link
api.datacite.org, dblp.org, openlibrary.orgLooking up a DataCite DOI, a computer-science paper or an ISBN
doi.org, api.unpaywall.org, arxiv.org and the publisher and repository sites they point toFinding a PDF
packages.typst.org, cdn.jsdelivr.net, raw.githubusercontent.com, github.comBrowsing templates and downloading the Typst and Tectonic tools
api.github.comSubmitting a template, only when you publish one
dash.cloudflare.com, api.cloudflare.comConnecting your Cloudflare account, and installing or updating your relay in it
<relay>.<your subdomain>.workers.devEditing a shared project and opening a share link: the relay in the Cloudflare account of whoever connected it
labshelf.orgOpening a share link in a browser

Shared projects and share links go through a relay that LabShelf installs in the Cloudflare account of the person who connects one, never in an account LabShelf runs. Connecting signs you in to Cloudflare in your browser and asks only to manage Workers, Workers KV and Realtime and to read account settings. LabShelf keeps that sign-in on your device, to update the relay, and Cloudflare's own privacy policy covers the account.

Everything a relay stores or forwards is encrypted on your device: files, edits, comments, cursors, paper metadata and PDFs. The key travels only inside the invite or the share link, after the #, which a browser never sends to a server. The account owner and Cloudflare see opaque identifiers, sizes and times, never the content. Revoking a share link deletes its copy from the relay.

A lookup by identifier sends only the identifier. Searching or matching by title sends the title. Finding a PDF for a paper without a DOI or arXiv id sends its title, and the first author's surname to export.arxiv.org. Registry lookups also send a contact address, contact@labshelf.dev.

10Citing LabShelf

If LabShelf helped your research, cite it with this entry (Listing 8).

Listing 8. BibTeX entry.
@software{labshelf,
  title   = {LabShelf: a local-first research paper manager},
  author  = {Nasser, Luca Marinho},
  year    = {2026},
  url     = {https://github.com/labshelf/labshelf}
}
labshelf-manual.pdfOctober 20265 pages