{"id":13906248,"url":"https://github.com/pamburus/hl","last_synced_at":"2026-01-24T03:18:01.469Z","repository":{"id":38297355,"uuid":"284906876","full_name":"pamburus/hl","owner":"pamburus","description":"A fast and powerful log viewer and processor that translates JSON or logfmt logs into a pretty human-readable format.","archived":false,"fork":false,"pushed_at":"2024-10-29T21:46:31.000Z","size":8962,"stargazers_count":251,"open_issues_count":5,"forks_count":10,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-29T21:47:21.109Z","etag":null,"topics":["cli","command-line-tool","hl","human","json","json-log","json-logging","json-logs","log","log-viewer","logging","logs","rust","structured-logging","translates-json-logs","viewer"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/pamburus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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}},"created_at":"2020-08-04T07:19:46.000Z","updated_at":"2024-10-29T21:44:37.000Z","dependencies_parsed_at":"2023-11-26T12:24:57.138Z","dependency_job_id":"29f818c2-4896-4d26-a1b3-ec9c025e71aa","html_url":"https://github.com/pamburus/hl","commit_stats":null,"previous_names":[],"tags_count":140,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pamburus%2Fhl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pamburus%2Fhl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pamburus%2Fhl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pamburus%2Fhl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pamburus","download_url":"https://codeload.github.com/pamburus/hl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226344589,"owners_count":17610172,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","command-line-tool","hl","human","json","json-log","json-logging","json-logs","log","log-viewer","logging","logs","rust","structured-logging","translates-json-logs","viewer"],"created_at":"2024-08-06T23:01:31.993Z","updated_at":"2026-01-24T03:18:01.463Z","avatar_url":"https://github.com/pamburus.png","language":"Rust","readme":"# hl [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![Release][release-img]][release]\n\n[![banner](doc/banner.svg)](#screenshot)\n\nHigh-performance log viewer and processor that transforms logs in JSON and logfmt formats into a human-readable output. Built with efficiency in mind, it enables quick parsing and analysis of large log files with minimal overhead.\n\n## Features overview\n\n* __[Automatic Pager Integration](#automatic-usage-of-pager)__: Automatically integrates with a pager for enhanced convenience, defaulting to [less](https://greenwoodsoftware.com/less/) if available, but fully supporting any compatible pager.\n* __Log Streaming Mode__: Enable log streaming with the `-P` flag, which disables the pager.\n* __[Field-Based Filtering](#filtering-by-field-values)__: Filter log records by key/value pairs using the `-f` option, with support for hierarchical keys.\n* __[Level Filtering](#quick-filtering-by-log-level)__: Easily filter logs by level with the `-l` option.\n* __[Timestamp Range Filtering](#filtering-by-time-range)__: Filter logs by timestamp range using the `--since` and `--until` options with intuitive formats:\n  * RFC-3339 timestamp format.\n  * Current configured timestamp output format (via the `-t` option or environment variable).\n  * User-friendly shortcuts like `today`, `yesterday`, `friday`, or relative offsets such as `-3h` or `-14d`.\n* __[Field Visibility Control](#hiding-or-revealing-selected-fields)__: Quickly hide or reveal specific fields using the `-h` option.\n* __Empty Field Hiding__: Automatically hide empty fields with the `-e` flag.\n* __Field Expansion__: Control multi-line field and message formatting with the `-x` option:\n  * `never`: Compact single-line output with escaped newlines.\n  * `inline`: Preserve newlines as-is in the output.\n  * `auto`: Automatically expand fields containing multi-line content.\n  * `always`: Expand all fields into structured multi-line format.\n* __[High-Speed Message Sorting](#sorting-messages-chronologically)__: Achieve lightning-fast message sorting with automatic indexing via the `-s` flag.\n  * Performs the initial scan at approximately 2 GiB/s, enabling rapid filtering by timestamp and level without re-scanning.\n  * Efficiently handles hundreds of local files totaling hundreds of gigabytes.\n  * Reindexes large, growing files at speeds up to roughly 10 GiB/s by skipping unmodified blocks.\n* __[Live Follow Mode](#sorting-messages-chronologically-with-following-the-changes)__: Use the `-F` flag for live, timestamp-sorted message updates across multiple sources, with a preview of recent messages via the `--tail` option.\n* __[Complex Query Support](#performing-complex-queries)__: Construct custom queries with logical conditions (AND/OR) and additional advanced filtering options.\n* __Non-JSON Prefix Handling__: Process logs with non-JSON prefixes using the `--allow-prefix` flag.\n* __Timezone Flexibility__: Displays timestamps in UTC by default while allowing effortless timezone switching with the `-Z` option or local timezone adjustments using the `-L` flag.\n* __Customizability and Themes__: Fully customizable through [configuration files](#configuration-files) and environment variables, with support for easy [theme switching](#selecting-current-theme) and custom [themes](#custom-themes).\n\n## Performance comparison chart\n\n### Performance comparison with [humanlog](https://github.com/humanlogio/humanlog), [hlogf](https://github.com/ssgreg/hlogf) and [fblog](https://github.com/brocode/fblog) on a 2.3 GiB log file\n\n![performance chart](doc/performance-chart.svg)\n\n* See [performance](#performance) section for more details.\n\n## Installation options\n\n### macOS\n\n* Install using [homebrew](https://brew.sh) on macOS\n\n    ```sh\n    brew install hl\n    ```\n\n\u003cdetails\u003e\n\u003csummary\u003eOther options\u003c/summary\u003e\n\n* Download and extract using `curl` and `tar` on macOS\n\n    ```sh\n    curl -sSfL https://github.com/pamburus/hl/releases/latest/download/hl-macos.tar.gz | tar xz\n    ```\n\n* Install using [cargo](https://www.rust-lang.org/tools/install)\n\n    ```sh\n    cargo install --locked --git https://github.com/pamburus/hl.git\n    ```\n\n* Download latest release from [download page](https://github.com/pamburus/hl/releases/latest)\n\n\u003c/details\u003e\n\n### Linux\n\n* Download and extract using `curl` and `tar` on Linux (x86_64)\n\n    ```sh\n    curl -sSfL https://github.com/pamburus/hl/releases/latest/download/hl-linux-x86_64-musl.tar.gz | tar xz\n    ```\n\n* Install [hl package](https://archlinux.org/packages/extra/x86_64/hl/) from Arch Linux extra repository\n\n    ```sh\n    pacman -S hl\n    ```\n\n\u003cdetails\u003e\n\u003csummary\u003eOther options\u003c/summary\u003e\n\n* Download and extract using `curl` and `tar` on Linux (arm64/aarch64)\n\n    ```sh\n    curl -sSfL https://github.com/pamburus/hl/releases/latest/download/hl-linux-arm64-musl.tar.gz | tar xz\n    ```\n\n* Install using [cargo](https://www.rust-lang.org/tools/install)\n\n    ```sh\n    cargo install --locked --git https://github.com/pamburus/hl.git\n    ```\n\n\u003c/details\u003e\n\n### Windows\n\n* Install from [Scoop](https://scoop.sh)\n\n    ```sh\n    scoop bucket add pamburus https://github.com/pamburus/scoop-bucket.git\n    scoop install hl\n    ```\n\n\u003e [!TIP]\n\u003e It is recommended to use [Windows Terminal](https://aka.ms/terminal) for better experience.\n\n\u003e [!TIP]\n\u003e To make mouse scrolling work in the [less](https://www.greenwoodsoftware.com/less/) pager, set the `LESS` environment variable to `-R --mouse`.\n\n\u003e [!IMPORTANT]\n\u003e Currently, `hl` does not provide a built-in pager and relies on external pagers such as [less](https://www.greenwoodsoftware.com/less/).\n\u003e However, the [build for Windows]([https://github.com/jftuga/less-Windows]) referenced on the original [download page](https://www.greenwoodsoftware.com/less/download.html) and distributed in the [WinGet](https://winget.run/pkg/jftuga/less) package manager does not work as expected.\n\u003e The authors state that they have not tested or verified this build and suggest that you use it at your own risk.\n\u003e Unfortunately, this build breaks some ANSI escape sequences and does not work properly with `hl` and many other programs that use ANSI escape sequences for colors and styles.\n\u003e It is recommended to install [less](https://www.greenwoodsoftware.com/less/) from the [Scoop](https://scoop.sh) or [Chocolatey](https://chocolatey.org/) package manager.\n\u003e If you are using [Scoop](https://scoop.sh) and install `hl` by running `scoop install hl`, it already installs [less](https://www.greenwoodsoftware.com/less/) automatically as a dependency. Just make sure you do not have any other conflicting installations by running `where less` in cmd or `Get-Command less` in powershell.\n\n* Download latest release from [download page](https://github.com/pamburus/hl/releases/latest)\n\n\u003cdetails\u003e\n\u003csummary\u003eOther options\u003c/summary\u003e\n\n* Install using [cargo](https://www.rust-lang.org/tools/install)\n\n    ```sh\n    cargo install --locked --git https://github.com/pamburus/hl.git\n    ```\n\n\u003c/details\u003e\n\n### NixOS\n\n* Run using [nix](https://nixos.org/download/)\n\n  ```sh\n  nix run github:pamburus/hl\n  ```\n\n  or binary package\n\n  ```sh\n  nix run github:pamburus/hl#bin\n  ```\n\n  or install with [nix profile](https://nix.dev/manual/nix/2.31/command-ref/new-cli/nix3-profile-add):\n\n  ```sh\n  nix profile add github:pamburus/hl\n  ```\n\n  or binary package\n\n  ```sh\n  nix profile add github:pamburus/hl#bin\n  ```\n\n* Install the package from source using [nix-flakes](https://wiki.nixos.org/wiki/Flakes)\n\n  \u003cdetails\u003e\n  \u003csummary\u003eExample how to update nix configuration\u003c/summary\u003e\n\n  ```nix\n  {\n    inputs = {\n      nixpkgs.url = \"github:NixOS/nixpkgs/nixos-25.05\";\n      hl.url = \"github:pamburus/hl\";\n    };\n    outputs = {nixpkgs, hl, ...}:\n    let\n      system = \"x86_64-linux\";\n    in\n    {\n      # this is just an example!\n      nixosConfigurations.yourHost = nixpkgs.lib.nixosSystem {\n        inherit system;\n        modules = [\n          ({...}: {\n            environment.systemPackages = [\n              hl.packages.${system}\n            ];\n          })\n        ];\n      };\n    };\n  }\n  ```\n\n  \u003c/details\u003e\n\n* Install the package with pre-built binaries using [nix-flakes](https://wiki.nixos.org/wiki/Flakes)\n\n  \u003cdetails\u003e\n  \u003csummary\u003eExample how to update nix configuration\u003c/summary\u003e\n\n  ```nix\n  {\n    inputs = {\n      nixpkgs.url = \"github:NixOS/nixpkgs/nixos-25.05\";\n      hl.url = \"github:pamburus/hl\";\n    };\n    outputs = {nixpkgs, hl, ...}:\n    let\n      system = \"x86_64-linux\";\n    in\n    {\n      # this is just an example!\n      nixosConfigurations.yourHost = nixpkgs.lib.nixosSystem {\n        inherit system;\n        modules = [\n          ({...}: {\n            environment.systemPackages = [\n              hl.packages.${system}.bin\n            ];\n          })\n        ];\n      };\n    };\n  }\n  ```\n\n  \u003c/details\u003e\n\n## Examples\n\n### Screenshot\n\n\u003cp align=\"center\"\u003e\n    \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/pamburus/hl-extra/37b444fcd812563963631071af581445851aa86e/screenshot/uni/dark.svg\" /\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/pamburus/hl-extra/37b444fcd812563963631071af581445851aa86e/screenshot/uni/light.svg\" /\u003e\n    \u003cimg alt=\"screenshot\" src=\"https://hl-uni.tiiny.site/dark.svg\" /\u003e\n    \u003c/picture\u003e\n\u003c/p\u003e\n\nSee other [screenshots](https://github.com/pamburus/hl-extra/blob/37b444fcd812563963631071af581445851aa86e/screenshot/README.md#current-mode)\n\n## Features and usage\n\n### Concatenation of multiple log files\n\n* Concatenate all log files\n\n    Command\n\n    ```sh\n    hl *.log\n    ```\n\n    Concatenates and displays all `*.log` files found in the current directory.\n\n### Support for compressed (bzip2, gzip, xz, zstd) log files\n\n* Concatenate all log files including compressed log files\n\n    Command\n\n    ```sh\n    hl $(ls -tr /var/log/example/*.{log,log.gz,log.zst,s})\n    ```\n\n    Concatenates and displays all `*.log`, `*.log.gz`, `*.log.zst` and `*.s` (will detect compression) files found in `/var/log/example/`.\n\n### Automatic usage of pager\n\n* Use the default pager with the default parameters\n\n    Command\n\n    ```sh\n    hl example.log\n    ```\n\n    Automatically opens `less` pager with the default parameters.\n\n* Override options for default pager\n\n    Command\n\n    ```sh\n    LESS=-SR hl example.log\n    ```\n\n    Opens `less` pager with disabled line wrapping.\n\n* Use custom pager\n\n    Command\n\n    ```sh\n    PAGER=\"most -w\" hl example.log\n    ```\n\n    Opens `most` pager with `-w` option.\n\n### Quick filtering by log level\n\n* Errors only\n\n    Command\n\n    ```sh\n    hl -l e\n    ```\n\n    Displays only error log level messages.\n\n* Errors and warnings\n\n    Command\n\n    ```sh\n    hl -l w\n    ```\n\n    Displays only warning and error log level messages.\n\n* Errors, warnings and informational\n\n    Command\n\n    ```sh\n    hl -l i\n    ```\n\n    Displays all log messages except debug level messages.\n\n### Using live log streaming\n\n* Command\n\n    ```sh\n    tail -f example.log | hl -P\n    ```\n\n    Tracks changes in the example.log file and displays them immediately.\n    Flag `-P` disables automatic using of pager in this case.\n\n### Filtering by field values\n\n* Command\n\n    ```sh\n    hl example.log --filter component=tsdb\n    ```\n\n    Displays only messages where the `component` field has the value `tsdb`.\n\n* Command\n\n    ```sh\n    hl example.log -f component!=tsdb -f component!=uninteresting\n    ```\n\n    Displays only messages where the `component` field exists and has a value other than `tsdb` or `uninteresting`.\n\n* Command\n\n    ```sh\n    hl example.log -f provider~=string\n    ```\n\n    Displays only messages where the `provider` field contains the `string` sub-string.\n\n* Command\n\n    ```sh\n    hl example.log -f 'provider!~=string'\n    ```\n\n    Displays only messages where the `provider` field exists and does not contain the `string` sub-string.\n\n* Command\n\n    ```sh\n    hl example.log -f 'request.method?!=GET'\n    ```\n\n    Displays only messages where the `request.method` field does not exist or exists and is not equal to `GET`. In JSON messages, this also matches composite fields, e.g., `{\"request\":{\"method\":\"POST\"}}`.\n\n* Command\n\n    ```sh\n    hl example.log -f 'span.[].name=sp0001'\n    ```\n\n    Displays only messages where the `span` field is an array that contains an object with a `name` field equal to `sp0001`.\n\n* Command\n\n    ```sh\n    hl example.log -f 'span.[1].name=sp0001'\n    ```\n\n    Displays only messages where the `span` field is an array with at least two elements, and the element at index 1 (i.e., the second element) is an object with a `name` field equal to `sp0001`.\n\n### Performing complex queries\n\n* Command\n\n    ```sh\n    hl my-service.log --query 'level \u003e info or status-code \u003e= 400 or duration \u003e 0.5'\n    ```\n\n    Displays messages that either have a level higher than info (i.e. warning or error) or have a status code field with a numeric value \u003e= 400 or a duration field with a numeric value \u003e= 0.5.\n\n* Command\n\n    ```sh\n    hl my-service.log -q '(request in (95c72499d9ec, 9697f7aa134f, bc3451d0ad60)) or (method != GET)'\n    ```\n\n    Displays all messages that have the 'request' field with one of these values, or the 'method' field with a value other than 'GET'.\n\n* Command\n\n    ```sh\n    hl my-service.log -q '.price?=3'\n    ```\n\n    Displays messages where the `price` field equals `3` OR the `price` field is absent. The `?` modifier after a field name includes records that don't have that field. Without the `?` modifier, filtering on a missing field will skip the record.\n\n* Command\n\n    ```sh\n    hl my-service.log -q '.status?!=error'\n    ```\n\n    Displays messages where the `status` field is not equal to `error` OR the `status` field is absent. This is useful to include records that may not have a status field at all.\n\n* Command\n\n    ```sh\n    hl my-service.log -q 'exists(.price)'\n    ```\n\n    Displays only messages that have the `price` field, regardless of its value. The `exists()` operator tests for field presence without any value comparison.\n\n* Command\n\n    ```sh\n    hl my-service.log -q 'exists(msg) and msg~=warning'\n    ```\n\n    Displays messages that have a `msg` field that exists AND contains the substring `warning`. This combines field existence checking with value matching.\n\n* Command\n\n    ```sh\n    hl my-service.log -q 'not exists(.internal)'\n    ```\n\n    Displays messages that do NOT have an `internal` field, effectively filtering out records with that field.\n\n* Complete set of supported operators\n\n  * Logical operators\n    * Logical conjunction - `and`, `\u0026\u0026`\n    * Logical disjunction - `or`, `||`\n    * Logical negation - `not`, `!`\n  * Comparison operators\n    * Equal - `eq`, `=`\n    * Not equal - `ne`, `!=`\n    * Greater than - `gt`, `\u003e`\n    * Greater or equal - `ge`, `\u003e=`\n    * Less than - `lt`, `\u003c`\n    * Less or equal - `le`, `\u003c=`\n  * String matching operators\n    * Sub-string check - (`contain`, `~=`), (`not contain`, `!~=`)\n    * Wildcard match - (`like`), (`not like`)\n      * Wildcard characters are: `*` for zero or more characters and `?` for a single character\n    * Regular expression match - (`match`, `~~=`), (`not match`, `!~~=`)\n  * Operators with sets\n    * Test if a value is one of the values in a set - `in (v1, v2)`, `not in (v1, v2)`\n    * Test if a value is one of the values in a set loaded from a file - `in @filename`, `not in @filename`, assuming that each element is a line in the file, which can be either a simple string or a JSON string\n    * Test if a value is one of the values in a set loaded from stdin - `in @-`, `not in @-`\n  * Field existence operators\n    * Test if a field exists - `exists(.field)` or `exist(.field)` (both forms are supported)\n\n* Notes\n\n  * __Include Absent Modifier (`?`)__: When appending `?` to a field name (e.g., `.field?=value`), the filter will match both:\n    * Records where the field exists and matches the condition\n    * Records where the field is absent (does not exist)\n\n    This is useful in logfmt or similar formats where fields may be optional. Without the `?` modifier, records with a non-existent field are excluded from the results.\n\n  * Special field names that are reserved for filtering by predefined fields regardless of the actual source field names used to load the corresponding value: `level`, `message`, `caller` and `logger`.\n  * To address a source field with one of these names instead of predefined fields, add a period before its name, i.e., `.level` will perform a match against the \"level\" source field.\n  * To address a source field by its exact name, use a JSON-formatted string, i.e. `-q '\".level\" = info'`.\n  * To specify special characters in field values, also use a JSON-formatted string, i.e.\n\n    ```sh\n    hl my-service.log -q 'message contain \"Error:\\nSomething unexpected happened\"'\n    ```\n\n### Filtering by time range\n\n* Command\n\n    ```sh\n    hl example.log --since 'Jun 19 11:22:33' --until yesterday\n    ```\n\n    Displays only messages that occurred after Jun 19 11:22:33 UTC of the current year (or the previous year if the current date is less than Jun 19 11:22:33) and before yesterday midnight.\n\n* Command\n\n    ```sh\n    hl example.log --since -3d\n    ```\n\n    Displays only messages from the past 72 hours.\n\n* Command\n\n    ```sh\n    hl example.log --until '2021-06-01 18:00:00' --local\n    ```\n\n    Displays only messages that occurred before 6 PM local time on June 1, 2021, and shows timestamps in local time.\n\n### Hiding or revealing selected fields\n\n* Command\n\n    ```sh\n    hl example.log --hide provider\n    ```\n\n    Hides field `provider`.\n\n* Command\n\n    ```sh\n    hl example.log --hide '*' --hide '!provider'\n    ```\n\n    Hides all fields except `provider`.\n\n* Command\n\n    ```sh\n    hl example.log -h headers -h body -h '!headers.content-type'\n    ```\n\n    Hides fields `headers` and `body` but shows a single sub-field `content-type` inside field `headers`.\n\n### Sorting messages chronologically\n\n* Command\n\n    ```sh\n    hl -s *.log\n    ```\n\n    Displays log messages from all log files in the current directory sorted in chronological order.\n\n### Sorting messages chronologically with following the changes\n\n* Command\n\n    ```sh\n    hl --sync-interval-ms 500 -F \u003c(kubectl logs -l app=my-app-1 -f) \u003c(kubectl logs -l app=my-app-2 -f)\n    ```\n\n    Runs without a pager in follow mode by merging messages from the outputs of these 2 commands and sorting them chronologically within a custom 500ms interval.\n\n* Command\n\n    ```sh\n    hl -F --tail 100 app1.log app2.log app3.log\n    ```\n\n    Runs without a pager in follow mode, following the changes in three log files in the current directory and sorting them chronologically at a default interval of 100ms.\n    Preloads 100 lines from the end of each file before filtering.\n\n### Configuration files\n\n* Configuration files are automatically loaded if found in predefined platform-specific locations.\n\n    | OS      | System-Wide Location                     | User Profile Location                                    |\n    | ------- | ---------------------------------------- |  ------------------------------------------------------- |\n    | macOS   | /etc/hl/config.{yaml,toml,json}          | ~/.config/hl/config.{yaml,toml,json}                     |\n    | Linux   | /etc/hl/config.{yaml,toml,json}          | ~/.config/hl/config.{yaml,toml,json}                     |\n    | Windows | %PROGRAMDATA%\\hl\\config.{yaml,toml,json} | %USERPROFILE%\\AppData\\Roaming\\hl\\config.{yaml,toml,json} |\n\n* The path to the configuration file can be overridden using the `HL_CONFIG` environment variable or the `--config` command-line option.\n\n    The order in which the configuration files are searched and loaded is as follows:\n    1. __The system-wide location.__\n    2. __The user profile location.__\n    3. __The location specified by the `HL_CONFIG` environment variable__ (unless the `--config` option is used).\n    4. __The locations specified by the `--config` option__ (can be specified multiple times).\n\n    If a configuration file is found in multiple locations, the file in each subsequent location overrides only the parameters it contains.\n\n    If `HL_CONFIG` or `--config` specifies `-` or an empty string, all default locations and any locations specified by previous `--config` options are discarded. The search for the configuration file locations starts over.\n\n    To disable loading of configuration files and use the built-in defaults, `--config -` can be used.\n\n* All parameters in the configuration file are optional and can be omitted. In this case, default values are used.\n\n#### Default configuration file\n\n* [config.toml](etc/defaults/config.toml)\n\n### Environment variables\n\n* Many parameters that are defined in command line arguments and configuration files can also be specified by environment variables.\n\n#### Precedence of configuration sources (from lowest priority to highest priority)\n\n* Configuration file\n* Environment variables\n* Command-line arguments\n\n#### Environment variables examples\n\n* `HL_TIME_FORMAT='%y-%m-%d %T.%3N'` overrides the time format specified in the configuration file.\n* `HL_TIME_ZONE=Europe/Berlin` overrides the time zone specified in the configuration file.\n* `HL_CONCURRENCY=4` overrides the concurrency limit specified in the configuration file.\n* `HL_PAGING=never` specifies the default value for the paging option, but it can be overridden by command line arguments.\n\n### Themes\n\n#### Stock themes\n\n* [themes](etc/defaults/themes/)\n\n#### Selecting current theme\n\n* Using `theme` value in the configuration file.\n* Using environment variable, i.e. `HL_THEME=classic`, overrides the value specified in configuration file.\n* Using command-line argument, i.e. `--theme classic`, overrides all other values.\n\n#### Theme overlays\n\nTheme overlays allow you to apply multiple theme modifications on top of your base theme and main configured theme, enabling compositional theming. Overlays are merged in order: `@base` → configured theme → overlays (in list order).\n\n* Configure overlays in your configuration file using the `theme-overlays` setting:\n\n    ```yaml\n    theme: \"uni\"\n    theme-overlays: [\"@accent-italic\"]\n    ```\n\n* Overlays are regular theme files that can customize specific aspects without replacing the entire theme\n* Overlays are applied in the specified order, allowing fine-grained control over theme composition\n* Empty array `[]` or omitting `theme-overlays` means no overlays are applied\n* Overlay themes are typically tagged with `overlay` and excluded from default theme listings (use `--list-themes=overlay` to view them)\n\n#### Selecting themes with preview\n\nTo select themes with preview [fzf](https://github.com/junegunn/fzf) tool can be used like this:\n\n```bash\nhl --list-themes | fzf --color='bg+:23,gutter:-1,pointer:210' --highlight-line --preview-window 'right,border-left,88%,\u003c142(up,88%,border-bottom)' --preview=\"hl -t '%b %d %T' --input-info minimal -c --theme {} sample/*.log\"\n```\n\n#### Custom themes\n\nFor complete theme configuration reference, see __[Theme Configuration Guide](doc/theme.md)__.\n\n* Custom themes are automatically loaded when found in a predefined platform-specific location.\n\n    | OS      | Location                                                             |\n    | ------- | -------------------------------------------------------------------- |\n    | macOS   | ~/.config/hl/themes/*.{yaml,yml,toml,json}                           |\n    | Linux   | ~/.config/hl/themes/*.{yaml,yml,toml,json}                           |\n    | Windows | %USERPROFILE%\\AppData\\Roaming\\hl\\themes\\*.{yaml,yml,toml,json}       |\n\n* __Structure__\n  * `version` (required): Must be `\"1.0\"`\n  * `tags` (optional): Theme classification and filtering\n    * Classification tags: `dark`, `light`, `16color`, `256color`, `truecolor`\n    * Special tags: `base` (foundation themes, excluded from default listings), `overlay` (composition themes, excluded from default listings)\n    * Use `--list-themes=base` or `--list-themes=overlay` to show themes with these tags\n    * Theme names starting with `@` (e.g., `@base`, `@accent-italic`) are a naming convention; filtering is based on tags, not name prefixes\n  * `styles` (optional): Reusable role-based styles that can inherit from each other\n  * `elements` (optional): Visual styles for specific log elements\n  * `levels` (optional): Per-level overrides for elements\n  * `indicators` (optional): Sync indicator styling for `--follow` mode\n\n* __Example__\n\n    ```toml\n    version = \"1.0\"\n    tags = [\"dark\", \"256color\"]\n\n    # Reusable styles with inheritance\n    [styles]\n    primary = { modes = [\"-faint\"] }\n    secondary = { style = \"primary\", modes = [\"faint\"] }\n    warning = { style = \"primary\", foreground = \"yellow\" }\n    error = { style = \"primary\", foreground = \"bright-red\" }\n\n    # Element-specific styles can reference roles\n    [elements]\n    message = { style = \"primary\", modes = [\"bold\"] }\n    time = { style = \"secondary\" }\n    level-inner = { style = \"primary\" }\n\n    # Level-specific overrides\n    [levels.warning]\n    level-inner = { style = [\"primary\", \"warning\"] }\n    message = { style = [\"primary\", \"warning\"] }\n\n    [levels.error]\n    level-inner = { style = [\"primary\", \"error\"] }\n    message = { style = [\"primary\", \"error\"] }\n    ```\n\n* __Roles__ (predefined): `default`, `primary`, `secondary`, `strong`, `muted`, `accent`, `accent-secondary`, `message`, `syntax`, `status`, `key`, `value`, `level`, `trace`, `debug`, `info`, `warning`, `error`\n\n* __Elements__ (predefined): `input`, `input-number`, `input-number-inner`, `input-name`, `input-name-inner`, `time`, `level`, `level-inner`, `logger`, `logger-inner`, `caller`, `caller-inner`, `message`, `message-delimiter`, `field`, `key`, `array`, `object`, `string`, `number`, `boolean`, `boolean-true`, `boolean-false`, `null`, `ellipsis`\n\n* __Mode operations__:\n  * `+mode` or `mode`: Add mode (e.g., `[\"+bold\"]` or `[\"bold\"]`)\n  * `-mode`: Remove inherited mode (e.g., `[\"-faint\"]`)\n  * Last occurrence wins for conflicts (e.g., `[\"+bold\", \"-bold\"]` removes bold)\n\n* __Inheritance chain__: `@base` theme → user theme's styles → element's `style` field → element's explicit properties\n  * All themes inherit from built-in `@base` theme\n  * Styles can reference other styles via `style` field\n  * Elements can reference styles via `style` field\n  * Explicit properties override inherited ones\n\n* __Color format__:\n  * Keyword `default` for terminal default color\n  * ASCII basic color names: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `bright-black`, `bright-red`, `bright-green`, `bright-yellow`, `bright-blue`, `bright-magenta`, `bright-cyan`, `bright-white`\n  * 256-color palette code: `0` to `255`\n  * RGB hex format: `#RRGGBB` (e.g., `#FFFF00` for bright yellow)\n\n* __Modes__: `bold`, `faint`, `italic`, `underline`, `slow-blink`, `rapid-blink`, `reverse`, `conceal`, `crossed-out`\n\n### Used terminal color schemes\n\n#### iTerm2\n\n* [One Dark Neo](https://gist.github.com/pamburus/0ad130f2af9ab03a97f2a9f7b4f18c68/746ca7103726d43b767f2111799d3cb5ec08adbb)\n* Built-in \"Light Background\" color scheme\n\n#### Alacritty\n\n* [One Dark Neo](https://gist.github.com/pamburus/e27ebf60aa17d126f5c879f06112edd6/a1e66d34a65b883f1cb8ec28820cc0c53233e3aa#file-alacritty-yml-L904)\n  * Note: It is recommended to use `draw_bold_text_with_bright_colors: true` setting\n* [Light](https://gist.github.com/pamburus/e27ebf60aa17d126f5c879f06112edd6/a1e66d34a65b883f1cb8ec28820cc0c53233e3aa#file-alacritty-yml-L875)\n  * Note: It is recommended to use `draw_bold_text_with_bright_colors: false` setting\n\n### Complete set of options and flags\n\n```text\nJSON and logfmt log converter to human readable representation\n\nUsage: hl [OPTIONS] [FILE]...\n\nArguments:\n  [FILE]...  Files to process\n\nOptions:\n      --config \u003cFILE\u003e                    Configuration file path [env: HL_CONFIG=]\n  -s, --sort                             Sort entries chronologically\n  -F, --follow                           Follow input streams and sort entries chronologically within time frame set by --sync-interval-ms option\n      --tail \u003cN\u003e                         Number of last entries to preload from each file in --follow mode [default: 10]\n      --sync-interval-ms \u003cMILLISECONDS\u003e  Synchronization interval for live streaming mode enabled by --follow option [default: 100]\n      --paging \u003cWHEN\u003e                    Control pager usage (HL_PAGER or PAGER) [env: HL_PAGING=] [default: auto] [possible values: auto, always, never]\n  -P                                     Handful alias for --paging=never, overrides --paging option\n      --help[=\u003cVERBOSITY\u003e]               Print help [possible values: short, long]\n  -V, --version                          Print version\n\nFiltering Options:\n  -l, --level \u003cLEVEL\u003e    Display entries with level \u003e= \u003cLEVEL\u003e [env: HL_LEVEL=]\n      --since \u003cTIME\u003e     Display entries with timestamp \u003e= \u003cTIME\u003e\n      --until \u003cTIME\u003e     Display entries with timestamp \u003c= \u003cTIME\u003e\n  -f, --filter \u003cFILTER\u003e  Filter entries by matching field values [k=v, k~=v, k~~=v, 'k!=v', 'k?!=v', etc]\n  -q, --query \u003cQUERY\u003e    Filter entries using a query expression ['status\u003e=400 or duration\u003e=15', etc]\n\nOutput Options:\n      --color [\u003cWHEN\u003e]        Whether to use ANSI colors and styles [env: HL_COLOR=] [default: auto] [possible values: auto, always, never]\n  -c                          Handful alias for --color=always, overrides --color option\n      --theme \u003cTHEME\u003e         Color theme [env: HL_THEME=] [default: uni]\n  -r, --raw                   Output raw source entries instead of formatted entries\n      --no-raw                Disable raw source entries output, overrides --raw option\n      --raw-fields            Output field values as is, without unescaping or prettifying\n  -h, --hide \u003cKEY\u003e            Hide or reveal fields with the specified keys, prefix with ! to reveal, provide '!*' to reveal all\n      --flatten \u003cWHEN\u003e        Whether to flatten objects [env: HL_FLATTEN=] [default: always] [possible values: never, always]\n  -t, --time-format \u003cFORMAT\u003e  Time format, see https://man7.org/linux/man-pages/man1/date.1.html [env: HL_TIME_FORMAT=] [default: \"%b %d %T.%3N\"]\n  -Z, --time-zone \u003cTZ\u003e        Time zone name, see column \"TZ identifier\" at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones [env: HL_TIME_ZONE=] [default: UTC]\n  -L, --local                 Use local time zone, overrides --time-zone option\n      --no-local              Disable local time zone, overrides --local option\n  -e, --hide-empty-fields     Hide empty fields, applies for null, string, object and array fields only [env: HL_HIDE_EMPTY_FIELDS=]\n  -E, --show-empty-fields     Show empty fields, overrides --hide-empty-fields option [env: HL_SHOW_EMPTY_FIELDS=]\n      --input-info \u003cLAYOUTS\u003e  Input number and filename layouts [default: auto] [possible values: auto, none, minimal, compact, full]\n      --ascii [\u003cWHEN\u003e]        Whether to restrict punctuation to ASCII characters only [env: HL_ASCII=] [default: auto] [possible values: auto, never, always]\n  -x, --expansion [\u003cMODE\u003e]    Whether to expand fields and messages [env: HL_EXPANSION=] [default: auto] [possible values: never, inline, auto, always]\n  -o, --output \u003cFILE\u003e         Output file\n\nInput Options:\n      --input-format \u003cFORMAT\u003e       Input format [env: HL_INPUT_FORMAT=] [default: auto] [possible values: auto, json, logfmt]\n      --unix-timestamp-unit \u003cUNIT\u003e  Unix timestamp unit [env: HL_UNIX_TIMESTAMP_UNIT=] [default: auto] [possible values: auto, s, ms, us, ns]\n      --allow-prefix                Allow non-JSON prefixes before JSON log entries [env: HL_ALLOW_PREFIX=]\n      --delimiter \u003cDELIMITER\u003e       Log entry delimiter [env: HL_DELIMITER=] [possible values: auto, cr, lf, crlf, nul]\n\nAdvanced Options:\n      --interrupt-ignore-count \u003cN\u003e  Number of interrupts to ignore, i.e. Ctrl-C (SIGINT) [env: HL_INTERRUPT_IGNORE_COUNT=] [default: 3]\n      --buffer-size \u003cSIZE\u003e          Buffer size [env: HL_BUFFER_SIZE=] [default: \"256 KiB\"]\n      --max-message-size \u003cSIZE\u003e     Maximum log entry size [env: HL_MAX_MESSAGE_SIZE=] [default: \"64 MiB\"]\n  -C, --concurrency \u003cN\u003e             Number of processing threads [env: HL_CONCURRENCY=]\n      --shell-completions \u003cSHELL\u003e   Print shell auto-completion script and exit [possible values: bash, elvish, fish, powershell, zsh]\n      --man-page                    Print man page and exit\n      --list-themes[=\u003cTAGS\u003e]        Print available themes optionally filtered by tags [possible values: dark, light, 16color, 256color, truecolor, overlay, base]\n      --dump-index                  Print debug index metadata (in --sort mode) and exit\n```\n\n## Performance\n\n![performance chart](doc/performance-chart.svg)\n\n* MacBook Pro (16-inch, 2021)\n  * __CPU__:   Apple M1 Max CPU\n  * __OS__:    macOS Tahoe 26.2\n  * __Data__:  ~ __2.3 GiB__ log file, __6 000 000__ lines\n    * [hl](https://github.com/pamburus/hl) __v0.35.2__ ~ *1.1 seconds*\n\n        ```sh\n        $ time hl --config - example.log -c -o /dev/null\n        hl --config - example.log -c -o /dev/null  9.33s user 0.45s system 922% cpu 1.060 total\n        ```\n\n    * [hl](https://github.com/pamburus/hl) with `-x always` flag __v0.35.2__ ~ *1.2 seconds*\n\n        ```sh\n        $ time hl --config - example.log -c -x always -o /dev/null\n        hl --config - example.log -c -x always -o /dev/null  11.19s user 0.50s system 936% cpu 1.248 total\n        ```\n\n    * [hlogf](https://github.com/ssgreg/hlogf) __v1.4.1__ ~ *8.8 seconds*\n\n        ```sh\n        $ time hlogf example.log --color always \u003e/dev/null\n        hlogf example.log --color always \u003e /dev/null  6.79s user 2.05s system 100% cpu 8.787 total\n        ```\n\n    * [humanlog](https://github.com/humanlogio/humanlog) __v0.8.9__ ~ *123 seconds*\n\n        ```sh\n        $ time humanlog \u003cexample.log --color always \u003e/dev/null\n        humanlog --color always \u003c example.log \u003e /dev/null  136.18s user 7.17s system 116% cpu 2:03.25 total\n        ```\n\n    * [fblog](https://github.com/brocode/fblog) __v4.17.0__ ~ *34 seconds*\n\n        ```sh\n        $ time fblog example.log \u003e/dev/null\n        fblog example.log \u003e /dev/null  31.92s user 2.39s system 99% cpu 34.327 total\n        ```\n\n    * [fblog](https://github.com/brocode/fblog) with `-d` flag __v4.17.0__ ~ *164 seconds*\n\n        ```sh\n        $ time fblog -d example.log \u003e/dev/null\n        fblog -d example.log \u003e /dev/null  147.57s user 16.20s system 99% cpu 2:43.82 total\n        ```\n\n  * See [#132](https://github.com/pamburus/hl/issues/132) for how to repeat measurements\n\n[ci-img]: https://github.com/pamburus/hl/actions/workflows/ci.yml/badge.svg\n[ci]: https://github.com/pamburus/hl/actions/workflows/ci.yml\n[cov-img]: https://codecov.io/gh/pamburus/hl/graph/badge.svg?token=464MN13408\n[cov]: https://codecov.io/gh/pamburus/hl\n[release-img]: https://img.shields.io/github/v/release/pamburus/hl?sort=semver\n[release]: https://github.com/pamburus/hl/releases/latest\n","funding_links":[],"categories":["Rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpamburus%2Fhl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpamburus%2Fhl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpamburus%2Fhl/lists"}