{"id":34094520,"url":"https://github.com/mpryor/nothing-less","last_synced_at":"2026-04-01T18:59:02.958Z","repository":{"id":316433249,"uuid":"1058835333","full_name":"mpryor/nothing-less","owner":"mpryor","description":"A TUI pager with advanced support for tabular data, inferring/swapping delimiters, and real-time event parsing. ","archived":false,"fork":false,"pushed_at":"2026-03-27T13:26:08.000Z","size":1038,"stargazers_count":106,"open_issues_count":16,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-03-27T23:56:50.956Z","etag":null,"topics":["cli","datawrangling","devops-tools","json","kubernetes","python","spreadsheet","tabular-data","terminal","terminal-based","textual","tsv","tui"],"latest_commit_sha":null,"homepage":"https://mpryor.github.io/nothing-less/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mpryor.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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":"2025-09-17T16:01:09.000Z","updated_at":"2026-03-27T15:05:38.000Z","dependencies_parsed_at":"2025-09-24T16:22:29.433Z","dependency_job_id":"e435c6ec-72e5-4b6d-ba16-75d1e0a15890","html_url":"https://github.com/mpryor/nothing-less","commit_stats":null,"previous_names":["mpryor/nothing-less"],"tags_count":53,"template":false,"template_full_name":null,"purl":"pkg:github/mpryor/nothing-less","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpryor%2Fnothing-less","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpryor%2Fnothing-less/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpryor%2Fnothing-less/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpryor%2Fnothing-less/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mpryor","download_url":"https://codeload.github.com/mpryor/nothing-less/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpryor%2Fnothing-less/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290992,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cli","datawrangling","devops-tools","json","kubernetes","python","spreadsheet","tabular-data","terminal","terminal-based","textual","tsv","tui"],"created_at":"2025-12-14T15:03:50.139Z","updated_at":"2026-04-01T18:59:02.950Z","avatar_url":"https://github.com/mpryor.png","language":"Python","readme":"\u003ch1 align=\"center\"\u003enless\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eexcel for your logs\u003c/strong\u003e — pipe in **anything**, wrangle it into columns.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/assets/demo.webp\" width=\"800px\" alt=\"nless demo — search, filter, sort, and pivot streaming K8s events\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.org/project/nothing-less/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/nothing-less\" alt=\"PyPI\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/nothing-less/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/pyversions/nothing-less\" alt=\"Python\"/\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License: MIT\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/mpryor/nothing-less/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/mpryor/nothing-less/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://mpryor.github.io/nothing-less/\"\u003eDocumentation\u003c/a\u003e ·\n  \u003ca href=\"https://mpryor.github.io/nothing-less/tutorials/\"\u003eTutorials\u003c/a\u003e ·\n  \u003ca href=\"https://mpryor.github.io/nothing-less/keybindings/\"\u003eKeybindings\u003c/a\u003e ·\n  \u003ca href=\"#installation\"\u003eInstall\u003c/a\u003e\n\u003c/p\u003e\n\n**nless** is a TUI pager for exploring and analyzing tabular data with vi-like keybindings, built on [Textual](https://textual.textualize.io/). Pipe in anything and nless infers the structure so you can filter, sort, pivot, and reshape without config. Works with CSV, TSV, JSON, logs, and any delimited output.\n\n## Installation\n\n```bash\npipx install nothing-less\n```\n\nor\n\n```bash\nbrew install mpryor/tap/nless\n```\n\nRequires Python 3.13+ for pipx/pip installs. You can also use `pip install nothing-less` if you prefer. The Homebrew formula manages its own Python dependency.\n\n## Usage\n\n```bash\nkubectl get events -w | nless    # stream K8s events\ncat access.log | nless           # explore log files\nnless data.csv                   # open CSV directly\nnless \u003c output.json              # redirect a file\n```\n\nPress `?` inside nless to view all keybindings.\n\n## Demos\n\n\u003cdetails\u003e\n\u003csummary\u003eCSV — open, search, filter, sort, pivot\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/assets/demo-csv.webp\" width=\"800px\" alt=\"nless CSV demo — open a file, search, filter, sort, and pivot\"/\u003e\n\u003c/p\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eJSON — pipe in API responses, auto-detect keys as columns\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/assets/demo-json.webp\" width=\"800px\" alt=\"nless JSON demo — auto-detect JSON keys as columns\"/\u003e\n\u003c/p\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eRegex — parse raw logs into columns with named capture groups\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/assets/demo-regex.webp\" width=\"800px\" alt=\"nless regex demo — parse raw logs into structured columns\"/\u003e\n\u003c/p\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003ePipe mode — use nless as a pipeline stage\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/assets/demo-pipe.webp\" width=\"800px\" alt=\"nless pipe mode — filter, transform, and output as JSON\"/\u003e\n\u003c/p\u003e\n\n\u003c/details\u003e\n\n## Why nless?\n\nI frequently need to explore streaming tabular data: server logs, kubectl output, CSV exports, CI pipelines. None of the existing tools had exactly the feature set I wanted, so I built nless.\n\n- **Zero config** — pipe in anything and nless infers the structure.\n- **Stream-native** — built for data that's still arriving, with streaming features like tail mode, arrival timestamps, and time window filtering.\n- **Vi-native** — if you know Vim, nless should feel familiar. If you don't, choose from the other built-in keymaps or build your own. \n- **Mouse-friendly** — click column headers to sort, double-click pivot rows to drill in, right-click for context menus, navigate via the menu bar.\n- **One tool, many formats** — CSV, TSV, JSON, space-aligned, regex, raw. Switch between them without leaving the pager.\n\n## Features\n\n- **Delimiter inference \u0026 swapping** — auto-detects CSV, TSV, space-aligned, JSON, and more. Swap with `D`, or use regex with named capture groups.\n- **Filtering \u0026 searching** — filter by column, cell value, or search match. Exclude rows. Full-text search with match navigation.\n- **Sorting \u0026 pivoting** — one-key sort on any column. Group by composite key with summary view and drill-in.\n- **Streaming \u0026 tail mode** — live-updating as new data arrives, with arrival timestamps and time window filtering.\n- **JSON \u0026 log parsing** — extract nested JSON fields into columns. Parse unstructured logs with regex.\n- **Pipe mode** — use nless as a pipeline stage with `Q` to pipe and exit, or `--no-tui` for batch mode.\n\n\u003cdetails\u003e\n\u003csummary\u003eAll features\u003c/summary\u003e\n\n- **Buffers** — mutating actions create a new buffer, letting you jump up and down your analysis history.\n- **Delimiter swapping** — swap between CSV, TSV, space-aligned, JSON, regex with named capture groups, and raw mode with `D`.\n- **Column delimiters** — split a column into more columns using JSON, regex, or string delimiters with `d`.\n- **Filtering** — filter by column (`f`/`F`), exclude (`e`/`E`), across all columns (`|`), or from a search (`\u0026`).\n- **Sorting** — toggle ascending/descending sort on any column with `s`.\n- **Searching** — search (`/`), search by cell value (`*`), navigate matches (`n`/`p`).\n- **Pivoting** — group records by composite key with `U`, focused summary view, dive into grouped data with `enter`.\n- **Column management** — show/hide columns (`C`), reorder columns (`\u003c`/`\u003e`).\n- **JSON extraction** — promote nested JSON fields to columns with `J`.\n- **Shell commands** — run a shell command and pipe its output into a new buffer with `!`.\n- **Tail mode** — keep the cursor at the bottom as new data arrives with `t`.\n- **Output** — write buffer contents to a file or stdout (`W`), copy cell values (`y`).\n- **Themes** — 10 built-in color themes (Dracula, Nord, Gruvbox, etc.) plus custom theme support, switch with `T`.\n- **Arrival timestamps** — every row records when it was received. Toggle the `_arrival` column with `A`.\n- **Time window filtering** — show only recent rows with `@` (e.g. `5m`, `1h`). Append `+` for rolling windows. Prefix with a column name to filter by parsed timestamps (e.g. `timestamp 5m`).\n- **Timestamp parsing \u0026 conversion** — auto-detects datetime columns (epoch, ISO 8601, syslog, etc.) for type-aware sorting. Convert formats with `@colname -\u003e target` (epoch, iso, relative, strftime, with optional timezone conversion). Also available from the CLI with `--format-timestamp` / `-F` for batch pipelines.\n- **Raw pager mode** — `--raw` or auto-detected. A fast virtual-rendering pager for unstructured text, handling million-line files without columnar overhead.\n- **Excluded lines** — view lines that failed to parse or were removed by filters with `~`, with chained accumulation across buffers.\n- **Pipe mode** — use nless as a pipeline stage. Interactive exploration with `Q` to pipe and exit, batch mode with `--no-tui`, or `--tui` to force interactive mode.\n- **Mouse support** — click column headers to sort, double-click pivot rows to drill in, right-click for context menus, navigate via the menu bar.\n- **Merge files** — combine multiple files into a single view with a `_source` column using `--merge`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eFull keybinding reference\u003c/summary\u003e\n\n**Buffers**:\n- `[1-9]` - select the buffer at the corresponding index\n- `L` - select the next buffer\n- `H` - select the previous buffer\n- `q` - close the current active buffer, or the program if all buffers are closed\n- `Q` - pipe current buffer to stdout and exit immediately (pipe mode shortcut)\n- `N` - create a new buffer from the original data\n- `r` - rename the current buffer\n- `M` - merge the current buffer with another buffer\n\n**Groups**:\n- `}` - switch to the next buffer group\n- `{` - switch to the previous buffer group\n- `R` - rename the current group\n- `O` - open a file in a new buffer group\n\n**Navigation**:\n- `h` - move cursor left\n- `l` - move cursor right\n- `j` - move cursor down\n- `k` - move cursor up\n- `0` - jump to first column\n- `$` - jump to final column\n- `g` - jump to first row\n- `G` - jump to final row\n- `w` - move cursor right\n- `b`/`B` - move cursor left\n- `ctrl+u` - page up\n- `ctrl+d` - page down\n- `c` - select a column to jump the cursor to\n\n**Column visibility**:\n- `C` - prompt for a regex filter to selectively display columns, or `all` to see all columns\n- `m` - pin or unpin the current column to the left side of the screen\n- `\u003e` - move the current column one to the right\n- `\u003c` - move the current column one to the left\n- `A` - toggle the `_arrival` metadata column showing when each row was received\n\n**Pivoting**:\n- `U` - mark the selected column as part of a composite key to group records by, adding a `count` column pinned to the left\n- `enter` - while over a composite key column, dive into the data behind the pivot\n\n**Filtering**:\n- `f` - filter the current column and prompt for a filter\n- `F` - filter the current column by the highlighted cell\n- `e` - exclude from the current column and prompt for a value\n- `E` - exclude the current column by the highlighted cell\n- `|` - filter ALL columns and prompt for a filter\n- `\u0026` - apply the current search as a filter across all columns\n- `@` - set a time window to show only recent rows (e.g. `5m`, `1h`); append `+` for rolling; prefix with column name for column-based filtering (e.g. `timestamp 5m`); use `-\u003e` for format conversion (e.g. `timestamp -\u003e relative`)\n\n**Searching \u0026 Highlighting**:\n- `/` - prompt for a search value and jump to the first match\n- `*` - search all columns for the current highlighted cell value\n- `n` - jump to the next match\n- `p` - jump to previous match\n- `+` - pin the current search as a persistent highlight\n- `-` - navigate or manage pinned highlights\n\n**Output**:\n- `W` - prompt for a file to write the current buffer to (`-` writes to stdout)\n- `y` - copy the contents of the currently highlighted cell to the clipboard\n\n**Shell Commands**:\n- `!` - run a shell command and pipe its output into a new buffer\n\n**Tail Mode**:\n- `t` - toggle tail mode\n- `x` - reset new-line highlights\n\n**Sessions \u0026 Views**:\n- `S` - open the session menu (save, load, rename, delete)\n- `v` - open the view menu (save, load, rename, delete)\n\n**Themes \u0026 Keymaps**:\n- `T` - open the theme selector\n- `K` - open the keymap selector\n\n**Excluded Lines**:\n- `~` - view excluded lines (parse failures + filtered rows), with chained accumulation\n\n**Sorting \u0026 Aggregations**:\n- `s` - toggle ascending/descending sort on the current column\n- `a` - show column aggregations (count, distinct, sum, avg, min, max)\n\n**JSON**:\n- `J` - select a JSON field under the current cell to add as a column\n\n**Delimiter/file parsing**:\n- `D` - swap the delimiter on the fly (common delimiters, regex with named capture groups, `raw`, `json`, or `  ` for double-space aligned output like kubectl)\n- `d` - split a column into more columns using a columnar delimiter (`json`, regex with named capture groups, or any string)\n- `P` - auto-detect a known log format and apply it as a regex delimiter\n\n**Help**:\n- `?` - show the help screen with all keybindings\n\n**Mouse**:\n- Left-click column headers to sort\n- Double-click pivot rows to drill in\n- Right-click cells, headers, tabs, or groups for context menus\n- Click buffer tabs or group bar to switch\n- Menu bar for mouse-driven access to all actions\n\nSee the [full keybinding reference](https://mpryor.github.io/nothing-less/keybindings/) and [tutorials](https://mpryor.github.io/nothing-less/tutorials/) for more.\n\n\u003c/details\u003e\n\n## Contributing\n\nContributions are welcome! See the [contributing guidelines](CONTRIBUTING.md) for details.\n\n## Alternatives\n\nIf nless doesn't have what you need, check out these other great tools:\n\n| | [nless](https://github.com/mpryor/nothing-less) | [VisiData](https://www.visidata.org/) | [csvlens](https://github.com/YS-L/csvlens) | [lnav](https://github.com/tstack/lnav) | [Toolong](https://github.com/Textualize/toolong) |\n|---|:---:|:---:|:---:|:---:|:---:|\n| **Focus** | Tabular data pager | Data multitool | CSV viewer | Log navigator | Log viewer |\n| **Language** | Python | Python | Rust | C++ | Python |\n| Streaming / stdin | :white_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :white_check_mark: | :white_check_mark: |\n| Delimiter inference | :white_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :x: | :x: |\n| Vi keybindings | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |\n| Filtering | :white_check_mark: | :white_check_mark: | :heavy_minus_sign: | :white_check_mark: | :x: |\n| Sorting | :white_check_mark: | :white_check_mark: | :white_check_mark: | :heavy_minus_sign: | :x: |\n| Pivoting / grouping | :white_check_mark: | :white_check_mark: | :x: | :heavy_minus_sign: | :x: |\n| JSON parsing | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :heavy_minus_sign: |\n| Log format detection | :white_check_mark: | :x: | :x: | :white_check_mark: | :heavy_minus_sign: |\n| Regex column parsing | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: |\n| Pipe mode | :white_check_mark: | :white_check_mark: | :heavy_minus_sign: | :heavy_minus_sign: | :x: |\n| Raw text pager | :white_check_mark: | :heavy_minus_sign: | :x: | :white_check_mark: | :white_check_mark: |\n| Themes | :white_check_mark: | :white_check_mark: | :heavy_minus_sign: | :white_check_mark: | :x: |\n| SQL queries | :x: | :x: | :x: | :white_check_mark: | :x: |\n| Python expressions | :x: | :white_check_mark: | :x: | :x: | :x: |\n| Timestamp parsing | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: |\n| Multi-file merge | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: |\n\n:white_check_mark: full support · :heavy_minus_sign: partial · :x: not supported\n","funding_links":[],"categories":["Data Manipulation"],"sub_categories":["Professional: Resume"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpryor%2Fnothing-less","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmpryor%2Fnothing-less","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpryor%2Fnothing-less/lists"}