murliv1.0.2
{ } github
§ Guides

What you configure

These are opt-in annotations. They add agent-useful metadata to your commands and flags without changing handler logic. Call them once per command, outside your handlers.

Metadata annotations

Attach a Metadata struct to a command. The fields appear in --schema and describe output so agents can understand the command without running it.

gocobra example
murliCobra.Annotate(queryCmd, murli.Metadata{
	AgentDescription: "Search the document index for semantically similar content.",
	WhenToUse:        "When the user wants to find documents by meaning rather than keyword.",
	Idempotent:       true,
	Returns: &murli.ReturnSchema{
		Type:        "json",
		Description: "Ranked list of search results",
		Shape: map[string]any{"path": "string", "score": "float32"},
	},
	Examples: []murli.Example{
		{Command: "mytool query woodworking", Description: "Find documents about woodworking", ExpectedExitCode: 0},
	},
})
pythonclick example
murli.annotate(query_cmd, murli.Metadata(
    agent_description="Search the document index for semantically similar content.",
    when_to_use="When the user wants to find documents by meaning rather than keyword.",
    idempotent=True,
    returns=murli.ReturnSchema(
        type="json",
        description="Ranked list of search results",
        properties={"path": "string", "score": "float"},
    ),
    examples=[
        murli.Example(command="mytool query woodworking", description="Find documents about woodworking"),
    ],
))

Metadata fields

Go fieldPython fieldTypePurpose
AgentDescriptionagent_descriptionstringDescription optimised for agent consumption
WhenToUsewhen_to_usestringGuidance on when to choose this command over alternatives
IdempotentidempotentboolSurfaced as safety.idempotent in schema
MutatingmutatingboolActivates the non-interactive confirmation guard
DryRunnabledry_runnableboolSurfaced as safety.dry_run_supported
DestructivedestructiveboolSurfaced as safety.destructive
Returnsreturns*ReturnSchemaShape and description of the JSON payload
Argumentsarguments[]ArgumentMetadataPositional argument descriptions
Examplesexamples[]ExampleWorked examples with command string and expected exit code
FlagAnnotationsflag_annotationsmap/dictPer-flag metadata. Key is the flag name.

Flag annotations

Per-flag metadata marks sensitive values, declares valid enumerations, and enables profile support.

go
murliCobra.Annotate(queryCmd, murli.Metadata{
	FlagAnnotations: map[string]murli.FlagAnnotation{
		"top":    {Enum: []string{"5", "10", "20", "50"}},
		"token":  {Sensitive: true},
		"format": {Profileable: true},
	},
})
python
murli.annotate(query_cmd, murli.Metadata(
    flag_annotations={
        "top":    murli.FlagAnnotation(enum=["5", "10", "20", "50"]),
        "token":  murli.FlagAnnotation(sensitive=True),
        "format": murli.FlagAnnotation(profileable=True),
    },
))

FlagAnnotation fields

Go fieldPython fieldTypeEffect
SensitivesensitiveboolValue redacted in schema output and logs
ProfileableprofileableboolFlag can be saved and recalled via named profiles
PersistentpersistentboolFlag applies to all subcommands
Enumenum[]string / list[str]Valid values. Surfaced in schema and error envelopes.
MutuallyExclusiveWithmutually_exclusive_with[]string / list[str]Flag names that cannot be set simultaneously
PatternpatternstringRegex the value must match (informational)
EnvenvstringEnvironment variable that sets this flag when present

Profiles

Profiles let users save named sets of flag values and recall them with --profile <name>. The profile subcommand is auto-mounted. Mark any flag as profileable to include it in profile operations.

shell
# Save current flags as a named profile
$ mytool profile set dev --top 10 --format table

# Use the profile in a subsequent call
$ mytool query woodworking --profile dev
# equivalent to: mytool query woodworking --top 10 --format table

# List available profiles
$ mytool profile list

Profile data is stored in ~/.config/<toolname>/profiles.json. See the Go reference for the full ProfileStore API.

shell
# Save flags as a named profile
$ mytool profile set dev --top 10 --format table

# Use the profile in a subsequent call
$ mytool query woodworking --profile dev

# Set a default profile
$ mytool profile set-default dev

# List available profiles
$ mytool profile list

Profile subcommands: list, set, delete, set-default, show. Profiles are stored in platformdirs.user_config_dir(tool_name) / "profiles.json". See the Python reference for details.

Conventions linter

murli.CheckConventions checks command and flag names against the conventional vocabulary and writes advisory warnings. Go only; requires -tags murlidev.

goconventions_test.go
func TestConventions(t *testing.T) {
	issues := murli.CheckConventions(
		[]string{"get", "list", "delete", "fetch"}, // "fetch" will warn
		[]string{"json", "force", "format"},         // "format" will warn
		os.Stderr,
	)
	if issues > 0 {
		t.Errorf("found %d convention issues", issues)
	}
}