No description
  • Rust 76.8%
  • JavaScript 13.1%
  • Shell 5.1%
  • HTML 2.1%
  • CSS 2.1%
  • Other 0.8%
Find a file
despiegk 6e31cdb049
All checks were successful
Tests / test (push) Successful in 3m37s
Build and Test / build (push) Successful in 4m44s
fix: enforce name as required field in RunCreateInput
The hero_proc server requires a name for ad-hoc runs but the SDK had it
as Option<String>, leading to confusing runtime errors. Now it is a
required String in both the OpenRPC spec and all generated/hand-edited
types, so callers get a compile-time error instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 19:50:49 +02:00
.claude socket rename 2026-04-06 11:55:52 +02:00
.forgejo/workflows fix: set RUST_MIN_STACK to prevent rustc SIGSEGV in CI 2026-04-06 20:41:40 +02:00
crates fix: enforce name as required field in RunCreateInput 2026-04-07 19:50:49 +02:00
docker Add hero_proc project structure and implementation 2026-03-19 07:03:35 +01:00
docs sdk: add layered factory API and OO service/run handles (issue #38) 2026-04-05 13:10:15 +02:00
embedded_scripts socket rename 2026-04-06 11:55:52 +02:00
etc/hero_proc Add hero_proc project structure and implementation 2026-03-19 07:03:35 +01:00
examples socket rename 2026-04-06 11:55:52 +02:00
scripts fix: increase hero_proc_ui socket wait timeout from 10s to 30s 2026-04-06 14:00:54 +02:00
testcases feat(tests): add parallel job logging integration tests and UI test cases 2026-03-31 10:34:29 +02:00
tests fix: enforce name as required field in RunCreateInput 2026-04-07 19:50:49 +02:00
.gitignore Add hero_proc project structure and implementation 2026-03-19 07:03:35 +01:00
buildenv.sh chore: bump buildenv.sh version to 0.4.4 2026-04-06 20:49:06 +02:00
Cargo.lock feat: restore openrpc_proxy in hero_proc_ui — fixes /rpc 404 2026-04-06 14:26:45 +02:00
Cargo.toml chore: bump version to 0.4.4 2026-04-06 12:04:24 +02:00
Makefile socket rename 2026-04-06 11:55:52 +02:00
README.md socket rename 2026-04-06 11:55:52 +02:00

hero_proc

A lightweight process supervisor with dependency management, similar to systemd but simpler.

Quick Start

Install from Source

make build      # Build all release binaries
make install    # Install to ~/hero/bin/

Run

# Set required environment variables
export FORGE_TOKEN=your_forgejo_token_here

# Start server + web dashboard
make run

# Use the CLI
hero_proc service list
hero_proc service status my-service
hero_proc service start my-service
hero_proc service stop my-service

The web admin dashboard is available at http://127.0.0.1:9999.


Documentation


Features

  • Dependency Graph: Services declare dependencies (requires, after, wants, conflicts)
  • State Machine: Explicit states (Inactive, Blocked, Starting, Running, Stopping, Success, Exited, Failed)
  • Process Groups: Signals sent to process groups, handling sh -c child processes correctly
  • Health Checks: TCP, HTTP, and exec-based health checks with retries
  • Ordered Shutdown: Dependents stop before their dependencies
  • Hot Reload: Reload configuration without full restart
  • Secrets Management: Encrypted secret storage with Forgejo sync (init, pull, push)
  • Scheduled Actions: Cron-based scheduling for recurring tasks
  • PTY Attach: Live terminal attach to running processes via WebSocket
  • Web Admin Dashboard: Real-time service management UI with charts, logs, events, and bulk operations
  • TUI Dashboard: Interactive terminal UI for service management (ratatui-based)
  • Fully Embedded UI: All assets (Bootstrap, Chart.js, icons) compiled into the binary — no CDN or network required
  • OpenRPC API: 92 JSON-RPC 2.0 methods over Unix socket

Architecture

hero_proc_server (daemon)
    | unix socket (IPC + JSON-RPC 2.0)
    v
hero_proc (CLI/TUI)        hero_proc_ui (web admin dashboard)
                         | unix socket + TCP :9999

Crate Structure

crates/
  hero_proc_sdk/               # OpenRPC client SDK — generated client + builders + factory
  hero_proc_server/            # Process supervisor daemon (JSON-RPC 2.0 via Unix socket)
  hero_proc/                   # Command-line interface + TUI
  hero_proc_ui/                # Web admin dashboard (Axum + Askama + Bootstrap)
  hero_proc_lib/               # SQLite persistence layer (jobs, runs, secrets, logging, services)
  hero_proc_examples/          # Runnable SDK usage examples
  hero_proc_integration_test/  # Integration test suite + stress tests

Dependency Graph

        hero_proc_sdk (no internal deps)
           ^         ^        ^         ^
           |         |        |         |
        server      CLI      UI       lib

All crates depend on hero_proc_sdk. No cross-dependencies between server, CLI, UI, or lib.

Ports and Sockets

Component Binding Default
hero_proc_server Unix socket (IPC) $HERO_SOCKET_DIR/hero_proc/rpc.sock
hero_proc_ui Unix socket (local) $HERO_SOCKET_DIR/hero_proc/ui.sock
hero_proc_ui TCP (HTTP dashboard) 9999

Core Concepts

Concept Role Lifetime
Action Executable template (script + interpreter + config) Stored, reusable
Service Supervision unit — desired state + auto-restart Ongoing, supervisor-managed
Job Single execution of an action Transient
Run Universal grouping unit — groups jobs under a single lifecycle Transient

Service

A service is a supervision unit (like a systemd unit). It declares a desired state and references one or more actions. The supervisor continuously reconciles reality with the desired state:

  • start — supervisor ensures the service is running; restarts on crash
  • stop — supervisor ensures the service is stopped
  • ignore — supervisor does not manage this service

Action

An action is a reusable executable template: a script, its interpreter, environment, timeout, retry policy, and dependency edges. Actions can declare depends_on other actions for intra-service ordering.

Job

A job is a single execution of an action. Jobs can be one-shot (run and exit) or long-running processes (is_process = true), where exiting is treated as failure. Each job tracks phase (pending -> running -> succeeded/failed), PID, exit code, and logs.

Run

A run is the universal execution grouping unit. It serves two roles:

  1. Service run — created automatically when a service is started. Named service_{name}, with service_id pointing back to the owning service. If a service has 3 actions, starting it creates 1 run with 3 jobs.
  2. Ad-hoc run — standalone execution of a set of actions (e.g., build pipelines, one-off tasks). Name is required. service_id is None.

A run can depend on other runs by ID — the supervisor will not start it until all dependency runs have reached "ok". Status progression: created → waiting_deps → starting → running → ok | error | halted.

Principles

  • Run is the universal grouping unit: both ad-hoc executions and service starts create a Run. The service_id field distinguishes them.
  • Cascade delete: deleting a Run or Service deletes all associated Jobs. A Job belongs to exactly one Run.
  • Clean restart: when a Service is started, previous Jobs for that Service are removed from the database by default (can be overridden).
  • Provenance tracking: each Job records its service_id and action_id so the origin is always traceable.

For the full data model specification, see docs/README.md.

CLI Commands

All CLI commands are organized into subcommand groups:

Service Management

hero_proc service list              # List all services
hero_proc service status <name>     # Show service status
hero_proc service start <name>      # Start a service
hero_proc service stop <name>       # Stop (cascades to dependents)
hero_proc service restart <name>    # Restart a service
hero_proc service kill <name>       # Send signal to service
hero_proc service add <name>        # Add a service at runtime
hero_proc service add-job <svc> ... # Add a job to a service
hero_proc service remove <name>     # Remove a service
hero_proc service logs <name>       # View service logs
hero_proc service why <name>        # Show why service is blocked
hero_proc service tree              # Show dependency tree

Job Management

hero_proc job list                  # List jobs
hero_proc job get <id>              # Get job details
hero_proc job create ...            # Create a job
hero_proc job delete <id>           # Delete a job
hero_proc job status <id>           # Job status
hero_proc job logs <id>             # Job logs
hero_proc job retry <id>            # Retry a failed job
hero_proc job cancel <id>           # Cancel a running job

Run Tracking

hero_proc run list                  # List runs
hero_proc run get <id>              # Get run details
hero_proc run logs <id>             # Run logs
hero_proc run stats                 # Run statistics

Log Management

hero_proc log query                 # Query logs
hero_proc log filter                # Filter logs
hero_proc log prune                 # Prune old logs
hero_proc log export                # Export logs

Secrets Management

hero_proc secret set <key> <val>    # Set a secret
hero_proc secret get <key>          # Get a secret
hero_proc secret list               # List secrets
hero_proc secret delete <key>       # Delete a secret
hero_proc secret init               # Initialize secrets store
hero_proc secret pull               # Pull secrets from Forgejo
hero_proc secret push               # Push secrets to Forgejo

Actions

hero_proc action list               # List actions
hero_proc action get <name>         # Get action details
hero_proc action set ...            # Register an action
hero_proc action delete <name>      # Delete an action

Scripts

hero_proc script scan               # Scan for scripts
hero_proc script list               # List registered scripts
hero_proc script get <name>         # Get script details
hero_proc script set ...            # Register a script
hero_proc script delete <name>      # Delete a script
hero_proc script run <name>         # Run a script

System

hero_proc system ping               # Check daemon connectivity
hero_proc system health             # Server health check
hero_proc system stats              # System statistics
hero_proc system shutdown [--force] # Shutdown daemon
hero_proc system reset [--force]    # Stop all, delete all configs
hero_proc system wipe               # Wipe all data
hero_proc system demo               # Create demo services
hero_proc system schedules          # List scheduled actions

Debug

hero_proc debug state               # Full graph state dump
hero_proc debug procs               # Process tree dump

Other

hero_proc attach <name>             # Attach to PTY of running process
hero_proc tui                       # Launch interactive TUI dashboard

Web Admin Dashboard

The hero_proc_ui crate provides a real-time web admin dashboard at http://localhost:9999 with tabs for:

  • Actions: Registered actions with interpreter, timeout, and tags
  • Jobs: Job instances with phase, status, and logs; includes statistics
  • Runs: Execution runs with status and job counts
  • Services: Service management, dependencies, and action mappings
  • Secrets: Encrypted configuration values
  • Logs: Query and filter system logs by source, level, and timestamp

All UI assets (Bootstrap 5.3.3, Bootstrap Icons) are embedded in the binary via rust-embed.

# Start server + UI
make run

# Or start separately
hero_proc_server &
hero_proc_ui --port 9999

SDK Usage

use hero_proc_sdk::*;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Connect to the default local socket
    let hp = hero_proc_factory().await?;

    // All RPC methods available directly
    let pong = hp.system_ping(SystemPingInput {}).await?;
    println!("server: {}", pong.version);

    // High-level helpers
    let svc = simple_service("myapp", "./myapp --serve");
    hp.start_service("myapp", svc, 30).await?;
    hp.stop_service("myapp", 10).await?;

    Ok(())
}

Builder API

use hero_proc_sdk::{ServiceBuilder, ActionBuilder};

let service = ServiceBuilder::new("myapp")
    .description("My application")
    .exec("./myapp --server")
    .requires(&["database"])
    .build();

Presets

use hero_proc_sdk::{simple_service, oneshot_service, system_service, sleep_service};

let svc = simple_service("myapp", "./myapp --serve");
let setup = oneshot_service("setup", "bash setup.sh");
let sys = system_service("logger", "/usr/bin/logger");

Remote Connection

let hp = HeroProcFactory::builder()
    .http("http://10.0.0.1:8080")
    .connect().await?;

Environment Variables

Required

Variable Description
FORGE_TOKEN Forgejo personal access token. Used for secrets sync and authentication.
WEBROOT Base URL of the hero_proc UI (e.g. http://127.0.0.1:9998/). make run sets this automatically.

Optional

Variable Default Description
HERO_PROC_LOG_LEVEL info Log level: trace, debug, info, warn, error
HERO_PROC_CONFIG_DIR ~/hero/cfg/hero_proc Service config directory
HERO_PROC_SOCKET $HERO_SOCKET_DIR/hero_proc/rpc.sock Unix socket path

Server Flags

hero_proc_server \
  --db-path ~/hero/var/hero_proc.db \
  --socket $HERO_SOCKET_DIR/hero_proc/rpc.sock \
  --log-level info \
  --screen  # Run in GNU Screen session

Shutdown Ordering

Services are stopped in reverse dependency order:

Example: database <- app <- worker

Startup order:   database -> app -> worker
Shutdown order:  worker -> app -> database

When stopping a single service, dependents are stopped first:

  • hero_proc service stop database stops worker, then app, then database
  • Dependencies are NOT auto-stopped (other services may need them)

Development

make check        # Verify workspace builds
make test         # Run unit tests
make build        # Build all release binaries
make install      # Build release and install to ~/hero/bin/
make lint         # Run clippy linter
make fmt          # Format code
make test-all     # Run all tests (unit + bash + rhai)

# Run server + UI
make run          # Release build, install, start on port 9999
make rundev       # Debug build, start on port 9999
make stop         # Graceful shutdown

# Integration tests
make test-bash      # Bash-based integration tests
make test-rhai      # Rhai-based integration tests
make test-shutdown  # Shutdown scenario tests

# Playground
make play-tui     # Launch TUI with sample services
make play-web     # Launch web UI with sample services

# Release
make ship-binary  # Tag and push for CI
make release       # Create release