Zinit
A lightweight process supervisor with Rhai scripting support.
Zinit manages services (long-running processes) with dependency ordering, health checks, automatic restarts, and a powerful scripting interface.
Features
- Rhai Scripting - Control everything via scripts, not CLI flags
- Interactive REPL - Tab completion, syntax highlighting, command history
- Real-time Output -
print()statements stream to client as they execute - Single Instance - Only one zinit runs at a time via socket locking
- Auto-start - Running a script automatically starts zinit if needed
- Service Dependencies - Start services in order with
after() - Health Checks - Optional test commands to verify service health
- Resource Stats - CPU and memory usage per service
- Name Normalization - Service names are case-insensitive,
-and_are equivalent
Quick Start
# Build and install
# Run a script (auto-starts zinit)
# Or use inline scripts
|
Usage
Interactive REPL
Start the interactive shell with zinit --ui:
╔═══════════════════════════════════════════════════════════╗
║ Zinit Interactive Shell (Rhai REPL) ║
╠═══════════════════════════════════════════════════════════╣
║ Tab: completion | Up/Down: history | Ctrl+D: exit ║
║ Type /help for commands, /functions for API ║
╚═══════════════════════════════════════════════════════════╝
zinit> zinit_list_md()
| Service | State | PID | Target |
|---------|-------|-----|--------|
| webserver | Running | 1234 | Up |
zinit>
REPL Features
- Tab Completion - Type
zinit_and press Tab to see all functions - Syntax Highlighting - Keywords, functions, strings are colored
- Command History - Up/Down arrows, persisted to
~/.zinit_history - Multi-line Input - Use
{}braces for multi-line scripts
REPL Commands
| Command | Description |
|---|---|
/help |
Show help |
/functions |
List all zinit functions with signatures |
/builder |
Show service builder pattern |
/load <file> |
Load and execute a .rhai script file |
/clear |
Clear screen |
/quit |
Exit (or Ctrl+D) |
Example Session
zinit> /functions
Zinit Functions:
Control:
zinit_ping() -> bool Check if zinit is responding
zinit_start() -> bool Start zinit daemon if not running
...
zinit> /load rhaiexamples/01_full_test.rhai
Loading: rhaiexamples/01_full_test.rhai
=== Zinit Full Test ===
Step 1: Creating webserver service...
...
zinit> zinit_stop("webserver")
true
zinit> /quit
Goodbye!
Fixed Paths
Zinit uses fixed paths - no configuration needed:
| Path | Purpose |
|---|---|
~/hero/cfg/zinit/ |
Service YAML files |
~/hero/var/zinit.sock |
Unix socket for RPC |
~/hero/bin/zinit |
Recommended binary location |
Example Script
// Create and start a web server service
let webserver = zinit_service_new()
.exec("python3 -m http.server 8080")
.log("ring");
zinit_monitor("webserver", webserver);
zinit_start("webserver");
// Wait for it to be running
if zinit_wait_for("webserver", 5) {
print("Web server is running!");
} else {
print("Failed to start web server");
}
// Show status
print(zinit_status_md("webserver"));
API Reference
Service Management
| Function | Returns | Description |
|---|---|---|
zinit_service_new() |
ServiceBuilder | Create service builder |
zinit_monitor(name, builder) |
bool | Register a service |
zinit_start(name) |
bool | Start a service |
zinit_stop(name) |
bool | Stop a service |
zinit_restart(name) |
bool | Restart a service |
zinit_forget(name) |
bool | Unregister a stopped service |
zinit_kill(name, signal) |
bool | Send signal (e.g., "SIGTERM") |
Service Builder
zinit_service_new()
.exec("command args") // Required: command to run
.test("health-check") // Optional: health check command
.oneshot(true) // Optional: run once, don't restart
.shutdown_timeout(10) // Optional: seconds before SIGKILL
.after("other-service") // Optional: dependency
.signal_stop("SIGTERM") // Optional: stop signal
.log("ring") // Optional: "ring", "stdout", "none"
.env("KEY", "value") // Optional: environment variable
.dir("/path") // Optional: working directory
Query Functions
| Function | Returns | Description |
|---|---|---|
zinit_list() |
array | List service names |
zinit_status(name) |
map | Get service status |
zinit_stats(name) |
map | Get CPU/memory stats |
zinit_is_running(name) |
bool | Check if running |
zinit_wait_for(name, secs) |
bool | Wait for service |
Markdown Output
| Function | Returns | Description |
|---|---|---|
zinit_list_md() |
string | Services as markdown table |
zinit_status_md(name) |
string | Status as markdown |
zinit_stats_md(name) |
string | Stats as markdown |
Zinit Control
| Function | Returns | Description |
|---|---|---|
zinit_ping() |
bool | Check if zinit responds |
zinit_start() |
bool | Start zinit if not running |
zinit_exit() |
void | Graceful shutdown |
zinit_stop_all() |
int | Stop all services |
zinit_start_all() |
int | Start all services |
Utilities
| Function | Description |
|---|---|
print(msg) |
Print (streams to client) |
sleep(secs) |
Sleep seconds |
sleep_ms(ms) |
Sleep milliseconds |
get_env(key) |
Get environment variable |
set_env(key, val) |
Set environment variable |
file_exists(path) |
Check if path exists |
Socket Protocol
Zinit uses a Unix socket at ~/hero/var/zinit.sock. You can interact with it directly using netcat or socat.
Protocol Format
Send script:
<rhai script lines>
===
Receive response:
ok
<output lines streamed in real-time>
=====
Using Netcat
# Simple query
|
# Multi-line script
Using Socat (Recommended for Interactive)
# Install socat (macOS)
# Simple query
|
# Interactive mode with readline support
# Then type your script and end with ===
# Example:
# zinit_list_md()
# ===
# Send a script file
(; ) |
Bash Function for Easy Access
Add this to your .bashrc or .zshrc:
# Send Rhai script to zinit
# Examples:
# zexec 'zinit_list_md()'
# zexec 'zinit_stop("myservice")'
# echo 'print("hello")' | zexec
Python Example
=
# Send script with delimiter
# Read response
= b
=
break
+=
break
=
= # "ok" or "error"
= # Remove status and delimiter
return ,
# Usage
, =
Real-Time Output
Output from print() streams to the client in real-time:
print("Starting long operation...");
sleep(2);
print("Step 1 complete");
sleep(2);
print("Step 2 complete");
print("Done!");
Each line appears as it executes, not all at once when the script finishes.
Service States
| State | Description |
|---|---|
Spawned |
Process started, not yet confirmed running |
Running |
Process is running |
Success |
Oneshot completed successfully |
Error |
Process exited with error |
Blocked |
Waiting for dependencies |
Unknown |
Service registered but not monitored |
Examples
See the rhaiexamples/ directory:
01_full_test.rhai- Complete workflow: create, start, query, stop, forget02_stream_test.rhai- Test real-time output streaming
Documentation
zinit --help- API documentation (also insrc/instructions.md)rhaiinstructions.md- Technical implementation details- docs.rs/zinit - Rust API documentation
Building
# Debug build
# Release build
# Run tests
License
Apache 2.0