Every once in a while, a developer scratches an itch so persistent it turns into something bigger. That’s exactly what CppForge is: a response to the pain of boilerplate, inconsistencies, and the lack of elegant BDD tooling in C++.

CppForge isn’t just another framework. It’s a developer-first, test-driven, and scaffold-powered engine designed to elevate the experience of writing, testing, and maintaining C++ applications.


🧱 Why I Started This

It began with a vision: building my own portable cloud, powered by a cluster of Raspberry Pis — not in a datacenter, but right at home. I wanted services I could control, scale, and take with me. Not just as a personal cloud, but as a resilient, modular system that could one day run anywhere.

To get there, I needed the right tools — tools that understood structure, automation, and developer-first thinking. Most C++ systems lacked that. They were brittle, boilerplate-heavy, and far from portable.

CppForge is my way of changing that — by building a framework that can scaffold services, generate testable modules, and orchestrate clusters with ease. It's not just about better code — it's about creating the backbone for portable, self-sovereign cloud systems.


🔍 What CppForge Solves

  • 🧪 Full BDD support in C++ with scenario-based test generation
  • 🛠 Template-powered scaffolding: libraries, executables, and testable interfaces
  • 💡 Feature-focused development: think in terms of outcomes, not just files

🧬 The Vision

CppForge isn't just for scaffolding or testing — it's laying the groundwork for a developer operating system for C++. Imagine a platform where:

  • You write your use case in plain language
  • The engine scaffolds the entire architecture
  • Tests, interfaces, and integrations are wired in from the start
  • You focus only on what matters: business logic

But a vision is only as powerful as the tools it delivers. So here’s what’s already working — and why it’s changing the game:


🧰 Scaffolding Engine

CppForge can generate fully structured modules — libraries or executables — with just a single scenario description. You define what the system should do, and CppForge builds the folder structure, CMake config, and interface contracts.

Think: monitor.bddmonitor/src, monitor/include, CMakeLists.txt, main.cpp, test stubs — all automatically created.

./agent
├── CMakeLists.txt
├── include
│   ├── agent.hpp
│   └── agent_factory.hpp
├── src
│   ├── agent.cpp
│   └── main.cpp
└── test
    ├── CMakeLists.txt
    ├── test_1_agent_heartbeat_agent_sends_heartbeat.cpp
    ├── test_2_monitor_local_services_docker_is_active.cpp
    ├── test_2_monitor_local_services_k3s_is_inactive.cpp
    ├── test_3_agent_package_reporting_agent_lists_all_packages.cpp
    ├── test_3_agent_package_reporting_agent_lists_simplified_packages.cpp
    ├── test_4_remote_command_execution_execute_shell_command_on_target_node.cpp
    ├── test_4_remote_command_execution_handle_command_timeouts.cpp
    ├── test_4_remote_command_execution_return_execution_result_to_master.cpp
    ├── test_4_remote_command_execution_sanitize_and_validate_incoming_commands.cpp
    └── test_main.cpp

🧪 Scenario-Driven Test Generation

At the heart of CppForge is a test-first mindset. Developers write features in plain English using BDD-style syntax, and CppForge translates them into structured, ready-to-run C++ test scaffolds using Google Test.

This approach bridges the gap between behavioral expectations and actual test code — enforcing structure, encouraging clarity, and ensuring nothing gets implemented without a test.

📜 Example Feature Spec

A developer defines a feature like this:

Feature: Monitor Local Services

  Scenario: Docker is active
    Given Docker is installed
    When the agent checks for running services
    Then Docker should be reported as running

  Scenario: K3s is inactive
    Given k3s is not running
    When the agent checks for running services
    Then it should report k3s as inactive

CppForge then automatically generates a test file with:

  • A virtual interface class representing the scenario
  • A stub implementation that causes the test to fail until implemented
  • A factory method forge_bdd_steps() to swap in the real implementation when ready
  • A runnable Google Test case that exercises the scenario
#include 
#include 
#include 

// Step Interface
class scn_2_monitor_local_services_docker_is_active {
public:
    virtual void given_docker_is_installed() {
        FAIL() << "[STEP NOT IMPLEMENTED] Given Docker is installed";
    }
    virtual void when_the_agent_checks_for_running_services() {
        FAIL() << "[STEP NOT IMPLEMENTED] When the agent checks for running services";
    }
    virtual void then_docker_should_be_reported_as_running() {
        FAIL() << "[STEP NOT IMPLEMENTED] Then Docker should be reported as running";
    }

    virtual ~scn_2_monitor_local_services_docker_is_active() = default;
};

// Stub fallback
class stub_scn_2_monitor_local_services_docker_is_active : public scn_2_monitor_local_services_docker_is_active {};

#ifdef HAS_IMPL_scn_2_monitor_local_services_docker_is_active
std::unique_ptr<scn_2_monitor_local_services_docker_is_active> forge_bdd_steps() {
    return std::make_unique<impl_scn_2_monitor_local_services_docker_is_active>();
}
#else
std::unique_ptr<scn_2_monitor_local_services_docker_is_active> forge_bdd_steps() {
    return std::make_unique<stub_scn_2_monitor_local_services_docker_is_active>();
}
#endif

// Executable scenario
TEST(scn_2_monitor_local_services_docker_is_active_test, executes_scenario) {
    auto steps = forge_bdd_steps();

    std::cout << "[GIVEN] Given Docker is installed" << std::endl;
    steps->given_docker_is_installed();
    std::cout << "[WHEN] When the agent checks for running services" << std::endl;
    steps->when_the_agent_checks_for_running_services();
    std::cout << "[THEN] Then Docker should be reported as running" << std::endl;
    steps->then_docker_should_be_reported_as_running();
}

🧑‍💻 Developer Implementation

Once ready, the developer creates their real implementation:

class impl_scn_2_monitor_local_services_docker_is_active
    : public scn_2_monitor_local_services_docker_is_active {
public:
    void given_docker_is_installed() override {
        // Simulate installation or validate system state
    }

    void when_the_agent_checks_for_running_services() override {
        // Trigger service check logic
    }

    void then_docker_should_be_reported_as_running() override {
        // Assert result or state output
        ASSERT_TRUE(service_report().docker_running);
    }
};

The test now passes — and the developer never has to touch the test runner logic. All they write is the behavior logic in one clean implementation file.


🧠 Smart CMake Integration

Every module, whether it’s an app or a library, is wired into your project’s build system automatically. CppForge knows how to cleanly register, link, and organize CMake targets — even supporting modular test discovery.

You never have to touch CMake unless you want to.


🧱 Composable Interfaces

CppForge creates standard, override-ready interfaces for every generated module. These are designed for testability, extension, and inversion of control. Developers write only the logic; the glue is already there.

Encourages a clean separation between core logic and system boundaries.


🔌 Plugin-Ready Foundation

From the start, the engine is built with plugins in mind — whether for source analysis, metadata extraction, DI, or CI hooks. CppForge is positioning itself as a pluggable, opinionated, developer-focused platform.

Future tools like DI or clustering will simply drop into place.


🧭 Run Configuration Support

Scenarios generate test runners with built-in CLion support — each test can have its own green button, making BDD development visible, trackable, and clickable.

That scenario you defined? It now lives in your IDE’s test runner — no config required.


This is just scratching the surface — we’re building towards something where the developer experience leads the architecture, not the other way around.