tach-org/tach
A Python tool to visualize + enforce dependencies, using modular architecture π Open source π Installable via pip π§ Able to be adopted incrementally - β‘ Implemented with no runtime impact βΎοΈ Interoperable with your existing systems π¦ Written in rust
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained β safe to depend on.
Has a license, tests, and CI β clean foundation to fork and modify.
Documented and popular β useful reference codebase to read through.
No critical CVEs, sane security posture β runnable as-is.
- βLast commit 3d ago
- β9 active contributors
- βMIT licensed
Show all 6 evidence items βShow less
- βCI configured
- βTests present
- β Single-maintainer risk β top contributor 84% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README β live-updates from the latest cached analysis.
[](https://repopilot.app/r/tach-org/tach)Paste at the top of your README.md β renders inline like a shields.io badge.
βΈPreview social card (1200Γ630)
This card auto-renders when someone shares https://repopilot.app/r/tach-org/tach on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: tach-org/tach
Generated by RepoPilot Β· 2026-05-09 Β· Source
π€Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale β STOP and ask the user to regenerate it before proceeding. - Treat the AI Β· unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/tach-org/tach shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything β but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
π―Verdict
GO β Healthy across all four use cases
- Last commit 3d ago
- 9 active contributors
- MIT licensed
- CI configured
- Tests present
- β Single-maintainer risk β top contributor 84% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
β Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live tach-org/tach
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale β regenerate it at
repopilot.app/r/tach-org/tach.
What it runs against: a local clone of tach-org/tach β the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in tach-org/tach | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | Last commit β€ 33 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of tach-org/tach. If you don't
# have one yet, run these first:
#
# git clone https://github.com/tach-org/tach.git
# cd tach
#
# Then paste this script. Every check is read-only β no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of tach-org/tach and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "tach-org/tach(\\.git)?\\b" \\
&& ok "origin remote is tach-org/tach" \\
|| miss "origin remote is not tach-org/tach (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift β was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~3d)"
else
miss "last commit was $days_since_last days ago β artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) β safe to trust"
else
echo "artifact has $fail stale claim(s) β regenerate at https://repopilot.app/r/tach-org/tach"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
β‘TL;DR
Tach is a Python dependency enforcer and architecture visualizer written in Rust, designed to prevent circular imports and enforce modular monolith boundaries at check-time with zero runtime overhead. It parses Python ASTs using Ruff's parser to build a static dependency graph, then validates that imports conform to declared module boundaries and public interfaces defined in tach.toml. Hybrid Rust/Python: core analysis engine in Rust (Cargo.toml, src/) exposes Python bindings via PyO3, wrapped by Python CLI in python/tach/ with subcommands (check, init, show). Documentation lives in docs/ with mkdocs.yml config. VSCode extension in separate tooling. Enforces modular architecture via tach.toml config files at project roots, with caching layer in python/tach/cache/.
π₯Who it's for
Python architects and senior engineers managing large codebases who need to enforce modular architecture patterns incrementally without refactoring everything at once. Contributors are those building tooling for dependency management, static analysis, or architecture enforcement in Python.
π±Maturity & risk
Actively developed and production-ready: v0.34.1 is published to PyPI with proper CI/CD via GitHub Actions (ci.yml, publish.yml, publish_vscode.yml). Has TypeScript VSCode extension (docs/usage/vscode.md), comprehensive documentation in docs/, and uses static analysis via basedpyright. Regular updates evident from version bumps and active dependency maintenance.
Moderate risk: 430KB of Rust code creates compilation complexity; uses git dependencies on Ruff (pinned to tag 0.14.3) which could diverge from upstream. Single Cargo.toml suggests monolithic Rust structure without clear feature flags for optional components. No visible lock/pinning strategy for Python dependencies beyond pyproject.toml, and pyo3 dependency means tight coupling to CPython ABI (abi3-py37 limits to Python 3.7+).
Active areas of work
Active development on v0.34.1+ with focus on incrementally adoptable dependency enforcement. GitHub Actions workflows indicate continuous publication to PyPI and VSCode marketplace. Docs expanding (usage/deprecate.md, usage/interfaces.md, usage/layers.md suggest recent feature additions). TypeScript VSCode extension suggests IDE integration is a current priority.
πGet running
Clone and build: git clone https://github.com/tach-org/tach && cd tach. Install Rust (if modifying Rust code) and Python 3.7+. For Python-only changes: pip install -e python/tach/. For full dev: cargo build (Cargo.toml defines workspace). Run tach init to configure a test project, then tach check to validate.
Daily commands:
Development: cargo build --release compiles Rust extension. CLI via python -m tach (invokes python/tach/main.py). For docs: mkdocs serve (mkdocs.yml configured). Makefile present but specific targets not listed β check make help or cat Makefile.
πΊοΈMap of the codebase
- Cargo.toml: Defines Rust dependency versions (ruff, pyo3, petgraph) and PyO3 extension module configuration β critical for both native compilation and Python ABI compatibility.
- python/tach/main.py: Entry point for CLI; routes commands (init, check, show, deprecate) to their handlers β start here to understand command structure.
- pyproject.toml: Python package metadata, tooling config (ruff, basedpyright, pytest), and dependencies β defines dev environment setup.
- tach.toml: Configuration schema and example β the user-facing contract defining modules, dependencies, interfaces, and layers that the tool enforces.
- docs/usage/configuration.md: Authoritative documentation of tach.toml schema, modules, dependencies, source-roots, interfaces β essential reference for understanding what the tool validates.
- .github/workflows/ci.yml: CI/CD pipeline: shows test, lint, and build steps β reveals how the project is tested and validated before release.
- python/tach/cache/: Caching layer for dependency analysis results β critical performance component for large codebases; start here for cache invalidation or performance issues.
π οΈHow to make changes
Python CLI changes: edit python/tach/ subdirectories (likely commands, cache, output formatting). Config/schema changes: edit tach.toml parsing logic (Rust side, likely src/); test via python/tach/tests/ if they exist. Documentation: markdown in docs/usage/ for feature docs, docs/contributing/ for process. VSCode extension: TypeScript files (not listed in top 60, likely in separate directory β check .vscode or root for extension source). New features requiring AST analysis: modify Rust parser bindings in src/.
πͺ€Traps & gotchas
Rust compilation required: even for Python-only changes, build process invokes cargo build. Ruff version pinning: dependencies on git tags for ruff mean updates require careful coordination; version mismatch with user's installed Ruff can cause subtle AST parsing bugs. Python 3.7+ only: abi3 wheels limit to Python 3.7 minimum due to pyo3 feature flag. tach.toml discovery: tool assumes tach.toml exists at project root; no clear fallback if missing. Multi-root workspaces: monorepo support exists (source-roots) but behavior unclear if tach.toml not at workspace root.
π‘Concepts to learn
- Modular Monolith β Core architectural pattern that Tach enforces β moving away from microservices and toward logical modules with clear boundaries within a single codebase. Tach's entire value proposition depends on understanding this pattern.
- Directed Acyclic Graph (DAG) + Cycle Detection β Tach uses petgraph 0.8.3 to model module dependencies as a DAG and detect cycles; understanding cycle detection algorithms is essential for debugging 'no cycles' validation.
- Abstract Syntax Tree (AST) Parsing β Tach's Rust core parses Python code into ASTs using Ruff's ruff_python_ast to extract import statements statically; this is how it knows what modules depend on what without executing code.
- PyO3 Extension Module (Rust-Python FFI) β Tach compiles Rust code as a CPython extension using PyO3; understanding the PyO3 binding layer is essential for debugging performance issues or ABI incompatibilities.
- Public Interface / Sealed Module Pattern β Tach enforces that cross-module calls only use declared public interfaces (interfaces in tach.toml), preventing hidden dependency creep even if imports exist β a form of API encapsulation.
- Language Server Protocol (LSP) β VSCode extension uses lsp-server 0.7.7 to communicate architecture violations in real-time as users edit code, following LSP standard for IDE integration.
- Disk-Backed Caching (cached crate with disk_store) β Tach caches dependency analysis results using cached 0.59.0 with disk persistence (python/tach/cache/) to avoid re-parsing on every check; crucial for large codebases where re-parsing would be prohibitive.
πRelated repos
astral-sh/ruffβ Tach's direct upstream dependency for Python AST parsing (ruff_python_ast, ruff_python_parser 0.14.3); understanding Ruff's AST structure is essential for Tach's analysis engine.sondrelg/pydepsβ Alternative Python dependency visualizer using static analysis; more mature but lacks interface enforcement and module boundary validation that Tach provides.PyCQA/pylintβ Overlapping ecosystem for static analysis of Python; Pylint has custom linting but doesn't specialize in dependency graphs and modular architecture enforcement like Tach.python-poetry/poetryβ Companion tool for Python dependency management; Tach complements Poetry's lock-file-based versioning by enforcing architectural boundaries within a monolith or workspace.microsoft/pylanceβ VSCode's built-in Python language server; Tach's VSCode extension (publish_vscode.yml) likely integrates with Pylance LSP protocol for real-time boundary violation warnings.
πͺPR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for the LSP server implementation
The repo has an LSP server (lsp-server and lsp-types dependencies in Cargo.toml) but there's no visible test coverage in the file structure. LSP is critical infrastructure for the VSCode extension (docs/usage/vscode.md). Adding integration tests would ensure the language server correctly handles requests/responses for features like hover, diagnostics, and go-to-definition.
- [ ] Create tests/lsp_server_tests.rs to test LSP initialization and basic request/response cycles
- [ ] Add tests for diagnostic publishing when tach violations are detected
- [ ] Test file watching and incremental updates when python/tach files change
- [ ] Verify tests run in CI by updating .github/workflows/ci.yml if needed
Add comprehensive tests for the caching layer (python/tach/cache/)
The caching system is a performance-critical feature (docs/usage/caching.md exists) but only has setup.py and access.py in the cache module with no visible test files. The caching uses disk_store feature from the 'cached' crate. Adding tests would ensure cache hits/misses work correctly and prevent regressions in this core performance feature.
- [ ] Create python/tach/cache/tests.py to test cache initialization and persistence
- [ ] Add tests verifying cache invalidation when tach.toml changes
- [ ] Test concurrent cache access using the dashmap/rayon parallelism
- [ ] Add integration tests in tests/ that verify performance improvements with caching enabled vs disabled
Add Rust documentation and examples for public APIs in the Rust codebase
The project exports Rust code as both a cdylib and lib (Cargo.toml lib section), but there are no visible Rust doc comments or examples. This makes it harder for contributors and users to understand the public API surface. Adding rustdoc would improve onboarding and enable doctest coverage.
- [ ] Add /// doc comments with examples to the main entry points in python/tach (or the root src/ lib.rs if it exists)
- [ ] Document the key public structs and functions exposed via PyO3 bindings
- [ ] Add module-level documentation explaining the architecture (parsing, dependency graph, caching layers)
- [ ] Run 'cargo doc --no-deps --open' locally and verify all public items are documented
πΏGood first issues
- Add integration tests for
tach checkwith a real multi-module Python project in tests/ β currently no visible test fixtures beyond CI workflows. Could create a minimal test monorepo to validate module detection and cycle detection. - Extend docs/usage/configuration.md with concrete examples of tach.toml for common patterns (Django app, FastAPI multi-router, package-per-feature) β documentation exists but lacks runnable examples.
- Implement
tach validate-configcommand to catch tach.toml syntax errors early β currently unclear if invalid TOML is caught at init time or check time; early validation would improve UX.
βTop contributors
Click to expand
Top contributors
- @DetachHead β 84 commits
- @dependabot[bot] β 5 commits
- @andre-vauvelle β 3 commits
- @imsut β 2 commits
- @scott-huberty β 2 commits
πRecent commits
Click to expand
Recent commits
193eb5aβ remove unnecessary steps from docs jobs (DetachHead)17a295fβ zensical (DetachHead)a660d28β drop support for python 3.9 (DetachHead)28569d6β remove abandoned git graph extension from vscode recommended extensions (DetachHead)d210adeβ v0.34.1 (DetachHead)e4ff548β fixtach testcrash caused by the pytest plugin being registered twice (DetachHead)118666cβ fix exit code 5 false positive when no tests are collected because they were all skipped (DetachHead)6287f0bβ update lockfiles (DetachHead)ab3f083β Bump the all group with 11 updates (dependabot[bot])a393df2β fix compile errors (DetachHead)
πSecurity observations
- High Β· Dependency on External Git Repository Without Version Pinning β
Cargo.toml - ruff dependencies (lines with git = 'https://github.com/astral-sh/ruff.git'). The Cargo.toml file depends on multiple packages from the ruff repository using git references with only a tag specification. This approach is vulnerable to tag spoofing or repository compromise. The dependencies include: ruff_python_ast, ruff_python_parser, ruff_linter, ruff_source_file, and ruff_text_size, all pointing to the same external git repository. Fix: Either: (1) Use crates.io published versions instead of git dependencies, or (2) Pin to specific commit hashes instead of tags to prevent tag spoofing attacks. Example: git = '...', rev = 'commit-hash' instead of tag = '0.14.3' - High Β· Potential Command Injection in Git Operations β
python/tach/filesystem/git_ops.py. The file 'python/tach/filesystem/git_ops.py' is present in the codebase, which typically contains git command execution. Without reviewing the actual code, git operations that use user input or unsanitized data can lead to command injection vulnerabilities. Fix: Review git_ops.py to ensure: (1) All git commands use subprocess with shell=False, (2) Arguments are properly escaped/quoted, (3) No user input is directly concatenated into git commands, (4) Use gitpython or similar libraries instead of shell invocation when possible - Medium Β· Unsafe Deserialization with serde_json and toml β
Cargo.toml dependencies: serde_json, toml, toml_edit. The project uses serde_json and toml libraries for deserialization. If user-controlled TOML or JSON files are deserialized without proper validation, this could lead to arbitrary code execution or DoS attacks, especially when combined with custom deserializers or dangerous features. Fix: Ensure strict validation of all TOML and JSON input files. Implement allowlists for acceptable configuration keys. Consider using serde's 'deny_unknown_fields' attribute when deriving Deserialize to reject unexpected configuration options. - Medium Β· Cached Data Without Security Validation β
Cargo.toml: cached = { version = '0.59.0', features = ['disk_store'] }, python/tach/cache/. The project uses the 'cached' crate with 'disk_store' feature for caching. Cached files may contain sensitive information about the codebase structure or dependencies. If cache files are stored in shared locations or with improper permissions, they could be accessed by unauthorized users. Fix: Ensure cache files are stored in secure directories with appropriate file permissions (e.g., 0600). Validate cache integrity before use. Consider encrypting sensitive cache data. Document where cache files are stored. - Medium Β· Potential Path Traversal in Filesystem Operations β
Cargo.toml: globset, glob dependencies; python/tach/filesystem/. The codebase includes filesystem operations (python/tach/filesystem/) and uses glob patterns. Without proper path validation, user input in glob patterns or file paths could lead to path traversal attacks. Fix: Validate and sanitize all file paths before use. Use canonicalize() to resolve paths and ensure they remain within expected directories. Reject paths containing '..' or other traversal sequences. Use globset with careful pattern validation. - Medium Β· External Process Execution Without Input Validation β
python/tach/filesystem/git_ops.py and cli.py. The presence of subprocess-like operations (implied by git_ops.py and potential shell integrations) without visible input validation could allow command injection if user-controlled data is passed to system commands. Fix: Use subprocess with shell=False and pass arguments as a list. Never concatenate user input into command strings. Use shlex.quote() if shell=True is unavoidable. Validate all user inputs before passing to external processes. - Low Β· Missing HTTPS Enforcement in Configuration β
Cargo.toml git dependencies. The Cargo.toml includes a git dependency pointing to https://github.com/astral-sh/ruff.git. While HTTPS is used, there's no explicit verification of repository identity or certificate pinning. Fix: Ensure git
LLM-derived; treat as a starting point, not a security audit.
πWhere to read next
- Open issues β current backlog
- Recent PRs β what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals β see the live page for receipts. Re-run on a new commit to refresh.