tailscale: Tailscale status & control (port of the v4 tailscale plugin) - #72
tailscale: Tailscale status & control (port of the v4 tailscale plugin)#72rylos wants to merge 10 commits into
Conversation
Port of the v4 tailscale plugin to the v5 Luau plugin API, built around fast host access: /ts launcher provider (Enter copies a peer's IP, "/ts n" copies its name), a panel with online-first peer list, per-row copy/ping/SSH/exit-node actions and live filter, connect/disconnect, Taildrop receive, last-seen for offline peers, up/down shortcut, and a desktop widget. All host interaction goes through the tailscale CLI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
• 1. blocking - tailscale/service.luau:224
|
Review follow-up on noctalia-dev#72: - shell-quote every interpolated value in spawned command lines (Taildrop dir, ping/exit-node IP, auth URL, ssh target) with a single-quote helper; tighten the auth-URL check and reject an ssh_username that is not a plain login name. - declare ssh, xdg-user-dir, gio and xdg-open in dependencies and document each one in the README Requirements section.
|
Thanks for the review — 1 and 2 are fixed in 9f71603, and the PR description is now filled in with the template. 1. Shell quoting. The runtime only exposes a command line (
2. Dependencies. 3. Template / thumbnail. The description now follows the PR template with the checklist filled in. Screenshots and a regenerated CI is green on the current head. |
The short name (and the MagicDNS FQDN) only resolve when MagicDNS is enabled, so the SSH button opened a terminal that exited immediately with an unresolved-hostname error. The Tailscale IP always works.
`tailscale ping` exits non-zero and prints "direct connection not established" when the peer answers only through a DERP relay, so a perfectly reachable host was reported as a ping failure. Report the last pong line and note that the connection is relayed.
noctalia.formatTime takes strftime patterns, so "hh:mm:ss" was echoed back verbatim and the panel footer read "Last check: hh:mm:ss".
A launcher `badge` is drawn in the icon slot and scaled to fill it, so "online"/"offline" covered half the row and hid the OS glyph. Put the state at the front of the subtitle instead.
|
Point 3 is done too: the description now has screenshots (bar widget with tooltip, panel, While taking those screenshots I also found and fixed three real bugs:
The plugin also ships an Italian translation now ( CI is green and |
The root column's height is what sizes the panel; keeping it as a named constant next to a note about plugin.toml stops the two from drifting.
|
The panel uses 24 predeclared callback slots and silently truncates the peer list at tailscale/panel.luau:255. The current plugin UI API supports closures directly in callback properties, with handlers replaced on each render. Capture each row's peer in its button callbacks instead, then remove MAX_SLOTS, the slot table, and the numbered callback globals. This removes the arbitrary peer limit and substantially simplifies the panel. Recommend removing:
Each row can capture its peer directly: ui.button({
glyph = "activity",
onClick = function()
sendCmd("ping", { ip = peer.ip, name = peer.name })
end,
}) |
Plugin
rylos/tailscaleplugin.toml)What it does
Tailscale status and control, built around fast host access: see which peers are online and copy their IP or name in
one gesture. A port of the v4
tailscaleplugin (credited in the README, MIT) to the v5 Luau plugin API.
Entries: bar widget (
bar), panel (panel), headless poller service (poller), up/down control-center shortcut(
toggle),/tslauncher provider (hosts), desktop widget (desktop).Highlights:
/ts <query>fuzzy-searches the tailnet and Enter copies the peer's IP (/ts n <query>copies itsTailscale short name); panel with online-first peer list, live filter, per-row copy IP / copy name / ping / SSH /
use-as-exit-node, last-seen for offline peers, exit-node banner, Taildrop receive. Duplicate host names are
disambiguated with the unique Tailscale short name.
Not ported from v4: Taildrop send (the plugin API has no file picker) and multi-account switching.
External dependencies
Declared in
dependenciesand documented in the READMERequirementstable:tailscaletailscale status --json),up/down,set --exit-node=…,ping -c 3 <ip>,file get <dir>.sshssh <tailscale-ip>), launched in the user's terminal vianoctalia.runInTerminal.xdg-user-dirtaildrop_dirsetting is empty.gioxdg-opengiois unavailable.Only
tailscaleis needed for the core flows; the rest back optional actions.Every network call, filesystem access, and spawned process
tailscale file getto report whichfiles arrived. No other reads or writes.
copied to the local clipboard.
directory, peer IP, auth URL, SSH target) is single-quote shell-escaped; the auth URL is pattern-checked and
ssh_usernameis rejected unless it is a plain login name.Testing
Developed and tested live against a real 18-peer tailnet: launcher copy flows (
/ts,/ts n), panel actions(copy IP/name, ping, SSH, exit node set/clear), Taildrop receive in operator mode, host-name deduplication, every bar
state (running / stopped / needs-login / not-installed), the desktop widget, and the control-center shortcut.
noctalia plugins lint: 0 errors, 0 warnings.Screenshots / Videos
Host names and Tailscale IPs are masked.
Bar widget (tooltip with state, this node and the peer count)
Panel (online-first peer list, filter, per-row copy / ping / SSH / exit-node buttons)
Launcher (
/ts <query>, Enter copies the peer's IP)Checklist
idafter the/inplugin.tomlexactly.plugin.toml,README.md,thumbnail.webp, andtranslations/en.json.README.mdfollows theREADME template, documents
every entry id and dependency, and includes exact panel IPC commands and launcher prefixes where applicable.
thumbnail.webpwith the thumbnail generator.versionfollows semver and is bumped in this PR;plugin_apiis the oldest API level this plugin requires.understand that language well enough to review and maintain it (no unreviewed machine/LLM translations).
(This PR ships
en.jsonandit.json; Italian is my native language.)catalog.toml; CI generates it.Code review attestation
licensedeclared inplugin.toml.Credits
Based on the v4 tailscale plugin, MIT.