daemon-cli
v1.5.0
Published
A macOS-exclusive CLI tool to turn arbitrary shell commands into background services managed by `launchd`. It uses a **Rust-based Governor** to securely execute scripts with Full Disk Access (FDA) permissions.
Downloads
173
Readme
daemon-cli
A macOS-exclusive CLI tool to turn arbitrary shell commands into background services managed by launchd. It uses a Rust-based Governor to securely execute scripts with Full Disk Access (FDA) permissions.
Why the Governor?
On macOS, background processes managed by launchd are often restricted by TCC (Transparency, Consent, and Control). This prevents scripts from accessing sensitive areas like your ~/Documents folder, ~/Desktop, or external drives without explicit permission.
Granting permission for a shell script is difficult because giving access to /bin/sh would open your entire system. The Governor solves this by:
- Single Permission: You grant "Full Disk Access" once to the
daemon-governorbinary. - Inheritance: On macOS, child processes inherit the TCC permissions of their parent. When the Governor runs your script, the script inherits the Full Disk Access.
- Security via Hashing: To prevent malware from abusing this, the Governor only runs scripts that have been registered with their SHA-256 hash in a root-owned allowlist.
Features
- Governor Pattern: Securely run background scripts with Full Disk Access.
- Integrity Verification: The Governor verifies that scripts haven't been modified since registration.
- Log Rotation: Integrated
logrotatesupport with configurable intervals and retention. - Node.js CLI: A user-friendly CLI built with TypeScript and
@clack/prompts.
Prerequisites
- macOS: Only compatible with macOS.
- logrotate: Required for log management.
brew install logrotate
Installation
From NPM (Recommended)
Install the CLI globally via your favorite package manager:
pnpm add -g daemon-cli
# or
npm install -g daemon-cliFrom Source
- Clone the repository.
- Install dependencies and build:
pnpm install pnpm run build - Link the binary:
pnpm link --global
Granting Full Disk Access
To allow your background daemons to access restricted folders without permission prompts, you must grant Full Disk Access to the Governor binary:
- Open System Settings.
- Go to Privacy & Security -> Full Disk Access.
- Click the + (plus) button.
- Navigate to the location of
daemon-governor.- The CLI automatically copies the binary to:
/usr/local/bin/daemon-governor
- The CLI automatically copies the binary to:
- Ensure the toggle is ON.
Usage
Create a Daemon
Turn any command into a background service. This will prompt for sudo to register the script's hash with the Governor.
daemon create <name> [command] [flags]Flags:
--rotation <daily|weekly|hourly>: Set log rotation interval.--keep <count>: Number of rotated logs to keep.--compress: Compress rotated logs.--no-keep-alive: Disable automatic restart if the process crashes.--throttle-interval <seconds>: Minimum time between restarts if the process crashes (default: 10).
List Daemons
Show all daemons managed by daemon-cli, including their status, PID, and log size.
daemon listStop a Daemon
Stop a running service without removing it.
daemon stop <name>Restart a Daemon
Restart a managed service. You can also update the throttle interval.
daemon restart <name> [--throttle-interval <seconds>]Edit a Daemon
Open the wrapper script in your preferred editor ($EDITOR or $VISUAL). Once you save and exit, the daemon will be automatically re-registered and restarted.
daemon edit <name>Read Logs
Read or tail the logs of a service.
daemon logs <name> [flags]Flags:
-f, --tail: Continuously output the log.-n, --lines <count>: Number of lines to output (default: 100).
Remove a Daemon
Stop the service and delete all associated configurations, wrappers, and logs.
daemon rm <name>Shell Completion
To enable zsh completion, add the following to your .zshrc:
source <(daemon completion zsh)Security Model
- The Allowlist: A root-owned JSON file located at
/Library/Application Support/daemon-cli/allowlist.json. This ensures that only an Administrator can authorize a script. - Registration: When you run
daemon create, the tool calculates the SHA-256 hash of the generated wrapper script and stores it in the allowlist viasudo daemon-governor register. - The Execution: When
launchdtriggers, it callsdaemon-governor run <name>. The Governor re-calculates the script's hash; if it doesn't match the one in the allowlist (due to unauthorized tampering), it refuses to execute. - Anti-Looping: If a hash mismatch is detected, the Governor automatically updates the service's
KeepAlivesetting tofalseand unloads it to preventlaunchdfrom repeatedly trying to start the broken script.
License
MIT
