Local dev dashboard for macOS: one console for everything running on your machine.
Dockmaster grew out of Port Authority — the single-file port
dashboard now lives in legacy/ for reference. The idea scaled: a dev tool should know
what's on your machine, and it should be able to safely act on it.
view images at the end of the README
| Module | What it does |
|---|---|
| Harbor | Landing overview: one live card per module plus a system vitals strip (uptime, load, memory, disk, battery). |
| Ports | Every listening dev server (lsof/ps), with a guarded stop button. Full Port Authority behavior: tree-kill, SIGTERM-then-confirmed-SIGKILL, PID-reuse protection, LAN-exposure badges. |
| Repos | Status board for every git repo under your dev root: dirty files, ahead/behind, stale branches, last commit. |
| Worktrees | Linked worktrees and branches older than 30 days. Remove worktrees, prune, delete branches — main worktree and default branches are off limits. |
| Health | "Is it up?" — a personal status page for localhost services and external URLs, with status code and latency. |
| Hosts | /etc/hosts viewer with profiles. Applying opens the macOS admin prompt (no sudoers edits), always backs up first, flushes the DNS cache. |
| Processes | Instantaneous CPU (two ps samples, one second apart) and memory. Stop is guarded like Ports: own processes only, never PID 1 or Dockmaster's ancestors. |
| Secrets | Credential-shaped strings in tracked files across all repos (AWS/Slack/GitHub/Google/OpenAI keys, private key blocks, generic assignments). Previews are redacted server-side; the API never returns full secret text. Also lists untracked .env files (the good kind). |
| Logbook | "Which project had you today" — samples the frontmost app via osascript. Fully demand-driven: it records only while the page is open and visible. Window titles are never stored. |
| Notepad | Local scratch pad: timestamped dev notes (tools you found, snippets, ideas) stored in ~/.dockmaster/notes.json. |
Every scanning module can be switched off from its own page (persisted in ~/.dockmaster/settings.json).
Nothing scans unless someone is looking:
- All discovery is demand-driven with a short TTL cache and request coalescing.
- Frontend polling pauses when the tab is hidden (
visibilitychange). - The Logbook heartbeat only runs while its page is open and tracking is on; there is no background timer anywhere in the server.
- Bulk git scans run with bounded concurrency (4-6 processes).
A running Dockmaster idles near zero; the Next.js server itself is the main resident cost.
Requirements: macOS, Node 20.12+.
npm install
cp .env.example .env # optional: all values have defaults
npm run dev # http://localhost:36252Production (lower memory, no file watching):
npm run build
npm start| Variable | Default | Meaning |
|---|---|---|
DOCKMASTER_PORT |
36252 |
Loopback listen port. Deliberately obscure so a 24/7 instance never fights a dev server for 3000. Applies to npm run dev, npm start, and the LaunchAgent. |
DOCKMASTER_DATA_DIR |
~/.dockmaster |
Settings, profiles, logbook, backups |
DOCKMASTER_DEV_ROOT |
~/Developer |
Where the repo scanner walks |
DOCKMASTER_WALK_DEPTH |
3 |
Repo scan depth |
DOCKMASTER_LOGBOOK_INTERVAL_MS |
10000 |
Logbook sample interval |
No private information is hardcoded; everything comes from the environment or your local data dir.
Install a per-user LaunchAgent (run a production build first):
npm run build
npm run agent:install # com.dockmaster.app, starts at login
npm run agent:uninstallLogs land in ~/.dockmaster/logs/.
The dashboard can kill processes and rewrite /etc/hosts, so it defends itself the way Port Authority did:
- Binds to
127.0.0.1only; middleware rejects any non-loopbackHostheader (DNS rebinding). - API requests require a per-process token injected into the page; a custom header forces a CORS preflight, which is answered without CORS headers so the browser blocks the real request. A missing or stale token is a 401; action refusals are 403.
Originis validated on every API request.- Destructive actions re-verify identity against a fresh scan (stale rows 409), and the process-tree kill refuses PID 1, Dockmaster itself, its ancestors, and any process owned by another user.
npm run typecheck
npm test # vitest — parsers and safety guardsContributions are welcome!