GHA Explorer
A terminal UI for exploring GitHub Actions workflow timing data. Fetches successful workflow runs from any repo you have access to straight from the GitHub API, caches everything locally in SQLite, and shows interactive trend charts of pipeline and job durations.
Features
- Incremental sync — on launch, cached data displays instantly, then new runs fetch in the background. No re-fetching what you already have.
- Multi-repo support — switch between any repo you own or have access to. All data lives in a single local cache DB.
- Dynamic discovery — workflows, jobs, and matrix shards all auto-detected from your actual run history. Nothing hardcoded.
- Trend charts — duration trends with rolling averages, per-job and pipeline-wide.
- Job groups — combine matrix shards (
Tests (1),Tests (2)) or a renamed job into one entry; grouped jobs get a per-member breakdown chart. - Per-repo settings — full-screen Settings page (
,or⚙ Settings): job groups (create, edit, rename — exclusions and notes follow a rename), and include/exclude tables for workflows, jobs and branches with Include all / Exclude all. Workflows and jobs are opt-out (everything included until you exclude it); branches are opt-in (a repo starts with its long-lived branches — main, develop… — and newly seen branches stay excluded until you include them, since branches are created constantly). Excluding a workflow removes its runs, and therefore its jobs. - Outlier filter — optional Hampel filter (rolling median + MAD) hides transient spikes — a stuck queue, a flaky runner — from the trend charts while keeping lasting duration changes visible. Tune sensitivity and window in Settings → General.
- Filters — by workflow, branch (top branches discovered from the data, multi-select), time range (1d / 1m / 3m / 6m / 1y / all, or a Custom from/through date range).
- Drag to zoom — click and drag across the trend chart to zoom to that period; it becomes the Custom range (whole days, never finer) and is saved with your filters.
- Notes — pin a note to a date/time ("switched runners", "enabled test cache"). It's drawn as a red vertical line on the trend charts with a clickable ⓘ that pops the note in a bubble, so you can eyeball before/after. A note applies to the job you're viewing by default, or to several jobs, or to all jobs (including ones that don't exist yet). Notes on jobs that later get grouped show on the group's chart prefixed with the source job. Each note has a colour (red by default). Manage them via
ⓘ Notesat the right of the stats line orn; a note's bubble has Edit and Delete (with confirmation). - Sticky state — repo, active tab, sidebar collapsed, and per-repo filter selections (workflow, job, branches, time range, y-axis) are saved in the database and restored next launch.
- Status tab — live sync phase and progress, GitHub API rate-limit gauge, call/error counters, cache stats, and a streaming log.
- Resilient — walks past the API's 1000-result cap per query, backs off on rate limits, and backfill resumes next launch.
- No
ghrequired — talks to the GitHub REST API directly. If you have theghCLI signed in it reuses that login silently; otherwise a one-time in-app sign-in (browser device flow, or paste a token). - Dark lavender theme — plus
--themeto use any built-in Textual theme (charts recolor to match).
Requirements
uv— providesuvx; it fetches Python 3.11+ and the dependencies for you- Charts use plotext 6, which ships compiled wheels for macOS (Intel/Apple silicon), Linux (x86_64/aarch64) and Windows x86_64; other platforms need a C compiler to build it
- A GitHub account. The
ghCLI is optional — see Signing in. - On Windows, use Windows Terminal (or another modern terminal) for colours, glyphs and mouse support.
Run
No clone needed — it's on PyPI:
uvx gha-explorer
uvx gha-explorer --repo owner/name # skip the picker
Or install it as a tool so gha-explorer is on your PATH:
uv tool install gha-explorer
gha-explorer --theme catppuccin-mocha # any built-in Textual theme
uv tool upgrade gha-explorer # pick up new releases
To run the latest unreleased code straight from main, point uvx at the repo instead:
uvx --from git+https://github.com/swils23/gha-explorer gha-explorer
From a checkout, the single file still runs directly (it carries inline script metadata):
./gha_explorer.py # or: uv run --script gha_explorer.py
Run it inside a git checkout whose origin is on GitHub and it opens that repository. Otherwise the first launch shows a repo picker listing every repo you have access to; pick one and it starts fetching. Your last choice — plus filters, active tab and sidebar state — is remembered for launches outside a checkout. s switches repo at any time.
Signing in
Credentials are looked up in this order, and you're only asked if none apply:
GH_TOKEN/GITHUB_TOKENin the environment.- The
ghCLI's login (gh auth token), whenghis installed and signed in — the default for gh users, so nothing changes for you. - The built-in sign-in, saved from a previous launch.
- Otherwise a sign-in dialog: authorize in your browser with a one-time code (GitHub's device flow, the same mechanism
gh auth loginuses), or paste a personal access token (classic:reposcope; fine-grained: Actions: read + Metadata: read). The token is saved inauth.jsonin the data directory, readable only by you.
Settings → General → GitHub access switches between the gh login and the built-in sign-in (the gh option is disabled, with an explanation, when gh isn't available), and has Sign in / Sign out buttons. gha-explorer --logout forgets the built-in login from the command line.
Where data lives
Everything — the runs cache, settings and notes — lives in one SQLite file, gha-explorer.db, alongside the log and the saved login (auth.json) in a per-user directory: ~/.local/share/gha-explorer (or $XDG_DATA_HOME/gha-explorer; %LOCALAPPDATA%\gha-explorer on Windows). Set GHA_EXPLORER_HOME to put the directory somewhere else, and gha-explorer --data-dir prints the resolved path. A checkout that already has a database next to the script keeps using it, and a cache.db from before the first release is renamed on first launch.
Settings → General has a Database section: change the file's path (to rename or move it — the current database is copied to the new location if nothing is there yet), or Reveal in Finder / Explorer. A custom path is remembered in paths.json in the data directory; GHA_EXPLORER_DB overrides it.
Keybindings
| Key | Action |
|---|---|
q |
Quit |
r |
Refresh (incremental sync) |
R |
Full rescan (re-walk history back to repo creation) |
s |
Switch repo (open picker) |
f |
Collapse / expand the filter sidebar (or the < / > buttons at its foot) |
n |
Open the notes manager (add / delete notes) |
, |
Open Settings for the current repo (Esc / Close to return) |
Esc |
Close an open note bubble |
1 |
Trends tab |
2 |
Runs tab |
3 |
Status tab (sync progress, API rate limit, log) |
Architecture
The script is a single file (gha_explorer.py) — also packaged as the gha-explorer console script via pyproject.toml — with four layers:
- Database (SQLite, WAL —
gha-explorer.db) —run_jobsstores the normalised run-list row + the raw/actions/runs/{id}/jobsJSON perrun_id, keyed by repo;sync_metarecords per repo whether backfill has reached the repo's creation date;settingsholds sticky UI state and per-repo config (global and per-repo scopes, JSON values);notesholds timestamped annotations per repo, each scoped to all jobs or a list of jobs. Never re-fetches the same run. - Fetch — GitHub REST API via stdlib
urllib(noghsubprocesses):/actions/runsfiltered bystatusandcreated,/actions/runs/{id}/jobs,/user/repos,/rate_limit. Incremental sync: forward-fetch runs newer than the newest cached run, then backfill backwards in 90-day windows until the repo's creation date. Every list call walks past the API's 1000-result cap by moving the upper date bound down and deduping, so busy windows don't silently drop runs. Once backfill completes it's skipped on later launches (Rforces it). Auth is a token from$GH_TOKEN,gh auth token, or the in-app OAuth device flow (resolve_token()); a 401 mid-sync re-opens the sign-in dialog. - Aggregation — stats (mean / median / min / max / stdev) and rolling averages for trend smoothing.
- TUI (Textual + plotext) — tabs with an inline sync status in the top bar, a filter sidebar inside the Trends/Runs tabs, ASCII charts, and a Status tab fed by a shared
SyncStatsobject and an in-memory log handler. Charts plot one point per run, so notes are placed between the runs that bracket them, proportional to elapsed time; plotext draws the line and ⓘ, then the ⓘ is made clickable by attaching the note id as Rich style meta.
Everything is derived from the data itself — no hardcoded workflow, job, or branch names, and no automatic grouping: matrix shards appear as separate jobs until you put them in a Group. Repo settings (groups, exclusions, rolling window) are applied on top of the cached runs (apply_repo_config) before anything is filtered or charted.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gha_explorer-0.1.6.tar.gz.
File metadata
- Download URL: gha_explorer-0.1.6.tar.gz
- Upload date:
- Size: 70.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e0c04af94a6808c24f545e8f663df2f533cdf6ca0a095a64b916698fb07a552
|
|
| MD5 |
f05565883ad2ea0a09267f2ea53ed5a5
|
|
| BLAKE2b-256 |
fd0cb07337b012f6a938bde1767340b5ab91280f6271f939aff6aef783690baa
|
File details
Details for the file gha_explorer-0.1.6-py3-none-any.whl.
File metadata
- Download URL: gha_explorer-0.1.6-py3-none-any.whl
- Upload date:
- Size: 71.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.7 {"installer":{"name":"uv","version":"0.12.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
510da8e3121f0e1819fec5aeebf4b6a528da9501c45017507e51a89928942423
|
|
| MD5 |
711364d8bafb06fecffd7cb482f2949c
|
|
| BLAKE2b-256 |
9aff23fc6af01fcd9a7efdde63aa25db7865faf05e7b8b029de04a8703ecf047
|