Back to articles

Version Manager - Cross-Machine Software Dashboard

Computer TechVersion Manager - Cross-Machine Software Dashboard
Updated 4/23/2026

Version Manager - Cross-Machine Software Dashboard

A real-time admin dashboard on the Midimaze platform that provides a single pane of glass for all installed software, git repo sync status, and configuration parity across multiple macOS machines.

Problem

Managing software across multiple machines (MacBook Pro and Mac mini) with 6+ package managers (Nix, Homebrew, pip, bun globals, Mac App Store, manual installs) creates fragmentation. Without a unified view, there's no way to quickly answer:

  • Is package X up to date?
  • Is package Y installed via multiple managers (conflict)?
  • Are my git repos (dotfiles, nix-config, claude skills) in sync across machines?
  • Which brew packages still need to be migrated to Nix?

Architecture

Collector-Push Model

A local Bun script runs on each machine and pushes data to Convex via authenticated HTTP actions. This is the same pattern used by monitoring tools like Datadog — each machine reports its own state to a central store.

┌─────────────┐     POST /software-inventory/collect
│  MacBook Pro │ ──────────────────────────────────────► ┌─────────┐
│  (collector) │                                         │  Convex │
└─────────────┘                                         │  Cloud  │
                                                         │         │
┌─────────────┐     POST /software-inventory/repos       │ Tables: │
│  Mac mini    │ ──────────────────────────────────────► │ - pkgs  │
│  (collector) │                                         │ - repos │
└─────────────┘                                         └────┬────┘
                                                              │
                                                    useQuery()│
                                                              ▼
                                                    ┌─────────────────┐
                                                    │ /admin/version- │
                                                    │ manager         │
                                                    │ (React dashboard)│
                                                    └─────────────────┘

Data Sources

CollectorCommandWhat it yields
Homebrewbrew info --installed --json=v2Name, version, latest, homepage, description
Bun globalsbun pm ls -gPackage name, version
pippip list --format=jsonPackage name, version
System Profilersystem_profiler SPApplicationsDataType -jsonGUI apps, App Store vs developer
Audit logsParse ~/.brew-audit-log.txtMigration status per package
Git reposgit commands on each repoBranch, HEAD, dirty, ahead/behind

Security

  • Dashboard: Admin-only via requireRole(ctx, "admin") — not even professor role can see it
  • Collector HTTP endpoints: Authenticated with SOFTWARE_INVENTORY_SECRET Bearer token (same pattern as vault-sync)
  • Data: Package names and versions are not sensitive; repo status shows only commit SHAs and branch names

Features

Package Inventory

  • Conflict Detection: Same package installed via 2+ managers gets flagged (e.g., VLC via both Nix and Homebrew cask)
  • Outdated Indicator: Compares installed version against latest available
  • Migration Tracking: Shows which brew packages are pending migration to Nix, already migrated, or intentionally kept in brew
  • Changelog Links: Auto-resolves GitHub releases URL from homepage; manual overrides for non-GitHub projects (Obsidian, Slack, Zoom, etc.)
  • Source Badges: Color-coded dots per package manager (sky=Nix, amber=Brew, pink=Bun, green=pip, gray=System)

Repo Sync Status

  • Cross-Machine Comparison: Groups repos by name, shows HEAD commit per machine — if they differ, shows DESYNC badge
  • Dirty Detection: Flags repos with uncommitted changes
  • Ahead/Behind Counts: Shows how many commits ahead/behind remote
  • Repo Types: Categorized as project, dotfiles, config, or claude for targeted filtering
  • Scans: ~/Code/github.com/theslyprofessor/, ~/nix-config, ~/dotfiles

Dashboard UI

  • Two tabs: Packages and Repos
  • Machine filter dropdown (All / 21-MBP / Nakuls-Mac-mini)
  • Filter presets: All, Conflicts, Outdated, Pending Migration, Out of Sync, Dirty
  • Sortable table columns
  • Click-to-expand detail sidebar for packages
  • Summary stat cards with counts

Running the Collector

bash
# From the midimaze-platform repo
export SOFTWARE_INVENTORY_SECRET=<your-secret>
bun run scripts/collect-software-inventory.ts

The collector:

  1. Detects which machine it's running on via scutil --get ComputerName
  2. Runs all package collectors in parallel
  3. Merges results with name normalization (handles aliases like python312python3)
  4. Scans git repos for sync status
  5. Pushes everything to Convex

Run it on both machines to populate cross-machine comparison data.

Convex Schema

Three tables in convex/schema/softwareInventory.ts:

  • softwarePackages: One row per (package, machine) pair with per-source version fields
  • repoSyncStatus: One row per (repo, machine) pair with branch, HEAD, dirty, ahead/behind
  • softwareCollectionRuns: Audit log of collector invocations with timestamps and stats

Key Files

FilePurpose
convex/schema/softwareInventory.tsSchema definition (3 tables)
convex/softwareInventory.tsQueries + internal mutations
convex/http.tsHTTP endpoints for collector
apps/web/src/routes/admin/version-manager.tsxDashboard UI
scripts/collect-software-inventory.tsLocal collector script

Future Ideas

  • Nix store path parsing: Extract versions from ~/.nix-profile/bin/ symlink targets for Nix-only packages
  • Scheduled collection: Run the collector on a cron (every 6 hours) via launchd
  • Diff view: Side-by-side comparison of what's on MBP vs Mac mini
  • Export: JSON/CSV export for auditing
  • Migration planner: Auto-generate brew uninstall commands for conflicting packages