Documentation
¶
Overview ¶
Package tools is abcd's explain-then-install mode (itd-63): the curated registry of the external tools abcd knows, the plain-language explanation a verb gives when it finds one missing, and the one place a confirmed install step is run.
It is a MODE other verbs call, never a surface of its own (the product thinker's decision 3, 2026-09-21): a verb that finds a tool missing asks Explain for what to say and, where it offers the install, hands Install a Confirm function its front door supplies. The package has no transport knowledge — it never reads a terminal and never writes to stdout — so the CLI asks on the terminal, the plugin page asks through the host's question tool, and this code is the same under both (criterion 5).
The trust boundary is Install. What it runs is fixed data in this file, compiled into the binary: an argv per platform, never composed from a flag, a repository file or an environment value, never a shell string. It runs only after the caller's Confirm returns yes, never in CI, and never a program that resolves inside the repository it was asked from. See install.go.
Index ¶
- func Known(name string) bool
- func Missing(cause error, name string, capability Capability) error
- func Names() []string
- func WithinTree(p, resolved, guard string) bool
- type Answer
- type Capability
- type Confirm
- type Explanation
- type Installer
- type MissingError
- type Requirement
- type Result
- type Step
- type Tool
- type Use
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Missing ¶
func Missing(cause error, name string, capability Capability) error
Missing wraps cause with the explanation for name as capability uses it.
func WithinTree ¶ added in v0.12.0
WithinTree reports whether the program at p, which resolves to resolved after symlinks, lies inside the tree at guard, judged lexically and after symlink resolution on both sides. It is the one in-checkout judgement for a program: the installer refuses to run what it holds, and ahoy's presence check does not count it as installed. Both p and guard are absolute; the caller has already resolved p.
Types ¶
type Answer ¶
Answer is a caller's reply to the install question: yes or no, and in words how the reply was reached (typed at a terminal, named with a flag, no terminal to ask at), which the result repeats so a no is never silent.
type Capability ¶
type Capability string
Capability names what a verb is doing when it finds a tool missing. The same tool is optional for one capability and required for another, so an explanation is always for a (tool, capability) pair.
const ( // TranscriptScan is the secret scan of captured session transcripts in a // repository that has NOT armed gitleaks: the native scanner covers it. TranscriptScan Capability = "transcript-scan" // TranscriptScanArmed is the same scan in a repository that armed gitleaks // in .abcd/config/gitleaks.json: without the binary a release refuses, // while the history store still stores the transcript on the native // scanner and names the gap in its receipt (the 2026-09-25 ruling on // iss-2608291814575788). TranscriptScanArmed Capability = "transcript-scan-armed" // GitHubSettings is every verb that reads or changes the repository's // settings on GitHub (ahoy remote, site setup), which abcd does only // through gh. GitHubSettings Capability = "github-settings" )
type Confirm ¶
type Confirm func(Explanation) Answer
Confirm asks the person whether to run the install the explanation shows. The front door supplies it; a nil Confirm is a no.
type Explanation ¶
type Explanation struct {
Tool string `json:"tool"`
Known bool `json:"known"`
Capability Capability `json:"capability"`
CapabilityName string `json:"capability_name,omitempty"`
Requirement Requirement `json:"requirement,omitempty"`
What string `json:"what,omitempty"`
Homepage string `json:"homepage,omitempty"`
Does string `json:"does,omitempty"`
WithoutIt string `json:"without_it,omitempty"`
NativeDefault string `json:"native_default,omitempty"`
OnDecline string `json:"on_decline,omitempty"`
StepManager string `json:"step_manager,omitempty"`
// Step is the exact argv Install would run on this platform; empty when
// the registry names none (an unknown tool, or a platform without a step).
Step []string `json:"step,omitempty"`
Effects string `json:"effects,omitempty"`
Verify []string `json:"verify,omitempty"`
// RegistryGap is set for a tool the registry does not know: the gap is
// abcd's own, and this names the capture that records it.
RegistryGap string `json:"registry_gap,omitempty"`
}
Explanation is what a verb says when it finds a tool missing (criterion 1): the tool, whether it is optional or required for this capability, what works without it, what it would do, and the exact install step, all from the registry. It is structured so each front door renders it its own way (the plugin page reads it from a verb's --json); Lines is the plain-text rendering every front door shares.
func Explain ¶
func Explain(name string, capability Capability) Explanation
Explain renders the explanation for name as capability uses it, on the running platform.
func (Explanation) Lines ¶
func (e Explanation) Lines() []string
Lines is the plain-text explanation, one line per part, the first naming the tool and whether it is optional or required.
func (Explanation) StepText ¶
func (e Explanation) StepText() string
StepText is the install step as a person would type it, or the reason there is none.
type Installer ¶
type Installer struct {
// LookPath resolves a bare program name on the operator's PATH.
LookPath func(string) (string, error)
// Run executes an argv whose argv[0] is already resolved, without a shell.
Run func(context.Context, []string) ([]byte, error)
// Getenv reads the environment (CI detection).
Getenv func(string) string
// GOOS selects the platform's step.
GOOS string
// Guard is the directory a resolved program must lie outside: the
// repository the verb was run from. A PATH entry pointing into it is
// repository content, which is trusted to choose nothing that runs.
Guard string
}
Installer runs confirmed install steps. Every process-touching seam is a field so the whole decision path is exercised in tests with no package manager; Default is the production wiring.
func Default ¶
Default is the production installer for a verb run from guard (its repository root, or its working directory outside one).
func (*Installer) Install ¶
func (in *Installer) Install(name string, capability Capability, confirm Confirm) Result
Install is the trust boundary. In order, and each refusal runs nothing:
- An unknown tool is refused: nothing is composed from a name.
- A platform without a step is refused.
- CI never installs, and is not asked.
- The caller's Confirm must return yes; nil is a no.
- The step's program must resolve on PATH to an absolute path outside the guarded tree, lexically and after symlinks.
The step then runs as an argv (no shell), with stdin closed, in its own process group, bounded in time (runArgv names the one limit of that bound's kill); the verify command follows under the same rules.
type MissingError ¶
type MissingError struct {
Cause error
Explanation Explanation
}
MissingError is a verb's refusal for a missing tool with the registry's explanation appended: the refusal stands exactly as it was (its cause stays reachable through errors.Is), and only its message grows to say what the tool is, whether this capability needs it, and the exact install step.
func (*MissingError) Error ¶
func (m *MissingError) Error() string
func (*MissingError) Unwrap ¶
func (m *MissingError) Unwrap() error
type Requirement ¶
type Requirement string
Requirement is whether a capability needs a tool or merely works better with it (adr-22: most dependencies are optional adapters over a native default).
const ( // Optional: the capability runs on its native default without the tool. Optional Requirement = "optional" // Required: the capability cannot run without the tool. Required Requirement = "required" )
type Result ¶
type Result struct {
Tool string `json:"tool"`
// Ran reports that the install step was executed.
Ran bool `json:"ran"`
// Argv is the step as run (argv[0] resolved), when Ran.
Argv []string `json:"argv,omitempty"`
// Installed reports that the step exited zero.
Installed bool `json:"installed"`
// Verified reports that the verify command exited zero afterwards.
Verified bool `json:"verified"`
// Declined reports that nobody said yes (a no, no confirmation, CI).
Declined bool `json:"declined"`
// Why is the reason nothing ran, or what failed.
Why string `json:"why,omitempty"`
// Output is the bounded tail of the step's output on a failure, or the
// verify command's first line on success.
Output string `json:"output,omitempty"`
// OnDecline is the capability's standing after a no or a failure.
OnDecline string `json:"on_decline,omitempty"`
// contains filtered or unexported fields
}
Result reports one Install: what it ran and whether it worked, or why it ran nothing and what the capability continues on (criterion 2).
func Install ¶
func Install(name string, capability Capability, confirm Confirm, guard string) Result
Install explains name as capability uses it, asks confirm, and on a yes runs the registry's step for this platform and then its verify command. It is the package-level spelling of Default(guard).Install.
type Step ¶
Step is one platform's install step: the package manager it uses, by name, and the exact argv run. Argv[0] is a bare program name resolved on PATH at run time; the rest are literal arguments.
type Tool ¶
type Tool struct {
Name string
What string // what the tool is, plainly
Homepage string // where to read what it is
Uses map[Capability]Use
Install map[string]Step // keyed by runtime.GOOS
// Effects is what the install does on the machine and over the network, and
// what it does not.
Effects string
// Verify is the argv that proves the tool runs once installed.
Verify []string
}
Tool is one registry entry.
type Use ¶
type Use struct {
// Capability is the capability's human name.
Capability string
// Requirement is optional or required, for this capability.
Requirement Requirement
// Does is what abcd uses the tool for here.
Does string
// WithoutIt is what works without the tool (for an optional use, the
// native default; for a required one, what fails and the way back).
WithoutIt string
// NativeDefault is what the capability continues on after a no; empty when
// there is none.
NativeDefault string
// OnDecline is the loud line's tail after a no or a failed install:
// "continuing on <native default>" for an optional use, the standing
// refusal for a required one.
OnDecline string
}
Use is what one capability does with a tool, in the words a person reads.