A command-line service manager for running and managing binary files on Linux and macOS.
- ✅ Create and manage tasks/services
- ✅ Start/stop services with graceful shutdown
- ✅ Environment variable support
- ✅ Automatic .env file loading
- ✅ Custom working directories
- ✅ Auto-restart configuration
- ✅ Task status monitoring with detailed information
- ✅ Restart command for running services
- ✅ Cross-platform support (Linux & macOS)
- ✅ Persistent task configuration
- ✅ Process monitoring with PID tracking
- ✅ Memory usage in list view (per-process MB)
- ✅ Log management with rotation (>10MB)
- ✅ Real-time log following (--follow flag)
- ✅ Separate stdout/stderr log viewing
- ✅ Enhanced process management with signal handling
- ✅ Process group and child-process cleanup on stop
- ✅ Diagnostic tools for troubleshooting
- ✅ Exit code tracking
- ✅ Restart count monitoring
- ✅ Persistent running-task state across hyperV restarts
- ✅ Compose-style YAML workflow with
upanddown
- Clone the repository
- Build the project:
cargo build --release
- The binary will be available at
target/release/hyperV
# Basic task
hyperV new --name "my-service" --binary "/path/to/binary"
# Task with arguments
hyperV new --name "web-server" --binary "/usr/bin/python3" --args "server.py" "--port=8080"
# Task with environment variables
hyperV new --name "api-service" --binary "/path/to/api" --env "PORT=3000" --env "NODE_ENV=production"
# Task with working directory and auto-restart
hyperV new --name "worker" --binary "/path/to/worker" --workdir "/opt/app" --auto-restartIf a .env file exists in the specified working directory (--workdir), it will be automatically loaded. Environment variables passed via the --env flag will take precedence over the variables in the .env file.
Example .env file:
DB_HOST=localhost
DB_USER=myuser
DB_PASS=secret
Creating a task with a .env file:
hyperV new --name "my-app" \
--binary "/path/to/app" \
--workdir "/path/to/my-app-folder" \
--auto-restartIf /path/to/my-app-folder contains a .env file, the variables within it will be loaded when the my-app service is started.
hyperV listhyperV start my-service
# or by partial ID
hyperV start abff48b0hyperV stop my-servicestop sends SIGTERM first, then SIGKILL if the process does not exit in time. On Unix, hyperV also targets the task process group and known child process groups so helper scripts do not leave the real app running in the background.
hyperV restart my-servicerestart stops the task if it is running, then starts it again.
# Show specific task
hyperV status my-service
# Show all tasks
hyperV statushyperV remove my-service# Show last 50 lines of stdout (default)
hyperV logs my-service
# Show last 100 lines of stdout
hyperV logs my-service --lines 100
# Show stderr logs
hyperV logs my-service --log-type stderr
# Show both stdout and stderr
hyperV logs my-service --log-type both
# Follow logs in real-time (like tail -f)
hyperV logs my-service --follow
# Follow stderr logs in real-time
hyperV logs my-service --log-type stderr --follow# Analyze binary file and configuration for issues
hyperV diagnose my-serviceDefine services in a YAML file, then create or update tasks from it:
# Uses hyperv.yaml by default
hyperV up --start
# Use a custom file
hyperV up --file ./startup.yaml --start
# Remove services defined in the YAML file
hyperV down --file ./startup.yamlYAML files use this shape:
services:
worker:
binary: "/bin/bash"
args: ["./tests/worker.sh"]
workdir: "/path/to/app"
env:
NODE_ENV: "production"
auto_restart: trueTasks with --auto-restart flag will automatically restart if they fail (up to 5 attempts):
hyperV new --name "critical-service" --binary "/path/to/service" --auto-restart- Logs are automatically rotated when they exceed 10MB
- Separate stdout and stderr log files
- Real-time log following capability
- Fast last-N reading for tail-like views (reads from end of file efficiently)
- Historical log preservation (.old files)
- Graceful shutdown with SIGTERM before SIGKILL
- Process group handling for shell scripts and child processes
- Proper cleanup of zombie processes
- Exit code tracking
The status command now shows:
- Last start time
- Restart count
- Last exit code
- Detailed process information
hyperV persists the set of running tasks to a small JSON file (running_tasks.json) under the configuration directory. On startup:
- It reads this file and checks each recorded PID to see if the process is still alive.
- Tasks whose PIDs are still running are marked as Running and their PID is restored.
- Stale entries (where the PID is no longer alive) are ignored.
This file is automatically updated when tasks start/stop and when the manager detects that a process has exited. You generally do not need to edit it manually.
Tasks are stored in JSON format at:
- macOS:
~/Library/Application Support/hyperV/tasks.json - Linux:
~/.config/hyperV/tasks.json
Logs are stored in:
- macOS:
~/Library/Application Support/hyperV/logs/<task-id>/ - Linux:
~/.config/hyperV/logs/<task-id>/
Runtime state (persisted running tasks) is stored in:
- macOS:
~/Library/Application Support/hyperV/running_tasks.json - Linux:
~/.config/hyperV/running_tasks.json
Daemon coordination state is stored in:
- macOS:
~/Library/Application Support/hyperV/daemon.pid - Linux:
~/.config/hyperV/daemon.pid
Each task contains:
id: Unique identifier (UUID)name: Human-readable namebinary: Path to executableargs: Command-line argumentsenv: Environment variablesworkdir: Working directory (optional)auto_restart: Auto-restart on failurestatus: Current status (Running/Stopped/Failed)pid: Process ID when runningpid_start_time: Process identity timestamp used to reduce PID-reuse mistakescreated_at: Creation timestamplast_started: Last start timestamprestart_count: Number of automatic restartslast_exit_code: Exit code from last runsuppress_restart: Internal flag that prevents an explicitly stopped task from being auto-restartedstdout_log_path: Path to stdout log filestderr_log_path: Path to stderr log file
hyperV new --name "flask-app" \
--binary "/usr/bin/python3" \
--args "app.py" \
--env "FLASK_ENV=production" \
--env "PORT=5000" \
--workdir "/opt/webapp" \
--auto-restart
hyperV start flask-apphyperV new --name "node-api" \
--binary "/usr/bin/node" \
--args "index.js" \
--env "NODE_ENV=production" \
--env "PORT=3000" \
--auto-restart
hyperV start node-apihyperV new --name "my-daemon" \
--binary "/usr/local/bin/mydaemon" \
--args "--config" \
--args "/etc/mydaemon.conf" \
--auto-restart
hyperV start my-daemonA helper script is provided to launch SurrealDB using environment variables: tests/surreal.sh.
Create a task that runs the script via bash:
hyperV new --name "surrealdb" \
--binary "/bin/bash" \
--args "./tests/surreal.sh" \
--workdir "/path/to/this/repo" \
--env "SURREAL_HOST=0.0.0.0" \
--env "SURREAL_PORT=8000" \
--env "SURREAL_STORAGE_PATH=/tmp/surreal_data" \
--env "SURREAL_LOG_LEVEL=info" \
--env "SURREAL_USER=root" \
--env "SURREAL_PASSWORD=secret" \
--auto-restart
# Start the database
hyperV start surrealdb
# View logs
hyperV logs surrealdb --followThe script builds and executes the command:
SURREAL_CMD="surreal start --bind $SURREAL_HOST:$SURREAL_PORT rocksdb:$SURREAL_STORAGE_PATH --log $SURREAL_LOG_LEVEL --user $SURREAL_USER --password $SURREAL_PASSWORD"Ensure the surreal binary is available in your PATH. Adjust environment variables as needed.
You can also define and run SurrealDB purely from hyperv.yaml without a helper script. Example hyperv.yaml fragment:
services:
surrealdb:
binary: "/bin/bash"
args:
- "-lc"
- "surreal start --bind $SURREAL_HOST:$SURREAL_PORT rocksdb:$SURREAL_STORAGE_PATH --log $SURREAL_LOG_LEVEL --user $SURREAL_USER --password $SURREAL_PASSWORD"
env:
SURREAL_HOST: "0.0.0.0"
SURREAL_PORT: "8000"
SURREAL_STORAGE_PATH: "/tmp/surreal_data"
SURREAL_LOG_LEVEL: "info"
SURREAL_USER: "root"
SURREAL_PASSWORD: "secret"
auto_restart: trueThen apply and start it with:
# create/update tasks from hyperv.yaml and start them
hyperV up -f hyperv.yaml --start
# inspect
hyperV list
hyperV logs surrealdb --follow
# remove the services defined in hyperv.yaml
hyperV down -f hyperv.yamlNotes:
- We use /bin/bash -lc so that environment variables in the command are expanded by the shell.
- The env block in YAML sets those variables for the process; adjust as needed.
- Ensure the surreal binary is available in PATH for the user running hyperV.
- Alternatively, you can keep using the provided tests/surreal.sh wrapper if you prefer.
- Systemd/launchd integration
- Web UI for management
- Task dependencies
- Scheduling support
- Richer CPU and resource usage reporting
- More structured error reporting for automation
MIT License