MCPcopy Index your code
hub / github.com/desertbit/grumble

github.com/desertbit/grumble @v1.3.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.3.1 ↗ · + Follow
292 symbols 1,305 edges 31 files 235 documented · 80% 2 cross-repo links
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Grumble - A powerful modern CLI and SHELL

GoDoc Go Report Card

There are a handful of powerful go CLI libraries available (spf13/cobra, urfave/cli). However sometimes an integrated shell interface is a great and useful extension for the actual application. This library offers a simple API to create powerful CLI applications and automatically starts an integrated interactive shell, if the application is started without any command arguments.

Hint: We do not guarantee 100% backwards compatiblity between minor versions (1.x). However, the API is mostly stable and should not change much.

asciicast

Introduction

Create a grumble APP.

var app = grumble.New(&grumble.Config{
    Name:        "app",
    Description: "short app description",

    Flags: func(f *grumble.Flags) {
        f.String("d", "directory", "DEFAULT", "set an alternative directory path")
        f.Bool("v", "verbose", false, "enable verbose mode")
    },
})

Register a top-level command. Note: Sub commands are also supported...

app.AddCommand(&grumble.Command{
    Name:      "daemon",
    Help:      "run the daemon",
    Aliases:   []string{"run"},

    Flags: func(f *grumble.Flags) {
        f.Duration("t", "timeout", time.Second, "timeout duration")
    },

    Args: func(a *grumble.Args) {
        a.String("service", "which service to start", grumble.Default("server"))
    },

    Run: func(c *grumble.Context) error {
        // Parent Flags.
        c.App.Println("directory:", c.Flags.String("directory"))
        c.App.Println("verbose:", c.Flags.Bool("verbose"))
        // Flags.
        c.App.Println("timeout:", c.Flags.Duration("timeout"))
        // Args.
        c.App.Println("service:", c.Args.String("service"))
        return nil
    },
})

Run the application.

err := app.Run()

Or use the builtin grumble.Main function to handle errors automatically.

func main() {
    grumble.Main(app)
}

Shell Multiline Input

Builtin support for multiple lines.

>>> This is \
... a multi line \
... command

Flags

You can pass flags in two ways: cmd --flag value or cmd --flag=value
There are some exceptions/additions to this:
- bool: cmd --boolflag offer a third option that does not require a value - string: cmd --stringflag="some test string" leads to value some test string, as double quotes are stripped from the value

Separate flags and args specifically

If you need to pass a flag-like value as positional argument, you can do so by using a double dash:
>>> command --flag1=something -- --myPositionalArg

Remote shell access with readline

By calling RunWithReadline() rather than Run() you can pass instance of readline.Instance. One of interesting usages is having a possibility of remote access to your shell:

handleFunc := func(rl *readline.Instance) {

    var app = grumble.New(&grumble.Config{
        // override default interrupt handler to avoid remote shutdown
        InterruptHandler: func(a *grumble.App, count int) {
            // do nothing
        },

        // your usual grumble configuration
    })  

    // add commands

    app.RunWithReadline(rl)

}

cfg := &readline.Config{}
readline.ListenRemote("tcp", ":5555", cfg, handleFunc)

In the client code just use readline built in DialRemote function:

if err := readline.DialRemote("tcp", ":5555"); err != nil {
    fmt.Errorf("An error occurred: %s \n", err.Error())
}

Samples

Check out the sample directory for some detailed examples.

Projects using Grumble

  • grml - A simple build automation tool written in Go: https://github.com/desertbit/grml
  • orbit - A RPC-like networking backend written in Go: https://github.com/desertbit/orbit

Known issues

  • Windows unicode not fully supported (issue)

Additional Useful Packages

  • https://github.com/AlecAivazis/survey
  • https://github.com/tj/go-spin

Credits

This project is based on ideas from the great ishell library.

License

MIT

Extension points exported contracts — how you extend this code

ArgOption (FuncType)
ArgOption can be supplied to modify an argument.
argopt.go

Core symbols most depended-on inside this repo

Run
called by 216
app.go
Println
called by 75
app.go
parse
called by 64
args.go
String
called by 58
args.go
Bool
called by 44
args.go
StringList
called by 35
args.go
Int
called by 33
args.go
Duration
called by 33
args.go

Shape

Function 138
Method 137
Struct 12
FuncType 3
TypeAlias 2

Languages

Go100%

Modules by API surface

flags_test.go54 symbols
flags.go42 symbols
app.go27 symbols
args_test.go26 symbols
args.go22 symbols
flagmap.go20 symbols
argmap.go18 symbols
commands.go12 symbols
strconv_test.go10 symbols
strconv.go10 symbols
functions.go8 symbols
command_test.go8 symbols

Used by 2 indexed graphs manifest dependencies, hub-wide

For agents

$ claude mcp add grumble \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact