Skip to main content

fyrer: Declarative Task Orchestration for Monorepos

fyrer is a declarative, language-agnostic monorepo task orchestrator written in Rust. In a large monorepo — whether it spans TypeScript, Rust, Go, Python, or any other language — running tasks across dozens of packages in the right order, without redundant rebuilds and without losing output, is painful. fyrer solves this by reading a single fyrer.yml config, turning your task relationships into a directed acyclic graph (DAG), and executing tasks in streaming DAG order (as soon as dependencies finish) so you get the fastest possible run every time.

What fyrer does

  • Reads fyrer.yml and resolves a task dependency graph — declare each package and its tasks; fyrer topologically sorts them and propagates failures so dependent tasks are cleanly skipped.
  • Runs tasks in streaming DAG order — each task starts as soon as its dependencies succeed, up to the concurrency limit, maximising CPU utilisation across your packages.
  • Streams colorized, prefixed output per task — every task's logs are prefixed with its package and task name, colorized for readability, and streamed live.
  • Caches successful build tasks keyed by inputs — tasks with cache: true are fingerprinted using a blake3 hash of their command, environment, and all matched input files. A second run reports ⚡ Cached and restores outputs instantly.
  • Provides an interactive TUI and a plain CI-friendly mode — by default fyrer run opens a full-screen terminal UI with a task list and scrollable log pane. Pass -n (--no-tui) for plain prefixed output that works cleanly in CI pipelines and pipes.

Who it's for

fyrer is designed for developers who manage polyglot monorepos — repositories that combine multiple languages or runtimes such as TypeScript/Bun, Rust, Go, Python, and more — and who need a lightweight, zero-boilerplate tool to coordinate builds, tests, code-generation steps, and development servers across all of them. If you have ever written a Makefile or shell script just to sequence cargo build before bun run dev, fyrer is for you.

Limitations

Keep these known constraints in mind as you design your fyrer.yml:

  • Persistent tasks only block their dependents. fyrer runs tasks in streaming order — a task starts as soon as its dependencies finish, up to the concurrency limit. A persistent: true task (e.g. a dev server) never exits, so any task that transitively depends on it will never start. Keep long-running dev servers on the leaves of the dependency graph so they don't block other work. Unrelated tasks continue to run concurrently.
  • watch is implemented via polling. Tasks with watch: true are watched by polling their inputs globs every 300ms (debounced 300ms). When inputs change, the task is restarted automatically. watch cannot be combined with cache.