Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyFlagAnnotation(fs *FlagSchema, ann FlagAnnotation)
- func CheckConventions(commandNames, flagNames []string, w io.Writer) int
- func FormatAgentsMD(out DescribeOutput) string
- func ProfilePath(toolName string) string
- func WriteDoctorTTY(w io.Writer, report DoctorReport)
- type AgentError
- type ArgumentMetadata
- type Capabilities
- type CheckResult
- type CommandSchema
- type DescribeCommandSchema
- type DescribeOutput
- type DoctorReport
- type Example
- type FlagAnnotation
- type FlagSchema
- type Logger
- type Metadata
- type OutputFormat
- type Profile
- type ProfileStore
- type ProfilesInfo
- type ProgressEvent
- type ReturnSchema
- type SafetyBlock
- type SubcommandSchema
- type Writer
- func (w *Writer) Flush()
- func (w *Writer) Format() OutputFormat
- func (w *Writer) IsDryRun() bool
- func (w *Writer) IsForced() bool
- func (w *Writer) IsTTY() bool
- func (w *Writer) Log(msg string)
- func (w *Writer) Progress(msg string)
- func (w *Writer) ProtocolVersion() string
- func (w *Writer) WriteError(err *AgentError)
- func (w *Writer) WriteEvent(v any)
- func (w *Writer) WritePlan(humanText string, plan any)
- func (w *Writer) WriteProgress(evt ProgressEvent)
- func (w *Writer) WriteSuccess(humanText string, jsonPayload any)
- type WriterOption
Constants ¶
const ( ExitOK = 0 // Success ExitUserError = 1 // Bad input or arguments ExitToolError = 2 // Environment/internal failure ExitPartial = 3 // Some operations succeeded, some failed )
Exit codes 0–3: table-stakes (present since v0.1).
const ( ExitTimeout = 4 // Operation timed out; retry may succeed ExitNotFound = 5 // Requested resource does not exist ExitPermission = 6 // Caller lacks permission; not retryable without auth change ExitConflict = 7 // State conflict (e.g. resource already exists) ExitRateLimited = 8 // Rate limit hit; retry after RetryAfterMs ExitCancelled = 9 // Operation cancelled by signal or context )
Exit codes 4–9: extended taxonomy (v0.2).
const SchemaVersion = "1.0"
SchemaVersion is the murli envelope schema version. Frozen at "1.0"; incrementing requires a documented migration.
Variables ¶
var ExitFunc = os.Exit
ExitFunc is swapped out in tests to capture exit codes without terminating.
var ToolVersion = ""
ToolVersion is the version of the CLI tool using murli. Set this in your main() using a version variable injected at build time:
murli.ToolVersion = version // where `version` is set via -ldflags "-X main.version=1.2.3"
Or inject directly at build time:
-ldflags "-X github.com/allank/murli.ToolVersion=1.2.3"
var ValidOutputFormats = []string{"json", "ndjson", "text"}
ValidOutputFormats lists the accepted --output values.
var ValidProtocolVersions = []string{"0.2"}
ValidProtocolVersions lists the accepted --protocol-version values.
Functions ¶
func ApplyFlagAnnotation ¶ added in v0.3.0
func ApplyFlagAnnotation(fs *FlagSchema, ann FlagAnnotation)
ApplyFlagAnnotation merges a FlagAnnotation onto a FlagSchema in place. Boolean fields (Sensitive, Persistent, Profileable) are one-way: they can be set to true but not cleared to false. This is intentional — ApplyFlagAnnotation is applied to a zero-value FlagSchema, so false is the default and only needs to be set once. Slice fields (MutuallyExclusiveWith, Enum) are deep-copied to prevent aliasing.
func CheckConventions ¶ added in v0.3.0
CheckConventions checks command names and flag names against the murli conventional vocabulary. Advisory warnings are written to w. Returns the number of warnings emitted. Never panics; suppressed output is safe (pass io.Discard).
func FormatAgentsMD ¶ added in v1.0.0
func FormatAgentsMD(out DescribeOutput) string
FormatAgentsMD generates an AGENTS.md stub from a DescribeOutput. The stub gives agents a quick orientation: tool name and purpose, how to introspect further, and a per-command summary with --schema references. Intended to be pasted as a starting point into the repository's AGENTS.md.
func ProfilePath ¶ added in v0.5.0
ProfilePath returns the path to the profiles file for the named tool. Resolves to ~/.{toolName}/profiles.json.
func WriteDoctorTTY ¶ added in v1.0.0
func WriteDoctorTTY(w io.Writer, report DoctorReport)
WriteDoctorTTY writes a human-readable doctor report to w. Used by adapter doctor commands when running in a terminal (TTY) context.
Types ¶
type AgentError ¶
type AgentError struct {
Code int `json:"code"`
ErrorType string `json:"error"`
Message string `json:"message"`
Suggestion string `json:"suggestion,omitempty"`
Recoverable bool `json:"recoverable"`
ValidValues []string `json:"valid_values,omitempty"`
RetryAfterMs int `json:"retry_after_ms,omitempty"`
DocURL string `json:"doc_url,omitempty"`
Field string `json:"field,omitempty"`
SchemaVersion string `json:"schema_version,omitempty"`
ToolVersion string `json:"tool_version,omitempty"`
}
AgentError is the structured error envelope written to stderr. Fields are serialised as JSON in agent mode; SchemaVersion and ToolVersion are auto-populated by WriteError — do not set them manually.
func NewToolError ¶
func NewToolError(message string) *AgentError
NewToolError returns a non-recoverable AgentError for internal/environment failures. Use when the fault is in the environment (network, filesystem, dependency) not the caller.
func NewUserError ¶
func NewUserError(message, suggestion string) *AgentError
NewUserError returns a recoverable AgentError for bad input. Use when the caller supplied invalid arguments or configuration.
func (*AgentError) Error ¶
func (e *AgentError) Error() string
Error implements the standard Go error interface.
type ArgumentMetadata ¶
type ArgumentMetadata struct {
Name string `json:"name"`
Type string `json:"type"`
Required bool `json:"required"`
Description string `json:"description"`
}
ArgumentMetadata documents a single positional argument.
type Capabilities ¶ added in v0.3.0
type Capabilities struct {
Streaming bool `json:"streaming"`
DryRun bool `json:"dry_run"`
OutputFormats []string `json:"output_formats,omitempty"`
SchemaVersion string `json:"schema_version"`
ToolVersion string `json:"tool_version,omitempty"`
ProtocolVersion string `json:"protocol_version,omitempty"`
Profiles bool `json:"profiles"`
}
Capabilities describes what the binary supports, auto-populated by murli in describe output.
func DefaultCapabilities ¶ added in v0.3.0
func DefaultCapabilities() Capabilities
DefaultCapabilities returns the Capabilities block reflecting the current murli build.
type CheckResult ¶ added in v1.0.0
type CheckResult struct {
Name string `json:"name"`
Status string `json:"status"` // "pass", "warn", or "fail"
Message string `json:"message,omitempty"`
}
CheckResult is the outcome of one doctor self-check.
type CommandSchema ¶
type CommandSchema struct {
Name string `json:"name"`
Summary string `json:"summary"`
WhenToUse string `json:"when_to_use,omitempty"`
AgentDescription string `json:"agent_description,omitempty"`
Idempotent bool `json:"idempotent"`
Mutating bool `json:"mutating,omitempty"`
Arguments []ArgumentMetadata `json:"arguments,omitempty"`
Flags []FlagSchema `json:"flags,omitempty"`
Returns *ReturnSchema `json:"returns,omitempty"`
Examples []Example `json:"examples,omitempty"`
Subcommands []SubcommandSchema `json:"subcommands,omitempty"`
Safety SafetyBlock `json:"safety"`
}
CommandSchema is the JSON payload emitted by --schema.
type DescribeCommandSchema ¶ added in v0.3.0
type DescribeCommandSchema struct {
Name string `json:"name"`
Summary string `json:"summary"`
WhenToUse string `json:"when_to_use,omitempty"`
AgentDescription string `json:"agent_description,omitempty"`
Idempotent bool `json:"idempotent"`
Mutating bool `json:"mutating,omitempty"`
Arguments []ArgumentMetadata `json:"arguments,omitempty"`
Flags []FlagSchema `json:"flags,omitempty"`
Returns *ReturnSchema `json:"returns,omitempty"`
Examples []Example `json:"examples,omitempty"`
Subcommands []DescribeCommandSchema `json:"subcommands,omitempty"`
Safety SafetyBlock `json:"safety"`
}
DescribeCommandSchema is the full recursive schema used in describe output. Unlike CommandSchema (for --schema), Subcommands here carry full recursive data.
type DescribeOutput ¶ added in v0.3.0
type DescribeOutput struct {
Name string `json:"name"`
Summary string `json:"summary"`
SchemaVersion string `json:"schema_version"`
ToolVersion string `json:"tool_version,omitempty"`
Capabilities Capabilities `json:"capabilities"`
Profiles *ProfilesInfo `json:"profiles,omitempty"`
Commands []DescribeCommandSchema `json:"commands,omitempty"`
}
DescribeOutput is emitted by the auto-mounted `describe` subcommand. Commands lists the root-level commands of the tool. Each DescribeCommandSchema within Commands has its own Subcommands field for nested commands, creating a recursive tree. The top-level field is named "commands" (not "subcommands") to distinguish root commands from nested subcommands.
type DoctorReport ¶ added in v1.0.0
type DoctorReport struct {
Checks []CheckResult `json:"checks"`
Passed int `json:"passed"`
Warnings int `json:"warnings"`
Failed int `json:"failed"`
}
DoctorReport is the aggregate result of all doctor checks. Embedded in the WriteSuccess result payload by the doctor command.
func RunDoctor ¶ added in v1.0.0
func RunDoctor(out DescribeOutput) DoctorReport
RunDoctor runs all self-checks against a DescribeOutput and returns a DoctorReport. Adapters call this after building the DescribeOutput in the doctor command handler.
type Example ¶ added in v0.3.0
type Example struct {
Command string `json:"command"`
Description string `json:"description,omitempty"`
ExpectedExitCode int `json:"expected_exit_code,omitempty"` // 0 = success; omitted
}
Example is a concrete usage example for a command, used in Metadata.Examples.
type FlagAnnotation ¶ added in v0.3.0
type FlagAnnotation struct {
Env string `json:"env,omitempty"`
Sensitive bool `json:"sensitive,omitempty"`
Persistent bool `json:"persistent,omitempty"`
MutuallyExclusiveWith []string `json:"mutually_exclusive_with,omitempty"`
Enum []string `json:"enum,omitempty"`
Pattern string `json:"pattern,omitempty"`
Profileable bool `json:"profileable,omitempty"`
}
FlagAnnotation provides extended metadata for a single flag, keyed by flag name in Metadata.FlagAnnotations. None of these fields can be auto-detected from the CLI framework; all must be supplied by the engineer via Annotate().
type FlagSchema ¶
type FlagSchema struct {
Name string `json:"name"`
Type string `json:"type"`
Default any `json:"default"`
Description string `json:"description"`
Env string `json:"env,omitempty"`
Sensitive bool `json:"sensitive,omitempty"`
Persistent bool `json:"persistent,omitempty"`
MutuallyExclusiveWith []string `json:"mutually_exclusive_with,omitempty"`
Enum []string `json:"enum,omitempty"`
Pattern string `json:"pattern,omitempty"`
Profileable bool `json:"profileable,omitempty"`
}
FlagSchema represents a single CLI flag in the JSON schema. Basic fields (Name, Type, Default, Description) are auto-populated by the adapter. Extended fields (Env, Sensitive, Persistent, MutuallyExclusiveWith, Enum, Pattern, Profileable) are populated from Metadata.FlagAnnotations[flagName] by the adapter schema emitters (see cobra/schema.go, cli/v2/schema.go, cli/v3/schema.go).
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger writes diagnostic messages to stderr. TTY mode: human-readable plain text. Agent mode: one NDJSON object per line {ts, level, msg}; consecutive duplicates are collapsed into a single entry with a "repeated" count.
func (*Logger) Log ¶
Log writes a message. In TTY mode: plain text. In agent mode: NDJSON with deduplication. ANSI escape codes are stripped in agent mode.
func (*Logger) LogProgress ¶
LogProgress writes a progress message. TTY: overwrites current line with carriage return. Agent: NDJSON with level "progress" and deduplication. ANSI codes stripped.
type Metadata ¶
type Metadata struct {
// AgentDescription is a detailed description of the command's scope.
AgentDescription string `json:"agent_description"`
// WhenToUse specifies when an agent should select this command.
WhenToUse string `json:"when_to_use"`
// Idempotent specifies if the command is safe to re-run on failure.
Idempotent bool `json:"idempotent"`
// Mutating marks commands that write, delete, or otherwise change state.
// When true and the output is not a TTY, the adapter rejects the command with a
// confirmation_required error to prevent accidental mutation in non-interactive mode.
// Pass --force or --yes to bypass the guard.
Mutating bool `json:"mutating,omitempty"`
// Arguments defines explicit positional argument documentation.
Arguments []ArgumentMetadata `json:"arguments,omitempty"`
// Returns defines the expected output format on success.
Returns *ReturnSchema `json:"returns,omitempty"`
// Examples contains concrete shell invocations for agent in-context learning.
// Changed from []string to []Example in v0.3.
Examples []Example `json:"examples,omitempty"`
// FlagAnnotations provides extended metadata keyed by flag name, for fields that
// cannot be auto-detected from the CLI framework (env var binding, enum values, etc.).
FlagAnnotations map[string]FlagAnnotation `json:"flag_annotations,omitempty"`
// DryRunnable marks commands that support --dry-run preview mode.
// When true, murli auto-registers a --dry-run flag on this command.
// Engineers must check IsDryRun() in their action and call WritePlan() if true.
DryRunnable bool `json:"dry_runnable,omitempty"`
// Destructive marks commands whose effects cannot be undone
// (e.g. delete, overwrite, truncate).
Destructive bool `json:"destructive,omitempty"`
}
Metadata provides LLM-specific parameters to supplement standard CLI command definitions.
type OutputFormat ¶ added in v0.3.0
type OutputFormat string
OutputFormat controls the serialization format of WriteSuccess.
const ( // OutputFormatDefault is unset — format is determined by TTY detection. OutputFormatDefault OutputFormat = "" // OutputFormatJSON writes a pretty-printed JSON envelope to stdout. OutputFormatJSON OutputFormat = "json" // OutputFormatNDJSON writes a minified single-line JSON envelope to stdout. OutputFormatNDJSON OutputFormat = "ndjson" // OutputFormatText writes human-readable plain text to stdout (same as TTY mode). OutputFormatText OutputFormat = "text" )
type ProfileStore ¶ added in v0.5.0
type ProfileStore struct {
Default string `json:"default,omitempty"`
Profiles map[string]Profile `json:"profiles"`
}
ProfileStore is the on-disk representation of all saved profiles for a tool.
func LoadProfileStore ¶ added in v0.5.0
func LoadProfileStore(toolName string) (*ProfileStore, error)
LoadProfileStore reads the profile store from disk. Returns an empty store (not an error) if the file does not exist.
func (*ProfileStore) Delete ¶ added in v0.5.0
func (s *ProfileStore) Delete(name string)
Delete removes a profile. Clears Default if the deleted profile was the default. No-op if the profile does not exist.
func (*ProfileStore) Get ¶ added in v0.5.0
func (s *ProfileStore) Get(name string) (Profile, bool)
Get returns the named profile. Returns a zero Profile and false if not found.
func (*ProfileStore) Names ¶ added in v0.5.0
func (s *ProfileStore) Names() []string
Names returns all profile names in sorted order.
func (*ProfileStore) Save ¶ added in v0.5.0
func (s *ProfileStore) Save(toolName string) error
Save writes the store back to disk, creating the directory if needed.
func (*ProfileStore) Set ¶ added in v0.5.0
func (s *ProfileStore) Set(name string, p Profile)
Set adds or replaces a named profile.
func (*ProfileStore) SetDefault ¶ added in v0.5.0
func (s *ProfileStore) SetDefault(name string) error
SetDefault marks a profile as the default. Returns an error if the named profile does not exist.
type ProfilesInfo ¶ added in v0.5.0
type ProfilesInfo struct {
Available []string `json:"available,omitempty"`
Default string `json:"default,omitempty"`
ProfileableFlags []string `json:"profileable_flags"` // always present; empty array when no flags are profileable
}
ProfilesInfo describes the profile system state for agent consumption. Included in DescribeOutput when the tool supports profiles.
type ProgressEvent ¶
type ProgressEvent struct {
Stage string `json:"stage,omitempty"`
Current int `json:"current,omitempty"`
Total int `json:"total,omitempty"`
Percent float64 `json:"percent,omitempty"`
EtaMs int64 `json:"eta_ms,omitempty"`
Message string `json:"message,omitempty"`
}
ProgressEvent carries typed progress state for long-running operations. All fields are optional — populate what is meaningful for the operation.
type ReturnSchema ¶
type ReturnSchema struct {
Type string `json:"type"`
Description string `json:"description"`
Shape map[string]any `json:"shape,omitempty"`
// OutputSchema carries a raw JSON Schema (draft-2020-12) blob when the engineer
// provides it via Annotate(). murli serialises it as-is into --schema and describe output.
OutputSchema json.RawMessage `json:"output_schema,omitempty"`
}
ReturnSchema describes the shape of successful command output.
type SafetyBlock ¶ added in v0.4.0
type SafetyBlock struct {
ReadOnly bool `json:"read_only"`
Idempotent bool `json:"idempotent"`
Destructive bool `json:"destructive,omitempty"`
DryRunnable bool `json:"dry_run_supported,omitempty"`
}
SafetyBlock summarises the safety properties of a command for agent consumption. Assembled from Metadata fields by the adapter at schema/describe emit time.
type SubcommandSchema ¶
SubcommandSchema represents a registered subcommand in --schema output (brief listing).
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer handles dynamic output routing based on terminal presence, agent flags, explicit output format, and negotiated protocol version.
func NewWriter ¶
func NewWriter(stdout, stderr io.Writer, agentMode bool, opts ...WriterOption) *Writer
NewWriter returns a configured output writer. Set agentMode true to force JSON output regardless of TTY state. Pass WriterOption values to set OutputFormat or ProtocolVersion.
func (*Writer) Format ¶ added in v0.3.0
func (w *Writer) Format() OutputFormat
Format returns the explicit output format (may be OutputFormatDefault).
func (*Writer) IsDryRun ¶ added in v0.4.0
IsDryRun returns true if --dry-run was passed on the command line. Engineers should check this at the start of their action and call WritePlan() if true.
func (*Writer) IsForced ¶ added in v0.4.0
IsForced returns true if --force or --yes was passed on the command line. Engineers may use this to suppress their own confirmation prompts in TTY mode. The non-interactive mutation guard bypass is automatic when IsForced is true.
func (*Writer) Log ¶
Log writes a message to stderr, deduplicating consecutive duplicates in agent mode.
func (*Writer) Progress ¶
Progress writes a progress update; overwrites current line in TTY, collapses in agent mode.
func (*Writer) ProtocolVersion ¶ added in v0.3.0
ProtocolVersion returns the negotiated protocol version (empty string = "0.2").
func (*Writer) WriteError ¶
func (w *Writer) WriteError(err *AgentError)
WriteError writes the structured error to stderr and exits with the error's exit code. In TTY mode: human-readable. In agent mode: JSON envelope with schema_version and tool_version.
func (*Writer) WriteEvent ¶
WriteEvent writes a single minified JSON object to stdout on one line. It is safe to call WriteEvent concurrently from multiple goroutines. However, WriteSuccess and WriteError are not mutex-protected — call them only after all WriteEvent goroutines have completed (e.g., after a sync.WaitGroup.Wait()). In TTY mode WriteEvent is a no-op (events are machine-only).
func (*Writer) WritePlan ¶ added in v0.4.0
WritePlan writes a dry-run plan to stdout. Format depends on outputFormat and isTTY:
- TTY or OutputFormatText: humanText plain line
- OutputFormatNDJSON: single minified JSON line with "status": "plan"
- OutputFormatJSON or default agent mode: pretty-printed JSON with "status": "plan"
func (*Writer) WriteProgress ¶
func (w *Writer) WriteProgress(evt ProgressEvent)
WriteProgress emits a structured progress event to stderr. Agent mode: minified JSON on one line (consistent with WriteEvent). TTY mode: formatted human-readable line with carriage return to overwrite.
func (*Writer) WriteSuccess ¶
WriteSuccess writes to stdout. Format depends on outputFormat and isTTY:
- TTY or OutputFormatText: humanText plain line
- OutputFormatNDJSON: single minified JSON line
- OutputFormatJSON or default agent mode: pretty-printed JSON envelope
type WriterOption ¶ added in v0.3.0
type WriterOption func(*Writer)
WriterOption is a functional option for NewWriter.
func WithDryRun ¶ added in v0.4.0
func WithDryRun(dryRun bool) WriterOption
WithDryRun sets the dry-run flag. Set to true when --dry-run is present on the command line.
func WithForce ¶ added in v0.4.0
func WithForce(force bool) WriterOption
WithForce sets the force flag, activating bypass of the non-interactive mutation guard. Set to true when --force or --yes is present on the command line.
func WithOutputFormat ¶ added in v0.3.0
func WithOutputFormat(f OutputFormat) WriterOption
WithOutputFormat sets the explicit output format, overriding TTY auto-detection.
func WithProtocolVersion ¶ added in v0.3.0
func WithProtocolVersion(v string) WriterOption
WithProtocolVersion sets the protocol version for envelope shaping. Valid values: "0.1", "0.2". Empty string defaults to "0.2" (current).