Skip to content

Releases: Wigata-Intech/kay

v0.2.0

Choose a tag to compare

@github-actions github-actions released this 02 Jul 03:48
de13cdc

A major dashboard and fleet release. Fleet now keeps one persistent, self-healing
SSH connection per host; the Overview is a responsive, customisable multi-column
grid with eight panels and richer metrics (per-core CPU, swap, inodes,
connections, failed services, kernel/OS); the tui toolkit gained reusable,
extractable widgets; and a ? help overlay plus fleet drill-in round out the UX.

Changed

  • Responsive Overview — the Overview now flows its panels into one, two, or
    three columns depending on terminal width (≥105 cols → two, ≥160 → three),
    filling the width with a divider between columns, laid out as an ordered grid
    (row-major, honouring your panel order), and using width up to 200 cols instead
    of the old 100-col cap. Customised layouts keep the multi-column rendering
    (previously a custom layout dropped to a single stacked column).
  • internal/tui gained reusable widgetsBar, Gauge, Sparkline,
    Columns, ColumnCount, HumanBytes, HumanDuration moved out of the
    dashboard so the toolkit stays UI-agnostic and reusable (domain colouring stays
    in the dashboard).

Fixed

  • kay version on local builds — when not built via GoReleaser it now falls
    back to the VCS revision/date Go embeds (kay dev (rev abc1234, <date>, dirty))
    instead of a bare dev.

Added

  • ? help overlay — press ? in the dashboard or kay fleet for a
    full, context-grouped key-binding reference; any key closes it. Footers now
    advertise ? help.

  • Better command help — every subcommand accepts -h/--help and prints its
    flags cleanly (exit 0), and kay with no arguments now leads with examples.

  • More Overview panels & metrics — the batched metrics script (still one SSH
    round-trip) now also collects per-core CPU, swap and cached memory,
    inode usage per filesystem, TCP connection counts (/proc/net/sockstat),
    failed systemd units, and the kernel / OS release. The Overview gains
    dedicated Memory (RAM + swap + cached), Disk (space + inodes),
    Connections (active / time-wait), and Services (failed units) panels; the
    System panel shows a per-core level strip (core ▇▂▅▂) and the header shows the
    OS. All eight panels are reorderable/hideable via the o editor and now lay out
    as an ordered grid (row-major, honouring your panel order) that fills the width
    with a divider between columns.

  • Customisable Overview — press o in the dashboard's Overview tab to reorder
    its panels (System, Top processes, Network, Docker) and hide the ones you don't
    want: j/k select, J/K move, space toggle, w save, Esc cancel. The
    layout persists in config.json under a new ui section and applies to every
    host. The config file gains a version field; older files (no version) load
    unchanged and are upgraded in place on the next save — no migration step, no
    data loss.

  • Fleet drill-in — press Enter on a host in kay fleet to open its full
    dashboard, and Esc/q to return to the overview; Ctrl-C (or SIGTERM) exits the
    whole app. A single screen and input reader are shared for the session, so the
    handoff is seamless (no flicker) and there are never two goroutines competing
    for stdin. Internally fleet.RunView/dashboard.RunView run a view against a
    caller-owned screen + event channel; cmd/kay coordinates the two. kay fleet
    gains --read-only for the drilled-in dashboard.

  • Per-host fleet state — the fleet overview now collects each host
    independently and streams results in as they arrive, so one slow or unreachable
    host no longer freezes the whole view or blocks input. The overview is
    interactive immediately; Enter on a host that is still connecting or offline
    shows a brief message instead of drilling in, and only ready hosts open.

  • Top containers (docker stats) — press t in the dashboard's Docker tab
    to open a live, sortable "top containers" overlay: CPU%, memory% (coloured),
    memory usage, and net I/O per container, sorted by CPU (c) or memory (m),
    with r to reload. The query is slow, so it runs on-demand and asynchronously
    with a loading state (Esc cancels) — the periodic snapshot stays fast.

  • Disk explorer — press Enter (or l) on a mount in the dashboard's Disk tab
    to drill into it: directories (recursive du size) and files (size via
    find) are listed largest-first, showing the name and extension. Enter/l/→
    descends into a directory, h/←/Backspace goes up (never above the mount), and
    Esc exits. Dotfiles are hidden by default; . toggles them and shown hidden
    entries are dimmed and tagged. Opening a file raises a dismissable
    "not supported" notice. Scans run on-demand over SSH, one level at a time, and
    asynchronously with a loading state so the dashboard stays responsive on
    large trees; keys are ignored mid-scan (except Esc to cancel). Paths are
    single-quoted so names with spaces or shell metacharacters are inert.

  • Vim-friendly keys — the dashboard is consistent across every tab and
    overlay: h/j/k/l to move, g/G for ends, H/L to switch tabs, and
    Esc/q to back out.

Changed

  • Persistent fleet connectionskay fleet now keeps one long-lived,
    self-healing SSH connection per host and reuses it for every refresh, instead
    of dialing a brand-new connection each tick. Reusing the transport skips the
    KEX + public-key-auth handshake on all but the first connect, which cuts CPU,
    network round-trips, and — most visibly on the server — the connection churn
    that spams auth.log and pressures sshd's MaxStartups. A shared dial cap
    bounds concurrent connects so a large fleet's cold start can't self-throttle,
    and reconnects use exponential backoff with jitter. Drilling into a host now
    reuses the connection the fleet already established (no second handshake),
    and the drilled-in dashboard inherits the connection's self-healing. New
    internal/sshx types Pool and Managed implement this, stdlib-only.

  • Responsive startup — the dashboard's first metric collection now runs
    asynchronously behind a "connecting…" screen instead of blocking, and both the
    dashboard and kay fleet ignore input (except quit) until the first data
    arrives. Keys pressed during the initial 1–3 s connect no longer queue up and
    fire when the view appears.

v0.1.2

Choose a tag to compare

@github-actions github-actions released this 01 Jul 13:34
a7dcefc

Internal cleanup: no behavior change and no new features. Reduces duplication,
splits an oversized file, tightens package seams, and makes the interactive code
testable (total coverage 66.9% → 73.7%).

Changed

  • Shared UI helpers — moved the duplicated setColor, clampAll,
    firstLine, and colour-threshold logic out of dashboard and fleet into the
    tui toolkit (SetColorMode, ClampAll, FirstLine, ThreshColor). No
    behavior change; both views now share one source of truth for colour and
    layout.
  • Split dashboard.go — the 1200-line file is now four focused files in the
    same package: dashboard.go (lifecycle + data), input.go (keys/actions),
    render.go (view builders), and format.go (pure formatting helpers). Pure
    code move, no behavior change.
  • Unified the SSH seamdashboard.Client is now an alias of
    metrics.Runner, so the dashboard and the metrics collector share one
    interface instead of two identical copies.
  • Split tui.List into List + Pager — the selectable list and the
    scrollable overlay were one dual-mode type gated by a selectable flag;
    they are now two focused widgets (List.Render(w, h) drops the flag), which
    removes the never-used pager branch from the list path.
  • Raised sshx coverage from ~48% to ~72% with white-box tests for the
    non-interactive helpers (termType, classifyDialError, contains,
    appendKnownHost, confirmHost, and the hostKeyCallback pinning/rejection
    paths). The remaining gap is interactive (Shell, terminal read).
  • Testability seams — extracted terminal-independent cores so the
    interactive paths can be tested without a real TTY, with no behavior change:
    the host-key TOFU prompt (confirmHost), the key passphrase decrypt path
    (parseSigner), and the dashboard/fleet event loops (loop, driven by an
    injected screen interface and input/signal/tick channels). Total coverage
    rose from ~67% to ~74% (dashboard 80%, fleet 62%, sshx 72%, keys 77%).

v0.1.1

Choose a tag to compare

@github-actions github-actions released this 01 Jul 11:46

Quality, tooling, and documentation hardening. No new features and no behavior
changes (one concurrency bug fixed).

Added

  • CI quality gateslint (golangci-lint v2), gosec, and govulncheck
    jobs, mirrored locally by make ci. gosec runs through the setup-go
    toolchain so CI matches local exactly.
  • Cyclomatic-complexity gategocyclo (min-complexity 15) added to the
    lint config; every function is now ≤15 (Go Report Card A+).
  • CodeQL advanced setup — a workflow + config carrying a query-filter for the
    intentional, opt-in --insecure host-key path.
  • Coverage toolingmake cover / make cover-html; a Coverage workflow
    publishing a self-hosted shields badge (no external service); and a CI coverage
    report with a 50% regression floor and a sticky per-package PR comment.
  • RELEASING.md — maintainer guide for cutting a release.

Changed

  • Reduced every function above cyclomatic complexity 15 to ≤15 via dispatch
    tables and helper extraction, with no change in behavior.
  • Standardized tests — external black-box packages, table-driven, positive-then-
    error ordering — and raised total coverage from 35.6% to 66.9%.
  • Relaxed the go.mod directive to go 1.26 (minor granularity).

Fixed

  • License detection — replaced LICENSE with the canonical Apache-2.0 text
    so pkg.go.dev reports Apache-2.0 instead of "UNKNOWN".
  • SSH client data racesshx.Client.Close reassigned the done channel
    while the keepalive goroutine read it; Close now closes the channel once via
    sync.Once and never reassigns it, so it is race-free and idempotent.

Security

  • Added audited //#nosec directives for the intentional paths: G106
    (--insecure opt-in), G304 (reads from kay's own key/config store), and G306
    (world-readable .pub).

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 01 Jul 05:47

Changelog

Features