Files
2026-10-02 15:29:35 +02:00

9.1 KiB
Raw Permalink Blame History

sjaur

Fast, fuzzy TUI search for the Arch User Repository and the official Arch Linux repositories — with real package installation, built on the official AUR metadata dump and your local pacman sync databases.

┌ Search: firfox ────────────────────────────────────────────────────────┐
├──────────────────────────────────────┬─────────────────────────────────┤
│ firefox              130.0-1  +3500  │ Name         firefox            │
│ firefox-nightly      131.0b1 +120    │ Version      130.0-1            │
│ firefox-wayland      129.0   +90     │ Maintainer   jonas              │
│ …                                    │ Votes        3500               │
│                                      │ Popularity   214.53             │
│                                      │ …                               │
├──────────────────────────────────────┴─────────────────────────────────┤
│ 9 results · 24 ms · cache 2.1 hours old                                │
└────────────────────────────────────────────────────────────────────────┘

Typo-tolerant ranking across name, description, maintainer, keywords, provides, and dependency fields — all served from a local snapshot, so searching never touches the network.

Install

cd sjaur
python -m venv .venv
.venv/bin/pip install .

Then link the executable onto your PATH (or copy it):

sudo ln -s "$(pwd)/.venv/bin/sjaur" /usr/local/bin/sjaur
# or, without root:
mkdir -p ~/.local/bin && ln -s "$(pwd)/.venv/bin/sjaur" ~/.local/bin/sjaur

Requirements: Python ≥ 3.10 and Linux (deps: rapidfuzz, textual).

Usage

sjaur              # launch the TUI
sjaur --update     # force a metadata refresh, then exit
sjaur --version
sjaur --help

Optional:

  • --cache-dir <dir> overrides the cache location (default ~/.cache/sjaur)
  • --no-repos searches the AUR only (skip official repository packages)
  • --repos-dir <dir> overrides the pacman sync database directory (default /var/lib/pacman/sync)

Official repository packages

By default, sjaur merges the packages of your local pacman sync databases (core, extra, …) into the search index. They appear with a repository badge (firefox [extra]), can be installed directly via sudo pacman -S <name> (i in the TUI — no build step, pacman asks for confirmation), and work with all search features including @maintainer (the packager email is used, e.g. @heftig). Votes, popularity, and out-of-date status are AUR-only concepts and are hidden for repo packages.

The databases are read-only and stay where pacman manages them; run pacman -Sy as usual to refresh them. On systems without sync databases, sjaur falls back to AUR-only search with a warning.

Search syntax

Query Meaning
firefox fuzzy search across all package fields
@max_musterman fuzzy-search the maintainer field
@max_musterman firefox maintainer search combined with a normal search
@john python editor maintainer query is john; python editor is the normal query

Rules:

  • Only the first whitespace-delimited word after @ is the maintainer query; everything after it is the normal search.
  • Matching stays fuzzy: @max_musterman also finds max_mustermann, max-musterman or max_musterman123 — no exact match required.
  • With @, the result score is maintainer_similarity × 0.65 + package_score × 0.35, so maintainer matches dominate while the text query still orders the results.
  • The parser is table-driven, so future operators (e.g. #keyword, depends:python) can be added without touching the search engine.

Results update while you type — no Enter needed:

  1. On every keystroke the current list is instantly narrowed client-side (packages that no longer match disappear immediately).
  2. After a short pause (0.18 s), the full fuzzy search over all fields runs in the background and refines the list.

Editing or retyping a recent query restores its result set instantly from an in-memory cache; the status line shows live while you are typing and the measured search time once the background search has finished.

Keys

Key Action
typing live search — results update on every keystroke
↑ / ↓ navigate results
enter open package details (esc returns)
i / ctrl+i install the selected package
tab / shift+tab switch between search field and results
page up / page down, home / end scroll / jump
ctrl+r reload AUR metadata now
f1 help overlay
esc clear search / leave current view
ctrl+c quit

Installing packages

With a package highlighted, press i (or ctrl+i) and confirm with y. sjaur then runs the classic AUR workflow with plain system tools:

  1. Clone the package repository from https://aur.archlinux.org/<name>.git into ~/.cache/sjaur/build/<name> (an existing clone is reused; confirm with u instead of y to hard-reset and update it first).
  2. Review the PKGBUILD — it is printed to the terminal, and you can open it in $EDITOR before deciding. Always read it: the AUR ships user-produced build scripts.
  3. Build & install via makepkg --syncdeps --install. pacman's confirmation, the sudo password prompt, and the whole build output appear directly in your terminal; the TUI suspends and resumes afterwards.

The result is reported in the terminal; press Enter to return to sjaur. If anything fails (clone error, dependency problem, aborted build), the message explains what happened and the TUI keeps running.

Security note: AUR packages are user-produced content. sjaur shows the PKGBUILD (and any bundled install scripts) before building — never install packages whose build steps you do not understand.

Package details

Selecting a package shows everything the local snapshot knows — name, version, description, maintainer, votes, popularity, last modified, out-of-date status, upstream URL, AUR page, licenses, groups, keywords, depends, makedepends, checkdepends, optdepends, provides, conflicts, replaces — without any additional network request.

Cache behavior

sjaur keeps a decompressed copy of the official extended metadata dump (https://aur.archlinux.org/packages-meta-ext-v1.json.gz) in:

~/.cache/sjaur/packages-meta-ext-v1.json
  • At startup the cache's modification time is checked; if it is younger than 24 hours it is used as-is, otherwise a fresh dump is downloaded.
  • The replacement is atomic: the dump is downloaded to a temporary file, decompressed, validated as JSON, and only then swapped in with os.replace. A failed download never destroys a working cache.
  • If the download fails but a (stale) cache exists, the old cache is used and a warning is shown. If there is no usable cache at all, sjaur exits with a clear error.
  • SJAUR_CACHE_DIR overrides the cache directory (XDG XDG_CACHE_HOME is respected).

Development

python -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest          # run the test suite
.venv/bin/mypy src        # type-check

Project layout:

sjaur/
├── src/sjaur/
│   ├── cli.py         argument parsing and startup flow
│   ├── cache.py       download / decompress / validate / atomic replace
│   ├── metadata.py    typed Package model, tolerant dump parsing
│   ├── repodb.py      local pacman sync database reader
│   ├── query.py       extensible query parser (@maintainer, …)
│   ├── search.py      fuzzy scoring and ranking engine
│   ├── installer.py   clone / review / makepkg / pacman install workflow
│   ├── config.py      paths and constants
│   ├── errors.py      user-facing error types
│   └── tui/           Textual application, detail view
└── tests/

License

MIT — see LICENSE.