Free tools Windows power users keep installed
One-click scans. No signup required.
Tach helps Python teams prevent accidental imports from breaking module boundaries. Configure which modules may depend on one another and which imports count as public interfaces, then run tach check to catch violations, including dependency cycles. It is a command-line tool implemented in Rust; its documentation says it has no runtime impact on the application.
What Tach checks
Tach analyzes a Python project against architectural rules defined by the team. Its core checks cover declared module dependencies, access to public interfaces, and cycles in the dependency graph. When an import violates a rule, the check reports it and returns a non-zero exit status, which makes the command usable in CI or pre-commit workflows.
As an Amazon Associate I earn from qualifying purchases.
The tool does not decide what your architecture should be. You choose the boundaries and rules; Tach checks imports against them. Its documentation describes it as having no runtime impact, but that is the project’s claim rather than an independent benchmark.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →How to get started
- Install Tach: run
pip install tachin the project environment. - Create an initial configuration: from the project root, run
tach init. The interactive tree lets you mark module boundaries. You can start with top-level packages or govern only selected modules. - Check the project: run
tach checkand review the reported violations. - Refine the rules: edit
tach.tomlto specify dependencies and public interfaces, then run the check again.
This incremental approach lets a team begin with the source areas it intends to govern instead of imposing rules on the entire repository at once. For a project whose Python import roots are in a subdirectory such as backend/, configure source_roots in tach.toml; if omitted, it defaults to the project root (.).
#1 Best Overall
Declare dependencies and protect module internals
Allowed and forbidden dependencies
In tach.toml, a module’s depends_on setting names the modules it is allowed to import. Patterns can describe groups of modules. Use cannot_depend_on to prohibit particular imports; when a rule conflicts with depends_on, the prohibition takes precedence.
If depends_on is omitted, Tach permits dependencies on other modules, subject to those modules’ public-interface rules and other applicable checks. That omission is not a blanket exemption from every architectural boundary. Configuration also supports visibility, utility modules, unchecked modules, and marking individual dependencies as deprecated.
Rank #2
Public interfaces are a separate rule
Dependency permission and interface permission answer different questions: may this module depend on that module, and which imports from that module are part of its supported surface? Configure interfaces separately with [[interfaces]] entries. An interface’s expose patterns identify imports treated as public; optional from, visibility, and exclusive settings can scope where an interface comes from and who adopts or may use it.
This separation is useful when one module may rely on another, but should import only its stable entry points rather than implementation details. An allowed module dependency alone does not make every import inside the target module public.
Use layers when dependency direction matters most
Layers express architectural direction across tiers. Tach’s convention is high to low: a higher layer may import from a lower one, but a lower layer may not import from a higher one. This can be more concise than listing every permitted dependency when the main rule is that dependencies flow in one direction.
By default, a higher layer can use lower-layer modules without listing each one in depends_on; modules in the same layer still need explicit dependency declarations. Set layers_explicit_depends_on = true if cross-layer imports must also be declared individually. A layer marked closed prevents higher layers from skipping it to import directly from still-lower layers.
The documentation’s UI, commands, and core example illustrates the distinction: commands can use core by virtue of their layer order, while two modules within core still declare their dependency. Layer direction and exact dependency declarations are complementary choices, not the same rule.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Put checks into the development workflow
Once the rules reflect the intended architecture, run tach check during normal development so new violations are caught promptly. Tach’s repository documents integration with both CI and pre-commit. When a check fails, decide whether the import is an architectural mistake or the rule no longer reflects the intended design; change the code or configuration accordingly.
Best Value
For investigation, tach show generates a local DOT dependency graph. tach report inspects dependencies and usages for a path. The README also documents tach show --web; that option generates the graph remotely and sends the contents of tach.toml to the remote graph-generation service, so consider that data flow before using it with sensitive configuration.
Monorepos: distinguish module rules from package dependencies
Tach’s configuration documentation covers multiple source roots, including monorepos and namespace packages. Internal module-graph rules govern imports within the analyzed project structure. A separate command, tach check-external, checks whether imports between packages are declared as package dependencies in the relevant pyproject.toml. For example, if one package imports a utility package, the consumer package should declare that dependency in its project configuration.
Do not assume that internal module rules automatically establish a guarantee across every workspace layout. An issue opened on July 2, 2026 reports a limitation involving module graph rules across workspace packages with multiple pyproject.toml files, but a user report alone does not establish the current behavior. Check the current documentation and validate the exact workspace layout you use before relying on cross-workspace enforcement.
Where Tach fits—and where it does not
Tach is for teams that want executable rules around Python import boundaries: explicit dependencies, public import surfaces, layer direction, and dependency cycles. It does not replace architectural decisions, package management, or every kind of structural analysis. In one public implementation example, PostHog documents using Tach interfaces to control imports across product boundaries and running checks in CI, alongside a separate tool for structure within a product. That is an example of one organization’s setup, not a claim that Tach covers every architectural concern.
The official README and documentation reviewed for this article do not establish quantitative benchmarks or version-specific compatibility claims. Treat their setup and configuration guidance as rolling documentation and confirm details for the Tach release and project layout you use.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




