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 recipe whenever one of that node's triggers activates. Synthesize has a wide variety of triggers:
- Recipe
Bshould run after recipeAruns. - Recipe
Wshould run every time fileFchanges. - Recipe
Rshould be restarted if it ever exits. - Recipe
Oshould run once when the flow starts.
These can all coexist as part of same flow, and can even be combined for a single recipe,
allowing for complex nodes like
"restart recipe W if it exits or if file F changes".
Features
- Recipe and trigger definitions can be factored out and shared across multiple nodes and flows.
- Recipes are just shell commands, so you can use any tools you'd like. Synthesize works with your existing tools, it doesn't replace them.
- Recipes can be parameterized with arguments (each recipe is actually a Jinja template) and environment variables. Arguments and environment variables can also be provided at the flow and recipe 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:
recipe: tests
triggers:
- code-changes
types:
recipe: types
triggers:
- code-changes
docs:
recipe: docs
triggers:
- delay: 1
- watch: ["docs/hooks/"]
recipes:
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 as a uv tool:
Then run synth --help to get started.
Or to try it out without a permanent install using uvx:
Or to add it as a development dependency in a uv project:
Then use uv run synth to run it within the project environment.
Synthesize does not work on Windows
We recommend using the Windows Subsystem for Linux (WSL) to run Synthesize on Windows.