Get Started
What is Grog?
Grog is a lightweight build orchestrator that runs your existing commands in parallel —rebuilding only what’s changed— while caching the results for future runs. It’s designed to be a simple and lightweight alternative to existing build systems like Bazel, Buck, and Pants.
Unlike those build systems, Grog remains agnostic to the actual build execution and focuses solely on incremental runs, parallel execution, and caching. It’s designed to be an intermediate solution that helps teams move towards a coherent monorepo approach by efficiently connecting their existing build tooling using a simple interface.
1. Install Grog
# Using Homebrewbrew tap chrismatix/grogbrew install grog
# Or download the binary
curl -L https://grog.build/latest/grog-darwin-arm64 -o /usr/local/bin/grogchmod +x /usr/local/bin/grog
# Download the binarycurl -L https://grog.build/latest/grog-linux-amd64 -o /usr/local/bin/grogchmod +x /usr/local/bin/grog
2. Initialize The Repository
To start using Grog in your project, you need to initialize it by creating a grog.toml
file at the root of your repository:
touch grog.toml
A minimal grog.toml
file can be empty, with all settings using default values.
Refer to the configuration reference to see all available options.
3. Define BUILD Files
BUILD
files define your build targets.
Each target is a command that runs when its file inputs or dependencies change.
Grog provides a wide array of build file formats:
targets: - name: build_app command: npm run build dependencies: # Dependencies are labels that point to # other targets that need to be built first. - :generate_proto - //path/to/other/package:target_name inputs: - src/**/*.js outputs: - dist/bundle.js
- name: generate_proto command: | # Yaml supports multiline commands protoc --js_out=src/generated proto/*.proto inputs: - proto/*.proto outputs: - dir::src/generated
Save this as BUILD.yaml
in your project directory.
{ "targets": [ { "name": "build_app", "command": "npm run build", "dependencies": [ ":generate_proto", "//path/to/other/package:target_name" ], "inputs": ["src/**/*.js", "package.json"], "outputs": ["dist/bundle.js"] }, { "name": "generate_proto", "command": "protoc --js_out=src/generated proto/*.proto", "inputs": ["proto/*.proto"], "outputs": ["dir::src/generated"] } ]}
Save this as BUILD.json
in your project directory.
# @grog# inputs:# - src/**/*.js# - package.json# outputs:# - dist/bundle.js# dependencies:# - :generate_proto# - //path/to/other/package:target_namebuild_app: npm run build
Add the grog metadata comments to your Makefile
goals to allow running them with Grog.
amends "package://grog.build/releases/v0.2.2/grog@0.2.2#/package.pkl"
targets { new { name = "build_app" command = "npm run build" dependencies { // Dependencies are targets that need to be // built first. They are defined using labels. ":generate_proto" "//path/to/other/package:target_name" } outputs { "dir::dist/" } }
new { name = "generate_proto" command = "protoc --js_out=src/generated proto/*.proto" inputs { "proto/*.proto" } outputs { "dir::src/generated" } }}
Save this as BUILD.pkl
in your project directory.
Things to note from the above examples:
- Targets are referenced using labels.
- Directory outputs are prefixed with
dir::
to indicate they are directories. - Command definition
command
are executed as sh scripts in the target’s directory.
5. Running Builds
To run a build, use the grog build
command followed by the target label:
# Build a specific targetgrog build //path/to/package:target_name
# Build all targets in and below a packagegrog build //path/to/package/...
# Build all targetsgrog build
Grog will re-run a build if any of the following conditions are met:
- A target’s definition has changed.
- A target’s inputs have changed.
- A target’s dependencies have changed.
6. Running Tests
Grog will automatically treat targets that end with test
as test targets.
They will only be executed if you run grog test
and will be ignored for grog build
Target Overview
Now we will look at the most important fields you can define on a target. You can find the complete target configuration reference here.
Inputs
Inputs are files that your build target depends on. When any of these files change, Grog will re-run the target’s command. You can specify inputs using file paths or glob patterns:
"inputs": [ "src/**/*.js", "package.json", "assets/*.{png,jpg}"]
src/**/*.js
- All JavaScript files in src directory and subdirectoriespackage.json
- A specific fileassets/*.{png,jpg}
- All PNG and JPG files in assets directory
Grog tracks inputs by computing a hash of their contents. This allows it to detect changes and only rebuild when necessary.
Dependencies
Dependencies are other targets that must be built before the current target. This creates a directed acyclic graph (DAG) of build steps:
"dependencies": [ "generate_proto", "//lib:build_lib"]
generate_proto
- A dependency on another target in the same package//lib:build_lib
- A dependency on a target in another package
When you specify dependencies:
- Grog ensures they are built before the current target.
- Changes to a dependency’s outputs will trigger a rebuild of dependent targets.
- Grog can parallelize the build by running independent targets concurrently.
Outputs
Outputs are artifacts that your build target produces and who you might want to share between machines using a remote cache. Grog, therefore, caches these outputs and restores them when possible to avoid unnecessary rebuilds.
"outputs": [ "dist/bundle.js", "dir::dist/assets/", "docker::some-image"]
dist/bundle.js
- A file outputdir::dist/assets/
- A directory outputdocker::some-image-tag
- A Docker image output
Next Steps
Now that you’ve set up Grog and created your first build targets, you might want to explore:
- Configuration Reference - Learn about all available configuration options
- Remote Caching - Set up remote caching for your builds
- Docker Outputs - Learn more about caching Docker images
- Troubleshooting - Solve common issues