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:
    - synthesize/
    - tests/
    - docs/examples/
    - docs/hooks/
    - pyproject.toml
    - .coveragerc
flowchart TD
  tests(tests)
  w_3f51ccc747550900835a2c06c122dc18[("synthesize/
tests/
docs/examples/
docs/hooks/
pyproject.toml
.coveragerc")]
  w_3f51ccc747550900835a2c06c122dc18 -->|👁| tests
  types(types)
  w_3f51ccc747550900835a2c06c122dc18 -->|👁| types
  docs(docs)
  docs -->|∞ 1s| docs
  w_4d475cb3916a7348ab85e5bf7180b6fa[("docs/hooks/")]
  w_4d475cb3916a7348ab85e5bf7180b6fa -->|👁| docs

Installation

Synthesize is available on PyPI.

We recommend installing Synthesize via pipx:

pipx install synthesize

Then run

synth --help
to get started.

Inspirations