{"id":47941309,"url":"https://github.com/thicclatka/ublx","last_synced_at":"2026-05-08T02:39:12.334Z","repository":{"id":348409102,"uuid":"1148594381","full_name":"thicclatka/UBLX","owner":"thicclatka","description":"TUI to index once, enrich with metadata, and browse a flat snapshot in a 3-pane layout with multiple modes.","archived":false,"fork":false,"pushed_at":"2026-04-21T22:57:19.000Z","size":1149,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-22T00:37:37.837Z","etag":null,"topics":["analysis","database","file-viewer","metadata","tui","visualization"],"latest_commit_sha":null,"homepage":"https://github.com/thicclatka/UBLX","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thicclatka.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-03T06:21:54.000Z","updated_at":"2026-04-14T19:55:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/thicclatka/UBLX","commit_stats":null,"previous_names":["thicclatka/ublx"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/thicclatka/UBLX","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thicclatka%2FUBLX","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thicclatka%2FUBLX/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thicclatka%2FUBLX/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thicclatka%2FUBLX/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thicclatka","download_url":"https://codeload.github.com/thicclatka/UBLX/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thicclatka%2FUBLX/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32368537,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-27T20:07:02.737Z","status":"online","status_checked_at":"2026-04-28T02:00:07.250Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analysis","database","file-viewer","metadata","tui","visualization"],"created_at":"2026-04-04T08:07:11.499Z","updated_at":"2026-04-28T08:08:17.119Z","avatar_url":"https://github.com/thicclatka.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UBLX\n\n[![Crates.io](https://img.shields.io/crates/v/ublx.svg)](https://crates.io/crates/ublx)\n[![docs.rs](https://img.shields.io/docsrs/ublx)](https://docs.rs/ublx)\n![Build](https://github.com/thicclatka/ublx/workflows/Build/badge.svg)\n![Rust](https://img.shields.io/badge/rust-1.95-orange.svg)\n\n[_Ublx ... Safe when taken as directed._](https://bookshop.org/p/books/ubik-philip-k-dick/1fc432e3ade32290)\n\nUBLX is a **TUI that turns any directory into a flat, navigable catalog** — categories, previews, metadata, and templates in the terminal. (Driven by [nefaxer](https://github.com/thicclatka/nefaxer) and [zahirscan](https://github.com/thicclatka/zahirscan))\n\n**_Currently in development, expect breaking changes._**\n\n## Before you start\n\n- a terminal emulator with **truecolor** (24-bit color) \u0026 image support\n- Strongly recommend using a terminal with a [**Nerd Font**](https://github.com/ryanoasis/nerd-fonts)\n\n**Optional**:\n\n| Tool                   | Role                                                                                    |\n| ---------------------- | --------------------------------------------------------------------------------------- |\n| `tree`                 | Directory preview in the Viewer when on `PATH`                                          |\n| `pdftoppm` or `mutool` | PDF page raster preview                                                                 |\n| `ffmpeg`               | Video frame preview                                                                     |\n| `netcdf`/`libnetcdf`   | Default features link to NetCDF. To build without: `cargo build --no-default-features`. |\n\n## Install\n\n### Homebrew\n\n```bash\nbrew tap thicclatka/ublx https://github.com/thicclatka/ublx\nbrew install thicclatka/ublx/ublx\n```\n\n### Cargo\n\n```bash\ncargo install ublx\n\n# or compile from source\ncargo build --release\n\n# compile without netcdf\ncargo build --release --no-default-features\n```\n\n## What it does\n\n- **Index once, then browse** — One run updates the catalog; the prior index enables fast diffs. Per-root SQLite under your user cache (`ubli/`; stem is sanitized dir name plus path hash; extension matches the `ublx` package name). Config file names and paths: [Configuration](#configuration).\n- **Path catalog vs full metadata** — By default, indexing records **paths and filetype/category** hints (fast, lightweight). **ZahirScan** adds the rich **Zahir JSON** used for deep previews, Templates, Writing stats, and Metadata tables. Batch that with `enable_enhance_all`, scope it with **`[[enhance_policy]]`**, or run **Enhance with ZahirScan** on demand (quick actions / multi-select). Keys and behavior: [Configuration](#configuration).\n- **TUI** — Main tabs (left to right when all are shown): **Snapshot** | **Lenses** | **Delta** | **Duplicates** | **Settings** — **Lenses** and **Duplicates** appear only when the DB has lenses or duplicate groups. Three-pane layout and keys: [Modes](#modes) and [Panes overview](#panes-overview). Search across \u0026 within files, vim motions, theme selector, quick actions menu, command mode, toast notifications, fullscreen toggle.\n- **Snapshot-only** — Index without the TUI (`-s` / `--snapshot-only`; [Usage](#usage)).\n- **Export** — Pretty-printed Zahir JSON ([Usage](#usage)); Lenses converted to markdown.\n\n## Use case\n\nLooking for a file manager? Use [yazi](https://github.com/sxyazi/yazi) for that; where UBLX comes in:\n\n- Best for navigating and handling project directories that you frequent\n- Preview \u0026 extract filetype specific metadata without having to open a file\n- **For large directories**: can still get a quick understanding of filetypes contained without metadata enhancement\n\n## Modes\n\n| Tab            | Description                                                                                                                                                                                                                   |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Snapshot**   | From the current index: categories and file list; right pane shows Templates / Viewer / Metadata / Writing for the selected row.                                                                                              |\n| **Delta**      | Added / Mod / Removed since last snapshot; same 3-pane layout with overview in the right pane.                                                                                                                                |\n| **Lenses**     | Saved lists of items with a specific focus (e.g. a “lens” on a subset of files); left = lens names, middle = paths in the selected lens. Shown when the DB has at least one lens.                                             |\n| **Duplicates** | Groups of duplicate files by content hash; left = group names, middle = paths in the group. Run duplicate detection from [Command Mode](#context-menu-multi-select--command-mode) to populate; tab appears when groups exist. |\n| **Settings**   | Global vs local `ublx.toml`: theme, layout, `bg_opacity`, bool toggles (e.g. `show_hidden_files`, `run_snapshot_on_startup`), and more; **e** opens the active scope's file in `$EDITOR`.                                     |\n\nCycle main tabs with `~`.\n\n## Panes overview\n\nThe right pane shows Viewer, Templates, Metadata, or Writing for the selected item. **Tab** switches focus between the left (categories) and middle (contents) panes; **h** / **l** also focus left or middle.\n\n- **Focus a right-pane tab** — **v** (Viewer), **t** (Templates), **m** (Metadata), **w** (Writing). **Shift+Tab** cycles through right-pane tabs.\n- **Scroll in the preview** — **Shift+b** / **Shift+e** (jump to top/bottom), **Shift+↑** / **Shift+↓** or **Shift+K** / **Shift+J** (line by line).\n- **Viewer fullscreen** — **Shift+F** toggles fullscreen for the Viewer tab.\n- **Viewer search** — **Shift+S** opens literal in-pane search in the preview (see in-app help for n/N and Esc).\n- **Catalog search** — **/** fuzzy-filters the category and content lists (left and middle) by path/category. Press **Esc** to clear filter.\n\n| Tab           | Content                                                                                                                                                                                                                                                                                       |\n| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Viewer**    | Previews for the selected file — details in [Viewer Previews](#viewer-previews). Footer: size and last-modified when available.                                                                                                                                                               |\n| **Templates** | Extracted template/structure snippet (e.g. document outline) when zahirscan provides it.                                                                                                                                                                                                      |\n| **Metadata**  | Enrichment metadata as **tables**: key/value pairs, and for supported types from [ZahirScan metadata extraction by format](https://github.com/thicclatka/zahirscan#metadata-extraction-by-format). Sections are parsed from the stored zahirscan result and rendered with headers and scroll. |\n| **Writing**   | **Writing stats** (writing footprint): word count, character counts, and similar stats when zahirscan has computed them. Shown in the same table layout as Metadata.                                                                                                                          |\n\n### Viewer Previews\n\n- **Markdown** — formatted preview (headings, lists, code blocks, tables inside the doc).\n- **CSV-style files** — for `.csv`, `.tsv`, `.tab`, `.psv`, render a pretty table when parsed width is 30 columns or fewer; for wider files, render a structured delimited fallback that shows only viewport-fitting leading columns with row/column truncation counts (still keyed off index type or path match when category labels are off).\n- **Images** — terminal preview via [ratatui-image](https://github.com/ratatui-org/ratatui-image) (downscaled for the pane; larger files may decode off the UI thread; recent previews cached for quick navigation).\n- **Zarr directory (`.zarr`)** — show a directory tree of the store\n- **Code and structured text** — [syntect](https://github.com/trishume/syntect) highlighting via [`sublime_syntaxes`](https://crates.io/crates/sublime_syntaxes); grammar from path/extension; colors match theme light/dark. Large buffers are cached for smooth scrolling.\n- **Other text** — raw text (length-capped).\n- **Binaries** — short label instead of dumping bytes.\n- **Directories** — `tree` when available.\n\n## Context Menu, Multi-select, \u0026 Command Mode\n\n| Feature                          | Keys           | Notes                                                                                                                                                                                              |\n| -------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Quick actions** (context menu) | **Space**      | Actions for the current row: open, reveal in folder, enhance / lens / copy / rename / delete — depends on tab and row type.                                                                        |\n| **Multi-select**                 | **Ctrl+Space** | Toggles multi-select on the **contents** pane (**Snapshot** or **Lenses** only). While on: **Space** toggles selection on the current row; **a** opens the bulk menu; **Esc** leaves multi-select. |\n| **Command Mode**                 | **Ctrl+A**     | “Leader” — press a second key for a global action, or wait briefly to see a centered menu listing the letters below. Not available while the catalog search bar is active.                         |\n\n**Command Mode** second key (after **Ctrl+A**):\n\n| Key   | Action                                                   |\n| ----- | -------------------------------------------------------- |\n| **d** | Run duplicate detection (background)                     |\n| **t** | Theme selector (writes theme to local config on confirm) |\n| **s** | Take snapshot (background)                               |\n| **r** | Reload config from disk                                  |\n| **x** | Export Zahir JSON to `ublx-export/`                      |\n| **l** | Export lenses as Markdown to `ublx-lenses/`              |\n| **p** | Switch indexed project (recents / `ubli/` roots)         |\n\nPress **?** to open the full keybinding help.\n\n## Configuration\n\nConfig is optional. If present, **global** config is applied first, then **local** overrides from the indexed directory.\n\n| Platform      | Global config              | Config Cache                   |\n| ------------- | -------------------------- | ------------------------------ |\n| macOS / Linux | `~/.config/ublx/ublx.toml` | `~/.local/share/ublx/configs/` |\n| Windows       | `%APPDATA%\\ublx\\ublx.toml` | `%LOCALAPPDATA%\\ublx\\configs\\` |\n\n**Local** config (same on all platforms): `.ublx.toml` (default) or `ublx.toml` in the directory you index. Only keys present in each file override defaults.\n\n**Global-only keys**:\n\n| Key                       | Type              | Allowable values / notes                                                                                                                                                                     |\n| ------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `opacity_format`          | string (optional) | When `bg_opacity` \u0026lt; 1: OSC 11 payload style — `rgba` (default) or `hex8` (`#RRGGBBAA`). Some terminals prefer one or the other.                                                           |\n| `ask_enhance_on_new_root` | bool (optional)   | If `false`, skip the first-run “Enhance all files?” prompt and apply `enable_enhance_all` from config immediately. If `true` or omitted (default), show the prompt for a newly indexed root. |\n\n**Configurable keys** (global and/or local unless noted):\n\n| Key                       | Type                 | Allowable values / notes                                                                                                                                                                                                                                   |\n| ------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `theme`                   | string               | See [Themes](src/themes/README.md#allowable-values).                                                                                                                                                                                                       |\n| `layout`                  | table                | Pane widths: `left_pct`, `middle_pct`, `right_pct` (each 0–100; must sum to 100). Default: `left_pct = 10`, `middle_pct = 30`, `right_pct = 60`.                                                                                                           |\n| `bg_opacity`              | float (optional)     | Page background opacity `0.0`–`1.0`: main pane uses terminal default fill (OSC 11) below `1.0` so wallpaper can show through; omitted or `1.0` = solid theme background. Adjustable in Settings.                                                           |\n| `show_hidden_files`       | bool                 | If `true`, include hidden files (e.g. `.*`) in the index.                                                                                                                                                                                                  |\n| `hash`                    | bool                 | If `true`, compute blake3 hash per file (slower; used for duplicate detection and change detection).                                                                                                                                                       |\n| `exclude`                 | array of strings     | Extra path patterns to exclude from indexing (startup only; not hot-reloadable).                                                                                                                                                                           |\n| `editor_path`             | string               | Path to editor for “Open (Terminal)” (e.g. `\"vim\"`, `\"nvim\"`). When unset, uses `$EDITOR`.                                                                                                                                                                 |\n| `enable_enhance_all`      | bool                 | If `true`, full metadata for all files on snapshot. If `false` (default), only get path plus file-type/category until **Enhance with ZahirScan** per file.                                                                                                 |\n| `run_snapshot_on_startup` | bool (optional)      | Default `true` (omit = true): spawn a **background snapshot** when the TUI opens (unless first-run defers it) and when **switching indexed roots** in-session. Set `false` to skip those automatic runs and use the existing DB until you take a snapshot. |\n| `[[enhance_policy]]`      | TOML array of tables | Optional per-subtree rules (see below). Hot-reloadable with the rest of the overlay.                                                                                                                                                                       |\n\nAll of the above except **`exclude`** are **hot-reloadable** when set in a file that UBLX loads (global and/or local). The **global-only** keys in the previous table are hot-reloadable only via **global** config edits, not from local project files.\n\n**`[[enhance_policy]]`** — Each row has `path` (relative to the indexed directory, `/` separators, e.g. `src` or `photos/2024`) and `policy`:\n\n- **`auto`** — ZahirScan runs for files under that prefix when you take a snapshot (same idea as `enable_enhance_all = true`, but only for this subtree).\n- **`manual`** — No batch Zahir on snapshot for that subtree (same idea as `enable_enhance_all = false`): the catalog is path-only there until you **Enhance with ZahirScan** on specific files.\n\nThe **longest** `path` prefix that matches a file wins. If no row matches, **`enable_enhance_all`** applies globally.\n\n**Live reload** — A file watcher monitors **both** the indexed directory’s local config and the **global** config path; saving either file triggers a debounced reload. A successful parse applies the new merged settings immediately, and the valid merged overlay is written to the per-directory config cache. If the file is invalid, an error is shown and the last successful config saved in cache is used.\n\n## Usage\n\n```text\nUsage: ublx [OPTIONS] \u003cDIR\u003e\n\nArguments:\n  \u003cDIR\u003e  Directory to index (default: current directory)\n\nOptions:\n  -s, --snapshot-only  Headless snapshot. Writes a local config file when this dir has none\n  -e, --enhance-all    With `--snapshot-only`: set `enable_enhance_all = true` in new local config and use it for this run\n  -f, --full-snapshot  Same as `--snapshot-only --enhance-all`\n  -x, --export         Headless: write each Zahir JSON to `ublx-export/` as flat `{path}.json` files. Recommended to run with `--full-snapshot` to get most complete \u0026 recent results. Adjust enhance policy in config to fine-tune which paths get ZahirScan\n      --dev            Dev mode: tui-logger drain + `move_events` + trace-level default filter\n      --themes         Print available themes grouped by appearance\n  -V, --version        Print version\n  -h, --help           Print help\n```\n\n## License\n\nDual-licensed under [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthicclatka%2Fublx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthicclatka%2Fublx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthicclatka%2Fublx/lists"}