Documentation
¶
Overview ¶
Package harness is what Aboard knows about each harness it sets up and delivers to, behind one interface. A harness's profile (adapters/<harness>/profile.yaml) holds the data: names, variables, files, hooks, checks. Generic reads the profile for the jobs every harness shares, and a harness's own package (claudecode, codex, omp) overrides only what the profile can't say. The CLI and the delivery daemon reach harnesses only through this package and the registry, so they name none.
Index ¶
- Constants
- func AndList(words []string) string
- func FillFile(source string, e Env) []byte
- func OrList(words []string) string
- func RulesFile(rule string) []byte
- func ShellWord(s string) string
- func VersionAtLeast(text, minimum string) bool
- func VersionNumber(text string) string
- type AllowRequired
- type Call
- type Check
- type CheckResult
- type Env
- type FallbackSpec
- type Generic
- func (g *Generic) Adapter(string) delivery.Adapter
- func (g *Generic) ConfigDir(e Env) string
- func (g *Generic) Detected(e Env) bool
- func (g *Generic) Fix(string) string
- func (g *Generic) HookCall(event string, _ HookInput) (Call, bool)
- func (g *Generic) Hooks(exe, version string) []Hook
- func (g *Generic) InstalledChecks(_ context.Context, e Env) ([]CheckResult, bool)
- func (g *Generic) Items(e Env, scope string) []Item
- func (g *Generic) Profile() *Profile
- func (g *Generic) Unsupported(version string) []HookSpec
- func (g *Generic) Version(ctx context.Context, e Env) string
- type Handler
- type Harness
- type Headless
- type Hook
- type HookInput
- type HookSpec
- type HooksMissing
- type InstallSpec
- type Interactive
- type Item
- type ItemKind
- type Op
- type Profile
- type Set
- func (s Set) Get(name string) (Harness, bool)
- func (s Set) InSession(e Env) (title string, ok bool)
- func (s Set) Names() []string
- func (s Set) NetworkBlocked(e Env) (title string, ok bool)
- func (s Set) RootSession(e Env) (delivery.SessionKey, bool)
- func (s Set) Sandboxed(e Env) (title, fix string, ok bool)
- func (s Set) Session(e Env) (delivery.SessionKey, bool)
- func (s Set) Subagent(e Env) (string, bool)
- func (s Set) Titles() []string
Constants ¶
const ( ScopeGlobal = "global" ScopeProject = "project" )
Scopes aboard init installs in: under the home directory for every project, or under the working directory for that project only.
const ( LevelOK = "ok" LevelWarning = "warning" LevelError = "error" )
Check levels.
const ( // LaunchEnv is ABOARD_AGENT and ABOARD_LAUNCH in the harness's environment. LaunchEnv = "env" // LaunchPrompt is the launch ticket in the first prompt, for a harness whose // sessions run in a process that may not have been started with that environment. LaunchPrompt = "prompt" )
Where swarm up puts a new session's identity (Interactive.Launch).
const Newest = "newest"
Newest is the version to give Hooks for every hook, as the newest version of the harness runs them, whatever is installed. Doctor and status recognize Aboard's hooks with it.
const SubagentEnv = "ABOARD_SUBAGENT"
SubagentEnv is the variable that marks a command as run by a subagent of the session it runs in. Its value is the harness's id for the subagent.
Variables ¶
This section is empty.
Functions ¶
func FillFile ¶
FillFile returns a file built into aboard for installing inside a harness, with this machine's aboard binary and ABOARD_HOME written where the file says {aboard_binary} and {aboard_home}. Each is written as the inside of a JSON string, which reads the same in a JavaScript or TypeScript string literal. A file aboard doesn't have is empty; LoadProfile has checked that every profile's files are there.
func VersionAtLeast ¶
VersionAtLeast reports whether the first dotted version number in text, such as "2.1.288 (Claude Code)", is at least minimum. Text without one counts as new enough.
func VersionNumber ¶
VersionNumber returns the first dotted version number in text, such as 2.1.288 in "2.1.288 (Claude Code)", or "" when it has none.
Types ¶
type AllowRequired ¶
type AllowRequired struct {
// Why is init's reason for asking.
Why string `yaml:"why"`
// Advice is the line init adds when it sets the harness up without the rule.
Advice string `yaml:"advice"`
// Missing is what init's overview says without the rule.
Missing string `yaml:"missing"`
// Allowed and NotAllowed are what doctor says with and without it.
Allowed string `yaml:"allowed"`
NotAllowed string `yaml:"not_allowed"`
}
AllowRequired holds what Aboard says about an allow rule the harness can't reach Aboard without, such as Codex's, whose sandbox blocks network access.
type Call ¶
type Call struct {
Op Op
// Wake is true for a prompt that is the harness handing back the bundle a waiting
// hook woke the session with: that prompt is the wake itself, not a later event.
Wake bool
}
Call is what one hook does.
type CheckResult ¶
type CheckResult struct {
Name, Level, Code, Message, Fix string
}
CheckResult is one line of aboard doctor.
type Env ¶
type Env struct {
// Getenv reads an environment variable.
Getenv func(string) string
// Dir is the working directory, the project of a project setup.
Dir string
// Aboard is the aboard binary that hooks and installed files run, by absolute path,
// and AboardHome the ABOARD_HOME aboard runs with, or "".
Aboard, AboardHome string
}
Env is what a harness reads from the machine.
type FallbackSpec ¶
FallbackSpec is one event a hook falls back to on an older version, with the first version that knows it. A profile may name the event alone, which any version knows.
func (*FallbackSpec) UnmarshalYAML ¶
func (f *FallbackSpec) UnmarshalYAML(n *yaml.Node) error
UnmarshalYAML reads a fallback written as an event name or as {event, since}.
type Generic ¶
type Generic struct {
// contains filtered or unexported fields
}
Generic is a harness made to work from its profile alone. A harness's own package embeds it and overrides only the methods where the harness really differs.
func MustLoad ¶
MustLoad returns the generic implementation of a harness whose profile is built into aboard. The profiles are part of the binary and checked against their schema by the tests, so one that can't be read is a broken build.
func NewGeneric ¶
NewGeneric returns the generic implementation of the harness a profile describes.
func (*Generic) Adapter ¶
Adapter returns the shared adapter for the harness's delivery mechanism, or nil.
func (*Generic) ConfigDir ¶
ConfigDir returns the folder the harness reads its global config from: the folder its variable names when that is an absolute path, else the default under HOME.
func (*Generic) Detected ¶
Detected reports whether the harness looks installed: its config folder exists or its command is on the PATH.
func (*Generic) Hooks ¶
Hooks returns the hook entries aboard init installs for a harness that reports version, each running "exe hook <harness> <run>": every hook that version runs as written, and for one it doesn't, the fallback events it knows. A version that can't be read is taken to be the oldest Aboard works with (checks.min_version), so no entry names an event the installed harness may not know. Newest gives every hook.
func (*Generic) InstalledChecks ¶
InstalledChecks reports a harness that isn't installed. An installed one needs no line of its own: its hooks' check follows.
func (*Generic) Unsupported ¶
Unsupported returns the profile's hooks that a harness reporting version runs neither as written nor on a fallback event, which Hooks leaves out.
type Handler ¶
type Handler struct {
Type string
Command string
// Timeout is in seconds; 0 leaves it out.
Timeout int
// Options are more settings in the harness's own words, written after the timeout.
Options map[string]any
}
Handler is one hook command in a harness's hook settings.
func (Handler) MarshalJSON ¶
MarshalJSON writes type, command and timeout, then the options with their keys sorted, so an entry is written the same way every time. A harness asks the person to trust its hooks again when an entry's text changes.
type Harness ¶
type Harness interface {
// Profile is the harness's profile.
Profile() *Profile
// Detected reports whether the harness looks installed on this machine.
Detected(e Env) bool
// ConfigDir is the folder the harness reads its global config from.
ConfigDir(e Env) string
// Version is what the harness reports as its version, or "" when no hook depends
// on it or it can't be told.
Version(ctx context.Context, e Env) string
// Hooks are the hook entries aboard init installs for a harness that reports
// version, each running exe. A version that can't be read gets what the oldest
// version Aboard works with runs; Newest gets every hook.
Hooks(exe, version string) []Hook
// Unsupported are the profile's hooks that Hooks leaves out for version, because
// that version runs neither them nor a fallback.
Unsupported(version string) []HookSpec
// Items are what aboard init installs in a scope, in order, with their paths.
Items(e Env, scope string) []Item
// InstalledChecks are aboard doctor's checks that the harness is there and can be
// delivered to. installed is false when doctor checks nothing more of it.
InstalledChecks(ctx context.Context, e Env) (checks []CheckResult, installed bool)
// HookCall says what "aboard hook <harness> <event>" does with the hook's input.
HookCall(event string, in HookInput) (Call, bool)
// Fix says how to fix a delivery that stopped for a reason this harness's
// adapter gave, or "".
Fix(reason string) string
// Adapter is the delivery daemon's adapter for the harness, or nil when it has no
// automatic delivery.
Adapter(clientVersion string) delivery.Adapter
}
Harness is one harness Aboard sets up and delivers to.
type Headless ¶
type Headless struct {
Via string `yaml:"via"`
Run []string `yaml:"run"`
Resume []string `yaml:"resume"`
SessionField string `yaml:"session_field"`
Model []string `yaml:"model"`
}
Headless is how the headless launcher runs one turn of the harness without a terminal: Via is native (Run and Resume below), acp or none.
type Hook ¶
type Hook struct {
// Event is the harness's name for the hook event.
Event string
// Arg is the event argument of "aboard hook <harness> <arg>".
Arg string
// Matcher is the matcher of the hook's group, such as Bash, or "" for none.
Matcher string
Handler Handler
}
Hook is one hook entry aboard init installs.
type HookInput ¶
type HookInput struct {
SessionID string `json:"session_id"`
Source string `json:"source"`
// AgentID is set when a hook fires inside a subagent.
AgentID string `json:"agent_id"`
// HookEventName is the event the harness ran the hook for; a tool hook's output
// names it back.
HookEventName string `json:"hook_event_name"`
// Prompt is the prompt text, on a prompt hook.
Prompt string `json:"prompt"`
// ToolInput is the input of the tool about to run, on a pre-tool hook. For a shell
// command it holds the command and the tool's other settings.
ToolInput json.RawMessage `json:"tool_input"`
}
HookInput is the part of a harness's hook input the hooks read.
type HookSpec ¶
type HookSpec struct {
Event string `yaml:"event"`
Run string `yaml:"run"`
Op Op `yaml:"op"`
Matcher string `yaml:"matcher"`
Timeout int `yaml:"timeout"`
Options map[string]any `yaml:"options"`
// Since is the first version of the harness that runs the hook as written: it knows
// the event, and honors its options and the output the hook gives.
Since string `yaml:"since"`
// Fallback are the events that run the same command on a version older than Since.
Fallback []FallbackSpec `yaml:"fallback"`
// Without is what the person loses on a version that runs neither the hook nor a
// fallback, such as "idle sessions don't wake for new messages".
Without string `yaml:"without"`
}
HookSpec is one hook a profile lists.
type HooksMissing ¶
HooksMissing is what doctor reports when the harness's hooks aren't installed.
type InstallSpec ¶
type InstallSpec struct {
Kind ItemKind `yaml:"kind"`
Global string `yaml:"global"`
Project string `yaml:"project"`
Format string `yaml:"format"`
Source string `yaml:"source"`
Rule string `yaml:"rule"`
Accepts []string `yaml:"accepts"`
Note string `yaml:"note"`
Required *AllowRequired `yaml:"required"`
Missing *HooksMissing `yaml:"missing"`
Text string `yaml:"text"`
ProjectText string `yaml:"project_text"`
}
InstallSpec is one item of a profile's install list, with its paths unresolved.
type Interactive ¶
type Interactive struct {
Start []string `yaml:"start"`
Resume []string `yaml:"resume"`
Model []string `yaml:"model"`
// Launch is where swarm up puts a new session's identity: LaunchEnv (the default)
// or LaunchPrompt.
Launch string `yaml:"launch"`
}
Interactive is how a launcher starts and resumes the harness in a terminal. Start and Resume hold {prompt} and {session}; Model holds {model}.
type Item ¶
type Item struct {
InstallSpec
// Path is where it goes in this scope. An allow rule without a path goes in the
// hooks file; a consent step has none.
Path string
// Data is what Aboard writes to a file it owns: the skill, a file, or the file
// holding an allow rule.
Data []byte
}
Item is one thing aboard init installs in a scope.
type ItemKind ¶
type ItemKind string
ItemKind is the kind of one thing aboard init installs.
const ( // ItemSkill is the Aboard skill, a file Aboard owns. ItemSkill ItemKind = "skill" // ItemHooks are the delivery hooks, merged into a file shared with the person. ItemHooks ItemKind = "hooks" // ItemFile is a file inside the harness that Aboard owns, such as an extension. ItemFile ItemKind = "file" // ItemAllowRule lets the agent run aboard commands without a permission prompt. ItemAllowRule ItemKind = "allow-rule" // ItemConsent is a step the person takes, such as trusting new hooks. ItemConsent ItemKind = "consent" )
Install item kinds.
type Op ¶
type Op string
Op is what a hook does, in terms common to every harness.
const ( // OpSessionStart registers the session. OpSessionStart Op = "session-start" // OpPrompt marks a turn running. OpPrompt Op = "prompt" // OpWait waits while the session is idle, and wakes it with a bundle. OpWait Op = "wait" // OpTurnEnd marks the turn ended. OpTurnEnd Op = "turn-end" // OpTool is a tool boundary, where the owner's messages are added to the turn. OpTool Op = "tool" // OpEnd closes the session. OpEnd Op = "end" // OpMarkSubagent marks an aboard command a subagent is about to run as the // subagent's, so it can't act as the parent. OpMarkSubagent Op = "mark-subagent" )
Hook operations.
type Profile ¶
type Profile struct {
Harness string `yaml:"harness"`
Name string `yaml:"name"`
Command string `yaml:"command"`
CheckName string `yaml:"check_name"`
Checks struct {
Installed Check `yaml:"installed"`
LoggedIn Check `yaml:"logged_in"`
// MinVersion is the oldest version Aboard works with. A harness whose version
// can't be read gets the hooks this version runs.
MinVersion string `yaml:"min_version"`
} `yaml:"checks"`
SandboxEnv []string `yaml:"sandbox_env"`
SandboxNetworkEnv []string `yaml:"sandbox_network_env"`
SandboxFix string `yaml:"sandbox_fix"`
SessionEnv []string `yaml:"session_env"`
ConfigDir struct {
Env string `yaml:"env"`
Default string `yaml:"default"`
} `yaml:"config_dir"`
Install []InstallSpec `yaml:"install"`
Interactive Interactive `yaml:"interactive"`
Headless Headless `yaml:"headless"`
Identity struct {
Kind string `yaml:"kind"`
Env string `yaml:"env"`
RootEnv string `yaml:"root_env"`
EnvFile string `yaml:"env_file"`
Precedence int `yaml:"precedence"`
YieldsTo []string `yaml:"yields_to"`
} `yaml:"identity"`
// SubagentIdentity is whether a subagent's commands can be told from its parent's:
// none, marked or seats.
SubagentIdentity string `yaml:"subagent_identity"`
Lifecycle struct {
Liveness string `yaml:"liveness"`
OutlivesTerminal bool `yaml:"outlives_terminal"`
ResumeKeepsID bool `yaml:"resume_keeps_id"`
ResumeStart string `yaml:"resume_start"`
SubagentField string `yaml:"subagent_field"`
} `yaml:"lifecycle"`
Delivery struct {
Method string `yaml:"method"`
Capabilities []string `yaml:"capabilities"`
Queue []string `yaml:"queue"`
Hooks []HookSpec `yaml:"hooks"`
MidTurn string `yaml:"mid_turn"`
// WaitingNotice is true when the tool hook also names the other waiting messages.
WaitingNotice bool `yaml:"waiting_notice"`
} `yaml:"delivery"`
}
Profile is the part of a harness profile (adapters/<harness>/profile.yaml, schema spec/harness-profile.schema.json) that Aboard's code reads. The rest of the file describes the harness for launchers, the conformance kit and people.
func LoadProfile ¶
LoadProfile reads the profile built into aboard for a harness.
func (*Profile) HasCapability ¶
HasCapability reports whether the harness's delivery has a capability, such as "idle-hook".
type Set ¶
type Set []Harness
Set is the harnesses Aboard knows, in the order they are listed and set up.
func (Set) InSession ¶
InSession reports the harness whose session a command runs in, from its markers or its sandbox's. title is "" when a marker is set but its harness gives way to one Aboard doesn't know: the command still runs in a session.
func (Set) NetworkBlocked ¶
NetworkBlocked reports the harness whose sandbox a command runs in when that sandbox blocks network access, as Codex's does by default: then neither the server's address nor the daemon's socket can be reached from there, running or not.
func (Set) RootSession ¶
func (s Set) RootSession(e Env) (delivery.SessionKey, bool)
RootSession returns the session of the conversation a command runs under: the one Session finds, except in a sub-agent of a harness that gives every command both its own thread's id and its root session's (Codex), where it is the root's. A subagent thus finds the same session, and so the same agent, in every harness.
func (Set) Sandboxed ¶
Sandboxed reports the harness whose sandbox a command runs in, and how to get the delivery daemon started outside it. A daemon started there would inherit the sandbox and couldn't reach the harness.
func (Set) Session ¶
func (s Set) Session(e Env) (delivery.SessionKey, bool)
Session returns the harness session a command runs in: ABOARD_SESSION, which Aboard's hooks or extension write, then the variable of a harness that gives every command its session id. A session of a harness that gives way to another one whose marker is set is not taken.
func (Set) Subagent ¶
Subagent returns the id of the subagent a command runs in: from the mark Aboard's hook or extension adds to a subagent's aboard commands, or, for a harness that gives every command both its own thread's id and its root session's (Codex), from the two being different. A mark inherited by a harness started inside that subagent doesn't count: a more specific marker says the command runs in another harness, as for ABOARD_SESSION.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package claudecode is Claude Code's harness: its profile, read by the generic implementation, and the one thing the profile can't say.
|
Package claudecode is Claude Code's harness: its profile, read by the generic implementation, and the one thing the profile can't say. |
|
Package codex is Codex's harness: its profile, read by the generic implementation, and what the profile can't say.
|
Package codex is Codex's harness: its profile, read by the generic implementation, and what the profile can't say. |
|
Package omp is omp's (oh-my-pi's) harness: its profile, read by the generic implementation, and the one check the profile can't say.
|
Package omp is omp's (oh-my-pi's) harness: its profile, read by the generic implementation, and the one check the profile can't say. |
|
Package registry lists the harnesses Aboard sets up and delivers to.
|
Package registry lists the harnesses Aboard sets up and delivers to. |