{"id":49917294,"url":"https://github.com/inxbit/pinghue","last_synced_at":"2026-05-20T21:00:53.378Z","repository":{"id":357916382,"uuid":"1239118753","full_name":"inxbit/pinghue","owner":"inxbit","description":"Colored, concurrent ICMP/TCP ping monitor for the terminal","archived":false,"fork":false,"pushed_at":"2026-05-15T02:24:38.000Z","size":112,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-16T17:51:17.499Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/inxbit/pinghue","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/inxbit.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","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-05-14T19:27:21.000Z","updated_at":"2026-05-15T02:24:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/inxbit/pinghue","commit_stats":null,"previous_names":["inxbit/pinghue"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/inxbit/pinghue","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inxbit%2Fpinghue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inxbit%2Fpinghue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inxbit%2Fpinghue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inxbit%2Fpinghue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inxbit","download_url":"https://codeload.github.com/inxbit/pinghue/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inxbit%2Fpinghue/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33149519,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T09:28:26.183Z","status":"ssl_error","status_checked_at":"2026-05-17T09:27:52.702Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6: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-05-16T17:29:30.651Z","updated_at":"2026-05-20T21:00:53.352Z","avatar_url":"https://github.com/inxbit.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pinghue\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/inxbit/pinghue/main/docs/assets/pinghue-hero.svg\" alt=\"pinghue - terminal ping monitor for maintenance windows\" width=\"920\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.org/project/pinghue/\"\u003e\u003cimg alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/pinghue?color=58a6ff\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/pinghue/\"\u003e\u003cimg alt=\"Python versions\" src=\"https://img.shields.io/pypi/pyversions/pinghue?color=7ee787\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/inxbit/pinghue/actions/workflows/ci.yml\"\u003e\u003cimg alt=\"CI\" src=\"https://github.com/inxbit/pinghue/actions/workflows/ci.yml/badge.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/inxbit/pinghue/blob/main/LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/github/license/inxbit/pinghue?color=f2cc60\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n`pinghue` is a colored, concurrent ICMP/TCP ping monitor for maintenance windows. It gives operators a dense terminal view for many hosts at once and can also write structured JSON for reports, cron jobs, and CI checks.\n\nCurrent version: `1.0.1`.\n\nThe command-line interface and JSON output are stable public interfaces. JSON output uses `schema_version: 1`; breaking JSON changes require a new schema version.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/inxbit/pinghue/main/docs/assets/pinghue-demo.svg\" alt=\"animated pinghue terminal demo\" width=\"920\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/inxbit/pinghue/main/docs/assets/pinghue-screenshot.svg\" alt=\"pinghue dense maintenance-window table with history bars and legend\" width=\"920\"\u003e\n\u003c/p\u003e\n\n## What This Is\n\n- A focused terminal monitor for maintenance windows, migrations, and quick reachability checks.\n- A concurrent ICMP/TCP probe runner with a readable Textual TUI.\n- A scriptable probe tool with `--no-tui`, `--count`, `--duration`, and `--output`.\n- A JSON-producing report helper for post-maintenance evidence.\n- A local operator tool designed for macOS and Linux.\n\n## What This Is Not\n\n- Not a Prometheus, Smokeping, Zabbix, or NMS replacement.\n- Not a long-running metrics database or alerting system.\n- Not a privileged daemon.\n- Not a packet capture or traceroute tool.\n- Not a service that accepts remote network requests.\n\n## Supported Platforms\n\nThe 1.0 support contract is macOS and Linux on Python 3.10 through 3.13. CI runs on both macOS and Linux for every supported Python version.\n\nThe TUI assumes an ANSI-capable terminal with Unicode glyph support. Windows and other POSIX platforms are outside the declared 1.0 support scope unless explicitly added later.\n\n## Stability Policy\n\n`pinghue` treats CLI flags and JSON exports as compatibility contracts. `schema_version: 1` is the JSON v1 contract: additive fields are non-breaking, but removing fields, changing field types, changing enum values, or changing required-field behavior requires a new schema version.\n\nCLI removals, flag renames, and incompatible behavior changes are deprecated for at least one minor release before removal. Deprecated flags continue to parse during that window and release notes identify the replacement. Patch releases do not intentionally break CLI or JSON consumers.\n\nStarting with `1.0.0`, release versions follow semantic versioning: patch releases are bug fixes, minor releases may add compatible behavior, and major releases are reserved for breaking CLI or JSON changes.\n\n## Install\n\nRecommended isolated installs from PyPI:\n\n```sh\nuv tool install pinghue\n```\n\nor:\n\n```sh\npipx install pinghue\n```\n\nPlain pip also works inside a virtual environment:\n\n```sh\npython -m pip install pinghue\n```\n\nHomebrew is available through the `inxbit/tap` tap:\n\n```sh\nbrew install inxbit/tap/pinghue\n```\n\nThe tap repository is `inxbit/homebrew-tap`; Homebrew exposes it as `inxbit/tap`.\n\nFor contributors, install from a local clone in editable mode:\n\n```sh\ngit clone https://github.com/inxbit/pinghue.git\ncd pinghue\npython -m venv .venv\n. .venv/bin/activate\npython -m pip install -e \".[dev]\"\n```\n\nThe `dev` extra installs the local package plus the test, type-checking, linting, build, and schema-validation tools used by the repository.\n\n## Quick Start\n\n```sh\npinghue 1.1.1.1 8.8.8.8 example.com\npinghue -f hosts.txt\npinghue -p 443 example.com\npinghue -p 1 127.0.0.1 -c 1 --no-tui\npinghue --output maintenance.json 1.1.1.1 example.com\npinghue --host-label maintenance-window --output maintenance.json 1.1.1.1\n```\n\nHost files are plain text. Blank lines and lines starting with `#` are ignored.\nHost files must be regular files, at most 1 MiB, and at most 5,000 lines.\n\n```text\n# edge and core checks\n1.1.1.1\n8.8.8.8\nexample.com\ninternal-db.corp\n```\n\n## Modes\n\n`pinghue` defaults to ICMP mode:\n\n```sh\npinghue 1.1.1.1 example.com\n```\n\nTCP mode is enabled by passing a port:\n\n```sh\npinghue -p 443 example.com api.internal\n```\n\nUse no-TUI mode for scripts, cron, CI, and package smoke tests:\n\n```sh\npinghue -p 443 example.com -c 3 --no-tui\n```\n\nExample no-TUI output:\n\n```text\n2026-05-14T18:32:11.420000+00:00 1.1.1.1 ok latency=9.20ms\n2026-05-14T18:32:11.421000+00:00 example.com ok latency=14.08ms\n2026-05-14T18:32:12.420000+00:00 api.internal timeout latency=-\n```\n\n## CLI Reference\n\n```text\npinghue [OPTIONS] [TARGET ...]\n```\n\n| Option | Default | Description |\n| --- | --- | --- |\n| `TARGET ...` | none | Hostnames or IP addresses to probe. Required unless `--check` is used. |\n| `-f, --file PATH` | none | Read targets from a plain-text host file. Blank lines and `#` comments are ignored. |\n| `-p, --port PORT` | ICMP | Enable TCP connect checks against `PORT`. Valid range: `1-65535`. |\n| `-4, --ipv4` | off | Force IPv4 resolution/probing. |\n| `-6, --ipv6` | off | Force IPv6 resolution/probing. |\n| `-n, --numeric` | off | Skip DNS and require IP literals. |\n| `-i, --interval SEC` | `1.0` | Seconds between probes. Minimum: `0.1`. |\n| `--timeout SEC` | interval | Per-probe timeout in seconds. Must be greater than `0`. |\n| `-c, --count N` | continuous | Stop after `N` probes per target. |\n| `--duration SEC` | continuous | Stop after elapsed seconds. |\n| `--no-tui` | off | Print one line per probe instead of launching the TUI. |\n| `--output PATH` | none | Write a JSON run summary on exit. |\n| `--no-samples` | off | Omit per-probe samples from JSON output. |\n| `--concurrency N` | `64` | Maximum concurrent probes, `1-1024`; ICMP mode uses a dedicated thread pool sized to this limit. |\n| `--jitter-threshold MS` | `50.0` | Mark jitter as attention-worthy above this standard deviation. |\n| `--fail-threshold COUNT` | `3` | Classify a host as down after this many consecutive failed probes. |\n| `--fail-on-any-down` | off | Return a non-zero exit code when any target finishes down. |\n| `--fail-on-all-down` | off | Return a non-zero exit code only when all targets finish down. `--fail-on-down` remains a compatibility alias. |\n| `--history-style STYLE` | `bar` | One of `bar`, `dots`, `sparkline`, or `none`. |\n| `--check` | off | Run the environment doctor and exit. |\n| `--resolve-name HOST` | `example.com` | With `--check`, resolve this host for DNS diagnostics. Defaults to the first target when provided. |\n| `--quiet` | off | With `--check`, suppress output and use only the exit code. |\n| `--host-label LABEL` | `local` | Operator-controlled host label written to JSON output. |\n| `-v, --version` | none | Print the installed version. |\n| `-h, --help` | none | Print help. |\n\n## TUI Controls\n\n| Key | Action |\n| --- | --- |\n| `q` | Quit. |\n| `a` | Show or hide resolved addresses. |\n| `r` | Reset the selected host. |\n| `R` | Reset all hosts. |\n| `b` | Probe the selected host immediately. |\n| `B` | Probe all hosts immediately. |\n\n## History Legend\n\nThe default history style is a fixed-scale colored bar:\n\n- Green bar: successful probe.\n- Amber bar: successful probe at or above the slow-latency threshold.\n- Red `.` / `·`: timeout, loss, or down state.\n- Amber `!`: TCP refused.\n\nSuccessful latency uses `▁▂▃▄▅▆▇█`.\n\nThe fixed mapping keeps rows comparable:\n\n| Latency | Glyph |\n| --- | --- |\n| `\u003c=1ms` | `▁` |\n| `\u003c=3ms` | `▂` |\n| `\u003c=10ms` | `▃` |\n| `\u003c=30ms` | `▄` |\n| `\u003c=100ms` | `▅` |\n| `\u003c=300ms` | `▆` |\n| `\u003c=1000ms` | `▇` |\n| `\u003e1000ms` | `█` |\n\nUse `--history-style dots`, `--history-style sparkline`, or `--history-style none` when a terminal font or workflow needs a simpler display.\n\n## Host States\n\n`pinghue` classifies each host from the **whole run**, not just the most recent probes. `down` requires `--fail-threshold` consecutive failures; any packet loss, or jitter above `--jitter-threshold`, marks a host `intermittent`. Because loss and jitter are cumulative over the run, a host that blips once and then recovers stays `intermittent` (not `healthy`) until you reset it (`r` or `R` in the TUI). This is intentional: a maintenance-window report should reflect everything that happened, not only the final moments.\n\n## Slate + Signal Palette\n\n`pinghue` uses a low-glare Slate + Signal palette designed for long maintenance windows: dark structure, high-contrast text, and saturated status colors that make the affected metric stand out quickly.\n\n| Role | Hex | Used for |\n| --- | --- | --- |\n| Background | `#101418` | Terminal body and empty space. |\n| Panel | `#151b22` | Table surface and primary content areas. |\n| Header | `#1b2630` | Title bars and footer bands. |\n| Border | `#2a313a` | Table outlines and separators. |\n| Text | `#e6edf3` | Normal readable values. |\n| Muted | `#8ea0b8` | Labels, secondary text, and inactive chrome. |\n| Green | `#7ee787` | Healthy state, successful probes, and normal history bars. |\n| Amber | `#f2cc60` | Slow latency, high jitter, intermittent state, and TCP refused markers. |\n| Red | `#ff7b72` | Loss, down state, timeouts, and failed history markers. |\n| Selection Blue | `#58a6ff` | Focus accents and selected-row treatment. |\n\n## Doctor\n\nRun the doctor before relying on ICMP mode:\n\n```sh\npinghue --check\n```\n\nLinux may block unprivileged ICMP sockets. TCP mode does not need special privileges:\n\n```sh\npinghue -p 443 example.com\n```\n\nIf `pinghue --check` reports that your GID is outside `net.ipv4.ping_group_range`, the preferred fix is to allow only your current group:\n\n```sh\ngid=\"$(id -g)\"\nsudo sysctl -w \"net.ipv4.ping_group_range=${gid} ${gid}\"\necho \"net.ipv4.ping_group_range=${gid} ${gid}\" \\\n  | sudo tee /etc/sysctl.d/99-pinghue.conf\n```\n\nThe broader range `0 2147483647` also works, but enables unprivileged ICMP for every local group on the system.\n\nThe capability alternative is available but must be re-applied after binary upgrades:\n\n```sh\nsudo setcap cap_net_raw+ep \"$(command -v pinghue)\"\n```\n\nDo not set capabilities on a shared Python interpreter.\n\n## JSON Output\n\n`--output PATH` writes one JSON document per run. The schema lives at `schemas/output-v1.schema.json`, and an example lives at `examples/pinghue-output-example.json`.\n\n```sh\npinghue -f hosts.txt --duration 180 --output maintenance.json\n```\n\nUse `--no-samples` when you only need final per-target statistics.\n\nEvery output document includes:\n\n- `schema_version`\n- `pinghue_version`\n- run metadata (including `samples_window`)\n- probe configuration\n- ordered target results\n- per-target stats\n- optional per-probe samples\n\nPer-target `stats` (sent, received, loss, latency, jitter) are computed over **every** probe in the run, so `stats.sent` reflects the whole run. The per-target `samples` array retains only the most recent `run.samples_window` probes (currently 1000). On long runs `stats.sent` therefore exceeds `len(samples)` — that is expected windowing, not a truncated file. When reconciling evidence, treat `samples` as the recent tail and `stats` as authoritative for the full run; `--no-samples` omits the array entirely.\n\nThe `run.host` field defaults to `local` to avoid leaking workstation hostnames. Use `--host-label` when a report needs an operator-selected system or maintenance-window label.\n\n## Security Model\n\n`pinghue` is a local CLI/TUI. It does not run a server, accept remote requests, store credentials, or require secrets. The security-sensitive areas are:\n\n- terminal rendering of operator-supplied hostnames and OS error strings\n- Linux ICMP privilege configuration\n- local output paths selected by the operator\n- release workflow integrity\n\nSee `pinghue-threat-model.md`, `security-best-practices-report.md`, and `SECURITY.md`.\n\n## Release Channels\n\nPublished release channels:\n\n1. GitHub repository: `inxbit/pinghue`\n2. GitHub Actions CI on Linux and macOS\n3. GitHub Release with sdist and wheel artifacts\n4. PyPI trusted publishing through a protected `pypi` environment\n5. Homebrew tap: `inxbit/tap` from `inxbit/homebrew-tap`\n\nThe release workflow is tag-driven:\n\n```sh\ngit tag -s vX.Y.Z -m \"Release vX.Y.Z\"\ngit push origin vX.Y.Z\n```\n\n## Development\n\n```sh\npytest\npytest --cov=pinghue --cov-report=term-missing --cov-fail-under=80\nruff check .\nmypy src\npip-audit\nSOURCE_DATE_EPOCH=0 python -m build --no-isolation\ntwine check dist/*\n```\n\nRun the development commands from a clone installed with `python -m pip install -e \".[dev]\"`. The `pytest --cov` line reports line and branch coverage; CI enforces a coverage floor.\n\n## License\n\nMIT. See `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finxbit%2Fpinghue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finxbit%2Fpinghue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finxbit%2Fpinghue/lists"}