§ Guides
Quickstart
A minimal working integration for each language and framework. The only change from a standard application is replacing one function call.
gomain.go · cobra
package main
import (
"github.com/murli-cli/murli-go"
murliCobra "github.com/murli-cli/murli-go/cobra"
"github.com/spf13/cobra"
)
var queryCmd = &cobra.Command{
Use: "query <text>",
Short: "Search the index",
RunE: func(cmd *cobra.Command, args []string) error {
w := murliCobra.NewWriter(cmd)
w.Progress("searching...")
results := []map[string]any{
{"path": "/docs/woodworking", "score": 0.95},
}
w.WriteSuccess("Found 1 result", results)
return nil
},
}
func main() {
root := &cobra.Command{Use: "mytool"}
root.AddCommand(queryCmd)
murliCobra.Annotate(queryCmd, murli.Metadata{
AgentDescription: "Search the document index.",
Idempotent: true,
})
_ = murliCobra.Execute(root) // replaces root.Execute()
}
gomain.go · urfave/cli v2
package main
import (
"os"
"github.com/murli-cli/murli-go"
murliCli "github.com/murli-cli/murli-go/cli/v2"
"github.com/urfave/cli/v2"
)
func main() {
queryCmd := &cli.Command{
Name: "query",
Usage: "Search the index",
Action: func(ctx *cli.Context) error {
w := murliCli.NewWriter(ctx)
w.Progress("searching...")
results := []map[string]any{
{"path": "/docs/woodworking", "score": 0.95},
}
w.WriteSuccess("Found 1 result", results)
return nil
},
}
murliCli.Annotate(queryCmd, murli.Metadata{AgentDescription: "Search the document index.", Idempotent: true})
app := &cli.App{Name: "mytool", Commands: []*cli.Command{queryCmd}}
_ = murliCli.Run(app, os.Args) // replaces app.Run(os.Args)
}
gomain.go · urfave/cli v3
package main
import (
"context"
"os"
"github.com/murli-cli/murli-go"
murliCli "github.com/murli-cli/murli-go/cli/v3"
"github.com/urfave/cli/v3"
)
func main() {
queryCmd := &cli.Command{
Name: "query",
Usage: "Search the index",
Action: func(ctx context.Context, cmd *cli.Command) error {
w := murliCli.NewWriter(cmd)
w.Progress("searching...")
results := []map[string]any{
{"path": "/docs/woodworking", "score": 0.95},
}
w.WriteSuccess("Found 1 result", results)
return nil
},
}
murliCli.Annotate(queryCmd, murli.Metadata{AgentDescription: "Search the document index.", Idempotent: true})
app := &cli.Command{Name: "mytool", Commands: []*cli.Command{queryCmd}}
_ = murliCli.Run(app, os.Args) // replaces app.Run(context.Background(), os.Args)
}
rustmain.rs · clap (derive)
use clap::{CommandFactory, Parser};
use murli::clap::GlobalArgs;
use murli::Writer;
use serde_json::json;
#[derive(Parser)]
#[command(name = "mytool", about = "My search tool")]
struct Cli {
#[command(flatten)]
murli: GlobalArgs, // --agent --schema --force --dry-run --output --profile
#[command(subcommand)]
command: Commands,
}
#[derive(clap::Subcommand)]
enum Commands {
Query { text: String },
}
fn main() {
let args = Cli::parse();
murli::clap::handle_builtins(&args.murli, &Cli::command(), None);
let mut writer = Writer::from_args(&args.murli);
match args.command {
Commands::Query { text } => {
writer.log("searching...");
let results = json!([{"path": "/docs/woodworking", "score": 0.95}]);
writer.write_success("Found 1 result", &results);
}
}
}
tomlCargo.toml
[dependencies]
murli = { version = "0.1", features = ["clap"] }
clap = { version = "4", features = ["derive"] }
serde_json = "1"
See the Rust reference for the clap builder API and argh adapter.
pythoncli.py · click
import click
import murli
@click.group()
def cli(): pass
murli.enable(cli) # adds --agent, --schema, --force, --dry-run, --output, --profile
# mounts describe, doctor, profile subcommands
@cli.command()
@click.argument("text")
@murli.pass_writer
def query(writer, text):
writer.log("searching...")
results = [{"path": "/docs/woodworking", "score": 0.95}]
writer.write_success("Found 1 result", results)
if __name__ == "__main__":
cli()
pythoncli.py · typer
import typer
import murli
app = typer.Typer()
murli.enable(app)
@app.command()
def query(ctx: typer.Context, text: str):
writer = murli.get_writer(ctx)
writer.log("searching...")
results = [{"path": "/docs/woodworking", "score": 0.95}]
writer.write_success("Found 1 result", results)
if __name__ == "__main__":
app()
pythoncli.py · argparse
import argparse
import murli
parser = argparse.ArgumentParser()
murli.enable(parser)
parser.add_argument("text")
args, writer = murli.parse(parser)
writer.log("searching...")
results = [{"path": "/docs/woodworking", "score": 0.95}]
writer.write_success("Found 1 result", results)
What this gives you immediately
| Feature | How to invoke |
|---|---|
| Dual-audience output | Run at a TTY for formatted output; pipe to any command for JSON |
--agent | Forces JSON output at a TTY |
--schema | Prints command schema as JSON and exits |
describe | Dumps full command tree: mytool describe |
doctor | Dev-only health check (Go: -tags murlidev) |
profile | Named flag profiles: mytool profile list |
--force / --yes | Non-interactive confirmation bypass |
--dry-run | Dry-run mode (handler checks w.IsDryRun() / writer.is_dry_run()) |