Go · urfave/cli v2
A complete integration walkthrough applying murli to the murli-work reference CLI — a sprint task tracker built with urfave/cli v2. The source is in the murli-demo repository on the go/urfavecliv2 branch.
✘
murli-work task create "My task" --agent --force✔
murli-work task create --agent --force "My task"
Step 1 — Update imports
Add the murli core package and the urfave/cli v2 adapter to your imports in main.go:
import ( "github.com/murli-cli/murli-go" murliCli "github.com/murli-cli/murli-go/cli/v2" )
Step 2 — Swap the executor
Replace urfave/cli's standard app.Run(os.Args) call with Murli's adapter entry point.
-if err := app.Run(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. The init command is a representative example:
{
Name: "init",
Aliases: []string{"i"},
Usage: "Initialize/Reset the database and config",
Action: func(c *cli.Context) error {
+ w := murliCli.NewWriter(c)
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. With urfave/cli v2, commands are referenced by index into the Commands and Subcommands slices:
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
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
{
"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 (note flag ordering)
Flags must come before the positional title argument:
{
"result": { "id": 6, "title": "Verify Urfave V2" },
"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 Urfave V2", "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"
}