A self-contained parallel task runner for the GitHub CLI.
InSitu brings parity between local development and CI by letting you define checks once in .insitu.yml and run them identically on your machine and inside GitHub Actions workflows.
Requires the GitHub CLI (gh) to be installed.
gh extension install devx-cafe/gh-insituVerify:
gh insitu --help# Bootstrap a starter .insitu.yml and a pre-commit hook
gh insitu init
# Validate the config and preview the execution plan
gh insitu plan
# Run all waves
gh insitu run
# Run a specific wave
gh insitu run static
# Apply a boilerplate commit from another repo
gh insitu boilerplate --repo lakruzz/boilerplates --ref cspellThe configuration file uses three top-level sections:
# .insitu.yml
# 1. Global defaults – inherited by all checks
defaults:
die-on-error: true # stop after the first failing wave
timeout: 5m # default per-check timeout (Go duration string)
verbose: false # print command output for every check (not just failures)
# 2. Inventory – the library of named checks
inventory:
- id: "build"
name: "Build" # human-readable label (optional; falls back to id)
command: "make build"
timeout: 10m # per-check timeout override (optional)
die-on-error: false # per-check die-on-error override (optional)
- id: "coverage"
name: "Unit Test with Coverage"
command: "make coverage"
# 3. Waves – ordered execution groups that reference inventory ids
waves:
- id: "static"
name: "Static Analysis & Build"
parallel: true # run all checks in this wave concurrently
checks:
- "build"
- id: "test"
name: "Post-Build Validation"
parallel: true
checks:
- "coverage"| Field | Required | Description |
|---|---|---|
defaults.die-on-error |
no | Stop after the first wave that has a failure. Default: false. |
defaults.timeout |
no | Fallback timeout for every check. Go duration string (e.g. 5m, 30s). Default: 5m. |
defaults.verbose |
no | Print full command output for all checks. Default: false (CI: true). |
inventory[].id |
yes | Unique identifier, referenced by waves. |
inventory[].name |
no | Display name shown in output. |
inventory[].command |
yes | Shell command to execute. |
inventory[].timeout |
no | Override defaults.timeout for this check. |
inventory[].die-on-error |
no | Override defaults.die-on-error for this check. |
waves[].id |
yes | Unique wave identifier. |
waves[].name |
no | Display name for the wave. |
waves[].parallel |
no | When true, all checks in the wave run concurrently. Default: false. |
waves[].checks |
yes | List of inventory id values to execute. |
By default every command looks for .insitu.yml in the current working directory. You can override this with the --config / -c flag on any command:
gh insitu run --config path/to/custom.yml
gh insitu plan -c ci/checks.ymlCreates a starter .insitu.yml and installs a .git/hooks/pre-commit hook that runs insitu run before every commit.
gh insitu init # create .insitu.yml + pre-commit hook
gh insitu init --force # overwrite an existing .insitu.yml
gh insitu init -c custom.yml # write config to a custom pathValidates the configuration and prints the resolved execution plan (timeouts, commands, die-on-error settings). No checks are actually run.
gh insitu plan
gh insitu plan --config custom.ymlExecutes one or more waves. Without arguments all waves run in order.
gh insitu run # run all waves
gh insitu run static # run only the 'static' wave
gh insitu run static test # run 'static' then 'test'
gh insitu run --verbose # always print all command output
gh insitu run --mark-pending # mark all checks as 'pending' (CI only)
gh insitu run trunk-worthy --mark-pendingInside a GitHub Actions workflow (GITHUB_ACTIONS=true):
- Each check result is automatically reported as a GitHub commit status.
- Output is wrapped in
::group::/::endgroup::for collapsible log sections. - Use
--mark-pendingas an early step to show checks as pending while the workflow runs.
Fetch the files changed by the tip commit of a branch (or any ref) from a remote GitHub repository and apply them to the current working tree.
For each file in the boilerplate commit:
- File does not exist locally → written directly (parent directories are created as needed).
- File already exists → merged according to
--strategy(see below). - File is removed by the commit → skipped.
--strategy merge (default)
Non-destructive apply. The template is used as BOTH the common ancestor and the "other" side; the local file is "current". Because base == other, git sees no incoming changes from the template — only local additions and modifications survive. All existing local content is preserved; template-only lines are not forced in.
--strategy combine
Full union. Uses an empty common ancestor and --union, so both the local file and the template contribute all their lines. The result contains every line from both sides in order. Zero conflict markers are ever produced.
--strategy inject
Programmatic deep-merge: for each key or array item in the template, add/update it in the existing file. Supported formats: .json, .jsonc (comments are stripped on write), .yml, .yaml. Other file types fall back to combine. Never produces conflict markers.
By default the command refuses to run on a dirty working tree. Use --allow-dirty to skip that guard.
gh insitu boilerplate --repo lakruzz/boilerplates --ref cspell
gh insitu boilerplate --repo org/templates --ref main --allow-dirty
gh insitu boilerplate --repo org/templates --ref cspell --strategy combine
gh insitu boilerplate --repo org/templates --ref cspell --strategy inject| Flag | Required | Description |
|---|---|---|
--repo |
yes | Source repository in owner/repo format. |
--ref |
no | Branch, tag, or commit SHA to fetch. Default: HEAD. |
--strategy |
no | merge (default), combine, or inject. See description above. |
--allow-dirty |
no | Skip the clean working-tree check before applying. |
A GitHub token must be available via GH_TOKEN or GITHUB_TOKEN.
- name: Mark checks pending
run: gh insitu run --mark-pending
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run all checks
run: gh insitu run
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}See the Releases page for all published versions and release notes. Releases are built and published automatically by the Release workflow.
See CONTRIBUTING.md for development guidelines, testing practices, and how to set up the local development environment.