Documentation
¶
Index ¶
Constants ¶
const ( ExitOK = 0 // success ExitGeneric = 1 // unclassified failure (reserved for anything we don't map) ExitAuth = 2 // 401 — user must re-authenticate ExitForbidden = 3 // 403 — authenticated but lacks scope / ownership ExitNotFound = 4 // 404 ExitInvalid = 5 // 400 validation ExitConflict = 6 // 409 ExitRateLimit = 7 // 429 ExitAPI = 8 // 5xx, network, timeout, malformed response )
Exit codes — keep this table in lock-step with the one in PLAN-CLI.md §7 and the reference CLI projects (basecamp-cli, fizzy-cli, hey-cli).
Agents branch on these in wrapper scripts; changing a value breaks their scripts silently. Only add new codes, never renumber.
Variables ¶
This section is empty.
Functions ¶
func ExitCodeFor ¶
ExitCodeFor maps any error returned by a command to the table above.
Resolution order:
- nil error → ExitOK
- *api.Error (HTTP status known) → matched by status
- network / URL errors, DNS failures → ExitAPI
- unknown / typed CLI errors → ExitGeneric
Callers just do `os.Exit(output.ExitCodeFor(err))`.
Types ¶
type Breadcrumb ¶
type Breadcrumb struct {
// Action is a short intent tag — agents route on this.
// Conventions: "view", "edit", "retry", "revert", "share", "delete",
// "list", "open", "configure", "docs".
Action string `json:"action"`
// Cmd is the exact shell-ready command string, including the `pura `
// prefix. Must be runnable verbatim. Placeholders in angle brackets
// (e.g. `<slug>`) are acceptable when a real value isn't known yet.
Cmd string `json:"cmd"`
// Description is a one-sentence rationale. Optional but recommended.
Description string `json:"description,omitempty"`
}
Breadcrumb describes one suggested follow-up command.
type Envelope ¶
type Envelope struct {
OK bool `json:"ok"`
Data any `json:"data,omitempty"`
Summary string `json:"summary,omitempty"`
Breadcrumbs []Breadcrumb `json:"breadcrumbs,omitempty"`
Error any `json:"error,omitempty"`
Meta any `json:"meta,omitempty"`
}
Envelope is the full response wrapper. Fields use `omitempty` so absent ones disappear from the JSON — keeps small responses small.
func NewError ¶
NewError creates a failure envelope. Breadcrumbs on errors are especially valuable for agents — e.g. "auth_required" naturally pairs with a `pura auth login` breadcrumb.
func NewOK ¶
NewOK creates a success envelope with optional summary / breadcrumbs / meta.
Simple case: NewOK(data) With summary: NewOK(data, WithSummary("Published %s", slug)) Full: NewOK(data,
WithSummary("…"),
WithBreadcrumb("view", "pura open abc", "Open in browser"),
WithBreadcrumb("edit", "pura chat abc \"…\"", "AI-edit"))
type ErrorDetail ¶
type ErrorDetail struct {
Code string `json:"code"`
Message string `json:"message"`
Hint string `json:"hint,omitempty"`
}
ErrorDetail is the structured error body.
type Option ¶
type Option func(*Envelope)
Option mutates an Envelope during construction. Pass via NewOK / NewError or via the variadic params on Writer.OK / Writer.Error.
Why functional options: call sites stay terse when there's nothing extra to say, but can layer on summary + breadcrumbs without a builder chain.
func WithBreadcrumb ¶
WithBreadcrumb appends a single suggested next command.
func WithBreadcrumbs ¶
func WithBreadcrumbs(crumbs ...Breadcrumb) Option
WithBreadcrumbs appends several suggestions at once.
func WithSummary ¶
WithSummary attaches a one-line human-readable summary.
type Writer ¶
type Writer struct {
Out io.Writer
Err io.Writer
Format Format
IsTTY bool
JQFilter string // jq expression to filter JSON output
}
Writer handles output formatting.
func NewWriter ¶
NewWriter creates a Writer with auto-detected TTY.
PURA_FORCE_STYLED=1 forces IsTTY=true so tests can assert the styled human-readable output without wiring a pseudo-terminal. Opposite escape: normal prod detection is via term.IsTerminal on stdout's fd.
func (*Writer) Error ¶
Error outputs an error message. Like OK, accepts options — mostly used to attach a "retry" breadcrumb such as `pura auth login`.
func (*Writer) OK ¶
OK outputs successful data. Accepts optional envelope Options (summary, breadcrumbs, meta) — agents consume those to decide the next step.
In --quiet mode we emit just the `data` payload (no envelope) because quiet is meant for raw piping; the breadcrumbs are still available to callers who use --json.