§ 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"
}