MacOS Launch Agent CLI - easily create, list, update, and delete launch agent PLIST files for MacOS login items.
Find a file
Erich Blume 5b78165e33 Rework edit command to open plist in $EDITOR
Instead of a CLI for editing plist arguments programmatically, the edit
command now opens the plist file directly in the user's $EDITOR (falls
back to vi). This provides more flexibility for editing any plist field.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-13 09:02:48 -08:00
.gitignore Add uv package structure and pytest test framework 2026-01-11 19:18:17 -08:00
.pre-commit-config.yaml Add pre-commit hooks with ty type checking 2026-01-11 19:51:34 -08:00
.python-version Add uv package structure and pytest test framework 2026-01-11 19:18:17 -08:00
CLAUDE.md Add CLAUDE.md for Claude Code guidance 2026-01-12 16:53:43 -08:00
conftest.py Add uv package structure and pytest test framework 2026-01-11 19:18:17 -08:00
mcquack.py Rework edit command to open plist in $EDITOR 2026-01-13 09:02:48 -08:00
pyproject.toml Add script entry point for uvx installation 2026-01-12 16:55:46 -08:00
README.md Rework edit command to open plist in $EDITOR 2026-01-13 09:02:48 -08:00
test_mcquack.py Rework edit command to open plist in $EDITOR 2026-01-13 09:02:48 -08:00
uv.lock Add pre-commit hooks with ty type checking 2026-01-11 19:51:34 -08:00

mcquack

A simple macOS LaunchAgent manager for executable scripts.

Named after Launchpad McQuack, the fearless (if accident-prone) pilot from DuckTales.

Requirements

  • macOS (uses launchctl and ~/Library/LaunchAgents)
  • uv

Installation

No installation required! Run directly with:

uvx git+https://forge.tail8d86e.ts.net/eblume/mcquack

Or clone and run the script directly (it's already executable).

Usage

# List all mcquack-managed LaunchAgents
mcquack list

# Create and load an executable as a LaunchAgent
mcquack create /path/to/your/script

# Create with additional arguments for the script (note the -- separator)
mcquack create /path/to/your/script -- --arg1 value1 --arg2

# Kickstart (immediately run) the LaunchAgent
mcquack launch /path/to/your/script

# Show the current arguments configured in the plist
mcquack show /path/to/your/script

# Edit the plist in $EDITOR (falls back to vi)
mcquack edit /path/to/your/script

# Unload (stop) the LaunchAgent
mcquack unload /path/to/your/script

# Delete the LaunchAgent plist file
mcquack delete /path/to/your/script

Passing Arguments to Your Script

When passing arguments to your script with create, you must use -- to separate mcquack's options from arguments intended for your script:

# Correct: passes --config and --debug to your script
mcquack create my_script.sh -- --config /path/to/config --debug

# Wrong: --help is interpreted as mcquack's --help flag, shows help instead
mcquack create my_script.sh --help

# Correct: passes --help as an argument to your script
mcquack create my_script.sh -- --help

The -- separator ensures that flags like --help, --verbose, etc. are passed to your script rather than being interpreted by mcquack itself.

To modify arguments after creation, use mcquack edit to open the plist in your editor.

How it works

mcquack creates plist files in ~/Library/LaunchAgents/ with the naming convention:

mcquack.eblume.<scriptname>.plist

The generated plist configures the script to:

  • Run at load
  • Keep alive (restart if it exits)
  • Log stdout/stderr to ~/Library/Logs/mcquack.<scriptname>.{out,err}.log

Development

mcquack uses uv for dependency management. Thanks to the uv shebang at the top of mcquack.py, you can always run the script directly without any setup:

./mcquack.py list

This works for users and developers alike—no virtual environment activation or python command needed. uv handles everything automatically.

Running Tests

uv run pytest

Virtual Environment (Optional)

If you prefer working in a virtual environment (e.g., for IDE support or running python mcquack.py directly), you can create and activate one:

uv venv
source .venv/bin/activate

After activation, python mcquack.py will work as expected. But again, ./mcquack.py always works without this step.

License

MIT