Skip to content

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Changed

  • Sort order is remembered — the column you sorted by (and its direction) is saved to config.toml and restored on the next start. The default is now Added, newest first, instead of file order. The sort also keeps applying if you hide its column.
  • Reorganized ? help screen — grouped into Keybindings, Search & filters (search syntax and saved filters together) and Command palette, with clearly separated headings, wrapped lines that hang under the description column, and a much shorter Filters section.
  • Column picker matches the keyword picker — columns are now a checklist toggled with Enter / x (Space no longer toggles), with a hint line in the same style as the other dialogs.
  • Entry viewer — the URL is now listed with the other fields (Author, Year, Journal, DOI, URL) instead of as a shortened link in the status row, and there is a blank line above the title. URLs — including ones in Other fields, such as bdsk-url-1 — stay on a single line, cut with "…" when the detail pane is too narrow to show them whole, rather than wrapping onto the next line.
  • Steadier status row — the Read / Urgency / Rating / PDF labels above the title now have fixed widths, so they stay put while you flick through entries instead of shifting sideways as each entry's values change. In a narrow detail pane the four labels stack into two rows rather than running off the edge.
  • Authors under the title, fixed height — the author list moved from the field list to directly below the title and always takes exactly three lines (long lists are cut off with "…"), so the rest of the entry no longer jumps up and down as you move between entries. Authors are shown JabRef-style as Last, First / Last, First, with LaTeX escapes decoded (Sch{\"o}ner → Schöner) and names kept whole on one line wherever they fit.
  • LaTeX in the table's Author column — the first-author surname in the entry table (and its sort order, and the PDF/.bib import reports) now shows decoded characters (Sch{\"o}ner → Schöner) instead of the raw LaTeX.
  • Start-up file picker preselects your last file — when you launch bibtui without a file, the most recently opened one is already highlighted, so Enter reopens it.

  • LaTeX in abstracts is rendered — abstracts now show ±, μ, ∼ and ° instead of $\pm$, \ensuremath{\mu}, $\sim$ and $^{\circ}$, and -- becomes a proper en dash. The same decoding already applied to author names now also covers maths and spacing macros, so titles and citation previews improve too.

  • Roomier entry viewer — the text now keeps clear of the scroll bar instead of running right up against it, the abstract wraps to the width of the pane (it used to wrap at a fixed column and then get folded a second time, leaving every other line hanging at the left margin), and the rule under the fields spans the pane.

Fixed

  • "Press w to write" hint — after editing an entry or its keywords, the confirmation read "Press to write." because [w] was swallowed as markup; it now shows the key.
  • Square brackets in abstracts — an abstract containing something like [1] or [Ca2+] had it silently swallowed as markup; it now shows literally.

[1.1.0] - 2026-09-14

Added

  • Saved filters — press f to save, pick, edit or delete a named filter you can jump back to, à la Papers2 smart collections. See Saved filters.
  • Richer search syntax — open-ended/comparison year filters (y:2010-, y:>2010, …), quoted values (k:"sea ice"), and r:/pr: read-state/urgency prefixes. See Searching your library.
  • Import from PDF files — from the n "New Entry" menu, choose "Import from PDF" and pick one or more files (e.g. an old downloads folder or a migrated Papers/Zotero library). Each PDF is scanned for a DOI or arXiv id (document metadata first, then its first two pages of text) and its metadata fetched via CrossRef, same as "Import by DOI". Nothing is written until you confirm: a report lists every file ✓/✗ with the reason for any failure, Space previews a file, and one click imports every ✓ row. Matching an existing library entry links the PDF to it instead of duplicating; an identical PDF already on disk (by content, not filename) is reused rather than copied again.
  • Import a .bib file — n then b, pick a file such as a journal's "download citation" export. A single-entry file is added directly, like DOI import; a multi-entry file shows the same kind of ✓/✗ report (duplicates matched by DOI) before you commit.
  • Open the online documentation — Ctrl+d, also linked from the ? help screen.

Changed

  • Adding an entry is now one key, n, with a mnemonic chooser — d DOI, p PDF, b .bib file, v paste, m manual — replacing the old separate top-level DOI/PDF-import keys.
  • PDF actions are now one key, p, with the same chooser style — Open/Fetch/Add/Copy PDF/Copy path/Delete, one letter each, unavailable ones grayed out rather than hidden. Space still opens the PDF directly. The detail pane's old PDF-actions button panel is gone, replaced by a compact status label. This freed up p from "cycle priority", which moved to u — and "Priority" is renamed "Urgency" throughout the UI (the .bib field itself is unchanged, still priority/prio1-3, for JabRef compatibility).
  • Trimmed and reordered the footer to New, Edit, Keywords, State, Urgency, Rating, Search, PDF, Show PDF, Quit, Write, Docs, Help — everything else (Max table, View, Browser, OpenAlex, …) still works, just via ? help or the command palette.
  • One consistent keyboard convention across every list-picker in the app (PDF/.bib pickers, the keywords editor): Space always previews, Enter/x always chooses or toggles. Pickers now also open with the first row already focused, so Enter/x acts immediately — press s to jump to the filter instead, mirroring the main view's Search key. The keywords editor is the one exception, still opening in its filter box, since typing a new keyword is the more common first move there.

Fixed

  • Auto-fetch failure after adding an entry read as if nothing had happened — it now leads with "Added '\', but its PDF could not be fetched." so it's clear the entry itself was saved; unaffected when fetching for an already-existing entry.
  • Import from PDF is more accurate and gentler on CrossRef — old-style arXiv ids (pre-2007, e.g. hep-th/9711200) are now recognized; a corrupt/unreadable file is no longer misreported as "scanned PDF?"; lookups now pause briefly between files that actually hit the network.
  • The URL indicator (↗) could render as invisible in some terminals — it used to be the 🔗 emoji, which needs color-emoji font support many terminals lack; now a plain Unicode arrow, like every other status icon.

[1.0.1] - 2026-09-14

Added

  • Cmd (⌘) aliases for Ctrl shortcuts — copy key/entry, save in every modal, and the command palette now also fire on ⌘ in terminals that forward Cmd as a distinct key (Kitty, WezTerm, Ghostty, iTerm2 with the Kitty keyboard protocol enabled). Ctrl is unchanged and still works everywhere, including macOS Terminal.app and stock iTerm2, where Cmd shortcuts never reach bibtui at all — the terminal keeps them for itself. The key strings are now defined once in bibtui.utils.keymap instead of being duplicated as literals at each binding.

Fixed

  • PDF detected in the table but "PDF Actions" still only showed Fetch/Add (macOS) — the entry-detail panel's PDF status icon and its action buttons (Open/Copy/Delete vs. Fetch/Add) checked only the exact path stored in the .bib file's file field, unlike the table's status column and every other "is a PDF linked?" check in the app, which also fall back to a search by entry key when the stored path doesn't resolve. The two could disagree whenever the exact stored path failed to resolve but the PDF was still findable — most commonly on macOS, where a filename's accented characters can be written to disk in a different Unicode normal form (NFD) than the one stored in the .bib file (NFC). The detail panel now uses the same lookup as the table, and that shared lookup itself now tolerates NFC/NFD filename differences directly.
  • "Open PDF" (and the Add-PDF preview) could silently fail on Windows — both always ran xdg-open on any non-macOS platform, but xdg-open doesn't exist on Windows. Opening a PDF now uses os.startfile on Windows, open on macOS, and xdg-open on Linux, from one shared helper.
  • Copying froze bibtui for ~5 seconds on Wayland — every copy (cite key, BibTeX entry, citation, PDF path) shelled out to wl-copy with its output captured, but wl-copy forks a background process to keep serving the clipboard (Wayland has no clipboard manager of its own) and that process inherits the captured pipes without closing them, so the app blocked waiting for output it was never going to get until the 5-second timeout ran out — even though wl-copy itself had already succeeded instantly. Output is now discarded instead of captured, so copying is immediate again.

Documentation

  • Clarified in the README and installation guide that bibtui is actively tested on Linux and macOS; Windows support is believed to work (pure Python + Textual, which supports Windows Terminal) but hasn't been tested yet.
  • Corrected the help screen and keybindings doc for Ctrl+Shift+C — they previously implied it always works like other Ctrl shortcuts. In practice it's the least reliable of the copy shortcuts, for two separate reasons: most terminal emulators claim Ctrl+Shift+C as their own built-in "copy" command and never forward it to bibtui at all (e.g. Kitty's default keymap binds it to copy_to_clipboard outright — unrelated to Kitty keyboard protocol support), and on terminals that don't claim it, it still can't be told apart from plain Ctrl+C at the byte level, so it falls back to "copy cite key" instead of "copy BibTeX entry". Ctrl+Y is the alias for "copy BibTeX entry" that's guaranteed to reach bibtui everywhere and is now listed first.
  • Copying now has its own section in the in-app ? help screen — previously scattered inside the catch-all "Other" section, low in the list. All copy shortcuts (cite key, citation, BibTeX entry) are now grouped under a dedicated Copy section placed right after Core, reflecting how central the feature is. The terminal-compatibility caveats for ⌘ and Ctrl+Shift+C are trimmed to a one-line pointer to the online Keybindings doc instead of the full explanation, to keep the in-app screen scannable.

[1.0.0] - 2026-09-09

First stable release. bibtui has been in daily use for months; the feature set, key bindings and on-disk config format are now considered stable and will follow semantic versioning from here on.

Added

  • Adjustable list/detail split — press / to grow or shrink the detail pane in 5% steps (between 20% and 80%). The chosen split is saved to ~/.config/bibtui/config.toml ([ui].detail_panel_percent) and restored on the next start. The narrow-terminal vertical layout and the maximized table view (m) are unaffected. Contributed by Paul Emsley (@pemsley) in #52.

Fixed

  • Copy now works in macOS Terminal.app, iTerm2 and tmux — every copy action (cite key, BibTeX entry, formatted citation, PDF path) previously relied only on an OSC 52 terminal escape, which macOS Terminal.app ignores entirely and iTerm2/tmux ignore unless clipboard access is explicitly enabled, so copying silently did nothing while still showing a "Copied" message. bibtui now also writes to the OS clipboard through the native tool (pbcopy on macOS, wl-copy/xclip/xsel on Linux, clip on Windows) and keeps emitting OSC 52 for SSH sessions and terminals without a CLI clipboard tool, so between them a copy lands in every common setup. The stale Ctrl+Y "terminal-safe fallback" help entry (it was a duplicate of Ctrl+Shift+C, not a fallback) has been corrected.

Changed

  • Installation no longer needs --prerelease=allow — bibtexparser 2.0.0 now has a stable release on PyPI, so uv tool install bibtui, uvx bibtui and pip install bibtui just work. The --prerelease / --pre flag is no longer required and the prerelease = "allow" workaround has been removed from pyproject.toml.

[0.18.0] - 2026-08-28

Changed

  • Omarchy theming now targets Omarchy 4 — Omarchy 4 moved its live theme from ~/.config/omarchy to ~/.local/state/omarchy/current and replaced the old palette format, which stopped bibtui's automatic desktop theming from working. bibtui now reads the Omarchy 4 theme.name and colors.toml and builds a matching theme directly from that palette — background, accent, light/dark mode (from the mode key) and the list/detail/modal surface colours all follow your desktop, still updating live within about two seconds when you switch themes. The previous name-to-builtin mapping is gone, so every Omarchy theme (including custom ones) is matched by its actual colours rather than only the handful that shared a name with a Textual builtin. Manual theme switching from the command palette is unchanged, and Theme: Reset to auto still hands control back to Omarchy.

Removed

  • Omarchy 3 support — the pre-4 layout (~/.config/omarchy, the color0–color15 palette and the light.mode marker file) is no longer detected. On Omarchy 3 bibtui falls back to its default theme; switch themes manually from the command palette.

[0.17.0] - 2026-07-14

Added

  • Customizable table columns — you can now choose which columns the entry table shows and in what order, from a new Table: Configure columns panel in the command palette (Ctrl+P). The available columns are discovered by analyzing the whole .bib file, so any BibTeX field present in your library (e.g. doi, keywords, volume, publisher) can be added as a column, alongside the built-in columns and a new optional cite key column. In the panel, Space toggles a column on or off and Shift+↑/↓ (or the ▲/▼ buttons) reorder the highlighted one; shown columns are marked with a filled ● in the theme's accent colour and hidden ones are dimmed, and Reset restores the default layout. Your choice is saved to ~/.config/bibtui/config.toml ([ui].table_columns) and applied live, so it persists across restarts. The default layout is unchanged, and the Title column still flexes to fill the available width — widest in the maximized "Max table" view (m).

Changed

  • Command palette ordering — bibtui's own commands (Settings, Table: Configure columns, Theme reset, Check for updates, and the Library actions) now appear in alphabetical order in the command palette instead of an arbitrary order.
  • Table column visibility is now user-controlled — the table no longer auto-hides the Journal and Added columns when the pane is narrow. Which columns appear is determined entirely by your saved column layout (configure it via Ctrl+P → Table: Configure columns).

[0.16.0] - 2026-07-08

Added

  • Entry validation on write — when you write a new or edited entry, bibtui validates it against the required-field rules for its type (from ENTRY_TYPES) before touching the .bib file, in three tiers: auto-fixed (a 12-23 page range → 12--23, a https://doi.org/… DOI → bare identifier, bare & % # → escaped — shown in the form for you to confirm with a second Write; intentional LaTeX/maths and Unicode are left alone), flagged (e.g. an implausible year — surfaced but never blocking), and blocked (missing required field, a non-numeric/missing year where the type requires one, or an empty/space-containing/unparseable cite key — the offending fields are outlined and the write is refused). Editing runs the same checks and feels identical to adding, with one deliberate difference: a required field that was already empty — or a year that was already non-numeric — when you opened the entry is only flagged, never blocked, so you're never trapped fixing an unrelated field. Opening a .bib file never validates or rejects anything.
  • Create a new entry from scratch (n) — press n to open a new-entry form. Choose the BibTeX entry type (article, book, inproceedings, …) and the form shows that type's fields under their real BibTeX names, with required fields marked * and listed in a hint, driven by the built-in ENTRY_TYPES table. doi, url and note are surfaced near the top; keywords is intentionally omitted because it is managed by the Keywords modal (k). Switching type re-shapes the form while preserving values you already typed. The cursor starts in the first content field (the cite key is auto-suggested from author + year in AuthorYear form and shown dimmed/italic while auto-generated, until you type your own). A custom fields section lets you add any additional field — pick one from a common-field shortlist or type any field name — so you can capture isbn, urldate, or anything else. Every newly added entry — from the form or from pasted BibTeX — is stamped with a date-added timestamp automatically if it doesn't carry one (DOI imports already do), and the entry is validated with bibtexparser before it can be written. New entries reuse the existing import pipeline, so duplicate cite keys are resolved the same way as DOI/paste imports.

Changed

  • Edit form now uses real BibTeX field names — the field-form editor (e) shares the new-entry form, so it shows the entry's fields under their actual BibTeX names for the entry type (and lets you change the type or add custom fields) instead of a fixed handful of relabelled inputs. Keywords, rating, read state and priority are managed by their own shortcuts and are left untouched by the edit form.

[0.15.2] - 2026-06-23

Fixed

  • Config could reset to defaults after an upgrade — the settings file (~/.config/bibtui/config.toml) is now written with a proper TOML serializer instead of hand-built strings, so values containing quotes, backslashes, or newlines can no longer produce an unparseable file. If a config still fails to parse, it is preserved as config.toml.corrupt before defaults load, so a subsequent save can never silently overwrite recoverable settings. (uv tool upgrade itself never touched the config; the reset was a parse-failure-then-overwrite.)

[0.15.2] - 2026-06-23

error, never published

[0.15.0] - 2026-06-23

Added

  • Manual "Check for updates" command — added a Check for updates entry to the command palette (Ctrl+P) that queries PyPI immediately for a newer bibtui release, bypassing the once-per-day automatic throttle, and reports the result.
  • Documentation site — added a Material for MkDocs documentation site (user guide, PDF fetching, search, a dedicated team-collaboration guide for sharing a library via Git, configuration, and development), published to GitHub Pages by a new docs workflow. Screenshots are generated from the running app by scripts/generate_screenshots.py and regenerated on every deploy so they never go stale. The README is now a concise overview that links to the site.

Fixed

  • Chicago citation preview — the Chicago (author-date) style no longer shows (unavailable) for entries with a page range. The bundled CSL declares page-range-format="chicago-16", which citeproc-py mishandled and raised an error on; unsupported page-range formats now fall back to an expanded range instead of failing the whole citation.
  • Help menu alignment — keybinding descriptions now line up in a consistent column across every section (the Other and Library actions sections were previously misaligned).
  • Help menu out-of-date entries — the help now reflects current commands, including the Check for updates library action that was missing.

Changed

  • Help menu internals — removed a duplicated, hand-maintained copy of the keybindings reference; the help screen is now rendered from a single source of truth, preventing the two copies from drifting apart.
  • Modal styling — all dialogs now share a common _BaseModal base class for their centered layout, border, background, and padding instead of each repeating the same CSS; individual modals only declare what differs (size, border color). No visual change.

[0.14.0] - 2026-05-29

Added

  • Citation preview in entry detail — added citeproc-py based formatted citation preview with a CSL style selector (currently bundled with copernicus-publications.csl).
  • Copy citation shortcut — added Shift+C to copy the currently rendered citation preview while keeping Ctrl+C as citekey/default copy behavior.
  • Config-based CSL styles directory — citation styles now live in ~/.config/bibtui/csl; on first run bibtui seeds common defaults: Copernicus, APA, IEEE, Vancouver, Chicago (author-date), and Harvard (Cite Them Right).
  • Import citekey conflict handling — DOI/paste imports now handle existing keys by rejecting same-title duplicates and otherwise assigning the next free lowercase suffix (a … z, e.g. Goelles2025a).

[0.13.0] - 2026-05-29

Added

  • PDF actions UI added - moved PDF operations into a dedicated collapsible PDF section with state-aware disabled actions.
  • Copy PDF action behavior — copy uses OS file clipboard formats (Linux wl-copy/xclip URI list, macOS osascript, Windows Set-Clipboard -Path).

Fixed

  • Safer OpenAlex DOI fetching — when a DOI is present but OpenAlex finds no DOI match, PDF fetching no longer falls back to title search, preventing false-positive downloads of wrong PDFs (regression covered with an inproceedings DOI case).

[0.12.4] - 2026-05-04

Fixed

  • bibtexparser import crash on startup — removed a runtime type annotation reference to bibtexparser.model.Library in the BibTeX parser, preventing AttributeError: module 'bibtexparser.model' has no attribute 'Library' on environments where that symbol is absent.

[0.12.3] - 2026-05-04

Error, release yanked

[0.12.2] - 2026-05-04

Changed

  • BibTeX save strategy — saving now preserves untouched source text and applies minimal diffs instead of rewriting the whole file.
  • Entry update granularity — changed entries are now patched at field level so unchanged fields in the same entry stay byte-identical whenever possible.
  • Change detection — entry change detection now uses bibtexparser-derived field maps instead of a hard-coded field tuple; custom / unknown fields in raw_fields are handled uniformly without any special-casing.

[0.12.1] - 2026-05-04

  • From DOI import compatibility — pinned httpx to <1.0 to avoid runtime breakage with habanero when pre-release httpx 1.0 variants are installed (get() got an unexpected keyword argument 'params').

[0.12.0] - 2026-05-02

Added

  • File browser startup mode — start bibtui without an initial file, using Textual's native file tree to browse and open library files. Includes quick access to recently opened files
  • Icon -- I made a simple pixel based icon. So you can install it as a TUI with an icon.
  • Optional OpenAlex PDF lookup — add an OpenAlex API key in Settings to enable an additional PDF fetch source (used before Unpaywall).
  • OpenAlex fetch strategy — OpenAlex now prefers DOI lookup first and falls back to title search when DOI is missing or unresolved.
  • BibTeX copy shortcut — added Ctrl+Shift+C to copy the currently selected full BibTeX entry, plus Ctrl+Y as a terminal-safe fallback.

Changed

  • PDF fetch success feedback — success messages now show which provider supplied the PDF (for example OpenAlex, arXiv, Copernicus, Unpaywall, or Direct URL).

Fixed

  • Theme synching with omarchy -- now it can sync with any omarchy theme and does it automatically.

[0.11.6] - 2026-04-01

Added

  • Copernicus PDF fetching — PDFs for all 10.5194 publications (preprints and articles) are now fetched directly from copernicus.org using the DOI structure.

Fixed

  • From DOI — preprint journal — journal name is now resolved for preprints via Crossref lookup; EGUsphere returns "EGUsphere" as a special case.
  • From DOI — preprint year — year extraction now falls back to the posted date field.

[0.11.0] — 2026-02-27

Added

  • Table-pane maximize toggle — press m to maximize/restore the entry table pane for focused browsing.
  • Date-added table column — entry list now includes an Added column with normalized date display and sorting support.
  • Library PDF fetch preflight modal — library-wide fetch now opens a dedicated confirmation modal with an Overwrite broken links toggle.
  • Release helper for minor bumps — added just minor to bump, tag, and push minor versions.

Changed

  • Library fetch workflow — existing local PDFs are auto-linked before batch fetching missing files.
  • PDF linking behavior — fetching now re-links an entry to an already existing destination PDF when the stored link is broken.
  • Entry refresh UX — entry selection is preserved after list refresh operations.
  • Layout behavior — entry list pane now uses flexible width (1fr) for better split behavior.
  • Release task naming — just release-patch was renamed to just patch.

Fixed

  • Date handling consistency — DOI imports now use centralized date-added timestamp utilities.
  • Regression coverage for dates — added tests for extracting, parsing, and formatting bibliography date fields.

[0.10.0] — 2026-02-26

Added

  • Library-wide PDF fetching — new command-palette workflow to fetch PDFs for all entries missing local files.
  • Library-wide citekey unification — new command to normalize citekeys to canonical AuthorYear form across the whole library.
  • OpenAlex quick lookup — Shift+B opens OpenAlex for the selected entry from the footer action; search uses title first and falls back to DOI.

Changed

  • Citekey generation and normalization — improved canonicalization and collision handling for more consistent keys.
  • Clipboard behavior in context — Ctrl+C now prefers focused text widgets (e.g., raw BibTeX view) and falls back to citekey copy when no text widget is focused.
  • Documentation updates — README installation/upgrade guidance and help text were updated for the new library and OpenAlex workflows.

Fixed

  • Raw-view copy usability — copying selected text now works reliably in non-edit raw BibTeX contexts.
  • Regression coverage expansion — added tests for library fetch and citekey normalization/unification paths.

[0.9.9] — 2026-02-26

Added

  • Background update check — checks PyPI once per day on startup in a non-blocking background thread and notifies when a newer stable release is available.
  • Update-check setting — new Settings toggle to enable/disable startup update checks (enabled by default).
  • Update metadata persistence — stores last check time, last notification time, and latest seen version in config under [updates].

Changed

  • PDF module consolidation — PDF path helpers and fetch logic are now grouped under bibtui.pdf.
  • Settings layout readability — helper text is shown before each control with clearer spacing between setting groups.

Fixed

  • Theme consistency in modals — removed hard-coded Rich color tags from Add PDF / Fetch PDF related messaging so colors follow theme tokens.
  • Safer PDF downloads — downloads now use atomic temp-file writes and cleanup to avoid leaving partial files.
  • Direct URL fetch robustness — falls back to GET when HEAD is blocked and validates PDF via content type or PDF magic bytes.
  • Config resilience — invalid or unreadable config files now fall back to defaults instead of crashing startup.

[0.9.8] — 2026-02-24

Added

  • Auto-fetch PDF on import — when the setting is enabled and a PDF base directory is configured, a PDF is automatically fetched after adding an entry via DOI or BibTeX paste.
  • Jump to newly added entry — after importing via DOI or pasting a BibTeX entry, the table cursor now scrolls to and selects the new entry.
  • Add PDF modal preview — the Add PDF dialog now shows a file preview before linking.
  • Citekey search filter — search supports c: / citekey: / key: prefix to filter by citation key.
  • Journal search filter — search supports j: / journal: prefix to filter by journal or booktitle.
  • fresh dev command — just fresh deletes config files to reproduce the first-run experience.
  • Improved onboarding — better first-run modal and config initialisation flow.

Fixed

  • Backspace now also triggers entry deletion (unified with Delete).
  • Config-related test fixed.