The command line package is now `tsunagi` and builds the `tsng` executable,
which the packages, the unit, the installers and the workflows install and
run. The core library package becomes `tsunagi-core`, keeping the library name
`tsunagi`, so no code changes `use tsunagi::...`. Directories follow
(crates/tsunagi-core, crates/tsunagi). Every command shown to a person is now
`tsng ...`.
Co-Authored-By: Claude <noreply@anthropic.com>
Release / tsunagi-linux-aarch64 (push) Successful in 2m44s
Release / tsunagi-linux-x86_64 (push) Successful in 4m37s
Release / tsunagi-macos-aarch64 (push) Canceled after 0s
Release / tsunagi-windows-x86_64 (push) Canceled after 0s
Release / Publish release (push) Canceled after 0s
The tray process holds only the icon and starts the same binary with
--window on Open; the window ends when closed, which works on Wayland where
a window cannot be hidden. The devices table now names devices as
hostname (id5), leaves out this device and counts the others.
Co-Authored-By: Claude <noreply@anthropic.com>
Release / tsunagi-linux-aarch64 (push) Successful in 3m14s
Release / tsunagi-linux-x86_64 (push) Successful in 5m21s
Release / tsunagi-macos-aarch64 (push) Canceled after 0s
Release / tsunagi-windows-x86_64 (push) Canceled after 0s
Release / Publish release (push) Canceled after 0s
tray-icon needs gtk::init() and a running GTK loop on Linux, which
eframe/winit never provide, so the tray panicked at startup with "GTK has
not been initialized". Build the tray on a dedicated GTK thread instead.
Co-Authored-By: Claude <noreply@anthropic.com>
- Bundle egui-phosphor (pinned to egui 0.31) and register its glyphs, so the
icon buttons render real icons instead of tofu: refresh, shuffle (generate
secret), pencil/check/x (rename host), copy (Copy secret).
- Copying is now the field itself, not a separate button: clicking the
shortened device id, the network name, the network id, a range or an address
copies the full value and the field flashes green "Copied" for a second
(tracked in egui temp memory, so it clears itself). The standalone copy
buttons are gone.
- In the devices window the connected-peers "rate / plot" column put the rate
and the inline sparkline in a shared row, so the plot shifted as the rate
text changed width ("0 B/s" vs "1.1 kB/s"). The rate now sits in a
fixed-width, truncating cell, so the plot stays put.
Builds and is clippy-clean (-D warnings) on macOS; the UI has not been run in
this headless session.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reworks the tray window per feedback and fills it in.
- Starts hidden in the tray (no window on launch); the window opens from the
menu. On macOS the app now uses the Accessory activation policy, so it lives
in the menu bar with no Dock icon (via a winit event-loop hook, pinned to
eframe's winit). Fixed, non-resizable 360x600 window; the layout targets it.
- Tidied layout: top bar (title + refresh), a bottom panel with the join form
and the action banner, and a scrolling list of network tiles between them.
Labels and values sit on two-column grids so they align; the join name and
secret inputs are the same fixed width.
- A ⟳ button beside the secret generates a fresh random secret
(NetworkSecret::generate), for creating a network.
- Each network tile shows id, range, this device's address, peers
(connected/known), the active and broadcast switches, a Leave button, and a
collapsing "peers (N)" section with a formatted per-peer table (short key,
address, handshake age, tx/rx packets, rate).
- Traffic: a new sampler turns the agent's cumulative packet counters into a
packets-per-second rate per network and per peer, from the deltas between
snapshots (the snapshot now carries a generation and timestamp so each
refresh is sampled once). The network tile shows the current rate and a small
hand-drawn sparkline of recent rates (no extra dependency).
Note: rates are packets/s — the report has no byte counters yet; bytes would
need an agent change. Builds and is clippy-clean (-D warnings) on macOS; the UI
has not been run in this headless session.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A native, lightweight tray application to manage a running agent — no web
engine. It is a thin client over the agent's local control socket, reusing
tsunagi::ipc and the report types directly; it owns its own runtime, logger and
event loop, like the CLI.
This first increment:
- tray icon with an Open/Quit menu (tray-icon); menu events are read on a
background thread so Open works even while the window is hidden;
- a small window that hides to the tray on close and reopens from the menu;
- a background tokio worker that polls status every 2s and runs commands off the
UI thread, writing a snapshot the UI renders from and repainting egui;
- UI: device header, a per-network card (name, id, range, this device's
address, peers connected/known, a Leave button, and the per-network active
and broadcast switches), a join form (name + secret), and a transient
action/error banner; an "agent unreachable" state that names the socket.
Socket resolution: TSUNAGI_CONTROL_SOCKET if set, else the platform default
(/var/run/tsunagi/agent.sock on macOS) — the same socket the group-access agent
serves.
Scope/notes: macOS first (Linux and Windows follow). Not yet done — macOS
accessory activation policy (so there is no dock icon), light/dark tray icons
from assets (the icon is drawn in code for now), and packaging/autostart. Builds
and is clippy-clean (-D warnings) on macOS; the UI itself has not been run in
this headless session.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>