Skip to main content
MoneyPrinter V2 includes several helper scripts in the scripts/ directory to streamline setup, validation, and operations. All scripts should be run from the project root directory.

Available Scripts

setup_local.sh

Automated local development bootstrap script that configures your environment for local-first operation. Location: scripts/setup_local.sh Purpose:
  • Creates Python virtual environment if it doesn’t exist
  • Installs/updates all Python dependencies from requirements.txt
  • Copies config.example.json to config.json if not present
  • Auto-detects ImageMagick and Firefox profile paths
  • Configures default local providers (Ollama, Whisper, etc.)
  • Automatically selects the best available Ollama model from your installed models
  • Runs preflight checks to validate setup
Usage:
bash scripts/setup_local.sh
What it does:
  1. Environment Setup: Creates venv/ and installs dependencies
  2. Configuration: Sets sensible defaults in config.json:
    • llm_provider: local_ollama
    • image_provider: local_automatic1111
    • stt_provider: local_whisper
  3. Path Detection: Automatically finds and configures:
    • ImageMagick binary path (magick or convert)
    • Firefox profile directory (macOS-specific detection included)
  4. Model Selection: Queries your local Ollama instance and selects from preferred models:
    • glm-4.7-flash:latest
    • qwen3:14b
    • phi4:latest
    • phi4:14b
    • gpt-oss:20b
    • deepseek-r1:32b
  5. Validation: Runs preflight_local.py to verify everything works
Example Output:
[setup] Root: /path/to/MoneyPrinterV2
[setup] Created config.json from config.example.json
[setup] Created virtual environment at venv/
[setup] Updated config.json
[setup] llm_provider=local_ollama model=phi4:latest
[setup] image_provider=local_automatic1111
[setup] stt_provider=local_whisper
[setup] Running local preflight...

preflight_local.py

Pre-flight validation script that checks your local environment before running automation tasks. Location: scripts/preflight_local.py Purpose:
  • Validates config.json exists and is readable
  • Checks ImageMagick installation (required for subtitle rendering)
  • Verifies Firefox profile path (required for Twitter/YouTube automation)
  • Tests Ollama connectivity and lists available models
  • Validates Nano Banana 2 (Gemini) API configuration
  • Confirms faster-whisper installation for local STT
Usage:
python3 scripts/preflight_local.py
Exit Codes:
  • 0: All checks passed
  • 1: One or more blocking issues detected
Sample Output:
[OK] stt_provider=local_whisper
[OK] imagemagick_path exists: /usr/local/bin/magick
[OK] firefox_profile exists: /Users/user/Library/Application Support/Firefox/Profiles/abc.default-release
[OK] Ollama reachable at http://127.0.0.1:11434
[OK] Ollama models available: phi4:latest, llama3.2:3b
[OK] nanobanana2_api_key is set
[OK] Nano Banana 2 base URL reachable: https://generativelanguage.googleapis.com/v1beta
[OK] faster-whisper is installed

Preflight passed. Local setup looks ready.
Common Warnings:
Issue: ImageMagick path not configured in config.jsonImpact: Subtitle rendering in videos will failFix: Install ImageMagick and set the path in config.json:
{
  "imagemagick_path": "/usr/local/bin/magick"
}
Issue: Firefox profile path not configuredImpact: Twitter and YouTube automation features will not workFix: Set your Firefox profile path in config.json. See troubleshooting guide.
Issue: Ollama is running but has no models installedImpact: LLM-based text generation will failFix: Pull a model:
ollama pull llama3.2:3b

upload_video.sh

Interactive script for uploading generated videos to YouTube Shorts. Location: scripts/upload_video.sh Purpose:
  • Lists all configured YouTube accounts from .mp/youtube.json
  • Prompts user to select an account
  • Triggers video generation and upload via src/cron.py
Usage:
bash scripts/upload_video.sh
Prerequisites:
  • YouTube account configured in .mp/youtube.json
  • Firefox profile with logged-in YouTube session
  • Generated video content (or will generate new content)
Interactive Flow:
What account do you want to upload the video to?
account-uuid-1
account-uuid-2
Enter the id: account-uuid-1
ID found
[Running video generation and upload...]
How it works:
  1. Reads .mp/youtube.json to get configured accounts
  2. Displays account IDs
  3. Validates user selection
  4. Executes: python src/cron.py youtube <account_id>
Account Configuration: Your .mp/youtube.json should look like:
{
  "accounts": [
    {
      "id": "account-uuid-1",
      "nickname": "My Channel",
      "niche": "Technology",
      "language": "English",
      "videos": []
    }
  ]
}

Script Best Practices

Running Scripts

Always run scripts from the project root:
# ✅ Correct
bash scripts/setup_local.sh

# ❌ Incorrect
cd scripts
bash setup_local.sh

Script Permissions

Ensure scripts are executable:
chmod +x scripts/*.sh
chmod +x scripts/*.py

Environment Activation

Some scripts expect an activated virtual environment:
source venv/bin/activate  # Unix/macOS
.\venv\Scripts\activate   # Windows

python3 scripts/preflight_local.py

Debugging Scripts

Enable verbose output in config.json:
{
  "verbose": true
}
This provides detailed logging from all scripts and the main application.

Creating Custom Scripts

You can create your own scripts in the scripts/ directory. Follow these guidelines: Shell Script Template:
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}").." && pwd)"
cd "$ROOT_DIR"

PYTHON_BIN="${ROOT_DIR}/venv/bin/python"

# Your script logic here
"$PYTHON_BIN" src/your_module.py
Python Script Template:
#!/usr/bin/env python3
import os
import sys

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(ROOT_DIR, "src"))

# Import MoneyPrinter modules
from config import get_verbose
from status import info, success, error

def main():
    # Your script logic
    pass

if __name__ == "__main__":
    sys.exit(main())
Key Points:
  • Calculate ROOT_DIR relative to script location
  • Use the virtual environment Python binary
  • Return appropriate exit codes (0 = success, 1 = failure)
  • Follow existing naming conventions

Build docs developers (and LLMs) love