Skip to content

Synthesize

Synthesize is a tool for managing long-lived development workflows that involve multiple tools executing concurrently, each of which might have bespoke conditions around when and how it needs to be run or re-run.

In Synthesize, a flow is a graph (potentially disjoint) of nodes, each of which runs a target whenever one of that node's triggers activates. Synthesize has a wide variety of triggers:

  • Target B should run after target A runs.
  • Target W should run every time file F changes.
  • Target R should be restarted if it ever exits.
  • Target O should run once when the flow starts.

These can all coexist as part of same flow, and can even be combined for a single target, allowing for complex nodes like "restart target W if it exits or if file F changes".

Features

  • Target and trigger definitions can be factored out and shared across multiple nodes and flows.
  • Targets are just shell commands, so you can use any tools you'd like. Synthesize works with your existing tools, it doesn't replace them.
  • Targets can be parameterized with arguments (each target is actually a Jinja template) and environment variables. Arguments and environment variables can also be provided at the flow and target levels (most specific wins).
  • Nodes can have multiple triggers, allowing you to express complex triggering conditions.
  • All command output is combined in a single output stream, with each node's output prefixed with a timestamp and its name.
  • The current time and the status of each node is displayed at the bottom of your terminal.
  • You can generate Mermaid diagrams of your flows for debugging and documentation.

Examples

As an example, here is Synthesize's own synth.yaml configuration file:

flows:
  default:
    nodes:
      tests:
        target: tests
        triggers:
        - code-changes
      types:
        target: types
        triggers:
        - code-changes
      docs:
        target: docs
        triggers:
        - delay: 1
        - watch: ["docs/hooks/"]

targets:
  tests:
    commands: |
      pytest -vv --cov

  types:
    commands: |
      mypy

  docs:
    commands: |
      mkdocs serve --strict

triggers:
  code-changes:
    watch:
    - src/
    - tests/
    - docs/examples/
    - docs/hooks/
    - pyproject.toml
    - .coveragerc
flowchart TD
  tests(tests)
  w_bb19edcd7b45bfcfbfcab4096798a339f9610617[("src/
tests/
docs/examples/
docs/hooks/
pyproject.toml
.coveragerc")]
  w_bb19edcd7b45bfcfbfcab4096798a339f9610617 -->|👁| tests
  types(types)
  w_bb19edcd7b45bfcfbfcab4096798a339f9610617 -->|👁| types
  docs(docs)
  docs -->|∞ 1s| docs
  w_f8192994ea74c4d2311ffd6eb936c7c30e96617f[("docs/hooks/")]
  w_f8192994ea74c4d2311ffd6eb936c7c30e96617f -->|👁| docs

Installation

Synthesize is available on PyPI.

We recommend installing Synthesize via pipx:

pipx install synthesize

Then run

synth --help
to get started.

Synthesize does not work on Windows

We recommend using the Windows Subsystem for Linux (WSL) to run Synthesize on Windows.

Inspirations