Skip to content

Repository files navigation

Launchboard

A native macOS menu bar dashboard for launchd. See your background jobs, understand their status, and inspect schedules and recent output without digging through Terminal.

Built with SwiftUI and AppKit. No dependencies, account, server, or telemetry.

The interface uses an off-black and grayscale palette, fine borders, and native monospaced typography. Full rows and metric panels are clickable, including their icons and surrounding whitespace.

Launchboard dashboard with synthetic demo jobs

Download v0.2.0 for Apple Silicon and Intel, or build from source. The app is Developer ID signed and Apple notarized, with its ticket stapled. ZIP and DMG downloads contain the same app; the DMG container itself is unsigned.

Launch video

Launchboard motion edition

The v2 motion edition is the featured product film: 30 seconds of native UI, animated panels and process views, with an original synchronized soundtrack.

Watch / download 4K · 60 fps · 1080p preview · Remotion project and audio setup

The film uses synthetic demo jobs to keep private task data out of public media. Earlier films remain available in release assets.

Menu bar panel Launchboard menu bar panel with demo jobs

Features

  • Menu bar overview with running, waiting, and last-failed counts. The panel fits the current screen's available height, with a scrolling list and persistent header and footer controls.
  • Full dashboard with search, pinned jobs, and user / third-party / all-service views.
  • Agent processes: detect Claude Code, Codex, Gemini CLI, OpenCode, Aider, Goose, Qwen Code, and Amp by known executable / package patterns. Inspect CPU, elapsed time, terminal attachment, parent agents, and the nearest visible launchd ancestor.
  • Honest status: waiting is normal; a live PID takes precedence over an older exit code. Signal interruptions are distinct from failed exits. Unloaded and disabled jobs are separate.
  • Schedules: readable calendar windows, interval and event triggers, and the next calendar match in your Mac's timezone. A window of minute-by-minute rules is summarized as one range.
  • Inspection: PID, last exit code, command, runtime details, plist location, and bounded stdout / stderr previews. Environment values are not displayed.
  • English and Traditional Chinese, following system language or an explicit preference.
  • Optional launch at login, using macOS Service Management.

Launchboard only reads the jobs it monitors. It does not start, stop, unload, or rewrite your services. The login toggle applies to Launchboard itself.

Build and run

Requires macOS 14 or later and Xcode or Command Line Tools with Swift 5.9+.

swift test
bash scripts/build-app.sh
open dist/Launchboard.app

Click the stacked-layers icon in the menu bar, then Open dashboard. Closing the dashboard leaves the menu bar app running; quit from its settings menu. When Launchboard is active, ⌘0 opens the dashboard and ⌘1 toggles the menu bar panel.

To install for your user, copy dist/Launchboard.app into ~/Applications/ and run that copy. Enable Launch at login from the settings menu if desired.

The build script signs locally with an ad-hoc signature and builds for the current Mac architecture by default. Set LAUNCHBOARD_ARCH=universal for both architectures. For a Developer ID build, set LAUNCHBOARD_SIGNING_IDENTITY before running the script. Notarization is a separate distribution step.

For universal DMG packaging, Developer ID signing and Apple notarization, see Distribution. It includes the Xcode cloud signing workflow used for 0.1.1 and an alternative for signing the outer DMG with a local certificate.

Local schedules

AI automations with synthetic demo tasks

AI automations automatically groups recognized AI tasks, including native harness definitions and launchd/crontab jobs that reference known AI tools. General services remain available in Local schedules. The category is derived from evidence; no manual tagging is needed. Inferred references are labeled.

The Local schedules view inventories saved tasks even when no agent process is running. Filter by Codex, Claude Code, other recognized CLIs, or Other / unknown. Each row shows its source, timing, state and the evidence behind its classification.

  • launchd: your LaunchAgents, plus non-Apple calendar/interval services. Includes paused, unloaded and on-demand jobs; a missing timer is shown as on demand. An observed descendant agent is stronger evidence than a script reference.

  • Codex Automations: reads v1 metadata from $CODEX_HOME/automations/*/automation.toml (default ~/.codex). Shows saved name, recurrence and active/paused state. Local files do not prove the execution location or current run status.

  • User crontab: reads crontab -l, hides command bodies and environment values, and shows timing rules. Runtime and exact next fire are not available.

  • Claude Desktop: discovers task folders in $CLAUDE_CONFIG_DIR/scheduled-tasks (default ~/.claude). These contain instructions, not schedule or enabled state; open Claude Desktop's Routines page for that information. Leftover/manual task definitions are not labeled active schedules.

  • OpenClaw / Hermes: reads local cron/jobs.json definitions, recurrence, enabled state and last result. Past-due next-run values are marked for review, never shown as upcoming runs. File state is not treated as proof of a live worker.

  • Orca: reads indexed local profiles' orca-data.json automations, retaining the configured executor and excluding SSH-targeted work. Profile identity is kept in the source path so identical task IDs from separate profiles stay distinct.

The external adapters follow Orca's provider mappings; see third-party notices and the harness test matrix. HERMES_HOME and OPENCLAW_STATE_DIR override their default homes when present in the app environment.

Coverage is displayed even when a source is empty or unreadable. Claude Code session /loop tasks are not discovered here; use CronList in the owning session. Cloud schedules, other users' crontabs, and arbitrary custom schedulers are not included. See Claude scheduling, Claude Desktop definitions, and Codex scheduling.

Classification never runs commands from a job. It can inspect the directly configured script (regular UTF-8 file, at most 256 KiB), without following imports. Tool names in shell commands or scripts are labeled inferred because comments, strings and conditional paths do not prove execution. Prompt bodies, scripts and environment values are not retained in task models. --tasks-json exports this same local metadata for diagnostics; names and file paths can still be personal, so do not publish a real snapshot.

How data is collected

Launchboard reads the current user's launchctl list, the system domain's launchctl print system, and each domain's print-disabled. It combines those with readable plists in:

~/Library/LaunchAgents
/Library/LaunchAgents
/Library/LaunchDaemons
/System/Library/LaunchAgents
/System/Library/LaunchDaemons

The default My jobs view contains plists from your own LaunchAgents directory. Empty placeholder plists left behind by uninstallers are ignored. All services also includes dynamically registered services without a discoverable plist. It covers the current user and system domains, not other users' sessions.

Data refreshes every 5 seconds while the interface is open, and every 30 seconds when hidden. Work happens off the main thread. Read failures appear in the interface; they do not silently erase the last successful snapshot.

Agent detection

The Agents view also samples the local process table with ps. It recognizes known CLI names and supported Node package entrypoints, and excludes known desktop renderers and crash helpers. A Codex app-server process is shown as App server; it is not counted as an individual task or conversation.

Each row represents an OS process. It may be interactive, unattended, or idle. Process alive and CPU usage do not establish whether the model is generating, waiting for a tool, or waiting for user input. Without TTY means there is no controlling terminal, not that the process is necessarily an autonomous agent.

Recognition is heuristic: renamed binaries, unsupported wrappers, remote/container agents, and agents hosted entirely inside an extension process may not be visible. Processes using the same generic executable name can require additional rules. Parent links describe process ancestry, not ownership of a model conversation.

Raw arguments are inspected transiently for recognition, then discarded. They are never included in the agent UI or diagnostics JSON, written to disk, or transmitted. The app does not read conversations, API keys, or session history to infer progress.

Agent process inspector using synthetic demo processes

What the dashboard cannot infer

  • A zero exit code is not proof that a scheduled job has ever run. Inspect runtime details for runs and the last recorded exit.
  • A calendar match is a forecast, not a guarantee. Sleep, disabled jobs, dependencies, overlapping executions, and launchd policy affect actual execution.
  • Exact next-fire times for StartInterval, sockets, and other event-driven jobs are not invented. These show their trigger type instead.
  • Conditional KeepAlive entries are identified as such; launchd owns their execution policy.
  • launchctl text is an OS interface, not a stable JSON API. Parsers are tested against representative output, but newer macOS versions can require updates.
  • This app shows current state and recent log tails, not a persistent execution history.
  • Logs are read only when a job is selected, up to 64 KB / 120 lines. Their contents may contain sensitive information; review before sharing screenshots.

Development

swift run Launchboard --dashboard       # Open full dashboard
swift run Launchboard --show-popover    # Open menu bar panel
swift run Launchboard --demo            # Synthetic data for safe public screenshots
swift run Launchboard --snapshot-json   # Read-only state diagnostics, no arguments/env
swift run Launchboard --agents-json     # Recognized processes, no prompts/arguments

--demo uses synthetic dev.example.* jobs and never reads local launchd state or logs. It disables login-item changes. Preferences (pins and language) are local to the app; no service definitions or logs are bundled into the repository.

See CONTRIBUTING.md. Licensed under MIT.

About

A native macOS menu bar dashboard for launchd jobs and local AI agent processes.

Topics

Resources

Contributing

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages