{"id":43943338,"url":"https://github.com/earentir/ttail","last_synced_at":"2026-04-14T12:01:50.861Z","repository":{"id":258416216,"uuid":"850844560","full_name":"earentir/ttail","owner":"earentir","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-07T00:53:42.000Z","size":99,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-07T11:20:40.550Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/earentir.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-09-01T23:42:04.000Z","updated_at":"2026-02-06T22:06:26.000Z","dependencies_parsed_at":"2026-02-07T03:07:36.564Z","dependency_job_id":null,"html_url":"https://github.com/earentir/ttail","commit_stats":null,"previous_names":["earentir/tui-tail"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/earentir/ttail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fttail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fttail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fttail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fttail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/earentir","download_url":"https://codeload.github.com/earentir/ttail/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/earentir%2Fttail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31795334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T11:13:53.975Z","status":"ssl_error","status_checked_at":"2026-04-14T11:13:53.299Z","response_time":153,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":[],"created_at":"2026-02-07T02:08:53.301Z","updated_at":"2026-04-14T12:01:50.856Z","avatar_url":"https://github.com/earentir.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ttail\n\nA TUI for viewing and filtering log files using matching rules.\n\n## Features\n\n- View **one or more** files side by side (each file gets a header and line list; **Tab** moves focus between files and the rules pane)\n- Optional follow (tail) mode; use **-F** to follow by name (reopen on log rotation)\n- Filter lines with regex-based **matching rules**\n- **Colour rules** via JSON config (e.g. highlight ERROR, WARN, INFO)\n- **Search** (`/`), **navigate**, **reload** (`r`), and **save** filtered content\n- **Load older lines** from the file without a full reload: extend the initial “last N lines” window toward the start of the file (see [Load older lines](#load-older-lines))\n- Configurable initial line count (`-n`), max lines in memory (`--max-lines`), **rollover** at list edges, and default **search case sensitivity** (see [Configuration](#configuration))\n- Optional **full** mode to navigate the whole file without loading everything into memory\n- Optional **head** mode to show the first N lines instead of the last\n\n## Build\n\n```bash\ngo build -o ttail .\n```\n\n## Configuration\n\nDefault values for many flags are read from a JSON config file. If the file does not exist, it is created on first run with built-in defaults and a message is printed to stderr:\n\n```text\nDefault config generated in /home/you/.config/ttail/ttail.json\n```\n\n### Config file location\n\n| OS      | Path |\n|---------|------|\n| Linux   | `$XDG_CONFIG_HOME/ttail/ttail.json` or `~/.config/ttail/ttail.json` |\n| Windows | `%APPDATA%\\ttail\\ttail.json` |\n| macOS   | `~/Library/Application Support/ttail/ttail.json` |\n\nOnly options that make sense as persistent defaults are stored in config. One-shot options (per run) are not in config and use flag defaults only: `--bytes` / `-c`, `-n +N` (from line N), `--full`, `--head`, `--retry`, `--zero-terminated` / `-z`.\n\n**Example `ttail.json`**\n\n```json\n{\n  \"num_lines\": 10,\n  \"max_lines\": 1000,\n  \"rules_file\": \"\",\n  \"colour_file\": \"\",\n  \"log_file\": \"\",\n  \"follow\": false,\n  \"follow_name\": false,\n  \"rollover\": \"both\",\n  \"searchcase\": false\n}\n```\n\n| Field | Meaning |\n|-------|---------|\n| `num_lines` | Default for `-n` / `--num-lines` (last N lines, or first N with `--head`) |\n| `max_lines` | Default for `--max-lines` (cap on lines kept in memory) |\n| `rules_file` | Default path for `--rules-file` |\n| `colour_file` | Default path for `--colour-file` |\n| `log_file` | Default for `--log-file` |\n| `follow` | Default for `-f` / `--follow` |\n| `follow_name` | Default for `-F` / `--follow-name` |\n| `rollover` | Default list wrap: `\"none\"`, `\"start\"`, `\"end\"`, or `\"both\"` (wrap at top, bottom, or both) |\n| `searchcase` | Default: if `true`, search is case-sensitive; if `false`, case-insensitive |\n\nCommand-line flags override config file values.\n\nWith `--follow` / `-f` the file is followed by descriptor (like GNU `tail -f`). With `--follow-name` / `-F` the file is followed by name (like GNU `tail -F`): if the file is replaced (e.g. by log rotation), ttail reopens it and continues following the same path. Passing `-F` implies `-f`. The defaults shown in the Flags table below are the built-in defaults when no config file exists.\n\n### Colour rule file (`--colour-file`)\n\nThe colour file is a JSON file that defines how to highlight parts of each line in the viewer. Pass its path via the main config (`colour_file`) or the `--colour-file` flag.\n\nThe file must contain a top-level array **`color_rules`**. Each element is an object with:\n\n| Field      | Meaning |\n|------------|--------|\n| `pattern`  | Regular expression. Every match in the line is highlighted with the rule’s color. |\n| `color`    | tview color tag applied to matches, e.g. `[red]`, `[green]`, `[yellow]`, `[blue]`. Use `[-]` to reset (normally added automatically after each match). |\n| `label`   | Short description of the rule (for reference). |\n| `rule_id`  | Unique identifier for the rule (for reference). |\n\nRules are applied in order. Each match is wrapped with the rule’s `color` and a reset, so overlapping patterns will show the colour of the rule that is applied last.\n\n#### Example colour rule file\n\n```json\n{\n  \"color_rules\": [\n    { \"pattern\": \"ERROR\", \"color\": \"[red]\", \"label\": \"Error Messages\", \"rule_id\": \"error-matcher\" },\n    { \"pattern\": \"WARN\", \"color\": \"[yellow]\", \"label\": \"Warning Messages\", \"rule_id\": \"warn-matcher\" },\n    { \"pattern\": \"INFO\", \"color\": \"[green]\", \"label\": \"Info Messages\", \"rule_id\": \"info-matcher\" },\n    { \"pattern\": \"DEBUG\", \"color\": \"[blue]\", \"label\": \"Debug Messages\", \"rule_id\": \"debug-matcher\" }\n  ]\n}\n```\n\nHere, any occurrence of `ERROR`, `WARN`, `INFO`, or `DEBUG` in a line is highlighted in the corresponding colour. You can use full regular expressions in `pattern`, e.g. `\\d{4}-\\d{2}-\\d{2}` to colour ISO dates. A full example is included as `colour_rule_example.json`.\n\n## Usage\n\n```text\nttail [FILE]... [flags]\n```\n\n### Arguments\n\n| Argument | Description |\n|----------|-------------|\n| `FILE`…  | One or more paths to view (required). Each file is shown in its own pane with a path header and scrollable line list. |\n\n### Flags\n\nFlags that match GNU tail have a short form in parentheses.\n\n| Flag            | Short | Description |\n|-----------------|-------|-------------|\n| `--num-lines`   | `-n`  | Lines: `N` = last N lines, `+N` = from line N to end (same as GNU tail -n; default: 10) |\n| `--max-lines`   |       | Maximum number of lines to keep in memory (default: 1000) |\n| `--bytes`       | `-c`  | Bytes: `N` = last N bytes, `+N` = from byte N to end (same as GNU tail -c) |\n| `--rules-file`  |       | JSON file with matching rules to load at startup |\n| `--colour-file` |       | JSON file for color rules and settings |\n| `--full`        |       | Load and navigate the full file without loading all lines into memory |\n| `--head`        |       | Show the first N lines instead of the last N |\n| `--log-file`    |       | Path or directory for application logs |\n| `--follow`      | `-f`  | Follow (tail) the file and show new lines as they are written (default: off) |\n| `--follow-name` | `-F`  | Follow by name: reopen when the file is replaced (e.g. log rotate); implies `-f` |\n| `--retry`           |       | Keep trying to open the file when it is unavailable (e.g. not yet created) |\n| `--pid`             |       | With `-f`, exit when the process with the given PID dies (GNU tail --pid; Unix) |\n| `--sleep-interval`  |       | With `-f`, poll file every N seconds (e.g. network FS); 0 = default (GNU tail -s) |\n| `--zero-terminated` | `-z`  | Input is NUL-delimited (GNU tail -z) |\n| `--help`            |       | Show help |\n| `--version`         |       | Show version |\n\n### Keyboard shortcuts (TUI)\n\nPress **`h`** or **`?`** in the app for the in-TUI help popup. Summary:\n\n**Global**\n\n| Key | Action |\n|-----|--------|\n| `q` | Quit |\n| `h`, `?` | Help |\n| `Tab` / `Shift+Tab` | Cycle focus between file list(s) and the rules pane |\n| `r` | Reload output from disk (same scope as startup; not while following `-f` or in `--full`) |\n| `o` | Cycle rollover mode (how the line list wraps at the first/last line) |\n\n**Messages / file view** (when focus is on a file’s line list)\n\n| Key | Action |\n|-----|--------|\n| `↑` / `↓` | Move selection |\n| `Enter`, `v` | View full selected line |\n| `f` | Toggle follow mode (`-f`) |\n| `/` | Open search |\n| `n` | Jump to next search match |\n| `c` | Toggle search case sensitivity (when not in the rules pane for rule-specific `c`) |\n| `l` | Load **10** more **older** lines from the file (see [Load older lines](#load-older-lines)) |\n| `L` | Prompt for how many older lines to load |\n\n**Rules pane**\n\n| Key | Action |\n|-----|--------|\n| `d` | Delete selected rule |\n| `c` | Toggle case sensitivity for the selected rule |\n| `p` | Toggle partial match for the selected rule |\n| `a` | Add matching rule (popup) |\n| `s` | Save (export) |\n\n**Popups** (search, add rule, load-older amount, help, view line)\n\n| Key | Action |\n|-----|--------|\n| `Enter` | Confirm |\n| `Esc` | Close |\n\n### Load older lines\n\nIn the default **last N lines** mode (not `--head`, not `-c`, not `-n +N`, not `--full`), you can extend the window backward toward the start of the file:\n\n- **`l`** — append **10** older lines at the **top** of the buffer; the selection stays on the **same logical line** (the view shifts).\n- **`L`** — open a popup to type a positive number of extra older lines, then **Enter** to apply.\n\n**When it is unavailable:** `--full`, **follow** (`-f`), `--head`, **byte mode** (`-c`), or **from-line mode** (`-n +N`). In those cases the app shows a short status message instead.\n\n**Limit:** The total number of lines cannot exceed **`--max-lines`**. If you are already at the cap, you will see a message to that effect.\n\n**Multiple files:** Load-older applies to the **focused** file pane (use **Tab** to switch).\n\n## Examples\n\n```bash\nttail /var/log/app.log\nttail /var/log/a.log /var/log/b.log              # two files side by side\nttail /var/log/app.log -n 100 --colour-file colour_rule_example.json\nttail /var/log/app.log -n +100                  # from line 100 to end (like GNU tail -n +100)\nttail /var/log/app.log -c 1024                  # last 1024 bytes\nttail /var/log/app.log -c +100                  # from byte 100 to end\nttail /var/log/app.log -f --pid 1234           # follow and exit when process 1234 dies\nttail /var/log/app.log -f --sleep-interval 2   # follow, poll every 2 seconds\nttail /var/log/app.log -z file.nul              # NUL-delimited input\nttail /var/log/app.log --rules-file rules.json --full\n```\n\n## License\n\nSee [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fearentir%2Fttail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fearentir%2Fttail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fearentir%2Fttail/lists"}