# How to Implement a Custom Main Function with Catch::Session in Catch2

> Learn to implement a custom main function with Catch::Session in Catch2. Control test runner initialization, configuration, and teardown for your C++ tests.

- Repository: [Catch Org/Catch2](https://github.com/catchorg/Catch2)
- Tags: how-to-guide
- Published: 2026-07-29

---

**To implement a custom main function with Catch::Session in Catch2, link your executable against the static `Catch2` library (instead of `Catch2WithMain`), instantiate exactly one `Catch::Session` object in your entry point, and invoke `session.run(argc, argv)` to drive the test runner while retaining full programmatic control over initialization, configuration, and teardown.**

When integrating Catch2 into complex C++ projects, you often need to perform custom setup before tests run or modify runtime configuration programmatically rather than via command-line arguments. By linking against the base `Catch2` static library rather than the `Catch2WithMain` convenience target, you bypass the framework's default entry point and gain direct access to the `Catch::Session` facade defined in [`src/catch2/catch_session.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_session.hpp). This class exposes the Clara command-line parser and `ConfigData` structures, allowing you to override defaults, inject custom logic, or extend the CLI with application-specific options.

## Basic Custom Main Implementation

`Catch::Session` serves as the central entry point that owns the configuration state and drives test execution. According to the Catch2 source code, you must create exactly one `Session` instance per process. The typical implementation follows a three-step pattern: instantiate the session, optionally perform custom initialization, and delegate to the framework's parsing and execution logic.

```cpp
#include <catch2/catch_session.hpp>

int main( int argc, char* argv[] ) {
    // Custom pre-test initialization (e.g., environment setup, logging)
    std::cout << "Initializing test environment...\n";

    // Create the single Session instance (required – exactly one per process)
    Catch::Session session;

    // Run the test suite and capture the exit code
    int result = session.run( argc, argv );

    // Custom post-test cleanup before exiting
    std::cout << "Tests completed.\n";
    return result;
}

```

In [`src/catch2/catch_session.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_session.hpp), the `run()` method parses the command line via the embedded Clara parser, populates an internal `ConfigData` object, and executes the test suite, returning an exit code that encodes success or specific failure types.

## Controlling Configuration Programmatically

If you need to tweak Catch2's configuration after parsing command-line arguments but before running tests, use `applyCommandLine()` followed by `configData()`. This approach validates CLI arguments first—returning a non-zero error code on failure—then exposes a mutable reference to the configuration structure defined in [`src/catch2/catch_config.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_config.hpp).

```cpp
#include <catch2/catch_session.hpp>

int main( int argc, char* argv[] ) {
    Catch::Session session;

    // Parse arguments manually; returns non-zero on parse errors
    int rc = session.applyCommandLine( argc, argv );
    if ( rc != 0 ) return rc;

    // Programmatically override configuration defaults
    auto& cfg = session.configData();
    cfg.reporter = "compact";          // Force compact reporter
    cfg.useColour = false;             // Disable ANSI colours
    cfg.minRequiredTestCases = 5;      // Example custom validation

    return session.run();
}

```

For complete control, skip `applyCommandLine()` entirely and populate the `ConfigData` structure manually before calling `run()`. The `configData()` method returns a reference to the raw configuration data, while `config()` returns the processed `Config` object used by framework internals during execution.

## Adding Custom Command-Line Options

Catch2 exposes its underlying Clara parser via `session.cli()`, allowing you to compose additional command-line options on top of the framework's defaults. As implemented in [`src/catch2/internal/catch_clara.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/internal/catch_clara.hpp), you can chain new options using the `|` operator and reinstall the extended parser with `session.cli()`.

```cpp
#include <catch2/catch_session.hpp>

int main( int argc, char* argv[] ) {
    Catch::Session session;
    int repetitions = 1;               // Variable to bind a new option

    using namespace Catch::Clara;
    auto cli = session.cli()            // Existing Catch2 parser
               | Opt( repetitions, "n" )
                     ["-r"]["--repeat"] // Short and long flags
                     ("Repeat test run n times");

    session.cli( cli );                // Install the extended parser

    int rc = session.applyCommandLine( argc, argv );
    if ( rc != 0 ) return rc;

    // Use the parsed custom value
    for ( int i = 0; i < repetitions; ++i ) {
        int result = session.run();
        if ( result != 0 ) return result;
    }
    return 0;
}

```

This pattern extends the CLI while maintaining full compatibility with Catch2's native arguments like `--reporter` or `--section`. The Clara library handles the parsing logic, storing values directly into your bound variables while validating types automatically.

## Summary

Implementing a custom main function with Catch2 requires linking against the static `Catch2` library and leveraging the `Catch::Session` API:

- **Instantiate** exactly one `Catch::Session` per process to manage configuration and execution state, as required by the header [`src/catch2/catch_session.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_session.hpp).
- **Parse** command-line arguments explicitly using `applyCommandLine()` to detect errors before testing begins and return appropriate exit codes.
- **Modify** runtime settings via `session.configData()` for programmatic overrides of reporters, filters, or colour settings after CLI parsing.
- **Extend** the CLI by composing new Clara options onto `session.cli()` for application-specific flags, utilizing the definitions in [`src/catch2/internal/catch_clara.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/internal/catch_clara.hpp).
- **Reference** the official documentation in [`docs/own-main.md`](https://github.com/catchorg/Catch2/blob/main/docs/own-main.md) for additional patterns and advanced use cases.

## Frequently Asked Questions

### Why should I implement a custom main function instead of using Catch2WithMain?

Linking against `Catch2WithMain` provides a default `main()` suitable for simple projects, but it prevents programmatic control over configuration and initialization. Implementing a custom main allows you to perform setup or teardown rituals, inject dependencies, and modify `ConfigData` before tests execute, which is essential for integration testing and complex build environments.

### How do I force a specific reporter programmatically without modifying CLI arguments?

After calling `session.applyCommandLine()`, obtain a mutable reference via `session.configData()` and set the `reporter` string member to your desired output format (e.g., `"xml"`, `"compact"`, or `"console"`). Then invoke `session.run()` to execute tests with the overridden configuration, bypassing the need for users to specify the reporter via command line.

### Can I run the test suite multiple times in a single process?

Yes. After constructing a `Catch::Session`, you may call `session.run()` multiple times within a loop. This is useful for stress testing or scenario-based execution where you need to repeat the same test suite with different programmatic configurations. Ensure you reset any necessary global state between runs, as the Session object retains configuration unless explicitly modified via `configData()`.

### Where is the Catch::Session class defined?

`Catch::Session` is defined in [`src/catch2/catch_session.hpp`](https://github.com/catchorg/Catch2/blob/main/src/catch2/catch_session.hpp) within the Catch2 repository. This header declares the `run()`, `applyCommandLine()`, `config()`, and `configData()` methods, along with the `cli()` accessors for parser manipulation. The companion implementation handles the Clara parser integration and `ConfigData` lifecycle management according to the architecture documented in [`docs/own-main.md`](https://github.com/catchorg/Catch2/blob/main/docs/own-main.md).