A macOS desktop app for inspecting and managing launchd jobs and plist files, built with Wails, Go, and React.
Download the latest darwin_universal.zip from GitHub Releases, extract it, and move Launchd Panel.app into your Applications folder.
The current build is not Apple-signed or notarized yet. If macOS blocks the first launch:
- right-click
Launchd Panel.appin Finder and chooseOpen - or allow it from
System Settings -> Privacy & Security
launchd-panel is a macOS desktop app for inspecting and managing launchd jobs.
It is built with Wails, uses Go for launchctl, plist, and log handling, and uses React for the desktop workspace. The current product focuses on:
- browsing user, local, and system
launchdjobs from one place - providing real management actions for user-scoped
LaunchAgentjobs - editing plist data through a friendlier UI instead of raw XML only
- combining logs, runtime status, validation, and action history in one workspace
- Scans the following locations into one unified workspace
~/Library/LaunchAgents/Library/LaunchAgents/Library/LaunchDaemons/System/Library/LaunchAgents/System/Library/LaunchDaemons
- Merges runtime data from
launchctl printandlaunchctl print-disabled - Shows job status, exit code, disabled state, schedule, command summary, log availability, and history count
- Provides summary cards and navigation counters
- Supports filtering by navigation group, search keyword, and current selection state
- Real write operations are available for
~/Library/LaunchAgents - Supported per-job actions
- start
- stop
- enable
- disable
- reload
- validate
- delete
- Supported batch actions
- batch validate
- batch disable
- System and global jobs are shown with real data but remain read-only
- Creating and editing jobs uses the same configuration drawer
- Three editing modes are available
- guided mode
- professional form
- raw plist
- Guided mode groups interval, daily, weekly, and monthly schedules under one
timedentry, and interval rules support seconds, minutes, hours, and days - The professional form includes a visual
StartCalendarIntervaleditor for common rules likeevery Friday at 17:50 - Structured editing is supported for
LabelProgramProgramArgumentsWorkingDirectoryRunAtLoadKeepAliveStartIntervalStartCalendarIntervalStandardOutPathStandardErrorPathEnvironmentVariablesWatchPaths
- Unmodified plist keys are preserved when saving from form mode
- New jobs can auto-fill friendly file names and suggested log paths
- You can save only, or save and immediately reload the job
- The detail drawer shows
- status highlights
- alerts and validation results
- plist-derived fields
launchctl printruntime output- recent action history
- The log drawer supports
stdoutstderr- combined view
- auto refresh
- live tracking
- downloading the current log view
- clearing the current log file
- Action history is persisted locally and remains available after app restarts
- Theme modes
- light
- dark
- follow system
- Remembers whether system jobs should be shown
- Can check the latest GitHub release on startup
- Can pre-download an update package and install it after restart
- Settings are persisted in the local config directory
| Scope | Path | Capability |
|---|---|---|
| Current user agent | ~/Library/LaunchAgents |
full management |
| Local agent | /Library/LaunchAgents |
read-only |
| Local daemon | /Library/LaunchDaemons |
read-only |
| System agent | /System/Library/LaunchAgents |
read-only |
| System daemon | /System/Library/LaunchDaemons |
read-only |
- The main screen uses a compact summary plus job table layout
- The left navigation switches between scope, status, logs, history, and related views
- Clicking a row opens the detail drawer by default
- The context menu and action dropdown can open details, editing, logs, or run actions directly
- Details, configuration, and logs all stay in the right-side drawer so the main table remains the primary workspace
- Go 1.23
- Wails v2
howett.net/plist
- React 18
- Vite
- Ant Design
- Monaco Editor
- simplebar-react
- Tailwind CSS v4
launchd-panel/
├── .github/
│ └── workflows/
│ └── release.yml
├── app.go
├── main.go
├── settings.go
├── internal/
│ └── launchd/
│ ├── history.go
│ ├── service.go
│ ├── service_test.go
│ └── types.go
├── scripts/
│ └── sync-version.mjs
├── frontend/
│ ├── package.json
│ ├── vite.config.js
│ ├── src/
│ │ ├── App.jsx
│ │ ├── style.css
│ │ └── components/
│ │ ├── ConfigurationPanel.jsx
│ │ ├── DetailPanel.jsx
│ │ ├── LogHistoryPanel.jsx
│ │ ├── Navigation.jsx
│ │ ├── PlistEditor.jsx
│ │ ├── ScrollArea.jsx
│ │ ├── SettingsPanel.jsx
│ │ ├── StatusTag.jsx
│ │ ├── SummarySection.jsx
│ │ └── TasksTable.jsx
├── build/
├── README.md
├── README.zh-CN.md
└── wails.json
- macOS
- Go 1.23 or later
- Node.js 18 or later
pnpm- Wails CLI
cd "frontend"
pnpm installcd "frontend"
pnpm devwails devcd "frontend"
pnpm buildwails buildPush any tag, for example v0.1.0, to trigger GitHub Actions.
The workflow will:
- sync the tag version into
wails.jsonandversion.go - build the macOS app with
wails build -clean -platform darwin/universal -ldflags "-X main.appVersion=${VERSION}" - repackage
build/bin/launchd-panel.appasLaunchd Panel.appinside the zip archive - publish a GitHub Release and upload the zip plus SHA-256 checksum
- push the updated version files back to the default branch automatically
- The current version only allows write operations for user-scoped
LaunchAgentjobs - System and local jobs are hidden by default and can be enabled from settings
- Log viewing depends on configured
StandardOutPathandStandardErrorPathvalues