murliv1.0.2
{ } github
§ Walkthroughs

Go · urfave/cli v3

A complete integration walkthrough applying murli to the murli-work reference CLI — a sprint task tracker built with urfave/cli v3. The source is in the murli-demo repository on the go/urfavecliv3 branch.

BEFORE YOU START This walkthrough assumes you have read the three concept guides: What you get free, What you configure, and What you build.
v3 ACTION SIGNATURE CHANGE urfave/cli v3 changes the Action function signature. The first parameter is now context.Context and the second is *cli.Command (replacing *cli.Context from v2). Pass the *cli.Command argument to murliCli.NewWriter().

Step 1 — Update imports

Add the murli core package and the urfave/cli v3 adapter to your imports in main.go:

go
import (
	"github.com/murli-cli/murli-go"
	murliCli "github.com/murli-cli/murli-go/cli/v3"
)

Step 2 — Swap the executor

Replace urfave/cli v3's standard app.Run(ctx, os.Args) call with Murli's adapter entry point.

diff
-if err := app.Run(ctx, os.Args); err != nil {
+if err := murliCli.Run(app, os.Args); err != nil {
 	os.Exit(2)
 }

Step 3 — Refactor handlers

Replace fmt.Println calls and bare error returns in each Action block with the Writer API. Note the v3 action signature: context.Context first, *cli.Command second.

diff
 {
 	Name:    "init",
 	Aliases: []string{"i"},
 	Usage:   "Initialize/Reset the database and config",
-	Action: func(c *cli.Context) error {
+	Action: func(ctx context.Context, cmd *cli.Command) error {
+		w := murliCli.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 murliCli.Annotate() outside the execution loop:

go
murliCli.Annotate(app.Commands[1].Subcommands[0], murli.Metadata{
	AgentDescription: "Create a new task in the database.",
	Mutating:         true,
	Arguments: []murli.ArgumentMetadata{
		{Name: "title", Type: "string", Required: true, Description: "Task title"},
	},
})

Verification outputs

These are real captured outputs from the completed integration.

Human TTY help

shell./bin/murli-work-go-urfavev3 --help
NAME:
   murli-work - A sprint and project task tracker

USAGE:
   murli-work [global options] command [command options]

COMMANDS:
   init, i   Initialize/Reset the database and config
   task      Manage sprint tasks
   label     Manage global task labels
   report    Display progress report
   describe  Print the full command tree and capabilities as a single JSON document
   profile   Manage saved flag profiles
   help, h   Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --profile value  Profile name to use for this invocation
   --agent          Force agent-optimized JSON mode (default: false)
   --help, -h       show help

Mutating command without confirmation

shell./bin/murli-work-go-urfavev3 init --agent
{
  "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

shell./bin/murli-work-go-urfavev3 init --agent --force
{
  "result": { "directory": "/Users/allank/Library/Application Support/murli-work", "status": "ok" },
  "schema_version": "1.0",
  "status": "ok"
}

Creating a task

shell./bin/murli-work-go-urfavev3 task create --agent --force --priority high "Verify Urfave V3"
{
  "result": { "id": 6, "title": "Verify Urfave V3" },
  "schema_version": "1.0",
  "status": "ok"
}

Listing tasks

shell./bin/murli-work-go-urfavev3 task list --agent
{
  "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 Urfave V3", "status": "todo", "priority": "high", "labels": [] }
  ],
  "schema_version": "1.0",
  "status": "ok"
}

Sprint report

shell./bin/murli-work-go-urfavev3 report --agent
{
  "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"
}