Script-like system automation wrapped in the security and type safety of the Go programming language
Go
122
68 commits
updated Jun 29, 2025
gexePackage with script-like API for system operation and automation!
The goal of project gexe is to make it simple to write code for system operation and task automation using a script-like API that offers the security and the type safety of the Go programming language (see /examples).
gexe?gexe.Run("echo $HOME"))fmt.Sprintf formatting in all string parameters (i.e. gexe.Run("echo %s", "Hello"))gexe.Pipe("cat /etc/hosts", "wc -l")gexe.RunConcur('wget https://example.com/files'; "date")go rungexego get github.com/vladimirvivien/gexe
The following executes command echo "Hello World!" and prints the result:
fmt.Println(gexe.Run(`echo "Hello World!"`))
Alternatively, you can create your own gexe session for more control and error hanlding:
g := gexe.New()
proc := g.RunProc(`echo "Hello World"`)
if proc.Err() != nil {
fmt.Println(proc.Err())
os.Exit(proc.ExitCode())
}
fmt.Println(proc.Result())
gexe methods now support Go's fmt.Sprintf formatting alongside variable expansion:
// Using Go formatting with variable expansion
gexe.SetVar("name", "Alice")
gexe.Run("echo Hello %s, your home is ${HOME}", "World")
// File operations with formatting
gexe.FileWrite("/tmp/log_%s.txt", time.Now().Format("2006-01-02"))
// Variable setting with formatting
gexe.SetVar("message", "User %s logged in at %s", username, timestamp)
// Error creation with formatting and variable expansion
err := gexe.Error("Failed to process %s in ${HOME}", filename)
The formatting is applied intelligently - if no format verbs are detected in the string, the arguments are ignored, maintaining backward compatibility.
Find more examples here!
$gexe with gexeThis example shows how gexe can be used to build Go project binaries for multiple
platforms and OSes. Note the followings:
func main() {
for _, arch := range []string{"amd64"} {
for _, opsys := range []string{"darwin", "linux"} {
gexe.SetVar("arch", arch).SetVar("os", opsys)
gexe.SetVar("binpath", fmt.Sprintf("build/%s/%s/mybinary", arch, opsys))
result := gexe.Envs("CGO_ENABLED=0 GOOS=$os GOARCH=$arch").Run("go build -o $binpath .")
if result != "" {
fmt.Printf("Build for %s/%s failed: %s\n", arch, opsys, result)
os.Exit(1)
}
fmt.Printf("Build %s/%s: %s OK\n", arch, opsys, gexe.Eval("$binpath"))
}
}
}
This example shows how gexe can be used to launch a long-running process and stream
its output. The code invokes the ping command, streams its output, displays the result,
and then kills the process after 5 seconds.
func main() {
execTime := time.Second * 5
fmt.Println("ping golang.org...")
p := gexe.StartProc("ping golang.org")
if p.Err() != nil {
fmt.Println("ping failed:", p.Err())
os.Exit(1)
}
go func() {
if _, err := io.Copy(os.Stdout, p.StdOut()); err != nil {
fmt.Println(err)
os.Exit(1)
}
}()
<-time.After(execTime)
p.Kill()
fmt.Printf("Pinged golang.org for %s\n", execTime)
}
This example uses the git command to print logs and commit info by using /bin/sh to start a shell for command piping:
func main() {
cmd := `/bin/sh -c "git log --reverse --abbrev-commit --pretty=oneline | cut -d ' ' -f1"`
for _, p := range strings.Split(gexe.Run(cmd), "\n") {
gexe.SetVar("patch", p)
cmd := `/bin/sh -c "git show --abbrev-commit -s --pretty=format:'%h %s (%an) %n' ${patch}"`
fmt.Println(gexe.Run(cmd))
}
}
Originally this project was named echo. However, another Go project by that name has gotten really popular.
So this project was renamed gexe (pronounced Jesse).
MIT
Overall
Maintained
Code review
Go module
Latest release
Releases this year
175 followers · starred Jun 2021
471 followers · starred May 2021
326 followers · starred Dec 2021
59 followers · starred Jan 2025
Script-like system automation wrapped in the security and type safety of the Go programming language
Go
122
68 commits
updated Jun 29, 2025
gexePackage with script-like API for system operation and automation!
The goal of project gexe is to make it simple to write code for system operation and task automation using a script-like API that offers the security and the type safety of the Go programming language (see /examples).
gexe?gexe.Run("echo $HOME"))fmt.Sprintf formatting in all string parameters (i.e. gexe.Run("echo %s", "Hello"))gexe.Pipe("cat /etc/hosts", "wc -l")gexe.RunConcur('wget https://example.com/files'; "date")go rungexego get github.com/vladimirvivien/gexe
The following executes command echo "Hello World!" and prints the result:
fmt.Println(gexe.Run(`echo "Hello World!"`))
Alternatively, you can create your own gexe session for more control and error hanlding:
g := gexe.New()
proc := g.RunProc(`echo "Hello World"`)
if proc.Err() != nil {
fmt.Println(proc.Err())
os.Exit(proc.ExitCode())
}
fmt.Println(proc.Result())
gexe methods now support Go's fmt.Sprintf formatting alongside variable expansion:
// Using Go formatting with variable expansion
gexe.SetVar("name", "Alice")
gexe.Run("echo Hello %s, your home is ${HOME}", "World")
// File operations with formatting
gexe.FileWrite("/tmp/log_%s.txt", time.Now().Format("2006-01-02"))
// Variable setting with formatting
gexe.SetVar("message", "User %s logged in at %s", username, timestamp)
// Error creation with formatting and variable expansion
err := gexe.Error("Failed to process %s in ${HOME}", filename)
The formatting is applied intelligently - if no format verbs are detected in the string, the arguments are ignored, maintaining backward compatibility.
Find more examples here!
$gexe with gexeThis example shows how gexe can be used to build Go project binaries for multiple
platforms and OSes. Note the followings:
func main() {
for _, arch := range []string{"amd64"} {
for _, opsys := range []string{"darwin", "linux"} {
gexe.SetVar("arch", arch).SetVar("os", opsys)
gexe.SetVar("binpath", fmt.Sprintf("build/%s/%s/mybinary", arch, opsys))
result := gexe.Envs("CGO_ENABLED=0 GOOS=$os GOARCH=$arch").Run("go build -o $binpath .")
if result != "" {
fmt.Printf("Build for %s/%s failed: %s\n", arch, opsys, result)
os.Exit(1)
}
fmt.Printf("Build %s/%s: %s OK\n", arch, opsys, gexe.Eval("$binpath"))
}
}
}
This example shows how gexe can be used to launch a long-running process and stream
its output. The code invokes the ping command, streams its output, displays the result,
and then kills the process after 5 seconds.
func main() {
execTime := time.Second * 5
fmt.Println("ping golang.org...")
p := gexe.StartProc("ping golang.org")
if p.Err() != nil {
fmt.Println("ping failed:", p.Err())
os.Exit(1)
}
go func() {
if _, err := io.Copy(os.Stdout, p.StdOut()); err != nil {
fmt.Println(err)
os.Exit(1)
}
}()
<-time.After(execTime)
p.Kill()
fmt.Printf("Pinged golang.org for %s\n", execTime)
}
This example uses the git command to print logs and commit info by using /bin/sh to start a shell for command piping:
func main() {
cmd := `/bin/sh -c "git log --reverse --abbrev-commit --pretty=oneline | cut -d ' ' -f1"`
for _, p := range strings.Split(gexe.Run(cmd), "\n") {
gexe.SetVar("patch", p)
cmd := `/bin/sh -c "git show --abbrev-commit -s --pretty=format:'%h %s (%an) %n' ${patch}"`
fmt.Println(gexe.Run(cmd))
}
}
Originally this project was named echo. However, another Go project by that name has gotten really popular.
So this project was renamed gexe (pronounced Jesse).
MIT
Overall
Maintained
Code review
Go module
Latest release
Releases this year
175 followers · starred Jun 2021
471 followers · starred May 2021
326 followers · starred Dec 2021
59 followers · starred Jan 2025