A product-neutral launcher, dependency orchestrator, and terminal monitor for local multi-service development environments.
hum is a fast, lightweight local development orchestrator and terminal monitor built with Rust, Ratatui, Crossterm, and Tokio. It coordinates detached local process groups, Docker Compose services, trusted direct-argv setup tasks, and scoped environment providers (such as 1Password or external command execution) from a unified dependency graph with zero resident daemon overhead.
- Overview & Architecture
- Installation
- Quick Start
- Key Features
- Configuration Reference & Discovery
- Runtime Mechanics & Execution Model
- Environment & Secrets Management
- TUI Commands & Keybindings
- CLI Reference & Subcommands
- Logging, In-Stream Redaction & Exporters
- Performance & Polling Budget
- Development & Testing
- License
hum coordinates complex development environments across disparate technologies without enforcing monolithic project structures:
┌──────────────────────────────────────────────┐
│ hum CLI / Ratatui TUI │
│ (Commands, Interactive Monitor & Views) │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────┴───────────────────────┐
│ Config Loader & Discovery │
│ (hum.yaml, hum.local.yaml, XDG Registry) │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────┴───────────────────────┐
│ Core & Graph Resolver │
│ (Topological Sort, Cycles, Readiness, │
│ Subtractive Exclusions) │
└──────────┬───────────────────┬───────────────┘
│ │
┌────────────────┴───┐ ┌───┴──────────────────┐
│ Runtime Adapters │ │ Scoped Env Providers │
└────┬───────────┬───┘ └───┬──────────────┬───┘
│ │ │ │
┌─────────┴─────┐ ┌─┴─────────────┐ ┌──┴───────────┐ ┌┴────────────┐
│ Process │ │ Compose │ │ one-password │ │ exec │
│ (Detached │ │ (Docker │ │ (1Password │ │ (Subprocess │
│ PGID / Lock) │ │ Compose CLI) │ │ CLI / op://)│ │ JSON/Env) │
└─────────┬─────┘ └───────────────┘ └──────────────┘ └─────────────┘
│
┌─────────┴───────────────────────────────────────────────┐
│ Persistent State & Observability │
│ - Atomic State Registry: $XDG_STATE_HOME/hum/<project>│
│ - Native Log Sink: Bounded rotation & regex redaction │
│ - HTTP Exporter: Non-blocking NDJSON telemetry stream │
└─────────────────────────────────────────────────────────┘
When you execute start, hum launches each selected unit through its configured runtime, writes minimal metadata into the persistent atomic registry, and exits immediately. Subsequent CLI or TUI invocations observe running services directly from the OS without relying on a background daemon.
Install the release formula via the official tap:
brew install delaudio/tap/humSee docs/HOMEBREW.md for tap bootstrap and release details.
Build and install locally using Cargo:
git clone https://github.com/delaudio/hum.git
cd hum
cargo install --path .-
Register a project from any repository checkout:
hum project register demo ./hum.yaml
-
Inspect the dependency plan before starting:
hum demo all-services plan
-
Start the stack (starts units in topological order and exits):
hum demo all-services start
-
Monitor services interactively in the terminal:
hum demo all-services tui # or simply hum demo all-services -
Synchronize provider secrets (e.g. 1Password) into local cached stores:
hum demo all-services secrets sync
-
Stop services cleanly in reverse dependency order:
hum demo all-services stop
- Daemonless Execution: Commands start processes, record atomic state, and exit. No resident supervisor daemon consumes background CPU or leaks state.
- Process Group Isolation: Each service runs in a dedicated session and process group (PGID) with a random, inherited identity lock to avoid signaling reused PIDs.
- Atomic Rollback: If a multi-service startup fails midway, only units created by that specific invocation are safely torn down.
- Topological Lifecycle: Units are started in strict dependency order and stopped in reverse order.
- Granular Readiness: Control when dependent units unblock via
depends_on_ready: started | listening | healthy. - Subtractive Exclusions: Refine service selection on the fly with
--exclude TEMPLATEand--exclude-service SERVICE.
- Native Process Adapter: Detached local processes with working directories, env files, and port monitoring.
- Docker Compose Adapter: Maps services to compose targets, manages project profiles, merges generated layers, and supports
reconcile: trueto update running containers when configurations change.
- 1Password & Exec Providers: Resolve secrets on demand from
op://vault references or external commands (dotenvorjsonpayloads). - Process-Level Scoping: Secrets are injected only into the target child processes—never leaked into the global
humenvironment or written to Compose files. - Cached & Schema-Validated: Plaintext caches are saved with mode
0600under.hum/cache/and checked against explicit key schemas.
- Native Log Sink: Captures stdout and stderr with configurable file rotation (e.g. 10 MiB, 3 files).
- In-Stream Masking: Redacts sensitive strings (tokens, keys, passwords) before displaying in CLI/TUI or exporting.
- NDJSON HTTP Exporters: Bounded, non-blocking telemetry stream to local or remote collectors.
- Pre-Flight Checks: Verifies CLI dependencies, file existence, port collisions, and provider executables without reading vault secrets.
- Port Diagnosis: Differentiates between managed listeners, foreign port owners, and stale registry entries.
- Live Monitoring: Non-blocking background polling with minimal resource usage (< 2% CPU, < 60 MiB RSS).
- Integrated Log Viewer: Search (
/), horizontal panning, paging from disk history, and live follow. - Service Details & Actions: View PID, PGID, port, uptime, health status, and trigger start/stop/restart or open URLs directly.
When a project path is not passed explicitly via --config, hum resolves configuration in the following order:
./hum.yamlsearching upward through parent directories.$XDG_CONFIG_HOME/hum/hum.yaml(defaulting to~/.config/hum/hum.yaml).- Machine-local overrides in
hum.local.yamllocated beside the resolvedhum.yaml.
Large version 3 projects can split committed configuration into explicit YAML
fragments. Declare each fragment once in the main hum.yaml:
version: 3
project: demo
imports:
- hum/core.yaml
- hum/services/api.yaml
- hum/templates.yamlImported files use the same top-level sections as hum.yaml, but must not
declare version, project, or another imports list. Paths are relative to
the directory containing the main configuration and must stay below it. Hum
loads fragments in declaration order, rejects duplicate paths and duplicate
named repositories, runtimes, providers, services, tasks, templates, or profiles, then
applies the optional machine-local hum.local.yaml override and validates the
complete configuration. All runtime paths remain relative to the main
hum.yaml, regardless of which fragment declares them.
For example, hum/services/api.yaml can colocate the service with its startup
task and focused template:
tasks:
prepare-api:
command: ["./scripts/prepare-api.sh"]
services:
api:
runtime: local
command: npm run dev
depends_on: [prepare-api]
templates:
api:
services: [api]Keep secrets and machine-specific paths in hum.local.yaml; imports are for
portable, versioned project configuration.
Register projects globally in ~/.config/hum/config.yaml (or $XDG_CONFIG_HOME/hum/config.yaml):
version: 1
projects:
demo:
config: ~/code/demo/hum.yamlManage registrations with the CLI:
hum project register <NAME> <PATH>Here is an annotated, production-ready Version 3 configuration:
version: 3
project: sample
# 1. Define runtime adapters
runtimes:
local:
type: process
containers:
type: compose
project_name: hum-sample
reconcile: true
files:
- docker-compose.yml
# 2. Configure scoped environment providers
environment_providers:
team-vault:
type: one-password
generic-exec:
type: exec
command:
- echo
- '{"PORT":"8080"}'
# Optional adapter for product-owned source/image runtime switching.
# Hum appends MODE, service names, --all, --template NAME, and --no-start.
# This argv is trusted configuration. Multi-component executable paths resolve
# from the project root; absolute paths and parent traversal are supported.
switch_provider:
command: [./scripts/runtime-switch]
# 3. Define trusted one-shot tasks
tasks:
migrate:
command:
- docker
- compose
- --project-name
- hum-sample
- --file
- docker-compose.yml
- run
- --rm
- migrate
depends_on:
- database
timeout: 2m
# 4. Define persistent services
services:
database:
runtime: containers
target: database
api:
runtime: local
command: python3 -m http.server 8080
port: 8080
url: http://localhost:8080
env_file: api.env
env_from:
- provider: team-vault
reference: op://Development/sample-api/environment
format: dotenv
optional: true
schema: api.env.example
cache: .hum/cache/api.env
- provider: generic-exec
args:
- --json
format: json
optional: true
depends_on:
- migrate
depends_on_ready: healthy
healthcheck:
type: http
url: http://localhost:8080/health
interval: 2s
timeout: 1s
retries: 15
# 5. Define selectable templates
templates:
backend:
services:
- api
infrastructure:
services:
- database
all-services:
services:
- database
- apiEnvironment variables for a service are resolved using the following strict precedence hierarchy (highest to lowest):
- CLI
--env KEY=VALUEexplicit overrides (repeatable). - Inherited environment from the launching shell.
service.env_overrides(often sourced fromhum.local.yamlfor host vs container routing).- Provider-backed values (
env_fromvia 1Password / Exec). service.envdeclared inhum.yaml.env_fileloaded from disk.
- Process Isolation: Each process is launched in its own process group (
setsid/setpgid) with stdin redirected to/dev/nulland stdout/stderr connected to the rotating log sink. - State Persistence: State is serialized atomically into
$XDG_STATE_HOME/hum/<project>/(or~/.local/state/hum/<project>/). It records PID, PGID, start time, working directory, port, and log file paths. - PID Verification: Before sending any signal (
SIGTERM,SIGKILL),humvalidates the process start time against OS process tables to eliminate PID reuse hazards. - Concurrency & Locking: File-based
project.lockserializes concurrent operations, guaranteeing that duplicate or racingstartinvocations are safe and idempotent.
- Target Mapping: Maps hum service names to Compose service targets.
- Dynamic Layers: Project tasks can emit
generated_files(e.g. host networking configurations) which Compose merges automatically once created. - Reconciliation: Runtimes with
reconcile: truereapply running containers when provider values or generated overlays change. - Clean Teardown vs Reset:
stoppreserves named volumes;resetdeletes Compose volumes and requires explicit confirmation or the--yesflag.
- Direct Argv: Tasks execute direct argument vectors (
["docker", "compose", "run", ...]) without shell string interpolation vulnerabilities. - Idempotency Checks: Tasks can define an optional
checkcommand to avoid rerunning completed tasks. - Doctor Diagnostic Sub-commands: Tasks can define a read-only
doctorcheck executed duringhum doctorto validate product prerequisites without exposing secret environments.
Control sequencing with depends_on_ready:
| Readiness Mode | Unblock Condition |
|---|---|
started |
Unblocks immediately once the process or container is launched. |
listening |
Unblocks once the configured TCP port actively accepts connections (50 ms connect deadline). |
healthy |
Unblocks once HTTP or TCP health check probes succeed for the configured retry threshold. |
one-password: Resolvesop://vault/item/fieldor whole-document dotenv secrets using the 1Password CLI (op).exec: Runs an arbitrary command returning key-value pairs formatted asdotenvorjson.
- Least Privilege: Secret values are passed exclusively through child process environment tables or Compose invocations. They are never exported to your shell or stored in world-readable temporary files.
- Safe Compose Inspection: Inspect effective configurations safely with
hum <project> <template> config compose --format yaml; all secrets are replaced with<redacted>tokens.
- Encrypted/Restricted Caches: Cached secret files are stored with
0600permissions under.hum/cache/(which should be added to.gitignore). - Fail-Closed Semantics: If a required provider fails and no valid cache exists, startup fails immediately. Optional sources continue gracefully.
- Manual Sync: Refresh cached secrets without starting services using:
hum <project> <template> secrets sync
Launch the interactive monitor with hum <project> <template> tui (or hum <project> <template>):
| Key / Shortcut | Action |
|---|---|
Up / k |
Move cursor up in service list |
Down / j |
Move cursor down in service list |
Space |
Toggle start / stop on selected service |
r |
Restart selected service |
Enter |
Open service details modal (PID, PGID, port, health, paths) |
l |
Open persistent log viewer for selected service |
o |
Open service URL in default web browser |
p |
Open template switcher modal |
d |
Run doctor pre-flight diagnostics in the background |
? |
Open keybindings help overlay |
q |
Open quit confirmation dialog |
| Key / Shortcut | Action |
|---|---|
Up / k |
Scroll logs up by 1 line |
Down / j |
Scroll logs down by 1 line |
PageUp / PageDown |
Scroll logs up / down by a page (20 lines) |
Home |
Scroll to oldest available log history on disk |
End |
Return to bottom and resume live follow mode |
Left / h |
Scroll log view horizontally left |
Right / l |
Scroll log view horizontally right |
0 |
Reset horizontal scroll to beginning |
/ |
Enter search query mode |
c |
Clear log buffer view |
Esc / q |
Close log viewer |
| Key / Shortcut | Action |
|---|---|
Esc |
Close any active modal dialog (details, doctor, help, template) |
l (in quit dialog) |
Leave services running and quit TUI |
s (in quit dialog) |
Stop selected template and quit TUI |
| Indicator | Process State | Health State | Description |
|---|---|---|---|
● (Green) |
running |
healthy |
Process is active and passing health checks. |
◐ (Yellow) |
starting / stopping |
checking |
State transition in progress or health check pending. |
✗ (Red) |
exited |
unhealthy |
Process has exited or failed health checks. |
○ (Gray) |
missing |
unchecked |
Not running / no health checks configured. |
hum [OPTIONS] <PROJECT> <TEMPLATE> [COMMAND]
hum [OPTIONS] project register <NAME> <CONFIG>--registry PATH: Override global registry path (default:~/.config/hum/config.yaml).--config PATH: Explicit projecthum.yamlpath (bypasses registry).--env KEY=VALUE: Override service environment variables (repeatable).
| Command | Description |
|---|---|
start [service...] |
Start the selected template or listed services in dependency order. |
stop [service...] [--timeout 10s] |
Stop services in reverse dependency order. |
restart [service...] [--timeout 10s] |
Restart services with a clean stop-start sequence. |
switch MODE [service...] [--all] [--no-start] |
Ask the project adapter to switch selected services to a product-defined runtime mode. |
status |
Show status, PID, port, and health check state for template services. |
plan [service...] [--json] |
Preview resolved dependency order and actions without executing. |
logs [service] [-n 100] [-f] |
Tail captured stdout/stderr logs for a service or template. |
reset [--yes] [--timeout 10s] |
Stop all project services and purge Compose volumes. |
doctor |
Run diagnostic pre-flight checks on ports, tools, and configs. |
tui |
Launch the interactive full-screen terminal monitor. |
MODE is project-defined and may be invoked without service names for
operations such as adapter status. Target-changing modes should use explicit
service names or --all according to the adapter contract.
# Register a project into the machine-local registry
hum project register <NAME> <CONFIG_PATH>
# Validate configuration syntax and template selection
hum <project> <template> config validate
# Render effective Docker Compose configuration with redacted secrets
hum <project> <template> config compose [--format yaml|json] [--runtime NAME]
# Synchronize provider-backed secrets into local 0600 cache files
hum <project> <template> secrets sync [service...]Refine startup and diagnostics on the fly:
--exclude TEMPLATE: Remove root services from that template. Reintroduced automatically with a warning if needed by a dependent unit.--exclude-service SERVICE: Strictly exclude a service; fails before starting if it remains a required dependency.
For native detached processes, hum start connects output pipes to a dedicated native log sink (hum __log-sink).
logs:
max_file_bytes: 10485760 # 10 MiB per log file
rotated_files: 3 # Keep 3 rotated archives (.1, .2, .3)
max_line_bytes: 65536 # 64 KiB buffer ceiling
retention: 7d # Remove rotated logs older than 7 days- Raw files on disk remain byte-accurate.
- Closing CLI/TUI log viewers never delivers
SIGPIPEto running services.
Define regular expressions in hum.yaml to redact sensitive credentials before they reach the terminal or telemetry exporters:
logs:
redact_patterns:
- "(?i)(token|password|secret)=[^ ]+"
- "bearer [a-zA-Z0-9_\\-\\.]+"Stream log events asynchronously to an observability collector:
logs:
exporters:
- type: http
endpoint: http://127.0.0.1:8687/events
timeout: 750ms
headers:
Authorization: "Bearer machine-local-token"- Bounded non-blocking queue: Collector downtime never slows or blocks services.
- Secret headers are passed via private Unix domain socket descriptors and never written to temporary files.
See docs/LOGGING.md for full logging mechanics and configuration contracts.
hum is engineered for negligible overhead in long-running development sessions:
- Startup Latency: 10 detached services start in < 2 seconds.
- TUI Frame Latency: First frame renders in < 250 ms.
- Resource Footprint: Steady-state monitor consumes < 2% average CPU and < 60 MiB RSS memory for 10 monitored services.
- Non-Blocking Polling: Port checks use 50 ms TCP timeouts;
lsofis never executed during steady-state polling.
See docs/POLLING.md for polling contract details and benchmarking procedures.
Run the full code quality and testing suite locally:
# Code formatting & clippy lints
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
# Execute test suite with minimum test count gate
scripts/verify-test-count.sh 60
# Build optimized release binary
cargo build --release
# Run performance smoke benchmarks
cargo test --release --test performance_smoke -- --ignored --nocapture
# Release validation
scripts/release-guard.sh v0.6.3For complete product specifications and acceptance criteria, see docs/PRD.md.
This project is licensed under the MIT License.