bonzai/README.md

15 KiB

Go Bonzai™ Command Compositor

logo

Meticulously manicured monoliths, on any device.

Have a look at rwxrob/z for now to get a sense of how it's coming along and how to use until the 1.0 release.

Or, you can get started right away by cloning/forking the sample foo template repo

Go Version GoDoc License Go Report
Card

Installation

🎉 Bonzai shamelessly requires Go 1.18+ 💋

  1. Install Go 1.18 and the tooling your require for it
  2. go install github.com/rwxrob/bonzai@latest
  3. import Z "github.com/rwxrob/bonzai"
  4. Consider using the template to get started

😎 Yes, we use the wonderful new generics all over. 👍

Welcome to Bonzai

Yes, "banzai" is something people yell going into battle. But isn't that what making command line utilities in Go (instead of your favorite shell script) actually is?

And yes, "bonsai" trees are well-manicured, meticulously crafted, miniature trees that rival their larger cousins, just like Bonzai command and data node trees. They are unlike anything you've probably encountered so far, no getopt dashes (we kind of hate them), no ugly commander interface to learn, no 12637 lines of shell tab completion bloat to source before your command will complete, just well manicured nested-tab-complete-with-magical-aliases-enabled commands organized into rooted node trees for your command-line enjoyment. Your right-pinky will be particularly grateful.

But wait, there's more! What about all those other tasks you need to do to make a command line application honorable in anyone's eyes? Tools are needed.

Contributors/PRs Welcome

... especially for "Completers", included popular commands, and Runtime Detection.

Speaking of sharing, why not send a PR for your addition to the ever growing collection of comp subpackage Completers for everything from days of the week, to tab-driven inline math calculations, to a list of all the listening ports running on your current system.

CONTRIBUTING

"It's spelled bonsai/banzai."

We know. The domains were taken. Plus, this makes it more unique and easier to find once you know the strange spelling we chose to use. Sorry if that triggers your OCD.

If you must know, the primary motivator was the similarity to a well-manicured tree (since it is for creating trees of composite commands).

The misunderstood word "banzai" is 'a traditional Japanese idiom meaning "ten thousand years" of long life,' a cheer used in celebrations like "Hurrah" or "Viva".' So combining the notion of a happy, well-manicured, beautiful tree and "ten thousand years of long life" works out just fine for us.

And, yes, Buckaroo Banzai was always a favorite. We like to think he would use Bonzai today to make amazing things and last for a long time to defeat evil aliens and save the world.

It turns out that the "call to war" associated with Bonzai is not entirely without merit as well. Bonzai is excellent for unorthodox, rapid applications development (instead of writing scripts) and makes short work of creating offensive and defensive tool kits all wrapping into one nice Go multicall binary, popular for building single-binary Linux container distros like BusyBox and Alpine, as well as root kits, and other security tools

"Why not just use Cobra?"

Just because something is popular (or first) doesn't mean it was well designed. In fact, often inferior designs are rushed to market just to gain adoption. Cobra seems to suffer from this. Discerning developers and engineers have been not-so-quietly complaining about Cobra's horrible design for years. It's time for something new. Read on if you want the specific reasons.

  • Cobra tab completion is wasteful and error-prone.

    Cobra often requires sourcing thousands of lines of shell code every time you run a new shell that needs to use a Cobra command with shell tab completion (kubectl requires 12637). It is not uncommon for operations people to be sourcing 100s of thousands of lines of shell code just to enable basic completion that could have been enabled easily with complete -C instead. Bonzai manages all completion in Go instead of shell and therefore allows the modular addition of any number of Completers including the standard file completion as well as calculators, dates, and anything anyone can conceive of completing. Completion is not dependent on any underlying operating system. Any Bonzai command can provide its own completion algorithm or use one of the many already provided. Cobra can never do this.

  • Corba is not designed to be a command compositor at all.

    This is really unfortunate because the designers missed a golden opportunity. Bonzai branches can be imported and composed into other branches and monoliths with just a few lines of Go. Registries of Bonzai commands can be easily inferred from dependencies on the bonzai package and creators are free to compose their monoliths or multicall binaries from a rich eco-system of Bonzai branches and commands. Bonzai allows creation of Go multicall binary monoliths (like BusyBox) to be made easily, and from a diverse, modular, importable, composable sources. Such is simply not possible with Cobra and never will be.

  • Cobra suffers from broken boomer "getopt" design.

    The world if finally realizing how bad dashed arguments and options have always been for good human-computer interactions from the command line, perhaps because more people are using chat interfaces as their command line. People simply cannot remember all sorts of ungodly combinations of dashes and equals signs hoping things will just work. Bonzai takes a no-dashes approach with aliases promoting cleaner, understandable command lines with context and promotion of domain specific languages (created with PEGN, scan.X, or others) that easily translate directly to chat and other command-line interfaces that most humans can use without even looking up the documentation, which, by the way, is embedded in any Bonzai command tree.

  • Cobra provides bad, brittle, command documentation.

    Cobra documentation is virtually unreadable in source form. And Cobra provides no means of markup or use of color and doesn't even promote the same look and feel of manual page documentation. In contrast, Bonzai has its own subset of Markdown, BonzaiMark, respects the well established readability of manual pages, and allows for the creation of elegant documentation that can be viewed from the command line or easily from a local browser on the same computer running the command. Bonzai command documentation is as easy to read in source form as the documentation itself.

  • Cobra suffers from crushing technical debt.

    The problems listed (and more) are never going to come out of Cobra. Because it is filled with bad design decisions and was rushed to market without serious consideration for its API, it is now doomed to never lose its warts (kinda like JavaScript). There is no possible way it can ever upgrade to address the very reasonable modern expectations for good command line user experiences. No wonder you never see people using Cobra for their replace-my-shell-scripts utilities. Cobra is simply horrible for this. Thankfully, Bonzai is a fresh, extensible, sustainable, human-friendly command compositor to take us into the future of command line interfaces.

What People Are Saying

"It's like a modular, multicall BusyBox builder for Go with built in completion and embedded documentation support."

"The utility here is that Bonzai lets you maintain your own personal 'toolbox' with built in auto-complete that you can assemble from various Go modules. Individual commands are isolated and unaware of each other and possibly maintained by other people." (tadasv123)

Examples

Design Considerations

  • Promote high-level package library API calls over Cmd bloat.

    Code belongs in package libraries, not Cmds.

    While Bonzai allows for rapid applications development by putting everything initially in Cmd Call first-class function, Cmds are most designed for documentation and completion, not heavy Call implementations (even though many will organically start there from people's personal Bonzai trees).

    Eventually, most Call implementations should be moved into their own package libraries, perhaps even in the same Go module. Cmds should never communicate with each other directly (other than calling one another on occasion). While the idea of adding a Channel attribute was intriguing, it quickly became clear that doing so would promote undesirable tight coupling --- even with channels --- between specific commands.

  • Cmds should be very light.

    Most Cmds should assign their first-class Call function to one that lightly wraps a similar function signature in a callable, high-level library that works entirely independently from the bonzai package. It's best to promote strong support for sustainable API packages.

  • Only bash completion and shell.Cmd planned.

    If it doesn't work with complete -C or equivalent then just run the Bonzai command tree monolith as a temporary shell (shell.Cmd) and use its cross-platform support for tab completion.

    Zsh, Powershell, and Fish have no equivalent to complete -C (which allows any executable to provide its own completion). This forces inferior dependencies on overly verbose external "completer" scripts written in only those languages for those specific shells. This dependency completely negates any possibility of providing modular completers and composable commands that carry their own completion logic. This one objective fact alone should give everyone pause before opting to use one of these inferior shells for their command line interactions.

    Bonzai commands leverage this best-of-breed completion functionality of bash to provide an unlimited number of completion methods and combinations. The equivalent implementations, perhaps as an export collected from all composed commands providing their shell equivalent of completion scripts, would be preposterously large just for its basic completion tree). Instead, Bonzai uses Go itself to manage that completion --- drawing on a rich collection of completers included in the standard Bonzai module --- and provides documented shortcut aliases when completion is not available (h|help, for example).

  • Bonzai commands may default to shell.Cmd or help.Cmd

    These provide help information and optional interactive assistance including tab completion in runtime environments that do not have complete -C foo foo enabled.

    shell.Cmd is still under development and likely will be for a while

  • One major use case is to replace shell scripts in "dot files" collections.

    By creating a cmd subdirectory of a dot files repo a multi-call Bonzai command named cmd can be easily maintained and added to just as quickly as any shell script. This has the added bonus of allowing others to quickly add one of your little commands with just a simple import (for example, import github.com/rwxrob/dot/cmd and then cmd.Isosec) from their own cmd monoliths. This also enables the fastest possible prototyping of code that would otherwise require significant, problematic mocks. Developers can work out the details of a thing just as fast as with shell scripting --- but with the power of all the Go standard library --- and then factor out their favorites as they grow into their own Bonzai command repos. This approach keeps "Go on the brain" (instead of having to port a bunch of bash later) and promotes the massive benefits of rapid applications development the fullest extent.

  • Use either foo.Cmd or cmd.Foo convention.

    People may decide to put all their Bonzai commands into a single cmd package or to put each command into its own package. Both are perfectly acceptable and allow the developer making the import to alias the packages as needed using Go's excellent package import design.

  • Use capital "Z" import name.

    People can easily change the default "Z" import name to whatever else if they don't like it (or worse, if has conflicts). But, we actually want naming conflicts even though this seems counter-intuitive. Developers should be putting most of their code into their own pkg libraries and calling into them from their wrapping Bonzai trees and branches that import Z. If someone is importing Z into their package library they are likely doing something they shouldn't. Bonzai should only be imported into the composable branch or standalone command (main). This is a reminder as well to Bonzai developers not to stuff things into the Z package that would never be used outside a Bonzai command, tree or main.go standalone.

  • Promote lower "z" personal Bonzai trees.

    Just as "dotfiles" has become a convention, use of the simple "z" GitHub repo should be promoted as a common, "ez" way to find people's personal monoliths. Obviously, people can use what they want. This is also consistent with the capital "Z" import name of the bonzai package.

Style Guidelines

  • Everything through go fmt or equiv, no exceptions
  • In Vim set textwidth=72 (not 80 to line numbers fit)
  • Use /* */ for package documentation comment, // elsewhere
  • Smallest possible names for given scope while still clear
  • Favor additional packages (possibly in internal) over long names
  • Package globals that will be used a lot can be single capital
  • Must be good reason to use more than 4 character pkg name
  • Avoid unnecessary comments
  • Use "deciduous tree" emoji 🌳 to mark Bonzai branches and commands

Acknowledgements

The https://twitch.tv/rwxrob community has been constantly involved with the development of this project, making suggestions about everything from my use of init, to the name "bonzai". While all their contributions are too numerous to name specifically, they more than deserve a huge thank you here.

Copyright 2022 Robert S. Muhlestein (mailto:rob@rwx.gg)
SPDX-License-Identifier: Apache-2.0

"Bonzai" and "bonzai" are legal trademarks of Robert S. Muhlestein but can be used freely to refer to the Bonzai™ project https://github.com/rwxrob/bonzai without limitation. To avoid potential developer confusion, intentionally using these trademarks to refer to other projects --- free or proprietary --- is prohibited.

TODO

Here is a list of major things that are still needed before a v1.0 release:

  • Complete default help.Cmd
  • Complete bonzai helper command
    • Initialize new branch including optional GitHub repo creation
    • Vet a branch repo for orphan commands, etc.
    • Cache/search list of package depending on bonzai as registry
  • Complete final art
    • Large logo for landing page
    • Small logo for lists
    • Animated emote suitable for Twitch
  • Create a Bonzai™ merch outlet