Go ● stable v1.0.2
Three adapters cover the major Go CLI frameworks: spf13/cobra, urfave/cli v2, and urfave/cli v3. Each adapter exposes the same conceptual operations with framework-idiomatic signatures.
cobra adapter
Import path: github.com/murli-cli/murli-go/cobra
| Function | Signature | Purpose |
|---|---|---|
| Execute | Execute(root *cobra.Command) error | Drop-in replacement for root.Execute(). Injects flags, mounts subcommands, wraps all RunE handlers. |
| Enable | Enable(root *cobra.Command) | Injects without replacing Execute. Use when you need to call root.Execute() yourself. |
| NewWriter | NewWriter(cmd *cobra.Command) *murli.Writer | Creates a Writer configured from the command’s injected flags (--agent, --force, --dry-run). |
| Annotate | Annotate(cmd *cobra.Command, meta murli.Metadata) | Serialises Metadata into cmd.Annotations["agentcobra"] for schema output. |
| EmitSchema | EmitSchema(cmd *cobra.Command) error | Writes the command schema as JSON to stdout. |
| BuildDescribeTree | BuildDescribeTree(cmd *cobra.Command) murli.DescribeCommandSchema | Builds the recursive schema tree for a command and its subcommands. |
urfave/cli v2 adapter
Import path: github.com/murli-cli/murli-go/cli/v2
| Function | Signature | Purpose |
|---|---|---|
| Run | Run(app *cli.App, args []string) error | Drop-in replacement for app.Run(args). |
| NewWriter | NewWriter(ctx *cli.Context) *murli.Writer | Creates a Writer from the action context. |
| Annotate | Annotate(cmd *cli.Command, meta murli.Metadata) | Attaches metadata to a command. Uses a pointer-keyed map internally (urfave/cli v2 has no native metadata field). |
| AnnotateApp | AnnotateApp(app *cli.App, meta murli.Metadata) | Attaches metadata to the root app. |
| EmitSchema | EmitSchema(cmd *cli.Command, w io.Writer) error | Writes the command schema as JSON to the provided writer. |
| BuildV2DescribeTree | BuildV2DescribeTree(cmd *cli.Command) murli.DescribeCommandSchema | Builds the schema tree for a command. |
urfave/cli v3 adapter
Import path: github.com/murli-cli/murli-go/cli/v3
| Function | Signature | Purpose |
|---|---|---|
| Run | Run(app *cli.Command, args []string) error | Drop-in replacement for app.Run(ctx, args). |
| Wrap | Wrap(app *cli.Command) | In-place setup: injects flags, wraps Actions, mounts subcommands. Use when you need to call app.Run yourself. |
| NewWriter | NewWriter(cmd *cli.Command) *murli.Writer | Creates a Writer from the command context. |
| Annotate | Annotate(cmd *cli.Command, meta murli.Metadata) | Stores metadata in cmd.Metadata["murli"]. |
| EmitSchema | EmitSchema(cmd *cli.Command, w io.Writer) error | Writes the command schema as JSON. |
| BuildV3DescribeTree | BuildV3DescribeTree(cmd *cli.Command) murli.DescribeCommandSchema | Builds the schema tree for a command. |
Writer
Package: github.com/murli-cli/murli-go
The Writer is the primary output surface. Obtain one via the adapter’s NewWriter in every handler. Do not construct one directly in normal use.
Constructor
func NewWriter(stdout, stderr io.Writer, agentMode bool, opts ...WriterOption) *Writer
Use the adapter’s NewWriter in handlers. The bare constructor is for testing or building custom adapters.
WriterOption functions
| Function | Effect |
|---|---|
| WithOutputFormat(f OutputFormat) | Override the output format (OutputFormatJSON, OutputFormatNDJSON, OutputFormatText) |
| WithProtocolVersion(v string) | Set the protocol version string in envelope output. Default: "0.2". |
| WithForce(force bool) | Set the forced state directly (used by adapters reading the --force flag) |
| WithDryRun(dryRun bool) | Set the dry-run state directly |
Output methods
| Method | Writes to | When |
|---|---|---|
| WriteSuccess(humanText string, jsonPayload any) | stdout | Command completed successfully |
| WritePlan(humanText string, plan any) | stdout | Dry-run: show what would happen |
| WriteError(err *AgentError) | stderr | Command failed; calls os.Exit with the error code |
| WriteEvent(v any) | stdout | One NDJSON line per call for streaming output |
| WriteProgress(evt ProgressEvent) | stdout (agent) / stderr (TTY) | Typed progress update |
| Log(msg string) | stderr | Diagnostic line with deduplication |
| Progress(msg string) | stderr | Unstructured progress line |
| Flush() | — | Flush buffered log/progress output |
State methods
| Method | Returns |
|---|---|
| IsTTY() bool | True if stdout is a terminal |
| IsForced() bool | True if --force or --yes was passed |
| IsDryRun() bool | True if --dry-run was passed |
| Format() OutputFormat | Current output format |
| ProtocolVersion() string | Protocol version string included in envelopes |
OutputFormat constants
| Constant | Value | Meaning |
|---|---|---|
| OutputFormatDefault | "" | Auto-detect: JSON if not TTY, text if TTY |
| OutputFormatJSON | "json" | Single JSON object |
| OutputFormatNDJSON | "ndjson" | Newline-delimited JSON |
| OutputFormatText | "text" | Plain text, no JSON envelopes |
ProgressEvent struct
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"`
}
Logger
Package: github.com/murli-cli/murli-go
The Logger writes diagnostic output to stderr with consecutive line deduplication. w.Log() and w.Progress() use an internal logger. Use NewLogger directly only when building outside a standard handler context.
| Function / Method | Signature | Purpose |
|---|---|---|
| NewLogger | NewLogger(writer io.Writer, isTTY bool) *Logger | Creates a logger writing to writer |
| Log | (l *Logger) Log(line string) | Writes a log line to stderr. Suppresses if identical to the previous line. |
| LogProgress | (l *Logger) LogProgress(line string) | Writes a progress line. In TTY mode, overwrites the previous progress line. |
| Flush | (l *Logger) Flush() | Flushes any buffered output |
AgentError
Package: github.com/murli-cli/murli-go
Constructors
| Function | Exit code | Use when |
|---|---|---|
| NewUserError(message, suggestion string) *AgentError | 1 | Invalid input, bad flags, user mistake |
| NewToolError(message string) *AgentError | 2 | Internal failure, dependency error |
For other exit codes, construct an AgentError directly:
w.WriteError(&murli.AgentError{
Code: murli.ExitNotFound,
ErrorType: "not_found",
Message: "index file does not exist",
Suggestion: "Run `mytool index build` to create it.",
Recoverable: true,
})
AgentError fields
| Field | Type | JSON key | Purpose |
|---|---|---|---|
| Code | int | code | Exit code. Use the Exit* constants. |
| ErrorType | string | error | Machine-readable error category (e.g. "user_error", "not_found") |
| Message | string | message | Human-readable description of what failed |
| Suggestion | string | suggestion | What the caller should do next |
| Recoverable | bool | recoverable | True if retrying the same call might succeed |
| ValidValues | []string | valid_values | Acceptable values when an enum constraint was violated |
| RetryAfterMs | int | retry_after_ms | Milliseconds to wait before retrying (rate-limit errors) |
| DocURL | string | doc_url | Link to relevant documentation |
| Field | string | field | Flag or argument name that caused the error |
| SchemaVersion | string | schema_version | Set automatically by WriteError |
| ToolVersion | string | tool_version | Set automatically by WriteError |
Metadata
Package: github.com/murli-cli/murli-go
Pass to the adapter’s Annotate function. All fields are optional.
type Metadata struct {
AgentDescription string
WhenToUse string
Idempotent bool
Mutating bool
Arguments []ArgumentMetadata
Returns *ReturnSchema
Examples []Example
FlagAnnotations map[string]FlagAnnotation
DryRunnable bool
Destructive bool
}
ArgumentMetadata
type ArgumentMetadata struct {
Name string `json:"name"`
Type string `json:"type"`
Required bool `json:"required"`
Description string `json:"description"`
}
ReturnSchema
type ReturnSchema struct {
Type string `json:"type"`
Description string `json:"description"`
Shape map[string]any `json:"shape,omitempty"`
OutputSchema json.RawMessage `json:"output_schema,omitempty"`
}
Example
type Example struct {
Command string `json:"command"`
Description string `json:"description,omitempty"`
ExpectedExitCode int `json:"expected_exit_code,omitempty"`
}
Profiles
Package: github.com/murli-cli/murli-go
The profile subcommand handles profile management automatically. Use the ProfileStore API directly only when you need programmatic access to profiles outside a command handler.
| Function / Method | Signature | Purpose |
|---|---|---|
| ProfilePath | ProfilePath(toolName string) string | Returns the path to ~/.config/<toolName>/profiles.json |
| LoadProfileStore | LoadProfileStore(toolName string) (*ProfileStore, error) | Loads profiles from disk. Creates an empty store if the file does not exist. |
| Save | (*ProfileStore) Save(toolName string) error | Writes the store to disk |
| Get | (*ProfileStore) Get(name string) (Profile, bool) | Returns the named profile and whether it exists |
| Set | (*ProfileStore) Set(name string, p Profile) | Creates or replaces a named profile |
| Delete | (*ProfileStore) Delete(name string) | Removes a profile |
| SetDefault | (*ProfileStore) SetDefault(name string) error | Sets the default profile (used when no --profile flag is given) |
| Names | (*ProfileStore) Names() []string | Returns all profile names in sorted order |
Profile struct
type Profile struct {
Flags map[string]string `json:"flags"`
}
type ProfileStore struct {
Default string `json:"default,omitempty"`
Profiles map[string]Profile `json:"profiles"`
}
Utilities
Package: github.com/murli-cli/murli-go
CheckConventions
Requires -tags murlidev. The function is a no-op stub in release builds.
func CheckConventions(commandNames, flagNames []string, w io.Writer) int
Checks command and flag names against the conventional vocabulary. Writes advisory warnings to w for non-standard names. Returns the count of issues found. Does not modify any state. Use in tests or CI to enforce naming standards.
Non-standard verbs flagged (with suggested replacement): fetch→get, info→get, retrieve→get, show-all→list, remove→delete, rm→delete, add→create, edit→update, modify→update.
Non-standard flags flagged: skip-confirmations→force, silent→quiet, preview→dry-run, format→output.
FormatAgentsMD
func FormatAgentsMD(out DescribeOutput) string
Generates an AGENTS.md stub from a DescribeOutput. Produces a Markdown document that lists each command, its description, flags, and examples. Intended as a starting point for agent-facing documentation.
Version constants
| Identifier | Type | Value / Purpose |
|---|---|---|
| SchemaVersion | const string | "1.0" — included in all envelope output as schema_version |
| ToolVersion | var string | Set at build time via -ldflags "-X github.com/murli-cli/murli-go.ToolVersion=1.0.2". Included in envelopes as tool_version. |
| ExitFunc | var func(int) | Defaults to os.Exit. Override in tests to prevent process exit: murli.ExitFunc = func(code int) { ... } |