A Go framework for building composable Unix-style command-line tools.
Gloo lets you build commands that work like traditional Unix tools - they read from stdin, write to stdout, and can be piped together. Commands are type-safe, composable, and easy to test.
go get github.com/gloo-foo/frameworkCommands are used just like Unix tools:
import (
"github.com/gloo-foo/framework"
"github.com/yupsh/grep"
)
func main() {
// Simple usage
gloo.MustRun(grep.Grep("error", "logfile.txt"))
// With flags
gloo.MustRun(grep.Grep("ERROR", "log.txt", grep.IgnoreCase))
// From stdin
gloo.MustRun(grep.Grep("pattern"))
}Commands can be piped together:
// cat file.txt | grep "error" | sort
pipeline := gloo.Pipe(
cat.Cat("file.txt"),
grep.Grep("error"),
sort.Sort(),
)
gloo.MustRun(pipeline)See framework-examples for complete examples of building your own commands.
package mycommand
import gloo "github.com/gloo-foo/framework"
type command struct {
inputs gloo.Inputs[gloo.File, Flags]
}
func MyCommand(params ...any) gloo.Command {
inputs := gloo.Initialize[gloo.File, Flags](params...)
return command{inputs: inputs}
}
func (c command) Executor() gloo.CommandExecutor {
// Implementation details...
}Commands can work with structured data:
type LogEntry struct {
Level string
Message string
}
// Commands can process strongly-typed data
inputs := gloo.Initialize[LogEntry, Flags](params...)See API_REFERENCE.md for complete API documentation.
Command- Interface for all commandsCommandExecutor- Function that executes a commandInputs[T, O]- Parsed parameters with positionals and flagsFile- Type for file path parameters
gloo.Run(cmd)- Execute a commandgloo.MustRun(cmd)- Execute a command, panic on errorgloo.Pipe(cmd1, cmd2, ...)- Chain commands togethergloo.Initialize[T, O](params...)- Parse command parameters
See framework-examples for complete working examples:
- Custom struct parameters with flags
- Strongly-typed positional arguments
- Building pipeable commands
Commands are easy to test:
func TestMyCommand(t *testing.T) {
input := strings.NewReader("test input")
output := &bytes.Buffer{}
cmd := MyCommand("args")
err := cmd.Executor()(context.Background(), input, output, os.Stderr)
// Assert on output.String()
}See LICENSE file.