# Where Is the Holehe Main Orchestration Logic Located?

> Discover the Holehe main orchestration logic in holehe/core.py. This file handles CLI parsing, module loading, and concurrent email verification for numerous services.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: internals
- Published: 2026-08-24

---

**The Holehe main orchestration logic is located entirely within [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), which coordinates command-line parsing, dynamic module loading, and concurrent email verification across hundreds of services.**

Holehe is an open-source email OSINT (Open Source Intelligence) tool maintained in the **megadose/holehe** repository. When you execute a search, the application’s workflow—from parsing your CLI flags to dispatching hundreds of asynchronous site checks—is governed by a single orchestration layer. This article breaks down the exact location and mechanics of that logic based on the current source tree.

## The Central Orchestrator: [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)

All execution paths converge on **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)**. Unlike tools that split orchestration across multiple modules, Holehe centralizes its control flow here. The file implements an asynchronous pipeline that initializes resources, discovers service modules dynamically, manages concurrent HTTP requests via Trio, and formats the final output.

According to the megadose/holehe source code, the orchestrator performs seven discrete steps between invocation and result display.

## Step-by-Step Orchestration Flow

### CLI Argument Parsing

The orchestration begins at **lines 80–99** with Python’s `ArgumentParser`. The code constructs the CLI interface, capturing the target email, optional CSV export flags, color settings, and session timeout values:

```python
parser = ArgumentParser(...)
args = parser.parse_args()

```

These arguments dictate how the subsequent service checks execute.

### Version Verification and Credits

Before loading modules, the orchestrator calls `check_update()` and `credit()` (around **lines 65–89**) to verify the installed version against PyPI and display author attribution. This ensures users are aware of available updates before consuming network resources.

### Dynamic Module Discovery

At **lines 105–107**, the system discovers every available service module using `import_submodules("holehe.modules")`. This dynamic import pattern allows Holehe to automatically incorporate new site checkers placed in the `holehe/modules/` directory without modifying the orchestration logic.

```python
modules = import_submodules("holehe.modules")

```

### Service Function Extraction

Immediately following discovery (lines 108–110), `get_functions(modules, args)` extracts callable site-checking functions from the imported modules. This transforms the module objects into an executable registry of services to query.

### Async HTTP Client Initialization

To optimize resource usage, the orchestrator instantiates a single shared `httpx.AsyncClient` at **lines 111–114**, configured with the user-specified timeout:

```python
client = httpx.AsyncClient(timeout=timeout)

```

This client instance is injected into every service check to ensure connection pooling and consistent header configuration.

### Concurrent Execution with Trio

The core parallelism logic resides at **lines 118–121**. Holehe uses the **Trio** library (an asynchronous I/O framework) to open a nursery and spawn `launch_module` tasks concurrently:

```python
nursery.start_soon(launch_module, website, email, client, out)

```

This line executes once per discovered service, allowing hundreds of site checks to run simultaneously without blocking.

### Result Aggregation and Output

After the nursery completes (lines 124–131), the orchestrator passes the collected results to `print_result()` for terminal display and optionally to `export_csv()` for file persistence. The results are sorted and deduplicated before presentation.

## Entry Point: From `main()` to `maincore()`

The orchestration exposes a clean entry point at **lines 132–134**. The synchronous `main()` function serves as the CLI entry point, while `maincore()` contains the asynchronous implementation:

```python
def main():
    trio.run(maincore)

```

This separation allows `main()` to be invoked via setuptools console scripts while `maincore()` can be imported for programmatic use.

## Programmatic Invocation

While the orchestrator typically consumes `sys.argv`, you can invoke it directly in Python for custom integrations. Note that `maincore()` expects the global argument state, so programmatic use requires proper setup:

```python
import trio
from holehe.core import maincore

async def run_holehe(email: str):
    # Configure sys.argv or args namespace before calling

    await maincore()

# Execute via Trio's event loop

trio.run(run_holehe, "target@example.com")

```

For standard CLI usage, the orchestrator activates automatically:

```bash
holehe target@example.com --csv --no-color

```

## Supporting Infrastructure

Several adjacent files support the main orchestration logic in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py):

- **[`holehe/modules/__init__.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/__init__.py)** – Enables the `import_submodules()` discovery mechanism by exposing the package structure.
- **[`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py)** – Implements `TrioProgress`, the progress-bar instrument passed to the Trio nursery for real-time status updates during concurrent execution.
- **[`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)** – Provides the default `ua` string injected into all HTTP requests via the shared AsyncClient.
- **`holehe/modules/*/*.py`** – Individual site-specific check functions (e.g., Twitter, Instagram) that the orchestrator dispatches via `launch_module`.

## Summary

- The **Holehe main orchestration logic** is consolidated in **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)**.
- It follows a seven-phase pipeline: CLI parsing, version checks, dynamic module loading, function extraction, HTTP client setup, Trio-based concurrent execution, and result formatting.
- **Trio** manages concurrency through `nursery.start_soon()`, while **httpx** handles asynchronous HTTP.
- The entry point `main()` wraps the async `maincore()` function, enabling both CLI and programmatic invocation.
- Supporting files in [`instruments.py`](https://github.com/megadose/holehe/blob/main/instruments.py) and [`localuseragent.py`](https://github.com/megadose/holehe/blob/main/localuseragent.py) provide instrumentation and request headers.

## Frequently Asked Questions

### Where is the `main()` function defined in Holehe?

The `main()` function is defined at **lines 132–134** of [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py). It acts as the synchronous entry point that launches the asynchronous `maincore()` function using `trio.run()`.

### How does Holehe discover new services without code changes?

Holehe uses `import_submodules("holehe.modules")` (lines 105–107) to dynamically import every Python file in the `holehe/modules/` directory. This introspection automatically registers new site checkers at runtime.

### What async library does Holehe use for orchestration?

Holehe uses **Trio** rather than asyncio. The orchestrator opens a Trio nursery at lines 118–121 to spawn concurrent tasks via `nursery.start_soon(launch_module, ...)`, managing hundreds of simultaneous HTTP requests.

### Can I use Holehe’s orchestration logic in my own Python scripts?

Yes, though it requires care. You can import `maincore` from `holehe.core` and run it with `trio.run()`, but you must properly initialize the argument namespace (normally handled by `ArgumentParser`) since `maincore()` depends on the global `args` object populated during CLI parsing.