app

package
v0.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package app is nib's entrypoint, importable so nib can be embedded in another binary. nib's own main.go is a thin wrapper over Main.

Index

Constants

View Source
const ExitCodeApprovalNoInput = 3

ExitCodeApprovalNoInput is the exit code for a CLI session that refused a tool call because stdin was closed and nothing could approve it. See cmd.ErrApprovalNoInput for why that is not a success.

It is deliberately neither 0 nor 1: a script piping a prompt in has to be able to tell "answered" from "refused to act" without reading stdout, and from a crash or a bad flag (2) without guessing. Scripts branch on this number, so it is part of nib's interface and does not change.

Variables

This section is empty.

Functions

func Main

func Main(argv []string) int

Main runs nib and returns a process exit code. argv is the full argument vector including the program name. It routes through the same code as Run, so the process-wide xlog side effect noted there applies here too.

func Run

func Run(ctx context.Context, o Options) error

Run runs nib and returns an error. It never calls os.Exit.

Every failure comes back as a bare ExitError carrying nothing but an exit code, the cause having been written to Stderr instead: an unparseable flag, an unknown --init shell, an MCP transport failure, the setup abort, the injected-stream refusal and a management subcommand's non-zero code are all indistinguishable to the caller. The code is 1 for every one of those except two: an unparseable flag is 2, and a CLI session that had to refuse a tool call because stdin could not approve it is ExitCodeApprovalNoInput.

Cancelling ctx unwinds whichever mode is running, the TUI included, and comes back as ExitError{1} with the context's error on Stderr. Signals are the caller's: this entrypoint installs no handler, and nothing below it listens for one either.

Run also reconfigures the process-wide xlog logger from the resolved config, which an embedder sharing that logger will observe.

Types

type ExitError

type ExitError struct{ Code int }

ExitError carries a non-zero exit code out of Run.

func (ExitError) Error

func (e ExitError) Error() string

type Options

type Options struct {
	// Args are the arguments after the program name (os.Args[1:]).
	Args []string
	// ProgramName is the name shown in the messages this package prints itself:
	// the --version line, the flag package's usage and parse errors, the setup
	// gate's two aborts, and the injected-stream refusal. Empty means "nib".
	//
	// It also renames the --init shell snippets, which is more than a cosmetic
	// substitution: the widget they define invokes this name, so an embedder's
	// Ctrl+Space runs the embedder's command rather than a `nib` its users do
	// not have. A name of several words ("local-ai chat") stays several words
	// in command position, and the widget's function name is derived from it by
	// reducing it to an identifier.
	//
	// It reaches nothing beyond that, so parts of an embedded nib still say
	// "nib" whatever this is set to: the management subcommands' usage strings
	// ("usage: nib plugin ..." and its skill and mcp equivalents), and the
	// "nib: ..." diagnostics that config loading and plugin/skill discovery
	// write straight to os.Stderr on every run. Threading the name through
	// those is follow-up work.
	ProgramName string
	// BaseDir overrides the config, plugins, and skills root. Empty means
	// nib's default XDG resolution.
	BaseDir string
	// Stdin, Stdout, Stderr default to the process streams when nil.
	//
	// CLI mode (--cli) reads and writes exactly these. The TUI, which is the
	// DEFAULT mode, does not: it renders on /dev/tty, because the terminal is
	// still there even when stdout is a pipe, and serving that case is why it
	// opens /dev/tty at all. Only the shell-capture line the TUI prints on exit
	// goes to Stdout.
	//
	// For an embedder that is a rule rather than a caveat: injecting a Stdin or
	// a Stdout that is NOT a terminal (a buffer, a pipe, a file) requires --cli,
	// or the run is refused with an error saying so, rather than rendering into
	// a stream the TUI cannot drive. Injecting the process streams, or any other
	// terminal, leaves every mode working.
	//
	// Only those two are gated (see decideStreamRefusal). A non-terminal Stderr
	// is always accepted, because every error this package prints goes through
	// o.stderr() rather than through the TUI, so a TUI session with its error
	// output captured to a buffer or a log file is a supported combination.
	//
	// One consequence is worth spelling out, because it inverts the usual
	// instinct that passing os.Stdout is the safe, explicit choice. An embedder
	// that wants nib's shell-capture idiom, where the user runs
	// `out=$(myprog agent)` and the TUI prints the selected command on stdout
	// for the shell to capture, must leave Stdout NIL rather than set it to
	// os.Stdout. Nil means "not injected": nib falls back to the process stream,
	// the TUI runs, and the capture line lands on stdout as it should. Setting
	// os.Stdout explicitly injects whatever stdout happens to be, and under
	// $(...) that is a pipe, so the run is refused for a stream nib would have
	// used anyway.
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer
	// Defaults seed config fields the config file leaves empty. Every field of
	// types.Config is seedable except BaseDir, which is ignored: the root has
	// exactly one knob, the BaseDir field above, and it overwrites any seeded
	// value. See config.LoadOptions.Defaults for what "empty" means for maps,
	// slices and booleans, including that a seeded true beats an explicit
	// `false:` in the config file for every bool.
	Defaults types.Config
	// SkipSetup suppresses the first-run model wizard. Embedders that resolve
	// the model themselves set this. It suppresses the whole gate, so an
	// explicit --setup in Args becomes a silent no-op rather than an error.
	SkipSetup bool
	// SkipBareEnv suppresses the bare MODEL / API_KEY / BASE_URL variables, and
	// only those three. nib's prefixed variables keep reading the ambient
	// environment and still outrank a seed: NIB_TRACE_DIR overrides a seeded
	// TraceDir, NIB_YOLO forces ApprovalMode to "auto" over a seeded one, and
	// LOG_FORMAT selects the log encoding.
	SkipBareEnv bool
}

Options configures a nib invocation. The zero value reproduces standalone nib's behavior exactly, so embedders opt in to each difference.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL