---
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]()