9.1 KiB
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-repossearches 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_mustermanalso findsmax_mustermann,max-mustermanormax_musterman123— no exact match required. - With
@, the result score ismaintainer_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.
Live search
Results update while you type — no Enter needed:
- On every keystroke the current list is instantly narrowed client-side (packages that no longer match disappear immediately).
- 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:
- Clone the package repository from
https://aur.archlinux.org/<name>.gitinto~/.cache/sjaur/build/<name>(an existing clone is reused; confirm withuinstead ofyto hard-reset and update it first). - Review the PKGBUILD — it is printed to the terminal, and you can open
it in
$EDITORbefore deciding. Always read it: the AUR ships user-produced build scripts. - 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,
sjaurexits with a clear error. SJAUR_CACHE_DIRoverrides the cache directory (XDGXDG_CACHE_HOMEis 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.