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. This means that you can keep using your existing scripts, Makefile rules, NPM commands, or any CLI you love—while grog transparently handles change detection, (remote) caching, and concurrent execution. This allows small teams to get an immediate boost to their monorepo productivity without having to buy into a complex tool.
Read more in Why Grog?.
1. Install Grog
# Using Homebrewbrew tap chrismatix/grogbrew install grog
# Or download the binarycurl -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_ui command: npm run build:ui inputs: - frontend/src/**/*.{js,ts,jsx,tsx} - frontend/package.json outputs: - dir::frontend/dist
- name: compile_backend command: go build -o backend/bin/app ./backend inputs: - backend/**/*.go outputs: - backend/bin/app
- name: build_image command: > docker build \ --file Dockerfile \ --tag myorg/myapp:latest . dependencies: - :build_ui - :compile_backend inputs: - Dockerfile outputs: - docker::myorg/myapp:latest
Save this as BUILD.yaml
in your project directory.
{ "targets": [ { "name": "build_ui", "command": "npm run build:ui", "inputs": [ "frontend/src/**/*.{js,ts,jsx,tsx}", "frontend/package.json" ], "outputs": [ "dir::frontend/dist" ] }, { "name": "compile_backend", "command": "go build -o backend/bin/app ./backend", "inputs": [ "backend/**/*.go" ], "outputs": [ "backend/bin/app" ] }, { "name": "build_image", "command": "docker build --file Dockerfile --tag myapp .", "dependencies": [ ":build_ui", ":compile_backend" ], "inputs": [ "Dockerfile" ], "outputs": [ "docker::myapp" ] } ]}
Save this as BUILD.json
in your project directory.
# @grog# inputs:# - frontend/src/**/*.{js,ts,jsx,tsx}# - frontend/package.json# outputs:# - dir::frontend/distbuild_ui: npm run build:ui
# @grog# inputs:# - backend/**/*.go# outputs:# - backend/bin/appcompile_backend: go build -o backend/bin/app ./backend
# @grog# dependencies:# - :build_ui# - :compile_backend# inputs:# - Dockerfile# outputs:# - docker::myapp:latestbuild_image: docker build --file Dockerfile --tag myapp:latest .
Add the grog metadata comments to your Makefile
goals to allow running them with Grog.
amends "package://grog.build/releases/v0.9.3/grog@0.9.3#/package.pkl"
targets { new { name = "build_ui" command = "npm run build:ui" inputs { "frontend/src/**/*.{js,ts,jsx,tsx}" "frontend/package.json" } outputs { "dir::frontend/dist" } }
new { name = "compile_backend" command = "go build -o backend/bin/app ./backend" inputs { "backend/**/*.go" } outputs { "backend/bin/app" } }
new { name = "build_image" command = "docker build --file Dockerfile --tag myapp:latest ." dependencies { ":build_ui" ":compile_backend" } inputs { "Dockerfile" } outputs { "docker::myapp:latest" } }}
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.
4. Inspect the Build Graph
The build targets defined in the example above form a directed acyclic (build) graph (DAG).
You can visualize this graph using the grog graph
command:
--- title: get_started dependency graph config: theme: default maxTextSize: 50000 maxEdges: 500 fontSize: 16 --- flowchart BT 0@{ shape: rect, label: "//:build_image"} style 0 fill:#E3F2FD,stroke:#1E88E5,stroke-width:2 1@{ shape: rect, label: "Dockerfile"} style 1 fill:#FFF8E1,stroke:#FB8C00,stroke-width:2,stroke-dasharray:6 3 2@{ shape: rect, label: "//:build_ui"} style 2 fill:#E3F2FD,stroke:#1E88E5,stroke-width:2 3@{ shape: rect, label: "frontend/package.json"} style 3 fill:#FFF8E1,stroke:#FB8C00,stroke-width:2,stroke-dasharray:6 3 4@{ shape: rect, label: "frontend/src/*"} style 4 fill:#FFF8E1,stroke:#FB8C00,stroke-width:2,stroke-dasharray:6 3 5@{ shape: rect, label: "//:compile_backend"} style 5 fill:#E3F2FD,stroke:#1E88E5,stroke-width:2 6@{ shape: rect, label: "backend/**/*.go"} style 6 fill:#FFF8E1,stroke:#FB8C00,stroke-width:2,stroke-dasharray:6 3 1 -.-> 0 3 -.-> 2 4 -.-> 2 6 -.-> 5 2 --> 0 5 --> 0
This representation reveals a few things:
- Grog can and will build
compile_backend
andbuild_ui
in parallel before buildingbuild_image
. - A change to any file in
backend/**/*.go
will trigger a rebuild ofcompile_backend
. This will in turn trigger a rebuild ofbuild_image
.
5. Run 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. Run 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
- Shell Completions - Enable target auto completion