Go · Cobra
A complete integration walkthrough applying murli to the murli-work reference CLI — a sprint task tracker built with spf13/cobra. The source is in the murli-demo repository on the go/cobra branch.
Step 1 — Update imports
Add the murli core package and the Cobra adapter to your imports in main.go:
import ( "github.com/murli-cli/murli-go" murliCobra "github.com/murli-cli/murli-go/cobra" )
Step 2 — Swap the executor
Replace Cobra's standard rootCmd.Execute() call with Murli's adapter entry point. This single change activates all automatic features.
-if err := rootCmd.Execute(); err != nil {
+if err := murliCobra.Execute(rootCmd); err != nil {
os.Exit(2)
}
Step 3 — Refactor handlers
Replace fmt.Println calls and bare error returns in each RunE block with the Writer API. The init command is a representative example of a mutating command:
var initCmd = &cobra.Command{
Use: "init",
Short: "Initialize/Reset the database and config",
RunE: func(cmd *cobra.Command, args []string) error {
+ w := murliCobra.NewWriter(cmd)
if err := shared.ResetDatabase(); err != nil {
- return err
+ w.WriteError(murli.NewUserError(err.Error(), "Could not reset the database."))
+ return nil
}
dir, _ := shared.GetStorageDir()
- fmt.Printf("Initialized/Reset murli-work database with sample data and configuration in %s\n", dir)
+ w.WriteSuccess(
+ fmt.Sprintf("Initialized/Reset murli-work database with sample data and configuration in %s", dir),
+ map[string]any{"status": "ok", "directory": dir},
+ )
return nil
},
}
Step 4 — Attach metadata
Annotate commands with murliCobra.Annotate() outside the execution loop to enable schema introspection. Mutating commands need Mutating: true so the confirmation guard fires automatically.
murliCobra.Annotate(taskCreateCmd, murli.Metadata{
AgentDescription: "Create a new task in the database.",
Mutating: true,
Arguments: []murli.ArgumentMetadata{
{Name: "title", Type: "string", Required: true, Description: "Task title"},
},
})
murliCobra.Annotate(taskListCmd, murli.Metadata{
AgentDescription: "List stored sprint tasks with filters and formats.",
Idempotent: true,
FlagAnnotations: map[string]murli.FlagAnnotation{
"status": {Enum: []string{"todo", "doing", "done"}},
"priority": {Enum: []string{"low", "medium", "high"}},
},
})
Verification outputs
These are real captured outputs from the completed integration.
Human TTY help
murli-work is a sprint and project task tracker
Usage:
murli-work [flags]
murli-work [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
describe Print the full command tree and capabilities as a single JSON document
help Help about any command
init Initialize/Reset the database and config
label Manage global task labels
profile Manage saved flag profiles
report Display progress report
task Manage sprint tasks
Flags:
--agent Force agent-optimized JSON mode
-h, --help help for murli-work
--output string Output format: json|ndjson|text
--profile string Profile name to use for this invocation
--protocol-version string Protocol version (0.2)
--schema Output agent-optimized JSON schema
Auto-generated JSON schema
{
"name": "murli-work",
"summary": "murli-work is a sprint and project task tracker",
"idempotent": false,
"flags": [
{ "name": "help", "type": "bool", "default": false, "description": "help for murli-work" }
],
"subcommands": [
{ "name": "completion", "summary": "Generate the autocompletion script for the specified shell" },
{ "name": "describe", "summary": "Print the full command tree and capabilities as a single JSON document" },
{ "name": "init", "summary": "Initialize/Reset the database and config" },
{ "name": "label", "summary": "Manage global task labels" },
{ "name": "profile", "summary": "Manage saved flag profiles" },
{ "name": "report", "summary": "Display progress report" },
{ "name": "task", "summary": "Manage sprint tasks" }
],
"safety": { "read_only": true, "idempotent": false }
}
Mutating command without confirmation
Running a mutating command in agent mode without --force triggers the confirmation guard:
{
"code": 1,
"error": "confirmation_required",
"message": "This command mutates state and requires explicit confirmation.",
"suggestion": "Pass --force or --yes to proceed without a TTY.",
"recoverable": true,
"schema_version": "1.0"
}
Bypassing the guard with --force
{
"result": { "directory": "/Users/allank/Library/Application Support/murli-work", "status": "ok" },
"schema_version": "1.0",
"status": "ok"
}
Creating a task
{
"result": { "id": 6, "title": "Verify Cobra" },
"schema_version": "1.0",
"status": "ok"
}
Listing tasks
{
"result": [
{ "id": 1, "title": "Setup workspace layout", "status": "done", "priority": "high", "labels": ["setup", "dev"] },
{ "id": 2, "title": "Implement Go Cobra reference", "status": "done", "priority": "high", "labels": ["go"] },
{ "id": 3, "title": "Implement Go urfave/cli v2 reference", "status": "doing", "priority": "medium", "labels": ["go"] },
{ "id": 4, "title": "Implement Go urfave/cli v3 reference", "status": "todo", "priority": "medium", "labels": ["go"] },
{ "id": 5, "title": "Implement Rust clap reference", "status": "todo", "priority": "high", "labels": ["rust"] },
{ "id": 6, "title": "Verify Cobra", "status": "todo", "priority": "high", "labels": [] }
],
"schema_version": "1.0",
"status": "ok"
}
Sprint report
{
"result": {
"completed_tasks": 2,
"percent_complete": 33.33,
"priority_breakdown": { "high": 4, "low": 0, "medium": 2 },
"status_breakdown": { "doing": 1, "done": 2, "todo": 3 },
"total_tasks": 6
},
"schema_version": "1.0",
"status": "ok"
}