Skip to content

feat: combine token usage from a remote Mac over SSH - #315

Open
yourconscience wants to merge 1 commit into
chattymin:mainfrom
yourconscience:feat/remote-mac-usage
Open

yourconscience wants to merge 1 commit into
chattymin:mainfrom
yourconscience:feat/remote-mac-usage

Conversation

@yourconscience

Copy link
Copy Markdown
Contributor

Summary

Adds pull-based cross-machine usage aggregation: a user can register a second Mac by SSH target under Settings → Advanced → Remote Macs, and PokeTokenBar imports that machine's local agent logs (Pi, omp, Claude Code, Codex, Gemini, Antigravity, OpenCode, Hermes, Cursor, Grok, Copilot, Kiro, Aside) and folds them into the combined today/week/month totals and companion progression.

How it works:

  • Settings → Advanced → Remote Macs: enter a name, an SSH target (alias from ~/.ssh/config or user@host), and the remote home (~ by default). New machines track all registered providers; Import/Remove and an enable toggle are on each row, with a status line showing the last import time or error.
  • A RemoteUsageImporter mirrors each remote provider's log roots locally under Application Support (RemoteUsage/<machine>/<provider>/root-N/) using /usr/bin/rsync over the existing SSH credentials (batch mode, keepalives, no password prompts).
  • Imports are pull-only: rsync runs in read mode, no --delete; remote files are never written, modified, or deleted. A failed or unreachable remote keeps the last imported snapshot and surfaces a status line instead of dropping usage to zero.
  • Imported mirrors join each provider's scan roots through a new provider-aware CustomScanRoots.providerUnion, so the existing parsers, blob caches, and global dedup handle remote data with no per-provider changes to the readers.
  • Automatic imports are throttled to one attempt per 5 minutes (manual Import button is immediate). One ssh probe per provider reports which remote roots exist, so machines that simply don't use a tool are skipped silently rather than erroring every refresh.
  • Remote paths are rewritten to $HOME inside double quotes (macOS openrsync does not expand ~ inside single quotes — observed on a real machine), and rsync gets a 600s timeout with one retry, because a first import mirrors the remote's whole history while later runs are incremental deltas.
  • Readers that consume exactly one database (Hermes state.db, Cursor state.vscdb, Copilot session-store.db) import only that file, so a multi-GB runtime tree on the remote is neither walked nor transferred.

Extensibility notes: this follows the provider-extension conventions — provider-specific remote root lists live in one switch (RemoteUsage.remoteRoots), generic aggregation is untouched, and there are no new providerID branches on generic paths. Not related to #257 (that issue is about syncing the companion save; this PR aggregates usage logs and never uploads anything).

Validated on a real two-machine setup (M4 local + M1 over SSH): adding the remote raised today's combined total from 28.5M to 98.1M tokens and surfaced an omp tab from the imported logs, without changing the local-only numbers when the machine is disabled. swift test: 1086 tests, 11 skipped, 0 failures.

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation
  • Other:

UI changes

Settings → Advanced gains a "Remote Macs" block between the limit-token row and Additional scan folders.

Before After
Advanced section ends after the limit-token row; cross-machine usage was only possible by hand-wiring external sync tools into Additional scan folders, with no status or health feedback. New "Remote Macs" block: hint text stating imports are read-only, a compact add row (Name / SSH target / home + Add), and one row per machine with an enable toggle, SSH target, status line (last import time, or the error in orange), and Import / Remove buttons.

The popover itself is unchanged: totals simply become combined when a remote is enabled. The canonical assets/ screenshots are regenerated at release, so none are updated here.

Checklist

  • swift build and swift test pass locally
  • PR title and description are written in English
  • UI changes are described above (before/after — images optional)
  • No copyrighted assets, secrets, or private tooling references are committed (see CONTRIBUTING)
  • Tests were added or updated for this change

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant