maru

Incremental builds · content-addressed cache · hermetic tasks

maru

Build only what changed. Cache by content, not by clock.

curl -fsSL https://get.maru.build | sh

Verified, reproducible, and about 1.8 MB. Also on Homebrew: brew install maru.

  1. Installing maru 2 min Install the maru binary, verify it, and scaffold a project in under a minute.
  2. Your first build 2 min Declare a task with explicit inputs and outputs, then watch maru skip it when nothing changed.
  3. Content-addressed caching 2 min How maru builds a cache key from content, dependencies, and toolchain — and how to share it across a team.
  4. Hermetic task graphs 2 min Sandboxed inputs, a scrubbed environment, and no network — the guarantees that make a maru build reproducible.

Or jump to the reference — CLI, config, and the task API

Incremental by digest

maru never trusts timestamps. Every task has a cache key derived from the exact bytes of its inputs, the command it runs, the outputs of the tasks it depends on, and the pinned toolchain. Change a comment in a file that nothing reads and maru does nothing. Change one byte that a hundred tasks depend on and maru rebuilds exactly those hundred tasks, in dependency order, and not one more.

Hermetic by default

A task sees only what it declares. maru runs each command in a sandbox where the working tree is a read-only tree of the declared inputs, the environment is scrubbed to a known allowlist, and the network is off unless you opt in. A build that passes on your laptop passes in CI because there is nothing left to differ.

One graph, many machines

The build is a single directed acyclic graph of tasks. Because cache keys are content addresses, the entry a colleague produced this morning is the entry your machine would have produced — so maru can pull it from a shared cache instead of rebuilding. The graph is the contract; the cache is just memoized truth.