--- title: internal/variantpool description: Go API reference for the variantpool package. --- # variantpool ```go import "github.com/jbcom/radioactive-ralph/internal/variantpool" ``` Package variantpool manages the subprocess lifecycle of spawned ralph variants \(green, professor, fixit, etc.\). Each spawned subprocess gets a lifeline pipe — when the supervising MCP server dies for any reason \(clean exit, SIGKILL, OOM, crash\), the child reads EOF on the pipe and self\-terminates within a few seconds. Per\-platform belt\-and\-suspenders \(Pdeathsig / kqueue NOTE\_EXIT / Job Objects\) is deferred to internal/proclife — the lifeline pipe is portable and sufficient for the portable/durable\-foreground cases. ## Index - [type Options](<#Options>) - [type Pool](<#Pool>) - [func New\(o Options\) \(\*Pool, error\)](<#New>) - [func \(p \*Pool\) Close\(ctx context.Context\) error](<#Pool.Close>) - [func \(p \*Pool\) Get\(id string\) \*Variant](<#Pool.Get>) - [func \(p \*Pool\) Spawn\(ctx context.Context, o SpawnOpts\) \(\*Variant, error\)](<#Pool.Spawn>) - [type SpawnOpts](<#SpawnOpts>) - [type Status](<#Status>) - [type Variant](<#Variant>) - [func \(v \*Variant\) Kill\(ctx context.Context\) error](<#Variant.Kill>) - [func \(v \*Variant\) ReadOne\(buf \[\]byte\) \(int, error\)](<#Variant.ReadOne>) - [func \(v \*Variant\) Say\(msg string\) error](<#Variant.Say>) - [func \(v \*Variant\) Status\(\) Status](<#Variant.Status>) ## type [Options]() Options configures a new Pool. ```go type Options struct { // Store is the plandag handle used for heartbeat + variant row // bookkeeping. Required. Store *plandag.Store // SessionID is the plandag sessions.id this pool owns. Every // spawned variant is registered under this session. SessionID string } ``` ## type [Pool]() Pool owns every live subprocess the MCP server has spawned on behalf of this session. Callers get back a handle per spawn. ```go type Pool struct { // contains filtered or unexported fields } ``` ### func [New]() ```go func New(o Options) (*Pool, error) ``` New allocates a Pool. Callers must call Close\(\) on shutdown so subprocess children receive SIGTERM and DB rows clean up. ### func \(\*Pool\) [Close]() ```go func (p *Pool) Close(ctx context.Context) error ``` Close SIGTERMs every managed variant and waits up to graceShutdown for each to exit, SIGKILLing stragglers. ### func \(\*Pool\) [Get]() ```go func (p *Pool) Get(id string) *Variant ``` Get returns the variant managed under id, or nil if the pool doesn't know about it \(e.g., it was killed or never spawned\). Read\-only — callers should treat the return value as a snapshot handle. ### func \(\*Pool\) [Spawn]() ```go func (p *Pool) Spawn(ctx context.Context, o SpawnOpts) (*Variant, error) ``` Spawn launches a variant subprocess with a lifeline pipe attached on FD 3. Returns a Variant handle; the caller can Say/Kill/Status. ## type [SpawnOpts]() SpawnOpts configures a Spawn call. ```go type SpawnOpts struct { // VariantName names the variant (green, professor, ...). VariantName string // ClaudeBin is the absolute path to the claude binary that the // variant will exec. The variantpool itself does NOT spawn // claude directly — it spawns a ralph _supervisor command that // owns the claude lifecycle. Empty defaults to looking up // "claude" on PATH inside the supervisor. ClaudeBin string // RalphBin is the absolute path to the radioactive_ralph binary. // Pool exec's it as " _supervisor --variant ". RalphBin string // WorkingDir is the working directory for the subprocess. WorkingDir string // Env is merged with the parent environment. Pool adds // RALPH_LIFELINE_FD=3 automatically. Env []string // LogSink receives the subprocess stdout+stderr. Nil → os.Stderr. LogSink io.Writer } ``` ## type [Status]() Status returns a snapshot of the subprocess state. ```go type Status struct { ID string Name string PID int Running bool } ``` ## type [Variant]() Variant is a managed subprocess handle. ```go type Variant struct { // ID is the plandag session_variants.id. ID string // Name is the variant name (green, professor, ...). Name string // contains filtered or unexported fields } ``` ### func \(\*Variant\) [Kill]() ```go func (v *Variant) Kill(ctx context.Context) error ``` Kill signals the subprocess to shut down. Closes the lifeline pipe \(which alone causes a well\-behaved child to exit\), then SIGTERMs, then SIGKILLs after graceWait. ### func \(\*Variant\) [ReadOne]() ```go func (v *Variant) ReadOne(buf []byte) (int, error) ``` ReadOne reads the next line of stdout. Callers typically loop calling this in a goroutine to drain output. ### func \(\*Variant\) [Say]() ```go func (v *Variant) Say(msg string) error ``` Say writes a line to the subprocess's stdin. The trailing \\n is added if not present. ### func \(\*Variant\) [Status]() ```go func (v *Variant) Status() Status ``` Status produces a lightweight read\-only snapshot suitable for MCP tool responses. Generated by [gomarkdoc]()