Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Tach helps Python teams prevent accidental coupling by checking which modules may import one another and which parts of a module are public. Add it with pip install tach, initialize boundaries using tach init, and run tach check to find violations. Its rules live in tach.toml and can be enforced in CI or pre-commit.

What Tach enforces

Tach is an open-source command-line tool for Python projects, implemented in Rust. It checks declared module dependencies, whether imports use public interfaces, and cycles in the dependency graph. The project says Tach has no runtime impact; that is a project claim, not a benchmark result. See the official README.

These checks address related but distinct architecture questions: which modules may depend on other modules, and which imports from an allowed module are part of its supported surface. An allowed module dependency does not necessarily grant permission to import that module’s internals.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Get started and adopt boundaries incrementally

  1. From the project environment, install Tach with pip install tach.

  2. Run tach init from the project root. Its interactive setup helps mark module boundaries. You can begin with top-level packages or select only the modules you want to govern.

  3. Review and edit tach.toml to describe allowed dependencies and public interfaces. If your Python import roots are under a subdirectory such as backend/, configure source_roots; it defaults to the project root (.) when omitted.

  4. Run tach check and review any reported imports. Decide whether the code should change or the intended architecture rule should be adjusted.

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  5. Add the check to CI or a pre-commit workflow if you want violations caught during routine development. Tach documents both integration approaches in its README.

Declare dependencies separately from public interfaces

Tach’s configuration distinguishes a module’s dependency rules from an interface’s public import patterns. The configuration options and their syntax are documented in the configuration reference.

Allow or forbid module dependencies

Use depends_on to list modules a module is allowed to import. Use cannot_depend_on to forbid particular imports; prohibitions take precedence when a pattern could match both settings. Patterns can cover groups of modules.

If a module omits depends_on, Tach treats its dependencies permissively: it may depend on any other module, subject to the other module’s public-interface rules. Omission therefore does not grant access to every internal import.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The configuration also supports visibility, utility modules, unchecked modules, and deprecating individual dependencies. These options let teams express exceptions or transitional rules, but they should be chosen deliberately so an exception does not quietly become the architecture.

Expose stable import surfaces

Define interfaces separately, using an interface’s expose patterns to identify imports that consumers may treat as public. Optional from, visibility, and exclusive settings let you scope which consumers adopt or may use an interface.

This separation is useful when one module is allowed to depend on another but should import only its stable surface, not implementation details. It makes the intended boundary explicit rather than relying on conventions that contributors may not know.

Use layers when dependency direction is the main rule

Layers express a high-to-low architecture: higher layers may import from lower layers, but lower layers may not import from higher ones. They provide a concise way to describe direction across tiers, while exact module dependency declarations remain a separate choice.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

By default, a higher layer may use modules in lower layers 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 explicitly. A layer can be marked closed to prevent higher layers from bypassing it and importing directly from still-lower layers.

The documented UI, commands, and core example illustrates the distinction: commands can use core without listing every dependency by default, while modules within core still declare their dependencies. Layer direction alone is not the same as a complete inventory of allowed module-to-module imports. See the layers documentation.

Inspect dependencies and investigate violations

These commands complement tach check: graph and report output help explore structure, while the check is the documented enforcement step and returns a non-zero exit status for violations, making it suitable for automated workflows. Command guidance is in the official README.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Monorepos: distinguish module rules from package dependencies

Tach’s configuration documentation describes multiple source roots for monorepos and namespace packages. Within a Python package, module rules govern internal imports. Separately, tach check-external checks whether imports between packages are declared in the relevant package’s pyproject.toml. For example, if a consumer package imports a utility package, the consumer’s package dependencies should declare it.

Those checks answer different questions: an internal module graph is not a substitute for declaring package-level dependencies. The documentation covers source roots and external dependency checks in the configuration reference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For workspace layouts with multiple pyproject.toml files, confirm the current documentation and validate the exact layout you use before relying on module-graph rules across workspace package boundaries. A public issue filed July 2, 2026 reported a limitation in that area, but a user-submitted issue alone does not establish the current behavior for every configuration.

Where Tach fits—and what it does not establish

Tach is useful when a team wants executable rules for module dependencies, public import surfaces, and dependency cycles, rather than relying only on review conventions. It does not by itself define the right architecture: the team must decide its module boundaries, exceptions, and stable interfaces.

A public PostHog architecture document describes using Tach interfaces to govern imports across product boundaries and running checks in CI. That document also describes a separate tool for checking structure inside a product. It is one implementation example, not evidence that Tach covers every architectural concern or that every team needs the same division of tools.

The official README and documentation are rolling pages rather than version-pinned release notes, so consult them for the configuration supported by the Tach version you install. They do not provide a quantitative benchmark necessary to assess this use case.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.