How Environment Variables Are Used for API Keys in MoneyPrinterV2: A Complete Guide to GEMINI_API_KEY Configuration
MoneyPrinterV2 implements a dual-source configuration system that checks config.json first and falls back to the GEMINI_API_KEY environment variable when the API key is missing or empty.
The open-source MoneyPrinterV2 repository by FujiwaraChoki manages sensitive credentials like the Gemini (Nanobanana2) API key through a flexible fallback mechanism. This approach allows developers to keep secrets out of version control while maintaining convenience for local development and CI/CD pipelines.
The Dual-Source Configuration Pattern
MoneyPrinterV2 stores non-sensitive configuration in config.json at the repository root. However, for security-critical values like API keys, the application implements a priority-based lookup system:
- Primary Source: The
nanobanana2_api_keyfield inconfig.json - Fallback Source: The
GEMINI_API_KEYenvironment variable
This pattern ensures that if the JSON configuration is empty or omitted, the application can still retrieve the credential from the shell environment.
How GEMINI_API_KEY Fallback Works in src/config.py
The core logic resides in src/config.py within the get_nanobanana2_api_key() function (lines 115-124). This helper reads the local configuration file and implements the environment variable fallback:
# From src/config.py
import json
import os
def get_nanobanana2_api_key():
with open("config.json", "r") as f:
config = json.load(f)
# Priority: config.json value, then GEMINI_API_KEY env var
configured = config.get("nanobanana2_api_key", "")
return configured or os.environ.get("GEMINI_API_KEY", "")
Key implementation details:
- The function uses
os.environ.get()to safely retrieve the environment variable without raising aKeyErrorif unset - The
oroperator ensures that an empty string inconfig.json(falsy) triggers the fallback - If neither source provides a value, the function returns an empty string
Validation and Preflight Checks
Before the main application executes, scripts/preflight_local.py performs sanity checks to ensure the API key is available from either source (lines 85-95):
# From scripts/preflight_local.py
import json
import os
import sys
def validate_api_key():
with open("config.json") as f:
cfg = json.load(f)
api_key = cfg.get("nanobanana2_api_key", "") or os.environ.get("GEMINI_API_KEY", "")
if not api_key:
print("ERROR: Gemini API key not found in config.json or GEMINI_API_KEY environment variable")
sys.exit(1)
return api_key
This validation step prevents runtime failures by ensuring the credential exists before any expensive operations begin.
Consuming the API Key in Provider Classes
Individual service providers retrieve the key through the configuration helper. For example, src/classes/YouTube.py uses the function to access Gemini capabilities for video title generation (lines 331-334):
# From src/classes/YouTube.py
from src.config import get_nanobanana2_api_key
class YouTube:
def generate_title(self, description):
api_key = get_nanobanana2_api_key()
# Use api_key with Gemini client...
This pattern ensures consistent credential management across all modules that interact with the Gemini API.
Configuration Precedence and Security Best Practices
Understanding the precedence rules helps prevent configuration conflicts:
Precedence Order (highest to lowest):
config.jsonvalue (if non-empty)GEMINI_API_KEYenvironment variable- Empty string (application handles as missing)
Security recommendations:
- Never commit
config.jsonwith real API keys to version control - Use
.env.example(provided in the repository root) as a template for required environment variables - Set
GEMINI_API_KEYin CI/CD pipelines via secret management tools rather than storing in repository files - Keep
config.jsonfor non-sensitive settings likeverboseorheadlessmode
Example environment setup:
# Export for current session
export GEMINI_API_KEY="your-actual-api-key-here"
# Or add to .env file (if using python-dotenv)
echo "GEMINI_API_KEY=your-actual-api-key-here" >> .env
Summary
- MoneyPrinterV2 uses a dual-source configuration system where
config.jsontakes precedence over environment variables - The
GEMINI_API_KEYenvironment variable serves as a fallback whennanobanana2_api_keyis empty inconfig.json - Implementation resides in
src/config.pywithin theget_nanobanana2_api_key()function - Validation occurs in
scripts/preflight_local.pyto ensure the key exists before runtime - Consumers like
src/classes/YouTube.pyretrieve the key through the centralized configuration helper
Frequently Asked Questions
What happens if both config.json and GEMINI_API_KEY are set?
If the nanobanana2_api_key field in config.json contains a non-empty string, that value takes precedence and the GEMINI_API_KEY environment variable is ignored. Only when the JSON value is empty or missing does the system check the environment variable.
Is it safe to commit config.json with an empty nanobanana2_api_key field?
Yes, committing config.json with an empty nanobanana2_api_key value (or placeholder text) is safe and recommended. This allows the repository to contain the configuration structure without exposing secrets, while the actual API key can be injected via the GEMINI_API_KEY environment variable during runtime.
How do I set GEMINI_API_KEY for development on Windows?
On Windows Command Prompt, use set GEMINI_API_KEY=your-key-here for the current session, or use setx GEMINI_API_KEY "your-key-here" to persist it across sessions. On Windows PowerShell, use $env:GEMINI_API_KEY="your-key-here". For permanent configuration, set the variable through System Properties > Environment Variables.
Does MoneyPrinterV2 support .env files for loading environment variables?
The repository includes a .env.example file suggesting support for environment variables, but the core configuration system in src/config.py uses os.environ.get() directly. To use .env files, you would need to load them manually using a library like python-dotenv before importing the configuration module, or export the variables in your shell before running the application.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →