https://github.com/aretw0/procio
Lightweight, standalone Go module for robust process lifecycle management and interactive I/O.
https://github.com/aretw0/procio
context-aware cross-platform go golang interactive-cli leak-free pdeathsig process-hygiene process-management signaling terminal-io windows-job-objects zombie-processes
Last synced: 24 days ago
JSON representation
Lightweight, standalone Go module for robust process lifecycle management and interactive I/O.
- Host: GitHub
- URL: https://github.com/aretw0/procio
- Owner: aretw0
- License: agpl-3.0
- Created: 2026-02-13T23:10:11.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-02-23T19:35:13.000Z (27 days ago)
- Last Synced: 2026-02-24T00:11:57.224Z (27 days ago)
- Topics: context-aware, cross-platform, go, golang, interactive-cli, leak-free, pdeathsig, process-hygiene, process-management, signaling, terminal-io, windows-job-objects, zombie-processes
- Language: Go
- Homepage:
- Size: 80.1 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# procio
[](https://goreportcard.com/report/github.com/aretw0/procio)
[](https://pkg.go.dev/github.com/aretw0/procio)
[](./LICENSE)
[](https://github.com/aretw0/procio/releases)
`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.
## Installation
```bash
go get github.com/aretw0/procio
```
## Usage
### Starting a Process Safely
```go
import "github.com/aretw0/procio/proc"
cmd := proc.NewCmd(ctx, "long-running-worker")
// Uses Pdeathsig (Linux) or Job Objects (Windows) to enforce cleanup
err := cmd.Start()
```
### Reading Input Robustly (Hardened)
```go
import "github.com/aretw0/procio/scan"
// Binds scanner to process liveness for deterministic EOF detection
scanner := scan.NewScanner(os.Stdin, scan.WithProcess(cmd))
scanner.Start(ctx)
```
### Enabling TTY Cancellation
For interactive CLIs that need Ctrl+C cancellation support:
```go
import (
"context"
"github.com/aretw0/procio/scan"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
scanner := scan.NewScanner(os.Stdin,
scan.WithInterruptible(), // Enables context cancellation via Ctrl+C
scan.WithLineHandler(func(line string) {
fmt.Println("Got:", line)
}),
)
scanner.Start(ctx) // Returns when context is cancelled or EOF
```
### Chained Cancels
`proc.NewCmd` integrates naturally with derived contexts, so cancellation hierarchies work as expected:
```go
// appCtx controls the whole application lifetime.
appCtx, appCancel := context.WithCancel(context.Background())
defer appCancel()
// subCtx adds a deadline for a specific subprocess.
subCtx, subCancel := context.WithTimeout(appCtx, 10*time.Second)
defer subCancel()
cmd := proc.NewCmd(subCtx, "worker")
if err := 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.
```
### Advanced Features
`procio` provides primitives for advanced process control:
#### Pseudo-Terminals (PTY)
Wrap interactive applications:
```go
import "github.com/aretw0/procio/pty"
cmd := exec.CommandContext(ctx, "vim")
p, err := pty.StartPTY(cmd)
// Forward p.Controller to/from host Stdin/Stdout
```
#### Streaming Telemetry
Monitor processes in real-time (Linux & Windows):
```go
ch, err := proc.Monitor(ctx, cmd, time.Second)
for m := range ch {
fmt.Printf("CPU: %.1f%% Mem: %d KB\n", m.CPUPercent, m.MemRSS/1024)
}
```
## Observability
`procio` is opinionated about specific mechanisms but unopinionated about logging/metrics.
You can inject your own observer:
```go
import "github.com/aretw0/procio"
procio.SetObserver(myObserver)
```
See [docs/RECIPES.md](./docs/RECIPES.md) for a complete `log/slog` adapter example.
## License
This project is licensed under the terms of the [AGPL-3.0](./LICENSE).