onboard#
import "github.com/jbcom/radioactive-ralph/internal/onboard"
Package onboard implements the guided first-run wizard: when a user runs the client cold on an interactive terminal and no supervisor is reachable, it OFFERS (with explicit consent) to install and start the background service, falling back to a foreground supervisor or the plain print-the-commands path. See docs/superpowers/specs/2026-07-17-guided-first-run-onboarding-design.md.
The wizard is pure orchestration: every side effect (prompting, installing the service, discovering the supervisor) is an injected dependency, so the whole decision tree is unit-testable without touching the real system.
Index#
Variables#
ErrQuit is returned by a Prompter when the user asks to quit the wizard.
var ErrQuit = errors.New("onboard: user quit")
type Deps#
Deps are the injected dependencies. Every field is required.
type Deps struct {
// Out receives the wizard's human-facing output.
Out io.Writer
// Prompt drives the yes/no questions.
Prompt Prompter
// Plan describes what installing the service will create.
Plan Plan
// InstallService installs AND (best-effort) starts the background service.
InstallService func() error
// WaitReachable blocks until a supervisor answers or the timeout elapses,
// returning true when one became reachable.
WaitReachable func(timeout time.Duration) bool
// ForegroundHint is the exact command a user runs to start a foreground
// supervisor (printed on the fallback path).
ForegroundCmd string
// ManualCommands is the multi-line fallback text (the pre-wizard message).
ManualCommands string
}
type Outcome#
Outcome reports how the wizard ended so the caller knows whether to proceed to the TUI.
type Outcome int
const (
// SupervisorReady means a supervisor is now reachable — proceed to the TUI.
SupervisorReady Outcome = iota
// PrintedForegroundHint means the wizard printed the `--supervisor`
// command for the user to run themselves; the caller should exit cleanly.
PrintedForegroundHint
// PrintedCommands means the wizard fell back to printing the manual
// commands; the caller returns its usual no-supervisor error.
PrintedCommands
)
func Run#
func Run(d Deps) (Outcome, error)
Run drives the first-run flow. It assumes the caller already confirmed the session is interactive and no supervisor is currently reachable.
type Plan#
Plan is the “what will be created” summary shown before any outward-facing action, so the user consents to concrete paths, not a vague promise.
type Plan struct {
StateDir string
DBPath string
ServiceUnit string
ServiceUnitPath string
}
type Prompter#
Prompter asks the user a yes/no question. Confirm returns (true, nil) for yes, (false, nil) for no, and a non-nil error to abort the whole wizard (e.g. the user typed ‘q’ to quit, or stdin closed).
type Prompter interface {
Confirm(question string, defaultYes bool) (bool, error)
}
type StdinPrompter#
StdinPrompter is the real Prompter: it writes the question to Out and reads one line from In, interpreting y/yes → true, n/no → false, q/quit → ErrQuit, and an empty line → the supplied default. Any other input re-asks (bounded, so a closed stdin doesn’t loop forever).
type StdinPrompter struct {
In io.Reader
Out io.Writer
// contains filtered or unexported fields
}
func NewStdinPrompter#
func NewStdinPrompter(in io.Reader, out io.Writer) *StdinPrompter
NewStdinPrompter builds a StdinPrompter over in/out.
func (*StdinPrompter) Confirm#
func (p *StdinPrompter) Confirm(question string, defaultYes bool) (bool, error)
Confirm implements Prompter.
Generated by gomarkdoc