Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generates, validates, and installs macOS LaunchAgent plist files for scheduling recurring tasks and daemons. Triggered when a user asks to create a LaunchAgent, schedule a script, automate a recurring macOS task, or set up a background daemon. Uses the com.berna namespace and validates plist syntax before writing. Always confirms before loading.
.claude/skills/0xjitsu-launchagent-builder/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 106% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 71% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 87% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 50% | 0% |
Generate, validate, and install macOS LaunchAgent plist files for scheduled tasks and daemons.
All agents use the com.berna. namespace:
com.berna.<descriptive-name>.plistExamples:
com.berna.secret-scanner-daily.plistcom.berna.wispr-flow-watchdog.plistcom.berna.git-backup-hourly.plistThe Label value inside the plist MUST match the filename (minus .plist).
Gather these inputs from the user (or infer from context):
| Parameter | Required | Default | |--------------------|----------|--------------------------------------------| | Script path | Yes | — | | Schedule type | Yes | interval or calendar | | Interval (seconds) | If interval | — | | Calendar day | If calendar | — (0=Sun, 1=Mon, …, 6=Sat) | | Calendar hour | If calendar | — | | Calendar minute | If calendar | 0 | | Log output path | No | ~/Reports/maintenance/<name>.log | | KeepAlive | No | false (true for daemons) | | RunAtLoad | No | true | | Environment vars | No | — | | WatchPaths | No | — (for file-triggered agents) |
xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.berna.AGENT_NAME</string> <key>ProgramArguments</key> <array> <string>/bin/bash</string> <string>/path/to/script.sh</string> </array> <key>StartInterval</key> <integer>SECONDS</integer> <key>RunAtLoad</key> <true/> <key>StandardOutPath</key> <string>/Users/bbmisa/Reports/maintenance/AGENT_NAME.log</string> <key>StandardErrorPath</key> <string>/Users/bbmisa/Reports/maintenance/AGENT_NAME.log</string> </dict> </plist>
Replace StartInterval with:
xml<key>StartCalendarInterval</key> <dict> <key>Hour</key> <integer>HOUR</integer> <key>Minute</key> <integer>MINUTE</integer> <!-- Optional: Day (0=Sunday), Weekday, Month --> </dict>
For multiple schedules, use an array of dicts:
xml<key>StartCalendarInterval</key> <array> <dict> <key>Hour</key> <integer>9</integer> <key>Minute</key> <integer>0</integer> </dict> <dict> <key>Hour</key> <integer>17</integer> <key>Minute</key> <integer>0</integer> </dict> </array>
KeepAlive (for daemons):
xml<key>KeepAlive</key> <true/>
Environment Variables:
xml<key>EnvironmentVariables</key> <dict> <key>PATH</key> <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string> <key>CUSTOM_VAR</key> <string>value</string> </dict>
WatchPaths (file-triggered):
xml<key>WatchPaths</key> <array> <string>/path/to/watched/file</string> </array>
Always validate the plist before writing:
bashplutil -lint /path/to/generated.plist
Expected output: <file>: OK
If validation fails, fix the XML and re-validate before proceeding.
bash# Ensure target directory exists mkdir -p ~/Library/LaunchAgents # Write the plist (tool writes the file) # Target: ~/Library/LaunchAgents/com.berna.<name>.plist
bashlaunchctl load ~/Library/LaunchAgents/com.berna.<name>.plist
bashlaunchctl list | grep com.berna.<name>
A successful load shows the agent with a PID (if running) or status code.
bashlaunchctl list | grep com.berna
bashlaunchctl unload ~/Library/LaunchAgents/com.berna.<name>.plist
bashlaunchctl unload ~/Library/LaunchAgents/com.berna.<name>.plist launchctl load ~/Library/LaunchAgents/com.berna.<name>.plist
bashtail -f ~/Reports/maintenance/<name>.log
bashlaunchctl list | grep com.berna.<name> # Column 1: PID (- if not running), Column 2: last exit status (0 = success)
| Schedule | StartInterval | StartCalendarInterval | |----------------|---------------|--------------------------------| | Every 5 min | 300 | — | | Every 30 min | 1800 | — | | Every hour | 3600 | — | | Daily at 9 AM | — | Hour: 9, Minute: 0 | | Weekdays 8 AM | — | Weekday: 1-5, Hour: 8 | | Weekly Sunday | — | Weekday: 0, Hour: 3 | | Monthly 1st | — | Day: 1, Hour: 0 |
plutil -lint before writing to ~/Library/LaunchAgents/mkdir -p ~/Reports/maintenance before setting log paths/opt/homebrew/bin in PATH| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 9,146 | 8,895 | -3% | 1 | 1 | 0% | 1,866 | 3,847 | +106% | 0 | 0 | — |
case-02 | fail→pass | 26,659 | 8,188 | -69% | 1 | 1 | 0% | 2,139 | 3,647 | +71% | 0 | 0 | — |
case-03 | fail→pass | 9,663 | 13,407 | +39% | 1 | 1 | 0% | 2,053 | 3,844 | +87% | 0 | 0 | — |
case-04 | pass→pass | 7,905 | 6,406 | -19% | 1 | 1 | 0% | 1,721 | 3,085 | +79% | 0 | 0 | — |
case-05 | pass→pass | 8,063 | 4,806 | -40% | 1 | 1 | 0% | 1,511 | 2,729 | +81% | 0 | 0 | — |
case-06 | pass→pass | 13,140 | 6,880 | -48% | 1 | 1 | 0% | 1,757 | 3,149 | +79% | 0 | 0 | — |
case-07 | fail→pass | 9,083 | 7,449 | -18% | 1 | 1 | 0% | 1,844 | 3,424 | +86% | 0 | 0 | — |
case-08 | pass→pass | 6,347 | 6,440 | +1% | 1 | 1 | 0% | 1,497 | 3,203 | +114% | 0 | 0 | — |
case-09 | fail→pass | 8,951 | 6,175 | -31% | 1 | 1 | 0% | 2,008 | 3,013 | +50% | 0 | 0 | — |
case-10 | fail→pass | 8,175 | 11,513 | +41% | 1 | 1 | 0% | 1,640 | 2,992 | +82% | 0 | 0 | — |
case-11 | pass→pass | 4,583 | 2,651 | -42% | 1 | 1 | 0% | 870 | 2,217 | +155% | 0 | 0 | — |
case-12 | pass→pass | 6,002 | 3,820 | -36% | 1 | 1 | 0% | 1,267 | 2,454 | +94% | 0 | 0 | — |
case-13 | fail→pass | 7,457 | 2,981 | -60% | 1 | 1 | 0% | 1,339 | 2,235 | +67% | 0 | 0 | — |
case-14 | fail→pass | 10,973 | 2,418 | -78% | 1 | 1 | 0% | 1,967 | 2,238 | +14% | 0 | 0 | — |
case-15 | pass→pass | 6,461 | 3,519 | -46% | 1 | 1 | 0% | 1,282 | 2,289 | +79% | 0 | 0 | — |
case-16 | fail→pass | 6,420 | 1,346 | -79% | 1 | 1 | 0% | 1,031 | 1,994 | +93% | 0 | 0 | — |
case-17 | fail→pass | 7,611 | 2,037 | -73% | 1 | 1 | 0% | 1,329 | 2,104 | +58% | 0 | 0 | — |
case-18 | pass→pass | 10,671 | 10,350 | -3% | 1 | 1 | 0% | 2,019 | 3,596 | +78% | 0 | 0 | — |
case-19 | fail→pass | 5,191 | 4,336 | -16% | 1 | 1 | 0% | 1,285 | 2,923 | +127% | 0 | 0 | — |
case-20 | fail→pass | 9,007 | 8,628 | -4% | 1 | 1 | 0% | 1,959 | 3,309 | +69% | 0 | 0 | — |
case-21 | pass→pass | 7,524 | 5,564 | -26% | 1 | 1 | 0% | 1,481 | 2,780 | +88% | 0 | 0 | — |
case-22 | pass→pass | 8,763 | 3,616 | -59% | 1 | 1 | 0% | 1,580 | 2,475 | +57% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +55 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/3/2026 | +32% |
Other measured skills in the registry, with their headline benchmark lift.