bazel run) or as steps that produce build outputs (with bazel build).
For this exercise, we’ll use the Cobra tool, https://cobra.dev/. It provides a CLI tool at 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 attools/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.
./tools/go mod tidy again, to add the cobra-cli tool to our Bazel repository.
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.query command to see what targets exist in the new external repository, like the following:
Run the tool
First let’s verify that thecobra-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.
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 for more on this pattern.
- Create a
tools/cobrasymlink to thetools/_run_under_cwd.shscript by runningln -s ./_run_under_cwd.sh tools/cobra - In
tools/_run_under_cwd.shadd thecobracase:
init command provided by Cobra to create a new application. Since this is a monorepo, we’ll make a subfolder for this project first.
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:
BUILD files:

