Skip to main content
  • Reusable - Makefile and Justfile work well, but reusing tasks across projects is hard. bakefile makes tasks Python class methods, so you inherit and share them like any other code.
  • Python - Write Python instead of a DSL. Real language features, type checking with ruff and ty, and the rest of Python’s tooling. ctx.run() still handles normal CLI commands through subprocess.
  • Language-agnostic - Tasks are Python, but the commands they run can target any language (Go, Rust, JS, etc.).

How it compares

bakefile vs the runners you probably already know: Legend: ✅ yes · ⚠️ partial · ❌ no · N/A not applicable. * Auto help + completion: ⚠️ tools list and complete task names. bakefile’s Typer renders full per-task --help (typed options) and completes flags too (bake --install-completion). ** Typed & validated config: typed Pydantic settings (Pydantic Settings) that export to shell, dotenv, JSON, or YAML, or inject into a subprocess’s environment (env, export). *** Single binary, no runtime: bakefile needs a Python runtime, eased by PEP 723 and uv. **** Inline deps (PEP 723): bakefile’s bakefile.py can declare its own dependencies inline (# /// script), so a single file carries its own dependencies, no project setup needed. PEP 723 is a Python-only standard, so non-Python runners are N/A. bakefile also works with pyproject.toml for normal Python projects. PEP 723 is optional. Invoke has no inline-deps mechanism. Most runners are DSLs over shell recipes. Invoke is Python too, but its tasks are flat module functions with no inheritance or composition model. bakefile is the only one where tasks are class methods you inherit, override, and compose, so reusable task libraries (bakelib Spaces) just work. bakefile is new, built on modern typed Python (Typer + Pydantic). Production-proven: I run it daily at my company.