This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
dappco.re/go/core/process is the process management framework for CoreGO. It handles process execution (spawn, monitor, stream, kill), daemon lifecycle (PID files, health checks, graceful shutdown, registry), and pipeline orchestration (parallel, sequential, or DAG-ordered multi-process runs). All process events broadcast via Core IPC actions.
core go test # Run all tests
core go test --run Name # Single test
core go fmt # Format
core go lint # Lint
core go vet # VetThe package has three layers, all in the root process package (plus a exec subpackage):
Service is a Core service (*core.ServiceRuntime[Options]) that manages all Process instances. It spawns subprocesses, pipes stdout/stderr through goroutines, captures output to a RingBuffer, and broadcasts IPC actions (ActionProcessStarted, ActionProcessOutput, ActionProcessExited, ActionProcessKilled — defined in actions.go).
The legacy global singleton API (process_global.go) was removed in favor of
explicit Core service registration.
Daemon composes three independent components into a lifecycle manager:
- PIDFile (pidfile.go) — single-instance enforcement via PID file with stale-PID detection (
Signal(0)) - HealthServer (health.go) — HTTP
/health(liveness) and/ready(readiness) endpoints - Registry (registry.go) — tracks running daemons as JSON files in
~/.core/daemons/, auto-prunes dead PIDs onList()
Daemon.Start() acquires PID → starts health → registers. Daemon.Run(ctx) blocks until context cancellation, then Stop() reverses in order (unregister → release PID → stop health).
Runner executes multiple RunSpecs with three modes: RunAll (DAG-aware, parallelizes independent specs in waves), RunSequential (stops on first failure), RunParallel (ignores dependencies). Dependency failures cascade via Skipped status unless AllowFailure is set.
Builder-pattern wrapper around os/exec with structured logging via a pluggable Logger interface. NopLogger is the default. Separate from the main package — no Core/IPC integration, just a convenience wrapper.
- Core integration:
Serviceembeds*core.ServiceRuntime[Options]and usess.Core().ACTION(...)to broadcast typed action messages. Tests create a Core instance viaframework.New(framework.WithService(Register)). - Output capture: All process output goes through a fixed-size
RingBuffer(default 1MB). Oldest data is silently overwritten when full. SetRunOptions.DisableCaptureto skip buffering for long-running processes where output is only streamed via IPC. - Process lifecycle: Status transitions are
StatusPending → StatusRunning → StatusExited|StatusFailed|StatusKilled. Thedonechannel closes on exit; use<-proc.Done()orproc.Wait(). - Detach / process group isolation: Set
RunOptions.Detach = trueto run the subprocess in its own process group (Setpgid). Detached processes usecontext.Background()so they survive parent context cancellation and parent death. - Graceful shutdown:
Service.OnShutdownkills all running processes.Daemon.Stop()performs ordered teardown: sets health to not-ready → shuts down health server → releases PID file → unregisters from registry.DaemonOptions.ShutdownTimeout(default 30 s) bounds the shutdown context. - Auto-registration: Pass a
RegistryandRegistryEntryinDaemonOptionsto automatically register the daemon onStart()and unregister onStop(). - PID liveness checks: Both
PIDFileandRegistryuseproc.Signal(syscall.Signal(0))to check if a PID is alive before trusting stored state. - Error handling: All errors MUST use
core.E(), neverfmt.Errorforerrors.New. Sentinel errors are package-level vars created withcore.E("", "message", nil).
dappco.re/go/core— Core DI framework, IPC actions,ServiceRuntimedappco.re/go/core/io— Filesystem abstraction (coreio.Local) used by PIDFile and Registrygithub.com/stretchr/testify— test assertions (require/assert)
- Tests spawn real subprocesses (typically
echo,sleep,cat). Use short timeouts to avoid hanging. - Test helper
newTestService(t)in service_test.go creates a Core instance with a small buffer (1024 bytes) and returns both theServiceandCore. - Uses
github.com/stretchr/testifywithrequirefor setup andassertfor checks.