Documentation menu

Dependencies

Dependency & structure atlas

Dependency graph of AutoTelegramForward: every module, resolved import, keystone ranking, cross-subsystem traffic and cycle, derived from the checkout.

Verified against the checkout built for v2.2.4 · updated 20 Oct 2026

On this page

524 modules, 1,869 resolved imports, 8 subsystems and 6 import cycles — counted from this checkout, not from memory. Every node on the map links back to its file on GitHub, so a claim about coupling here can be checked in one click.

How to read the map

One node = one unit of dependency

Python, Dart, Rust and TypeScript nodes are files; Go nodes are packages (a Go file is never a unit of dependency on its own). The legend on the canvas says which is which, per language.

One edge = one resolved import

Edges come from parsing import/from … import, Go import blocks, use/mod statements and relative ES imports, then resolving each specifier against the file index. Anything that resolves outside the repository (a third-party package) is intentionally not drawn.

Size = lines, colour = subsystem

A node grows with the square root of its line count, so a 3,000-line service does not swallow the canvas. Node size is a scale, not a score: coupling is what fan-in and fan-out measure.

The graph

524 modules, laid out by subsystem, relaxed so that linked modules sit near each other — which is why the visual clusters below line up with the architecture rather than with the directory listing. Hover to trace a module's neighbourhood, click to inspect its imports and its dependents.

Subsystems
Filter524 modules · 1,869 import edges
loading graph…drag to pan · scroll to zoom · click a module

core/domain/entities.py

view on GitHub ·module (file) · python · 1,842 lines ·106 dependents · 4 imports

Subsystem core. Click any node in the map to inspect its imports and its dependents, and to follow the module back to its source file.

Keystone modules

Ranked by coupling — two points per dependent, one per import — with generated stubs and tests excluded, because a file that 40 other files import is a file nobody can change casually. The top entry alone carries 106 dependents.

core/domain/entities.pycorepython1,842 lines · 106 in · 4 out
core/infrastructure/persistence/database.pycorepython1,003 lines · 72 in · 0 out
core/infrastructure/persistence/sqlite_repositories.pycorepython2,338 lines · 59 in · 7 out
core/infrastructure/telegram/pro_bot_ui.pycorepython10,464 lines · 44 in · 28 out
website/src/utils/paths.tswebsitetypescript28 lines · 57 in · 0 out
core/domain/value_objects.pycorepython102 lines · 52 in · 0 out
core/infrastructure/telegram/i18n.pycorepython90 lines · 49 in · 0 out
website/src/layouts/DocsLayout.astrowebsiteastro316 lines · 44 in · 5 out
website/src/components/Icon.astrowebsiteastro89 lines · 40 in · 0 out
core/infrastructure/security/crypto.pycorepython18 lines · 39 in · 0 out
core/application/pipeline.pycorepython1,105 lines · 26 in · 11 out
atfcli/commands/__init__.pyclipython5 lines · 31 in · 0 out

Cross-subsystem traffic

Every import that crosses a subsystem boundary. Inside one subsystem the count is deliberately omitted: the interesting question is never "how coupled is the core to itself", it is "which subsystems know about each other".

4 cross-subsystem import directions
FromToImport linksSignal
coreatfcli51 Test suite only — no production import exists
coreatf.py1 Test suite only — no production import exists
atf.pycore1 1 runtime import — shared contract
atf.pyatfcli1 1 runtime import — shared contract

Cycles

Import cycles are found with Tarjan's strongly-connected-components pass over the resolved graph, so this list is exhaustive for the edges the sweep could resolve — not a sample. 6 groups of modules import each other.

Largest modules

Size is not a defect, but it is where a defect hides best. The largest authored module is api/internal/handlers at 11,376 lines with 1 dependents.

Largest authored modules
ModuleSubsystemLinesIn / out
api/internal/handlersapi11,3761 / 5
core/infrastructure/telegram/pro_bot_ui.pycore10,46444 / 28
core/proto/autoforward_pb2_grpc.pycore3,3334 / 2
api/internal/ratelimitapi2,7852 / 1
core/infrastructure/persistence/sqlite_repositories.pycore2,33859 / 7
core/infrastructure/grpc_server/servicers.pycore2,15412 / 14
web/frontend/src/components/TaskOverviewModal.tsxweb-frontend2,1521 / 5
web/frontend/src/App.tsxweb-frontend2,1319 / 26
core/domain/entities.pycore1,842106 / 4
core/infrastructure/persistence/postgres_repositories.pycore1,79312 / 4
mobile/lib/core/models.dartmobile1,76118 / 2
mobile/lib/features/rules/rule_editor_screen.dartmobile1,4702 / 12

Language mix

Per-language totals, counted as non-blank non-comment lines
LanguageNodesSource filesLinesShare
python32432492,431
go87729,711
typescript606025,597
dart555523,577
astro757514,160
proto111,032
rust11252

Python carries 92,431 of those lines across 324 files, which is what "the engine is the product" looks like in numbers.

Loosely coupled ends

Modules with no resolved import in either direction, with package markers (__init__.py), tests and entrypoints already excluded. 1 remains — a module nobody imports and that imports nobody is either an entrypoint or dead weight, and this is the list where that question gets asked.

Next: the same components, but as live connections — the 3D connection map draws the 23 links that cross process boundaries, which imports cannot describe. Back to the atlas overview