Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

slab-menubar: tailnet peer submenu with click-to-ssh

Adds a "Tailnet: N/M online" submenu populated from `tailscale status
--json`, sorted online-first. Clicking a peer opens Terminal.app and
runs `ssh <hostname>`. Gracefully degrades if tailscale isn't installed
or responding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+70
+70
slab/bin/slab-menubar.py
··· 8 8 ● N work items in flight, lid open 9 9 ◉ ambient playing (lid closed + active work + sleep disabled) 10 10 """ 11 + import json 11 12 import os 13 + import shutil 12 14 import subprocess 13 15 from pathlib import Path 14 16 15 17 import rumps 16 18 from AppKit import NSApplication, NSApplicationActivationPolicyAccessory 19 + 20 + TAILSCALE_BIN = shutil.which("tailscale") or "/opt/homebrew/bin/tailscale" 17 21 18 22 SLAB_HOME = Path(os.environ.get("SLAB_HOME", os.path.expanduser("~/.local/share/slab"))) 19 23 SLAB_BIN = Path(os.environ.get("SLAB_BIN", os.path.expanduser("~/.local/bin"))) ··· 64 68 return AMBIENT_FLAG.exists() 65 69 66 70 71 + def tailscale_peers(): 72 + """Return [{hostname, os, online, active}, ...] sorted online-first, or None if tailscale unavailable.""" 73 + try: 74 + out = subprocess.check_output( 75 + [TAILSCALE_BIN, "status", "--json"], 76 + text=True, stderr=subprocess.DEVNULL, timeout=2, 77 + ) 78 + except (subprocess.CalledProcessError, FileNotFoundError, 79 + subprocess.TimeoutExpired, OSError): 80 + return None 81 + try: 82 + data = json.loads(out) 83 + except json.JSONDecodeError: 84 + return None 85 + peers = [] 86 + for peer in (data.get("Peer") or {}).values(): 87 + peers.append({ 88 + "hostname": peer.get("HostName", ""), 89 + "os": peer.get("OS", ""), 90 + "online": bool(peer.get("Online")), 91 + "active": bool(peer.get("Active")), 92 + }) 93 + peers.sort(key=lambda p: (not p["online"], p["hostname"])) 94 + return peers 95 + 96 + 97 + def open_ssh(host: str): 98 + """Open a Terminal.app window and run `ssh <host>`.""" 99 + subprocess.run([ 100 + "osascript", 101 + "-e", f'tell application "Terminal" to do script "ssh {host}"', 102 + "-e", 'tell application "Terminal" to activate', 103 + ], check=False) 104 + 105 + 67 106 class SlabApp(rumps.App): 68 107 def __init__(self): 69 108 super().__init__("slab", title="◦", quit_button=None) 70 109 self.status_item = rumps.MenuItem("Status: —") 71 110 self.prompts_item = rumps.MenuItem("Prompts in flight: 0") 72 111 self.subs_item = rumps.MenuItem("Subagents in flight: 0") 112 + self.tailnet_item = rumps.MenuItem("Tailnet: —") 113 + # Seed a child so rumps creates the underlying NSMenu; refresh_tailnet() will replace it. 114 + self.tailnet_item.add(rumps.MenuItem("…")) 73 115 self.awake_item = rumps.MenuItem( 74 116 "Stay awake (lid closed)", callback=self.toggle_awake 75 117 ) ··· 79 121 None, 80 122 self.prompts_item, 81 123 self.subs_item, 124 + None, 125 + self.tailnet_item, 82 126 None, 83 127 self.awake_item, 84 128 rumps.MenuItem("Sleep now", callback=self.sleep_now), ··· 120 164 self.prompts_item.title = f"Prompts in flight: {prompts}" 121 165 self.subs_item.title = f"Subagents in flight: {subs}" 122 166 self.awake_item.state = 1 if sd else 0 167 + self.refresh_tailnet() 168 + 169 + def refresh_tailnet(self): 170 + peers = tailscale_peers() 171 + self.tailnet_item.clear() 172 + if peers is None: 173 + self.tailnet_item.title = "Tailnet: unavailable" 174 + self.tailnet_item.add(rumps.MenuItem("(tailscale not responding)")) 175 + return 176 + online = sum(1 for p in peers if p["online"]) 177 + self.tailnet_item.title = f"Tailnet: {online}/{len(peers)} online" 178 + if not peers: 179 + self.tailnet_item.add(rumps.MenuItem("(no peers)")) 180 + return 181 + for p in peers: 182 + if p["active"]: 183 + dot = "●" 184 + elif p["online"]: 185 + dot = "○" 186 + else: 187 + dot = "·" 188 + label = f"{dot} {p['hostname']} ({p['os']})" 189 + host = p["hostname"] 190 + self.tailnet_item.add( 191 + rumps.MenuItem(label, callback=lambda _, h=host: open_ssh(h)) 192 + ) 123 193 124 194 def toggle_awake(self, sender): 125 195 cmd = "auto" if sender.state else "awake"