procio is a lightweight, standalone set of composable primitives for safe process lifecycle and interactive I/O in Go.
It provides three core primitives:
- proc: Leak-free process management (ensures child processes die when parent dies).
- termio: Interruptible terminal I/O (handling interrupts and safe terminal handles).
- scan: Robust input scanning with deterministic protection against "Fake EOF" signals on Windows.
go get github.com/aretw0/procioimport"github.com/aretw0/procio/proc"cmd:=proc.NewCmd(ctx, "long-running-worker")
// Uses Pdeathsig (Linux) or Job Objects (Windows) to enforce cleanuperr:=cmd.Start()import"github.com/aretw0/procio/scan"// Binds scanner to process liveness for deterministic EOF detectionscanner:=scan.NewScanner(os.Stdin, scan.WithProcess(cmd))
scanner.Start(ctx) For interactive CLIs that need Ctrl+C cancellation support:
import (
"context""github.com/aretw0/procio/scan"
)
ctx, cancel:=context.WithCancel(context.Background())
defercancel()
scanner:=scan.NewScanner(os.Stdin,
scan.WithInterruptible(), // Enables context cancellation via Ctrl+Cscan.WithLineHandler(func(linestring) {
fmt.Println("Got:", line)
}),
)
scanner.Start(ctx) // Returns when context is cancelled or EOFproc.NewCmd integrates naturally with derived contexts, so cancellation hierarchies work as expected:
// appCtx controls the whole application lifetime.appCtx, appCancel:=context.WithCancel(context.Background())
deferappCancel()
// subCtx adds a deadline for a specific subprocess.subCtx, subCancel:=context.WithTimeout(appCtx, 10*time.Second)
defersubCancel()
cmd:=proc.NewCmd(subCtx, "worker")
iferr:=cmd.Start(); err!=nil {
log.Fatal(err)
}
cmd.Wait()
// worker is terminated when subCtx expires OR when appCtx is cancelled —// whichever comes first. Platform hygiene (Job Objects / Pdeathsig) is// still applied regardless of which signal arrives first.procio provides primitives for advanced process control:
Wrap interactive applications:
import"github.com/aretw0/procio/pty"cmd:=exec.CommandContext(ctx, "vim")
p, err:=pty.StartPTY(cmd)
// Forward p.Controller to/from host Stdin/StdoutMonitor processes in real-time (Linux & Windows):
ch, err:=proc.Monitor(ctx, cmd, time.Second)
form:=rangech {
fmt.Printf("CPU: %.1f%% Mem: %d KB\n", m.CPUPercent, m.MemRSS/1024)
}procio is opinionated about specific mechanisms but unopinionated about logging/metrics.
You can inject your own observer:
import"github.com/aretw0/procio"procio.SetObserver(myObserver)See docs/RECIPES.md for a complete log/slog adapter example.
This project is licensed under the terms of the AGPL-3.0.