Skip to content

feat: macOS menu-bar plugin (sshshot menubar install)#26

Merged
flamerged merged 1 commit into
masterfrom
feat/menubar-install
May 12, 2026
Merged

feat: macOS menu-bar plugin (sshshot menubar install)#26
flamerged merged 1 commit into
masterfrom
feat/menubar-install

Conversation

@flamerged
Copy link
Copy Markdown
Owner

Summary

  • New sshshot menubar install / uninstall / status subcommands that drop a SwiftBar plugin at ~/SwiftBarPlugins/sshshot.5s.sh. The plugin renders a 📸 icon in the macOS menu bar showing daemon state and active target; clicking opens a submenu with target switcher (all configured remotes), pause/resume/restart, and open-config/log shortcuts.
  • All menu actions are click-throughs to existing sshshot subcommands — no new daemon endpoints. Refresh interval: 5 s. Status reads sshshot status --json with ~/.config/sshshot/config.json as fallback when the daemon isn't running yet.
  • Two CLI-side fixes the menu needed: sshshot start <target> now accepts a positional target so SwiftBar can bypass the interactive prompt; the plugin prepends node's directory to PATH so the shebang resolves under SwiftBar's minimal env (the root cause of "switch notifications fire but daemon never starts").

Why

Manually running sshshot target <one-of-16-remotes> from a terminal is friction. The menu bar replaces a tab-completed CLI dance with a click, and surfaces "paused" / "not running" state visibly — easy to forget the daemon is paused without it.

Implementation

  • src/menubar.ts — the plugin script is embedded as a TS template literal so the CLI distribution stays a single file. install() writes atomically (tmprename), detects SwiftBar presence, prints the right next-step message. Non-macOS platforms get a clear "macOS-only" message.
  • src/index.ts — dispatcher wires menubar subcommand; startCommand() accepts optional targetArg to make the start-daemon button work non-interactively.
  • README — adds the new commands, a usage section, and notes that the Phase 6b clipboard-mode work will surface as menu entries when it lands.

Test plan

  • yarn test — 12 new tests in test/menubar.test.ts (53 passing total)
  • yarn lint, yarn typecheck, yarn format:check, yarn build — all green
  • On macOS: brew install --cask swiftbar → launch SwiftBar → point at ~/SwiftBarPlugins → 📸 appears
  • Click "Start daemon" → daemon comes up with active target (validated in sim with minimal PATH)
  • Click "Switch target" entries → notifications fire + ~/.config/sshshot/config.json updates
  • Click "Pause"/"Resume" → daemon state flips + header changes to ⏸
  • sshshot menubar uninstall → file removed
  • sshshot menubar status → reports correctly when installed and when not
  • On Linux/Windows: sshshot menubar install exits cleanly with "macOS-only" message

Future work (out of scope)

The clipboardMode: "auto" | "manual" | "always" setting from the Phase 6b roadmap will surface in the menu's daemon-control block as a mode toggle once it lands. Noted in README.

@flamerged flamerged force-pushed the feat/menubar-install branch 2 times, most recently from bd1b7e1 to c6bce4a Compare May 12, 2026 17:50
Drops a SwiftBar plugin script at ~/SwiftBarPlugins/sshshot.5s.sh that
renders a 📸 icon in the menu bar showing the daemon state (running /
paused / idle) and the active target. Clicking the icon opens a submenu
to switch target across all configured remotes, pause/resume/restart,
or open config/log files — every action is a click-through to existing
sshshot CLI subcommands, no new daemon endpoints needed.

The plugin script is embedded as a template literal in src/menubar.ts
so the CLI distribution is a single file. Install is idempotent, writes
atomically (tmp-then-rename), and detects whether SwiftBar is installed
to print the right next-step message.

Two CLI-side fixes that the menu bar needs:

- 'sshshot start' now accepts an optional target argument:
  'sshshot start <target>' bypasses the interactive promptSelect. The
  menu bar can't answer interactive prompts, so without this the
  Start-Daemon button silently did nothing. Existing 'sshshot start'
  with no args is unchanged (still prompts).
- The plugin exports PATH with node's directory prepended at the top.
  SwiftBar runs plugin scripts with a minimal PATH (/usr/bin:/bin) that
  doesn't include nvm; without this prepend, the #!/usr/bin/env node
  shebang fails and every menu click silently no-ops behind the
  notifications. node's directory is captured from process.execPath at
  install time. Users on nvm should re-run 'sshshot menubar install'
  after switching node versions.

New commands:
  sshshot menubar install     write the plugin (creates dir if needed)
  sshshot menubar uninstall   remove the plugin file
  sshshot menubar status      show install state + SwiftBar presence

Linux/Windows are no-ops with a clear message — SwiftBar is macOS-only.

The clipboardMode work (Phase 6b context-aware routing) will surface in
this menu later with auto/manual/always toggle entries.
@flamerged flamerged force-pushed the feat/menubar-install branch from c6bce4a to ab1a968 Compare May 12, 2026 17:59
@flamerged flamerged self-assigned this May 12, 2026
@flamerged flamerged merged commit f38130b into master May 12, 2026
5 checks passed
@flamerged flamerged deleted the feat/menubar-install branch May 12, 2026 18:16
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 0.9.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant