> ## Documentation Index
> Fetch the complete documentation index at: https://aspect.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Running Go tools

> Run Go tools like cobra-cli with Bazel using the tools.go unused imports pattern, replacing go install with hermetic bazel run invocations.

Some Go packages ship runnable programs. We’d like to be able to invoke these programs with Bazel, either for side-effects (with `bazel run`) or as steps that produce build outputs (with `bazel build`).

For this exercise, we’ll use the Cobra tool, [https://cobra.dev/](https://cobra.dev/). It provides a CLI tool at [https://github.com/spf13/cobra-cli/blob/main/README.md](https://github.com/spf13/cobra-cli/blob/main/README.md) which we can run with Bazel, instead of using `go install` to make a local installation.

## Fetching the tool

Create a file at `tools/tools.go` which contains only unused imports. This pattern allows the standard Go tooling to fetch the tool, even though none of our application code depends on it.

```go theme={null}
//go:build tools
// +build tools

package go_tools

import (
    _ "github.com/spf13/cobra-cli"
)
```

Now just run `./tools/go mod tidy` again, to add the cobra-cli tool to our Bazel repository.

<Note>
  It’s also possible to have tools in a separate `go.mod` file so they don’t have their dependencies constraint-solved along with application code in a monorepo. This is currently experimental, using a new `--experimental_isolated_extension_usages` flag in Bazel. See [https://github.com/bazel-contrib/rules\_go/blob/master/docs/go/core/bzlmod.md#depending-on-tools](https://github.com/bazel-contrib/rules_go/blob/master/docs/go/core/bzlmod.md#depending-on-tools).
</Note>

To see that it’s working, we could use a `query` command to see what targets exist in the new external repository, like the following:

```bash theme={null}
% bazel query --output=label_kind @com_github_spf13_cobra_cli//:al
l
go_binary rule @com_github_spf13_cobra_cli//:cobra-cli
go_library rule @com_github_spf13_cobra_cli//:cobra-cli_lib
_package_info rule @com_github_spf13_cobra_cli//:gazelle_generated_package_info
```

## Run the tool

First let’s verify that the `cobra-cli` executes correctly. We’ll run the `--help` flag. Note the extra `--` argument, which is a delimiter used to note where the flags to `bazel` end, and the flags to the program begin.

```bash theme={null}
% bazel run @com_github_spf13_cobra_cli//:cobra-cli -- --help
Cobra is a CLI library for Go that empowers applications.
...
```

`bazel run` has some bugs with handling the working directory. Since we want the cobra tool to create files in our source folder, the working directory matters. Since we already have a pattern in the `tools/` folder, we’ll follow that. See [run tools installed by bazel](/blog/run-tools-installed-by-bazel) for more on this pattern.

1. Create a `tools/cobra` symlink to the `tools/_run_under_cwd.sh` script by running
   `ln -s ./_run_under_cwd.sh tools/cobra`
2. In `tools/_run_under_cwd.sh` add the `cobra` case:

```bash theme={null}
  cobra)
    target="@com_github_spf13_cobra_cli//:cobra-cli"
    ;;
```

Now you can run the `init` command provided by Cobra to create a new application. Since this is a monorepo, we’ll make a subfolder for this project first.

```bash theme={null}
% mkdir dice
% cd dice
% ../tools/cobra init
% cd ..
```

This will create some files that provide our CLI application: `main.go` and `cmd/root.go`. These files contain some new dependencies we haven’t already installed, so we need to update `go.mod` again:

```bash theme={null}
% ./tools/go mod tidy
```

And then update `BUILD` files:

```bash theme={null}
% aspect gazelle
```

Now we can run our newly-generated program:

```bash theme={null}
% bazel run dice
A longer description...
```

## Using the tool as a build step

This section is coming soon.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.