# How Configuration is Loaded from config.json in MoneyPrinterV2

> Discover how MoneyPrinterV2 loads runtime settings from config.json on every getter call, enabling real-time configuration updates without restarts. Learn more now.

- Repository: [FujiwaraChoki/MoneyPrinterV2](https://github.com/FujiwaraChoki/MoneyPrinterV2)
- Tags: internals
- Published: 2026-03-20

---

**MoneyPrinterV2 loads runtime settings by reading [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json) from the repository root on every getter call, ensuring real-time configuration updates without application restarts.**

The MoneyPrinterV2 repository centralizes all user-editable settings in a single JSON file. The loading logic resides entirely in [`src/config.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/config.py), which exposes type-safe getter functions that downstream modules import and use. This architecture guarantees that changes to [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json) take effect immediately, as the file is parsed fresh each time a configuration value is requested.

## Configuration Architecture Overview

The configuration system is built around a deterministic path resolution strategy and a stateless loading pattern.

### Project Root Detection

At module initialization, [`src/config.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/config.py) calculates an absolute project root that remains valid regardless of the current working directory. Line 8 establishes the `ROOT_DIR` constant:

```python
ROOT_DIR = os.path.dirname(sys.path[0])

```

This path is then used to construct the absolute location of [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json), ensuring the file is found even when scripts are executed from subdirectories.

### Stateless Loading Pattern

Unlike typical applications that load configuration once at startup, MoneyPrinterV2 implements a **read-on-every-call** strategy. Each getter function opens, parses, and extracts data from [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json) independently. This eliminates the need for configuration reloading mechanisms and guarantees that manual edits to the JSON file are reflected in the next function invocation.

## Step-by-Step Configuration Loading Process

When any module requests a configuration value, the following sequence executes:

1. **Path Construction**: The getter builds the full file path using `os.path.join(ROOT_DIR, "config.json")`.
2. **File Opening**: The JSON file is opened in read mode within a `with` statement to ensure proper resource handling.
3. **JSON Parsing**: `json.load(file)` deserializes the contents into a Python dictionary named `config_json`.
4. **Value Extraction**: The function retrieves the specific key (e.g., `"verbose"`, `"headless"`, `"email"`). Optional defaults are provided via `.get(key, default)` for backward compatibility.
5. **Return**: The extracted value is returned to the caller, and the file handle is automatically closed.

This sequence repeats for every configuration access, as seen in [`src/config.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/config.py) at lines 39-40 for email credentials and lines 42-44 for the verbose flag.

## Key Configuration Getters

The [`src/config.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/config.py) module exposes numerous typed getter functions that isolate the loading logic from business logic.

### Boolean Flags

**`get_verbose()`** and **`get_headless()`** return boolean values controlling debug output and browser visibility:

```python
def get_verbose() -> bool:
    with open(os.path.join(ROOT_DIR, "config.json"), "r") as file:
        config_json = json.load(file)
    return config_json.get("verbose", False)

```

The `headless` configuration, retrieved via `get_headless()` at lines 70-71, determines whether Selenium or Playwright browsers run without a GUI.

### String and Numeric Values

**`get_email()`** returns the sender address for notification systems, while **`get_script_sentence_length()`** (lines 328-339) provides an optional integer limit for text generation:

```python
def get_script_sentence_length() -> int | None:
    with open(os.path.join(ROOT_DIR, "config.json"), "r") as file:
        config_json = json.load(file)
    return config_json.get("script_sentence_length")

```

### First-Run Detection

**`get_first_time_running()`** (lines 18-23) checks for the existence of a hidden `.mp` directory to determine if the application is initializing for the first time, though the directory creation logic resides elsewhere.

## Usage in Downstream Modules

Modules throughout the codebase import specific getters rather than accessing the configuration file directly.

In [`src/main.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/main.py), the verbose flag influences logging behavior at line 213:

```python
from config import get_verbose, get_headless

if get_verbose():
    print("Debug information enabled")

```

Provider classes under `src/classes/`—such as [`YouTube.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/YouTube.py) and [`Twitter.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/Twitter.py)—use these getters to retrieve API credentials and behavior modifiers without hardcoding values.

## Adding Custom Configuration Options

To extend the configuration system, follow the established pattern in [`src/config.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/config.py):

1. **Add the key to [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json)**:
   ```json
   {
     "my_custom_setting": "value"
   }
   ```

2. **Implement a getter function**:
   ```python
   def get_my_custom_setting() -> str:
       with open(os.path.join(ROOT_DIR, "config.json"), "r") as file:
           config_json = json.load(file)
       return config_json.get("my_custom_setting", "default_value")
   ```

3. **Import and use** in application code:
   ```python
   from config import get_my_custom_setting
   setting = get_my_custom_setting()
   ```

This pattern ensures consistency with the existing codebase and maintains the real-time update capability.

## Summary

- **Centralized storage**: All settings reside in [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json) at the repository root.
- **Dynamic loading**: [`src/config.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/config.py) parses the JSON file on every getter invocation, ensuring changes take effect immediately.
- **Path resilience**: `ROOT_DIR` calculation at line 8 guarantees consistent file access regardless of execution context.
- **Typed accessors**: Individual getter functions like `get_verbose()`, `get_headless()`, and `get_script_sentence_length()` provide clean APIs for the rest of the application.
- **Validation helper**: [`scripts/preflight_local.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/scripts/preflight_local.py) verifies that [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json) exists before the application starts.

## Frequently Asked Questions

### Where is the configuration file located in MoneyPrinterV2?

The configuration file is named [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json) and must be placed in the repository root directory. The [`src/config.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/config.py) module calculates the absolute path dynamically using `ROOT_DIR = os.path.dirname(sys.path[0])`, ensuring the file is found even when running scripts from subdirectories.

### Does MoneyPrinterV2 reload configuration without restarting?

Yes. MoneyPrinterV2 does not cache configuration values in memory. Instead, every getter function in [`src/config.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/src/config.py) opens and parses [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json) fresh each time it is called. This design allows users to edit the JSON file while the application is running and see the changes reflected immediately in subsequent operations.

### How does MoneyPrinterV2 handle missing configuration keys?

The getter functions use the dictionary `.get()` method with sensible defaults. For example, `get_verbose()` returns `config_json.get("verbose", False)`, ensuring the application defaults to non-verbose behavior if the key is absent. Optional settings like `script_sentence_length` return `None` when missing, allowing the application to fall back to internal defaults.

### What is the purpose of [`config.example.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.example.json) in the repository?

[`config.example.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.example.json) serves as a template for users to create their own [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json). It contains all available configuration keys with example values. The preflight script [`scripts/preflight_local.py`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/scripts/preflight_local.py) checks for the existence of [`config.json`](https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/main/config.json) at startup and alerts the user if it is missing, directing them to copy the example file.