# mcquack A simple macOS LaunchAgent manager for executable commands and scripts. Named after Launchpad McQuack, the fearless (if accident-prone) pilot from DuckTales. ## Requirements - macOS (uses launchctl and ~/Library/LaunchAgents) - [uv](https://github.com/astral-sh/uv) ## Installation No installation required! Run directly with: ```bash uvx git+https://forge.tail8d86e.ts.net/eblume/mcquack ``` Or clone and run the script directly (it's already executable). ## Usage ```bash # List all mcquack-managed LaunchAgents mcquack list # Create and load an executable as a LaunchAgent mcquack create /path/to/your/script # Or use a command from $PATH mcquack create mycommand # Create with additional arguments (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 ``` ### Command Resolution: Paths vs Commands mcquack intelligently handles two types of arguments: **Paths** (contains `/`, `~`, or `.`): - Relative paths: `./script.sh`, `../bin/tool` - Absolute paths: `/usr/local/bin/script` - Home paths: `~/bin/myscript` - All paths are expanded and resolved to absolute paths - Symlinks are resolved to their targets **Commands** (no `/`): - Searched on `$PATH`: `python`, `node`, `mycommand` - Stored as-is (not expanded to absolute paths) - Must exist on `$PATH` or creation fails ```bash # Path examples (expanded to absolute paths in plist) mcquack create ./myscript.sh mcquack create ~/bin/backup.sh mcquack create ../tools/monitor # Command examples (kept as-is in plist) mcquack create python -- -m http.server 8000 mcquack create node -- server.js ``` ### Passing Arguments to Your Command When passing arguments to your command with `create`, you **must** use `--` to separate mcquack's options from arguments intended for your command: ```bash # Correct: passes --config and --debug to your command 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 command mcquack create my_script.sh -- --help ``` The `--` separator ensures that flags like `--help`, `--verbose`, etc. are passed to your command 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..plist ``` The generated plist configures the command to: - Run at load (or on schedule if `--interval` or `--calendar` specified) - Keep alive (restart if it exits, unless scheduled) - Log stdout/stderr to `~/Library/Logs/mcquack..{out,err}.log` ### Path Resolution Details When you provide a path (containing `/`, `~`, or `.`), mcquack: 1. Expands `~` to your home directory 2. Resolves relative paths to absolute paths 3. Resolves `..` and `.` components 4. Resolves symlinks to their targets 5. Validates the file exists and is executable 6. Stores the absolute path in the plist When you provide a command name (no `/`), mcquack: 1. Searches for the command on your `$PATH` 2. Validates the command is executable 3. Stores the command name as-is in the plist (not the full path) 4. Lets launchd resolve the command at runtime using its environment ## Development mcquack uses [uv](https://github.com/astral-sh/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: ```bash ./mcquack.py list ``` This works for users and developers alike—no virtual environment activation or `python` command needed. uv handles everything automatically. ### Running Tests ```bash 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: ```bash 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