<p align="center" <img src="https://raw.githubusercontent.com/allenhori/zhao-dbt-plan/master/docs/assets/logo.png" alt="zhao logo" width="128" </p
zhao-dbt-plan
A static microbatch cascading time-window planner for dbt. dbt's microbatch incremental strategy applies one flat --event-time-start/--event-time-end window across an entire selection — so when a rolling-window model reads a wider span than its immediate upstream was recomputed for, dbt has no way to know it needs a wider batch too. zhao-dbt-plan reads your compiled manifest, walks the DAG within whatever you --select, and computes the correct, per-model expanded window — as a plan you review, never a command it runs for you.
$ zhao-dbt-plan --select tag:microbatch_demo --event-time-start 2026-07-01 --event-time-end 2026-07-01 --pretty
[layer 0] mb_orders_daily [2026-07-01 .. 2026-07-01]
[layer 1] mb_orders_rolling_7d [2026-06-28 .. 2026-07-05]
[layer 2] mb_orders_rolling_14d [2026-06-26 .. 2026-07-06]
[layer 3] mb_orders_summary [2026-06-25 .. 2026-07-07]
[layer 3] mb_orders_wide_lookback [2026-04-07 .. 2026-07-11]
warning: mb_orders_wide_lookback: expanded window (96 days) exceeds max_window_expansion_days (90)Why
If Model A aggregates a 7-day trailing window and Model B reads Model A over a further [-3, +4] window, a backfill to Model A on day T silently corrupts Model B's outputs from T-4 through T+3 — and native dbt only ever re-triggers Model B for day T itself. Manually widening the whole selection's window instead wastes compute recomputing everything that wasn't actually touched. zhao-dbt-plan computes the real, minimal per-model window instead.
It never executes anything. Not dbt build, not dbt run — plan-only, permanently. You decide how to actually run the plan: raw dbt, Dagster, Airflow, a Databricks Asset Bundle, whatever you already use.
Install
macOS / Linux — Homebrew:
brew install allenhori/zhao/zhao-dbt-planWindows — Scoop:
scoop bucket add zhao https://github.com/allenhori/zhao-scoop
scoop install zhao-dbt-planPython / dbt projects — PyPI, with uv or pip:
uv tool install zhao-dbt-plan # or: pip install zhao-dbt-planA pre-built binary in a wheel, no Rust toolchain needed — pin it next to dbt-core in your project's own dependencies so local dev and CI get the same version.
Any platform — the install script:
curl -fsSL https://raw.githubusercontent.com/allenhori/zhao-dbt-plan/master/scripts/install.sh | shUpdate with brew upgrade zhao-dbt-plan, scoop update zhao-dbt-plan, or uv tool upgrade zhao-dbt-plan / pip install --upgrade zhao-dbt-plan; re-run the install script if you used that. Homebrew, Scoop and PyPI carry stable releases only.