Skip to content

Releases

Crowsnest 0.12.0

Choose a tag to compare

@github-actions github-actions released this 05 Nov 16:31

Crowsnest 0.12.0

Syspeek is now Crowsnest. Same product, same 33-view console, same local-only
collection — a name that says what it is: the lookout above the fleet.

What changed

  • The binary, packages, config path, systemd/LaunchAgent/MSI entries, focus
    bridges, docs, site and the relay dashboard all say Crowsnest.
  • Repositories: codeafridi/Crowsnest and codeafridi/crowsnest-relay
    (old URLs redirect).

Upgrading is not a reinstall

  • On first start the new config file is seeded from ~/.config/syspeek
    (or Syspeek), and SYSPEEK_CONFIG is still read.
  • The stable machine id and the offline spool are copied from the old cache
    directory first, so the relay does not see a brand-new machine.
  • Installers remove the old systemd unit, XDG autostart, LaunchAgent, HKCU Run
    value, shims and GNOME/KWin focus bridges before installing the new ones.
  • Packages declare Conflicts/Replaces/Obsoletes on syspeek; the MSI keeps
    the existing UpgradeCode; the Homebrew cask conflicts with the old cask.

Deliberately breaking

  • Prometheus metrics are crowsnest_* (were syspeek_*).
  • The --record JSON envelope key is "crowsnest".
  • Webhook payload source/receiver labels name crowsnest.
  • Relay sessions use __Host-crowsnest; existing logins sign in again.

The ingest token hash, session hash and channel-secret HKDF domains keep their
historical values on purpose — those strings are stored data, not branding, and
renaming them would invalidate every token, session and sealed secret.

Assets

Platform Asset
Linux (any glibc ≥ 2.34, bundled Qt) crowsnest-portable.tar.gz, Crowsnest-0.12.0-x86_64.AppImage (+ .zsync)
Debian/Ubuntu crowsnest_0.12.0_amd64.deb
macOS 12+ (universal) Crowsnest-0.12.0-macos.dmg
Windows 10+ Crowsnest-0.12.0-windows.msi, Crowsnest-0.12.0-windows-portable.zip

SHA256SUMS covers all six downloadables.

Proof

CI green on Ubuntu 24.04, macOS 15 and Windows, plus both clean-room Debian
container jobs (22.04/24.04 install + --dump + --probe). The portable bundle
and AppImage in this release were built locally and each ran --dump and
--probe before upload.

Not run on real hardware: a real Mac battery, NVIDIA silicon, a real X11
desktop with click-through, a real cloud account.

Syspeek 0.11.2

Choose a tag to compare

@github-actions github-actions released this 01 Nov 22:55

Syspeek 0.11.2 — appearance: an accent, a quieter strip, and backdrops that stay readable

What this adds

Appearance, in Settings → APPEARANCE — three decisions, nothing more.

Accent — one colour, applied only to chrome that carries no meaning: the rail
selection bar, chips, primary section banners, focus rings, and the SYSPEEK
wordmark on the collapsed strip. Four desaturated presets (Classic, Slate, Moss,
Ember) plus a colour picker for anything else. It applies live — no restart.
The surface palette and the ok / warn / crit trio are deliberately not
editable: hand someone the ability to recolour those and the console stops being
readable, which is why the purple went in 0.10.

Strip opacity — the collapsed HUD can go down to 40% so it stops shouting
over an editor. The expanded console is always fully solid; a see-through table
would be a readability bug, not a style.

Backdrop — six curated gradients: Plain, Graphite, Slate, Moss, Ember, Dusk.
They are painted, not loaded, on purpose. The first cut of this feature accepted
any image, and a test image made the PID and CPU numbers unreadable — a correct
outcome, because a photograph cannot promise that white 9 px mono text survives
on top of it. Every preset sits in a narrow dark band (gradient ends under 0.06
relative luminance, which keeps the readout at 7:1 or better), and a test now
asserts that bound so a future "nicer" colour cannot quietly break it.

The backdrop is used in both shapes: full strength behind the collapsed
strip, and as a 40% tint behind the console page with the cards left solid — so
you see the gradient at the edges and never read a table row over it.

Fixes in this release

  • The wallpaper file picker opened behind the always-on-top HUD and froze the
    console until the file manager was closed. It is gone; the accent colour
    picker now opens in front of the HUD instead of behind it.
  • The opacity slider restyled the whole console and synced the config file on
    every pixel
    of a drag. It now changes one window property per step and writes
    the config once, 400 ms after you let go.
  • CI moved from macos-14 (retired on 2026-11-02, and cancelled at dispatch
    during its brownout) to macos-15.
  • One test asserted a silence countdown to the exact minute and could tip over
    milliseconds; the arithmetic is asserted on the helper, the row test checks
    that a countdown renders.

Upgrading

Same one-liners; syspeek update, and the AppImage's zsync channel resolves
(Syspeek-0.11.2-x86_64.AppImage.zsync is published).

14/14 tests on Linux, macOS and Windows, plus the two clean-room Debian/Ubuntu
container builds.

Syspeek 0.11.1

Choose a tag to compare

@github-actions github-actions released this 01 Nov 06:39

Syspeek 0.11.1 — two fixes for problems hit on a real machine

"HUD already running" when nothing was on screen.
The single-instance gate keyed on the user alone, so a HUD running on any
display held the lock for every later launch — a nested server, an Xvfb, a
second seat, or an instance you had forgotten about. The refusal named neither
the display nor the process, and there was no way past it.

  • The lock is now per session: <user>-<platform>_<display>, derived from the
    platform the app will actually use (so an X11 session with a leftover
    WAYLAND_DISPLAY no longer collides two X displays).
  • The refusal names what holds it: a HUD is already running on DISPLAY :99 (pid 996796).
  • syspeek --new-instance starts one anyway.

syspeek update failing with "install a downloader manually".
The real error was a write failure — the bundle was going into /tmp, which is
a tmpfs on most desktops, and on the machine that reported this it was 82% full
(wget: short write: Disk quota exceeded). The installer could not tell "no
downloader" from "the disk is full", so it recommended apt-get install curl
to someone who has curl, and asked for a sudo password to retry a download that
could not succeed.

  • Downloads go to real disk now (SYSPEEK_TMPDIR → $XDG_CACHE_HOME → $HOME →
    TMPDIR → /tmp), on Linux, macOS and Windows.
  • A write failure stops the ladder immediately and says so, with the free space
    of the directory and the XDG_CACHE_HOME escape.
  • The package-manager rescue only runs when there is no downloader at all, and
    the final message quotes the last real error and what was tried.

Test hermeticity. The Windows fake-CLI cases could lose a race with the real
aws.exe on the image and fail intermittently; the provider options now carry a
cliPath so a test — or an operator with two aws installs — can pin the binary
instead of trusting PATH.

Also: the README claimed a "27-page console" in one place and "32-view" in
another. The list is now the rail order and matches the 32 rows the tests pin.

Nothing else changed; 14/14 tests on Linux, macOS, Windows, and both clean-room
Debian/Ubuntu container builds.

Syspeek 0.11.0

Choose a tag to compare

@github-actions github-actions released this 01 Nov 04:16

Syspeek 0.11.0 — one event stream, correlated incidents, and cost that means something

What this release adds

Timeline — one event stream, and "why did this spike"
Every change the console observes (monitor fired/recovered, process/container/unit
action, file integrity change, Kubernetes change, service restart, synthetic check
transition) lands in one bounded ring. The Timeline page lists it with a kind
picker and a filter; every chart carries annotation ticks, so a spike and the
change that caused it sit on the same axis. Hover for the label, click to open the
Timeline narrowed to that instant.

Alert correlation, ownership and flap suppression
Rules now have a grouping key and an owner ([alerts] <id>_group= / _owner=):
app_cpu, host_cpu and host_steal fold into one "compute" incident instead of three
pages, the row names who owns it, and group_wait/repeat_interval follow
Alertmanager's notification cadence. A monitor that flips faster than you can act
on it is marked [FLAPPING] and its outbound notifications are held while the
breach stays visible. Webhook payloads carry group/owner labels and a real
groupKey. New: /metrics exposes incidents open/flapping/unowned.

Cloud cost that means something

  • Burn rate: current $/hour against the account's own trailing baseline, with
    1.5x/3x bands, a cloud_burn monitor, and syspeek_cloud_burn_usd_hour.
  • Idle containers: a container that stays under 1% CPU and 1 KB/s for 15
    minutes is reported in a new IDLE column and on the DOCKER card.
  • Per-pod right-sizing: the Cost page now lists a recommendation per pod —
    request → usage × 1.2, priced at the cluster's own rates. Suggestions are
    floored at 25m CPU / 32Mi memory, because a zero request is BestEffort, not a
    right-size.
  • IaC drift: point [cloud] terraform_state= at terraform show -json output
    (or a raw .tfstate) and the Cloud page diffs it against the account listing —
    MISSING (deleted out of band) and UNMANAGED (created out of band).
  • [cloud] identity=<provider>/<region>[/<account>]: for hosts behind a
    network policy that blocks the instance metadata service. IMDS always wins; the
    override is only a fallback, and the page says which one it used.

Kubernetes contexts
The kubeconfig's contexts are listed on the Kubernetes page and [k8s] context=
targets one — every kubectl call follows it.

Logs page fix
The Logs page had never been wrapped in a scroll area (since well before 0.10.0),
so it rendered as a narrow strip of cards. Fixed, and journalctl failures now
say why instead of just "failed".

Classic palette
The purple/neon look is gone: steel blue accent, azure/muted-green series, navy
banners. Dropdowns are readable on a dark theme (they had no palette at all, so a
combo popup fell back to the light platform theme).

What is proven, and how

Proven by CI on every push (ubuntu, macOS, Windows, plus clean-room
ubuntu:22.04 and ubuntu:24.04 containers for the .deb): 14 test targets, the
--dump headless JSON with its self-test blocks, the probe with a worstMs
budget gate, the recorder, and 32 rendered console pages as an artifact.

Proven against a live endpoint (this cut): the AWS fleet inventory and the
billed-spend query were driven end to end against a local AWS emulator on :4566 —
not fixtures. That is where three defects came from:

  1. a refused forecast (an IAM policy without ce:GetCostForecast, or a provider
    that does not implement it) used to discard the whole billed month-to-date;
  2. billing day keys were not normalised, so the cost burn baseline reported a
    249x spike on a flat account;
  3. right-sizing recommended a zero request for an idle pod — a QoS downgrade
    that would have been worse than the over-request.

Proven against a live cluster: per-pod right-sizing ran on minikube with
metrics-server (15 pods): 11 of 15 pod(s) measured — $221.91/month of request headroom, including both a shrink and a raise.

Never run on real hardware (unchanged from 0.10.0): a real cloud account
(--cloud-prices, the billed-spend card against a provider console), real NVIDIA
silicon, a real Mac battery, and X11 click-through on a real desktop. Azure/GCP/OCI
cost paths remain gated — AWS is the only provider whose spend query is
implemented.

Upgrading

Same one-liners; syspeek update, and the AppImage's zsync channel resolves
(Syspeek-0.11.0-x86_64.AppImage.zsync is published).

Syspeek 0.10.0

Choose a tag to compare

@github-actions github-actions released this 31 Oct 04:09

Billed spend — what you were actually charged

The Cloud page could already estimate what this instance costs from a rate and its uptime. It now also reads what the provider actually billed the account, and keeps the two numbers labelled differently on purpose:

  • AWS via Cost Explorer — ce get-cost-and-usage with UnblendedCost (not blended: blended averages the organization's rates, so a single-account user cannot reconcile it against the invoice), then ce get-cost-forecast for the rest of the month.
  • Azure via consumption usage list (--top 1000, filtered on properties/usageStart).
  • GCP (billing lives in a BigQuery export, there is no CLI cost API) and OCI (usage API not wired) are gated before anything spawns — the page says so instead of showing a zero.
  • Both are queried through the CLI you already logged in with. Syspeek never reads or stores your credentials.

The window is UTC — CE's TimePeriod and Azure's usageStart are UTC dates, so a machine in IST and one in UTC ask for the same month.

what you see meaning
MTD billed so far this month
month end MTD + the provider's own forecast
daily chart per-day billed amount, syspeek.cloud.spend_daily
by service each service's share of the spend

Cost Explorer and Azure consumption calls are billable to your account, so this runs every 6 h, has its own switch ([cloud] spend, default on) and its own budget (spend_timeout_ms, 30 s), and is named in the CLOUD FOOTPRINT card next to the link-local read and the inventory listing.

Prometheus gains syspeek_cloud_spend_month_usd, syspeek_cloud_spend_forecast_usd and syspeek_cloud_spend_service_usd{provider,service}, emitted only when the query actually answered.

AppImage auto-update works again

Every release since 0.5.0 shipped an AppImage advertising an UPDATE_INFORMATION channel that 404'd — appimagetool writes the .zsync into the current directory, so it landed gitignored in the repo root and never reached the release. build_appimage.sh now moves it next to the image and hard-fails the build if none was produced. An image that advertises an update channel that does not exist is worse than a failed build.

Syspeek-0.10.0-x86_64.AppImage.zsync is attached to this release and served from releases/latest/download/.

What this release's CI actually proves

  • Runs on every push, all five jobs (ubuntu-24.04, macos-14, windows-latest, .deb clean-room on ubuntu:22.04 and ubuntu:24.04): 14/14 ctest, --probe with a worstMs blocking-call gate, --record CSV/JSON, and the --dump self-tests including all fifteen cloud ones (rate lookup, cost maths, app share, top consumers, staleness, four-provider fleet parsing, fleet age/self/cost, AWS + Azure spend parsing, forecast fold, UTC window, provider gate).
  • Cloud CLI end-to-end (synthetic accounts): generated aws/az/gcloud/oci executables on PATH drive the real probeCloudFleet, CloudFleetRunner and --cloud-prices — exact argv per provider, listing→rows with resolved ages, a logged-out CLI surfacing the credential gate that names aws configure, non-JSON refused rather than half-parsed, a hanging CLI killed at its budget, a missing CLI surfacing the install gate, and the polled runner delivering with no update blocking.
  • The identity path runs against a real cloud metadata service on every push: the GitHub runners are Azure VMs, so the ubuntu and windows jobs read a genuine IMDS answer (instance id, Standard_D4ads_v5, region, 4 vCPU, uptime).

What is proven by fixtures and maths, not by a live account

  • The AWS CE and Azure consumption parsers are proven against the documented response shapes (botocore 1.43.120 ce/2017-10-25 model, azure-cli 2.91.0 consumption usage list), including the {"value":[…]} wrapper, string-or-numeric pretaxCost, the 1000-row page cap and the Estimated flag.
  • Forecast fold, service aggregation and money formatting are unit-tested; the --dump self-tests fold a fixture of 12.5 + 1.5 + 10.0 into $24.00 billed / $74.00 month end with a $50 forecast.
  • Never run on real hardware / a real account: a live Cost Explorer answer, a live Azure invoice comparison, and --cloud-prices against a credentialed CLI. There is no cloud account behind this project — that is why the CLI stub tests exist, and why the page states its gates instead of guessing.

Everything else from 0.9.0 is unchanged

GPU page, sensors + battery, process/unit/container actions, the history ring with rewind, alert silences with chart bands, the token-guarded /metrics bind, cloud identity/inventory, and the Qt 6.2/6.4 floor with the clean-room container install gate.

Syspeek 0.9.0

Choose a tag to compare

@github-actions github-actions released this 29 Oct 16:44

The biggest Syspeek release so far: four new console pages, real actions on the things it watches, and a local cloud-cost surface — with the packaging gaps that only show up on a real distribution fixed before shipping.

Highlights

  • GPU page — device utilisation, VRAM, temperature and the processes on the GPU. Linux reads fdinfo/amdgpu/nvidia-smi, macOS IOAccelerator, Windows PDH GPU Engine counters.
  • Sensors & battery — hwmon thermal/fan/power plus battery charge, health, cycles and AC state, with host_temp and battery_low monitors wired to the same editable rule table.
  • Actions — TERM/KILL/HUP/PAUSE/RESUME, NICE ±5, I/O priority and OOM adjustment on the selected process; START/STOP/RESTART on containers through the Docker Engine socket; RESTART on systemd/launchd/SCM units. Every refusal names the OS reason, and destructive verbs take a second press.
  • History ring + rewind — a bounded on-disk ring (default 1 h at 1 s) with first/prev/next/latest paging and stored-window charts.
  • Alert silences, chart bands, healthy-only — snooze a monitor for a rolling window without disabling it, see the threshold as a band on the chart, and hide healthy rows in the process tree.
  • Cloud page — instance identity from the link-local metadata service (AWS/Azure/GCP/OCI), accrued cost since this boot, per-app share of the instance rate, and fleet inventory + instance age from your own provider CLI. Prices are never invented: syspeek --cloud-prices imports the on-demand rate through the aws CLI when you ask it to. Read-only, no credentials stored, and a CLOUD FOOTPRINT card on the page lists every outbound action with its cadence and budget.
  • /metrics bind + bearer token — a non-loopback bind is refused unless a token is set, and refused scrapes get 401 with a challenge and zero samples.
  • Per-process disk I/O — iotop's DISK READ/WRITE semantics (write_bytes - cancelled_write_bytes) plus a machine-wide top-consumers card.
  • No more popups — desktop notification popups are gone; alerts live in the console and outbound delivery is [webhook]-only, off by default.
  • Cost + Settings console pages, plus overlay robustness: X11 click-through, sticky across desktops, geometry persisted and rescued if a monitor disappears.

Packaging and honesty (this release's hardening)

  • The tree now builds and runs its suite on Ubuntu 22.04 (Qt 6.2) and 24.04 (Qt 6.4), not only on the newer Qt CI builds against. The .deb links the distribution's Qt, so this is the configuration users actually get.
  • Found and fixed by that gate: Depends: was missing libqt6network6 (a clean install died with libQt6Network.so.6 => not found), and QDateTime on Qt 6.4 renders ISO dates as +00:00 where 6.5+ renders Z, which broke the Alertmanager webhook payload's RFC3339 timestamps. Both are fixed and gated in CI.
  • syspeek --probe now prints the sampler's own cost (tickMs, slowest section, self CPU and RSS) and CI fails a probe whose worst tick exceeds 1.5 s — a blocking call on a sampler tick cannot land silently. Settings states the same numbers.

What CI proves, what the code proves, what nobody has run yet

  • Proven in CI: builds + 14/14 ctest on Linux (apt Qt 6.4.2), macOS 14 (Qt 6.8) and Windows (MSVC Qt 6.8); the .deb installed in a clean Ubuntu 22.04/24.04 container with every shared object resolving and --dump/--probe running; the Azure identity path against a real metadata service (the GitHub Linux/Windows runners are Azure VMs); the gated cloud path plus all cloud cost/rate/fleet maths self-tests on a host with no IMDS; container install, screenshot and installer smokes.
  • Proven by fixtures and self-tests: every provider parser (AWS/Azure/GCP/OCI), rate-file staleness, cost/share arithmetic, fleet state/age/rate rules, webhook payload schemas, history ring layout and corruption handling, sensor/battery parsing.
  • Never run on real hardware: a real cloud account with --cloud-prices credentials; a Mac with a real AppleSmartBattery (runners are VMs); NVIDIA silicon (the development box is Intel i915 without hwmon); a real X11 desktop for click-through; a laptop whose battery actually discharges. Those paths state their gate rather than pretending.

Full changelog: v0.8.9...v0.9.0

Syspeek 0.8.9

Choose a tag to compare

@github-actions github-actions released this 25 Oct 08:46

Syspeek 0.8.9

Local system HUD for your machine — Linux, macOS, Windows. No telemetry; data leaves only if you point a scraper at it.

Highlights

  • Windows console lifecycle fixes — Ctrl+C / Ctrl+Break / console-close now quit the HUD cleanly via a SetConsoleCtrlHandler hook (no more hanging terminal or Task Manager), and the bare syspeek launcher now detaches correctly with a safely quoted shim path (fresh-launch fixes; verified by a new Windows CI smoke).
  • Native FSEvents FIM on macOS (first in 0.8.8) — file integrity monitoring now uses a native FSEventStream with FileEvents|WatchRoot|NoDefer at 0.2 s latency: per-file created/removed/renamed/modified events feed the existing stat+sha256 diff pipeline, watched roots report replacement/removal, and metadata-only churn no longer forces full rescans. Grounded against osquery's FSEventsEventPublisher contract; live-tested on the macOS CI runner.
  • Kubernetes depth (first in 0.8.7) — per-pod/per-node CPU millis + memory from metrics.k8s.io (the kubectl top numbers) in the Kubernetes page.
  • Editable monitors (first in 0.8.7) — all 11 alert rules live-editable in Settings → MONITORS with threshold + sustained-cycle fields, persisted to [alerts].
  • Windows thread profiles (first in 0.8.7) — Profiles page THREADS/OFF-CPU via NtQuerySystemInformation.

Assets

File Use
syspeek_0.8.9_amd64.deb Debian/Ubuntu (all features; systemd/journald/cgroups)
Syspeek-0.8.9-macos.dmg macOS 12+ (universal arm64+x86_64; unsigned — see docs/macos.md for the Gatekeeper one-liner)
Syspeek-0.8.9-windows.msi / -portable.zip Windows 10+ (MSI per-machine; portable zip with dual shims)
syspeek-portable.tar.gz Linux portable bundle (any distro; sh install.sh uses it)
Syspeek-0.8.9-x86_64.AppImage Linux AppImage
SHA256SUMS sha256 for all six files (hashed from the published bytes)

Same one-liner on every OS: sh install.sh (macOS/Linux; Git Bash on Windows also works) — or PowerShell on Windows: irm https://raw.githubusercontent.com/codeafridi/Syspeek/main/cpp/packaging/windows/install.ps1 | iex.

v0.8.8

Choose a tag to compare

@github-actions github-actions released this 24 Oct 15:24

Full Changelog: v0.8.7...v0.8.8

Syspeek 0.8.7

Choose a tag to compare

@github-actions github-actions released this 24 Oct 11:11

Syspeek 0.8.7

Local system HUD for your machine — Linux, macOS, Windows. No telemetry; data leaves only if you point a scraper at it.

Highlights

  • Kubernetes depth — per-pod and per-node CPU millis + memory bytes from metrics.k8s.io (the numbers kubectl top prints): Kubernetes page pods table gains CPU/MEM columns with a server-aware metrics: ok - N pods, M nodes with usage summary; missing metrics-server degrades honestly.
  • Editable monitors — all 11 alert rules are live-editable in Settings → MONITORS: per-rule threshold + sustained cycles (monit-style for N cycles model), applied instantly and persisted to [alerts]; RESET restores the built-ins.
  • Windows thread profiles — the Profiles page (THREADS cpu, OFF-CPU/WAIT) now works on Windows via NtQuerySystemInformation per-thread CPU times + wait reasons; MEMORY (PSS) stays Linux-only.
  • Containers (0.8.6): per-container CPU %, MEM vs limit, NET I/O, PIDS straight from the Docker Engine API socket (multiplexed stats, no CLI needed; named-pipe aware).

Assets

File Use
syspeek_0.8.7_amd64.deb Debian/Ubuntu (all features; systemd/journald/cgroups)
Syspeek-0.8.7-macos.dmg macOS 12+ (universal arm64+x86_64; unsigned — see docs/macos.md for the Gatekeeper one-liner)
Syspeek-0.8.7-windows.msi / -portable.zip Windows 10+ (MSI per-machine; portable zip with dual shims)
syspeek-portable.tar.gz Linux portable bundle (any distro; sh install.sh uses it)
Syspeek-0.8.7-x86_64.AppImage Linux AppImage
SHA256SUMS sha256 for all six files (hashed from the published bytes)

Same one-liner on every OS: sh install.sh (macOS/Linux via Git Bash: also irm https://raw.githubusercontent.com/codeafridi/Syspeek/main/cpp/packaging/windows/install.ps1 | iex on PowerShell).

Syspeek 0.8.6

Choose a tag to compare

@github-actions github-actions released this 24 Oct 05:45

Syspeek 0.8.6

Ships M64 — per-container depth from the Docker Engine API:

  • Containers page goes deep: CPU %, memory usage vs limit, network I/O, and process count per container — the numbers docker stats prints — read straight from the local Engine socket (/var/run/docker.sock, Docker Desktop's socket on macOS, the named pipe on Windows; DOCKER_HOST unix:// and [docker] socket= override). No CLI spawn: depth works even without the docker CLI installed. Without a reachable engine the page keeps the plain docker ps fields.
  • Multiplexed sampling: one socket per container, requests issued together — wall time is the slowest request (~2 s), not the sum; stayed honest with big fleets (budget-capped, missing depth shows --).
  • State coloring from the engine's own health semantics (unhealthy red, healthy green).

Platform packages: Debian .deb, macOS DMG, Windows MSI + portable zip, Linux portable tar.gz + AppImage, unified SHA256SUMS (6 files, hashed from the published bytes).