# Where Is the Entry Point for Holehe's Execution? CLI Setup Explained

> Discover Holehe's execution entry point in setup.py. Learn how the CLI setup maps the holehe command to the core module for asynchronous scanning. Get started with holehe now.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: how-to-guide
- Published: 2026-08-30

---

**Holehe's entry point is declared in [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py) as a console script that maps the `holehe` command to `holehe.core:main`, which then launches the asynchronous scanning workflow via `trio.run(maincore)`.**

Holehe, the popular email OSINT tool by megadose, follows standard Python packaging conventions for its command-line interface. Understanding how the **entry point for Holehe's execution** works helps developers who want to extend the tool, debug issues, or integrate it into larger workflows. The architecture separates the CLI wrapper from the core logic, making it clean to maintain and easy to invoke programmatically.

## How Python Console Scripts Work in Holehe

Python packages use **setuptools entry points** to create executable commands without manual script management. In Holehe's case, the [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py) file declares exactly how the `holehe` command gets built during installation.

### The setup.py Entry Point Declaration

In [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py), the entry point is defined as follows:

```python
entry_points = {'console_scripts': ['holehe = holehe.core:main']}

```

This single line does three critical things:

- Creates a system-wide `holehe` executable after `pip install`
- Routes all invocations to the `main` function inside [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)
- Generates a platform-appropriate wrapper script automatically

When you run `pip install holehe`, setuptools creates a small executable stub (platform-specific) that essentially performs this operation:

```python

# Generated automatically by setuptools

import sys
from holehe.core import main

if __name__ == '__main__':
    sys.exit(main())

```

## The Core Execution Path: holehe/core.py

The actual **Holehe execution entry point** lives in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py). This file contains two key functions that handle the transition from synchronous CLI to asynchronous scanning.

### The Synchronous main() Wrapper

```python
def main():
    trio.run(maincore)                      # ← entry point execution

```

The `main()` function serves a single purpose: **bridge sync and async worlds**. Since Python's `asyncio` or `trio` coroutines cannot be called directly from synchronous code, this wrapper uses `trio.run()` to execute the true async entry point `maincore`.

### The Async maincore Coroutine

While not shown in the analysis, `maincore` is the **asynchronous driver** that:

1. Parses email arguments
2. Loads module configurations
3. Spawns concurrent site checks across Holehe's service modules
4. Aggregates and formats results

The separation between `main()` and `maincore` follows Python best practices for CLI tools using **structured concurrency** via the Trio library.

## Practical Usage Patterns

### Standard Command-Line Invocation

```bash
$ holehe test@example.com

```

Behind the scenes, this triggers the chain: shell → setuptools wrapper → `holehe.core.main()` → `trio.run(maincore)` → full scan execution.

### Programmatic Library Use

You can bypass the CLI entirely by importing the same entry point:

```python
from holehe.core import main

# Calls the identical entry point that console script uses

main()                     # Executes full Holehe scan

```

**Warning**: This still requires proper argument handling since `main()` expects `sys.argv` or equivalent configuration. For cleaner programmatic use, consider importing and calling `maincore` directly with prepared parameters.

## Entry Point Architecture Comparison

| Component | File | Role | When It Runs |
|-----------|------|------|--------------|
| **Console script declaration** | [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py) | Maps `holehe` command to Python callable | Install time (creates wrapper) |
| **Synchronous bridge** | [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) → `main()` | Launches Trio event loop | Every CLI invocation |
| **Async core logic** | [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) → `maincore()` | Orchestrates email checks across services | Inside `trio.run()` context |

## Summary

- **Holehe's execution entry point** is declared in [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py) as `holehe = holehe.core:main`
- The `main()` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) wraps the async `maincore` coroutine using `trio.run()`
- Setuptools generates the actual `holehe` executable at install time
- Both CLI and programmatic use converge on the same `holehe.core:main` callable
- The architecture cleanly separates **packaging metadata**, **sync/async bridging**, and **core scanning logic**

## Frequently Asked Questions

### Can I run Holehe without installing it via pip?

You can execute [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) directly with `python -m holehe.core` if the package structure supports it, but the recommended path uses the installed console script. Running uninstalled may fail due to missing dependencies or improper `sys.path` configuration.

### Why does Holehe use Trio instead of asyncio for its entry point?

The `main()` function uses `trio.run(maincore)` because Holehe's concurrent site checking relies on **Trio's structured concurrency** primitives. Trio provides stricter task supervision and cancellation semantics compared to `asyncio`, which matters when running dozens of network requests that may hang or fail.

### Where would I add custom arguments to the Holehe CLI?

Custom arguments should be processed in `maincore` within [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), since `main()` exists solely to launch the event loop. The argument parsing logic typically resides in `maincore` or a dedicated parser module called from it.

### Is `holehe.core:main` the only entry point defined?

Based on the source analysis, yes—[`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py) declares only the single console script `holehe = holehe.core:main`. No additional entry points like GUI launchers or plugin hooks appear in the standard configuration.