Getting Started
Build your first command in 5 minutes.
Install the framework
shell
go get github.com/gloo-foo/framework
Zero transitive dependencies beyond rill for concurrent streams and afero for testable filesystem access.
Choose a pattern
Every command maps to one of 7 patterns. For your first command, use Map — the simplest. One in, one out.
| I want to… | Pattern |
|---|---|
| Transform each item | Map |
| Filter items | Filter |
| Collect and reorder | Accumulate |
| Reduce to summary | Aggregate |
| Split into many | Expand |
See all 7 patterns →
Implement a command
Build uppercase — converts each line to upper case:
go
func Uppercase(opts ...any) gloo.Command[[]byte, []byte] {
return patterns.Map(func(line []byte) ([]byte, error) {
return bytes.ToUpper(line), nil
})
}
One function, one pattern, zero boilerplate.
Write tests
Test without touching the filesystem:
go
func TestUppercase(t *testing.T) {
source := gloo.SliceSource([][]byte{
[]byte("hello"),
[]byte("world"),
})
results, _ := gloo.Chain(source).
To(Uppercase()).
Collect()
// results.([][]byte) == {[]byte("HELLO"), []byte("WORLD")}
}
No files, no I/O, no mocks. Pure in-memory streams.
Compose into a pipeline
Import command aliases and compose with Run or Chain:
go
// Run: source, sink, then commands
gloo.Run(source, gloo.ByteWriteTo(os.Stdout),
Grep("error", IgnoreCase),
Sort(Reverse),
Uniq(Count),
)
// Chain: fluent builder
gloo.Chain(source).
To(Grep("error", IgnoreCase)).
To(Sort(Reverse)).
To(Uniq(Count)).
Sink(gloo.ByteWriteTo(os.Stdout))
Commands are values. Pipelines are composition.
Next steps
You’ve built a command, tested it without I/O, and composed it into a pipeline. Now explore:
- All 7 patterns → — understand the full pattern system
- 44 commands → — see every reimplemented Unix tool
- Pipeline recipes → — real-world examples