{"owner":"FujiwaraChoki","repo":"MoneyPrinter","hasSkills":true,"totalSkillsCount":3,"totalTokensCount":3685,"categories":["project-spec","root-instruction","claude-rule"],"hasMcp":false,"mcpConfig":null,"found":["docs/architecture.md","AGENTS.md","CLAUDE.md"],"skills":{"docs/architecture.md":"# Architecture\n\nMoneyPrinter now uses a database-backed queue architecture designed for reliability, restart safety, and future scaling.\n\n## Overview\n\n- `Frontend` submits generation requests and polls job status/events.\n- `API (Flask)` validates input and enqueues jobs in Postgres.\n- `Worker` claims queued jobs and runs the generation pipeline.\n- `Postgres` is the source of truth for job state, progress events, and artifacts.\n\n```mermaid\nflowchart LR\n    U[User] --> F[Frontend\\nindex.html + app.js]\n    F -->|POST /api/generate| A[API\\nBackend/main.py]\n    F -->|GET /api/jobs/:id| A\n    F -->|GET /api/jobs/:id/events| A\n    F -->|POST /api/jobs/:id/cancel| A\n\n    A -->|insert job| DB[(Postgres)]\n    A -->|read status/events| DB\n\n    W[Worker\\nBackend/worker.py] -->|claim queued job| DB\n    W -->|write logs/events| DB\n    W -->|update final state| DB\n    W --> P[Pipeline\\nBackend/pipeline.py]\n    P --> FS[(temp/subtitles/output files)]\n```\n\n## Runtime Services (Docker)\n\n```mermaid\nflowchart TB\n    subgraph Compose\n      FE[frontend]\n      API[backend]\n      WK[worker]\n      PG[(postgres)]\n    end\n\n    FE --> API\n    API --> PG\n    WK --> PG\n    WK --> API\n```\n\n## Generation Lifecycle\n\n```mermaid\nstateDiagram-v2\n    [*] --> queued\n    queued --> running: worker claims job\n    queued --> cancelled: cancel before claim\n    running --> completed: success\n    running --> failed: unrecoverable error\n    running --> cancelled: cancellation requested\n    completed --> [*]\n    failed --> [*]\n    cancelled --> [*]\n```\n\n## API + Worker Sequence\n\n```mermaid\nsequenceDiagram\n    participant UI as Frontend\n    participant API as Flask API\n    participant DB as Postgres\n    participant WK as Worker\n    participant PL as Pipeline\n\n    UI->>API: POST /api/generate\n    API->>DB: INSERT generation_jobs(status=queued)\n    API-->>UI: { status: success, jobId }\n\n    loop Polling\n      UI->>API: GET /api/jobs/:id\n      API->>DB: SELECT job\n      API-->>UI: job state\n      UI->>API: GET /api/jobs/:id/events?after=n\n      API->>DB: SELECT events > n\n      API-->>UI: event list\n    end\n\n    WK->>DB: claim queued job\n    WK->>DB: UPDATE status=running + INSERT event\n    WK->>PL: run generation pipeline\n    PL-->>WK: result path OR error\n    WK->>DB: UPDATE status + INSERT terminal event\n\n    UI->>API: POST /api/jobs/:id/cancel\n    API->>DB: set cancel_requested=true\n    WK->>DB: observes cancel and marks cancelled\n```\n\n## Data Model (Current Core)\n\n```mermaid\nerDiagram\n    projects ||--o{ generation_jobs : contains\n    generation_jobs ||--o{ generation_events : has\n    generation_jobs ||--o{ scripts : produces\n    generation_jobs ||--o{ artifacts : produces\n\n    projects {\n      int id PK\n      string name\n      datetime created_at\n    }\n\n    generation_jobs {\n      string id PK\n      int project_id FK\n      string status\n      json payload\n      boolean cancel_requested\n      int attempt_count\n      int max_attempts\n      string result_path\n      text error_message\n      datetime created_at\n      datetime started_at\n      datetime completed_at\n      datetime updated_at\n    }\n\n    generation_events {\n      int id PK\n      string job_id FK\n      string event_type\n      string level\n      text message\n      json payload\n      datetime created_at\n    }\n\n    scripts {\n      int id PK\n      string job_id FK\n      string model_name\n      text content\n      datetime created_at\n    }\n\n    artifacts {\n      int id PK\n      string job_id FK\n      string artifact_type\n      string path\n      json metadata_json\n      datetime created_at\n    }\n```\n\n## Current Guarantees\n\n- API is fast and non-blocking for generation requests.\n- Job state and logs survive API/worker restarts.\n- Cancellation is job-scoped (`cancel_requested`) and checked during processing.\n- Frontend can recover progress after refresh by polling persisted events.\n\n## Planned Next Hardening\n\n- Add migration tool (Alembic) for schema versioning.\n- Add retries/backoff with `next_retry_at` and dead-letter semantics.\n- Add artifact metadata population and checksum tracking.\n- Add worker concurrency controls and queue metrics endpoints.\n","AGENTS.md":"# AGENTS Guide for MoneyPrinter\n\nThis file is the operating manual for coding agents working in this repository.\nFollow it before making changes.\n\n## 1) Repository Layout\n\n- `Backend/`: Flask API, DB-backed job queue, and video generation pipeline.\n- `Frontend/`: static HTML/JS client served by `python -m http.server`.\n- `docs/`: source-of-truth setup and runtime docs.\n- `fonts/`, `Songs/`, `subtitles/`, `temp/`: runtime assets/output folders.\n- Root output artifact: `output.mp4`.\n\n## 2) Source of Truth and Existing Rules\n\n- No `.cursor/rules/` directory found.\n- No `.cursorrules` file found.\n- No `.github/copilot-instructions.md` file found.\n- If any of the above appear later, treat them as higher-priority constraints and update this file.\n\n## 3) Environment and Setup Commands\n\n- Python version: `>=3.11` (from `pyproject.toml`).\n- Dependency manager used in docs: `uv`.\n- Create local env file: `cp .env.example .env`.\n- Install dependencies: `uv sync`.\n- Run backend: `uv run python Backend/main.py`.\n- Run worker (new terminal): `uv run python Backend/worker.py`.\n- Run frontend (new terminal): `python3 -m http.server 3000 --directory Frontend`.\n- Docker workflow: `docker compose up --build`.\n\n## 4) Build, Lint, and Test Commands\n\nThis project has a baseline `pytest` setup for backend repository tests.\nUse the commands below as the expected agent workflow.\n\n### 4.1 Build / Runtime Verification\n\n- Backend syntax check: `uv run python -m compileall Backend`.\n- Frontend syntax sanity (lightweight): open `Frontend/index.html` in browser and run generation flow.\n- API smoke check after backend start: `curl http://localhost:8080/api/models`.\n- Queue smoke check: `curl -X POST http://localhost:8080/api/generate -H \"Content-Type: application/json\" -d '{\"videoSubject\":\"test\",\"voice\":\"en_us_001\",\"paragraphNumber\":1,\"customPrompt\":\"\"}'`.\n- Full local run: backend + worker + frontend servers, then generate a short sample video.\n\n### 4.2 Lint / Formatting (Recommended)\n\n- There is no enforced formatter in-repo today.\n- Follow existing style and keep diffs minimal.\n- If linting is requested, prefer adding tooling in a separate PR.\n- Suggested ad-hoc checks when available locally:\n  - `uv run python -m py_compile Backend/*.py`\n  - `uv run python -m compileall Backend`\n\n### 4.3 Test Commands (Current and Future)\n\n- Run all tests: `uv run pytest`\n- Run one file: `uv run pytest tests/test_file.py`\n- Run a single test: `uv run pytest tests/test_file.py::test_name`\n- Run a single class test: `uv run pytest tests/test_file.py::TestClass::test_name`\n- Current suite location: `tests/`.\n\n## 5) High-Confidence Conventions from Existing Code\n\nThese conventions are inferred from current source and should guide new changes.\n\n### 5.1 Python Imports\n\n- Prefer standard library imports first, then third-party, then local modules.\n- Use one import per line for readability in long modules.\n- Avoid wildcard imports in new code (`from module import *`), even if legacy files use them.\n- Prefer explicit local imports, e.g. `from utils import ENV_FILE, TEMP_DIR`.\n\n### 5.2 Formatting and Structure\n\n- Use 4-space indentation in Python.\n- Keep line length readable; split long calls across multiple lines.\n- Favor small helper functions for distinct pipeline stages.\n- Keep side-effectful startup logic near application boot (`load_dotenv`, env checks).\n\n### 5.3 Typing and Signatures\n\n- Add type hints to all new/modified function signatures.\n- Reuse `Optional`, `List`, `Tuple`, `dict` typing already used in backend.\n- Prefer explicit return types (`-> str`, `-> None`, `-> Tuple[...]`).\n- Use `Path` for filesystem paths where practical.\n\n### 5.4 Naming Conventions\n\n- Python functions/variables: `snake_case`.\n- Constants/env keys: `UPPER_SNAKE_CASE`.\n- JS variables/functions in frontend: `camelCase`.\n- Keep API route names simple and verb-oriented (`/api/generate`, `/api/cancel`).\n\n### 5.5 Error Handling and Logging\n\n- Fail fast on missing critical env vars (current code exits early in startup checks).\n- Catch exceptions at boundary layers (HTTP handlers, external API calls, file IO).\n- Return user-safe JSON error messages from Flask endpoints.\n- Log actionable context with existing logger/log-stream helpers.\n- Do not swallow exceptions silently; at minimum emit error logs.\n\n### 5.6 Filesystem and Path Safety\n\n- Prefer `pathlib.Path` operations.\n- Ensure directories exist before writing (`mkdir(parents=True, exist_ok=True)`).\n- Sanitize uploaded filenames (`os.path.basename`) before save.\n- Avoid hardcoded OS-specific paths; rely on env vars and `Path.resolve()`.\n\n### 5.7 Backend API Patterns\n\n- Keep endpoint payloads consistent with `{\"status\": \"success|error\", ...}`.\n- Use appropriate HTTP status codes for conflict/client errors (e.g., `409`, `400`).\n- Long-running work should run in worker process from DB queue, not on request thread.\n- Preserve cancellation semantics using per-job cancellation and persisted job events.\n\n### 5.8 Frontend Patterns\n\n- Use centralized API helper (`apiRequest`) for backend calls.\n- Validate required fields before firing requests.\n- Keep user feedback explicit via toasts and status area toggles.\n- Preserve localStorage key patterns (`<fieldId>Value`).\n\n## 6) Change Scope Rules for Agents\n\n- Make minimal, targeted edits.\n- Do not rename files/modules unless required by task.\n- Do not introduce new frameworks/toolchains without request.\n- Keep backward compatibility for existing API payload shape when possible.\n- Update docs in `docs/` when setup, env vars, or runtime behavior changes.\n\n## 7) Validation Checklist Before Finishing\n\n- Ran relevant command(s) from section 4.\n- Confirmed backend still starts (`uv run python Backend/main.py`).\n- Confirmed worker still starts (`uv run python Backend/worker.py`).\n- Confirmed frontend still loads (`python3 -m http.server 3000 --directory Frontend`).\n- Verified changed endpoints still return JSON and preserve `status` field.\n- Checked no secrets were added to tracked files.\n\n## 8) Notes for Future Tooling PRs\n\n- Keep tests standardized on `pytest` and document exact paths/selectors here.\n- If adding linting, prefer `ruff` for lint + format and commit config files.\n- If adding type checks, document command and strictness level (`mypy` or equivalent).\n- Keep this file updated whenever workflow commands change.\n\n## 9) Agent Workflow Expectations\n\n- Prefer minimal diffs and preserve current behavior unless the task requires changes.\n- Keep API responses machine-parseable and consistent for frontend consumers.\n- Avoid checking in generated media/output artifacts unless explicitly requested.\n- Before returning work, include what was validated and what was not validated.\n- When adding commands or tooling, update this file and `docs/` together.\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nMoneyPrinter automates YouTube Shorts creation from text topics. It uses Ollama for script generation, TikTok TTS for voiceover, Pexels for stock footage, and moviepy/ImageMagick for video composition. Output: a 9:16 vertical video (`output.mp4`).\n\n## Commands\n\n### Setup\n```bash\ncp .env.example .env        # then fill in API keys\nuv sync                     # install dependencies\nollama serve                # start Ollama (separate terminal)\nollama pull llama3.1:8b     # pull default model\n```\n\n### Run (local)\n```bash\nuv run python Backend/main.py                              # API on :8080\nuv run python Backend/worker.py                            # queue worker\npython3 -m http.server 3000 --directory Frontend           # frontend on :3000\n```\n\n### Run (Docker)\n```bash\ndocker compose up --build   # frontend :8001, backend :8080, postgres :5432\n```\n\n### Verify\n```bash\nuv run python -m compileall Backend          # syntax check\ncurl http://localhost:8080/api/models         # API smoke test\n```\n\n### Tests\nNo test suite exists yet. If added, use pytest:\n```bash\nuv run pytest -q                                           # all tests\nuv run pytest tests/test_file.py::test_name -q             # single test\n```\n\n## Architecture\n\n### Video Generation Pipeline (end-to-end flow)\n\n```\nUser input (Frontend) → POST /api/generate → generation_jobs (Postgres queue)\n  → worker.py claims queued job\n  → gpt.py: generate_script() via Ollama\n  → gpt.py: get_search_terms() → JSON keywords\n  → search.py: Pexels API → download stock clips to temp/\n  → tiktokvoice.py: TTS per sentence → MP3 chunks (threaded)\n  → video.py: generate_subtitles() → .srt (AssemblyAI or local timestamps)\n  → video.py: combine_videos() → concatenate/crop to 9:16\n  → video.py: generate_video() → burn subtitles via ImageMagick, merge audio\n  → (optional) mix background music from Songs/ at 10% volume\n  → (optional) youtube.py: OAuth2 upload\n  → output.mp4\n```\n\n### Frontend ↔ Backend Communication\n- **REST**: JSON payloads to Flask endpoints (`/api/generate`, `/api/jobs/:id`, `/api/jobs/:id/events`, `/api/jobs/:id/cancel`, `/api/models`, `/api/upload-songs`)\n- **Polling**: frontend polls job status and persisted generation events.\n\n### Key Backend Modules\n| File | Responsibility |\n|------|---------------|\n| `main.py` | Flask app and queue/job endpoints |\n| `worker.py` | Job consumer that executes generation pipeline |\n| `db.py`/`models.py`/`repository.py` | DB engine, schema, queue/event persistence |\n| `gpt.py` | Ollama client: script generation, search terms, YouTube metadata |\n| `video.py` | Video processing: combine clips, burn subtitles, merge audio |\n| `search.py` | Pexels stock video search and download |\n| `tiktokvoice.py` | TikTok TTS API (60+ voices, 300-char chunking, threaded) |\n| `youtube.py` | YouTube upload via Google API with OAuth2 |\n| `utils.py` | Path constants, env validation, ImageMagick detection |\n| `pipeline.py` | Reusable generation pipeline used by worker |\n\n### Frontend\n- `index.html`: UI with inline CSS, form fields, live log viewer\n- `app.js`: API client (`apiRequest()`), job polling UI, localStorage persistence\n\n### Runtime Directories\n- `temp/`: intermediate video/audio files (cleared each generation)\n- `subtitles/`: generated .srt files (cleared each generation)\n- `Songs/`: user-uploaded background music MP3s\n- `fonts/`: subtitle font (`bold_font.ttf`)\n\n## Required Environment Variables\n\n- `TIKTOK_SESSION_ID` — TikTok cookie for TTS\n- `PEXELS_API_KEY` — stock video API\n- `IMAGEMAGICK_BINARY` — leave empty to auto-detect from PATH\n\nOptional: `OLLAMA_BASE_URL`, `OLLAMA_MODEL`, `ASSEMBLY_AI_API_KEY`, `DATABASE_URL`\n\n## Conventions\n\n- **Python**: 4-space indent, `snake_case`, type hints on all new/modified signatures, `pathlib.Path` for filesystem ops\n- **JS**: `camelCase`, centralized API calls via `apiRequest()`\n- **API responses**: `{\"status\": \"success|error\", ...}` with proper HTTP codes\n- **Long-running work**: database-backed queue and separate worker process\n- **Concurrency**: multiple jobs can be queued; worker processes them safely via DB locking\n- Update `docs/` when setup, env vars, or runtime behavior changes\n"},"files":{"docs/architecture.md":"# Architecture\n\nMoneyPrinter now uses a database-backed queue architecture designed for reliability, restart safety, and future scaling.\n\n## Overview\n\n- `Frontend` submits generation requests and polls job status/events.\n- `API (Flask)` validates input and enqueues jobs in Postgres.\n- `Worker` claims queued jobs and runs the generation pipeline.\n- `Postgres` is the source of truth for job state, progress events, and artifacts.\n\n```mermaid\nflowchart LR\n    U[User] --> F[Frontend\\nindex.html + app.js]\n    F -->|POST /api/generate| A[API\\nBackend/main.py]\n    F -->|GET /api/jobs/:id| A\n    F -->|GET /api/jobs/:id/events| A\n    F -->|POST /api/jobs/:id/cancel| A\n\n    A -->|insert job| DB[(Postgres)]\n    A -->|read status/events| DB\n\n    W[Worker\\nBackend/worker.py] -->|claim queued job| DB\n    W -->|write logs/events| DB\n    W -->|update final state| DB\n    W --> P[Pipeline\\nBackend/pipeline.py]\n    P --> FS[(temp/subtitles/output files)]\n```\n\n## Runtime Services (Docker)\n\n```mermaid\nflowchart TB\n    subgraph Compose\n      FE[frontend]\n      API[backend]\n      WK[worker]\n      PG[(postgres)]\n    end\n\n    FE --> API\n    API --> PG\n    WK --> PG\n    WK --> API\n```\n\n## Generation Lifecycle\n\n```mermaid\nstateDiagram-v2\n    [*] --> queued\n    queued --> running: worker claims job\n    queued --> cancelled: cancel before claim\n    running --> completed: success\n    running --> failed: unrecoverable error\n    running --> cancelled: cancellation requested\n    completed --> [*]\n    failed --> [*]\n    cancelled --> [*]\n```\n\n## API + Worker Sequence\n\n```mermaid\nsequenceDiagram\n    participant UI as Frontend\n    participant API as Flask API\n    participant DB as Postgres\n    participant WK as Worker\n    participant PL as Pipeline\n\n    UI->>API: POST /api/generate\n    API->>DB: INSERT generation_jobs(status=queued)\n    API-->>UI: { status: success, jobId }\n\n    loop Polling\n      UI->>API: GET /api/jobs/:id\n      API->>DB: SELECT job\n      API-->>UI: job state\n      UI->>API: GET /api/jobs/:id/events?after=n\n      API->>DB: SELECT events > n\n      API-->>UI: event list\n    end\n\n    WK->>DB: claim queued job\n    WK->>DB: UPDATE status=running + INSERT event\n    WK->>PL: run generation pipeline\n    PL-->>WK: result path OR error\n    WK->>DB: UPDATE status + INSERT terminal event\n\n    UI->>API: POST /api/jobs/:id/cancel\n    API->>DB: set cancel_requested=true\n    WK->>DB: observes cancel and marks cancelled\n```\n\n## Data Model (Current Core)\n\n```mermaid\nerDiagram\n    projects ||--o{ generation_jobs : contains\n    generation_jobs ||--o{ generation_events : has\n    generation_jobs ||--o{ scripts : produces\n    generation_jobs ||--o{ artifacts : produces\n\n    projects {\n      int id PK\n      string name\n      datetime created_at\n    }\n\n    generation_jobs {\n      string id PK\n      int project_id FK\n      string status\n      json payload\n      boolean cancel_requested\n      int attempt_count\n      int max_attempts\n      string result_path\n      text error_message\n      datetime created_at\n      datetime started_at\n      datetime completed_at\n      datetime updated_at\n    }\n\n    generation_events {\n      int id PK\n      string job_id FK\n      string event_type\n      string level\n      text message\n      json payload\n      datetime created_at\n    }\n\n    scripts {\n      int id PK\n      string job_id FK\n      string model_name\n      text content\n      datetime created_at\n    }\n\n    artifacts {\n      int id PK\n      string job_id FK\n      string artifact_type\n      string path\n      json metadata_json\n      datetime created_at\n    }\n```\n\n## Current Guarantees\n\n- API is fast and non-blocking for generation requests.\n- Job state and logs survive API/worker restarts.\n- Cancellation is job-scoped (`cancel_requested`) and checked during processing.\n- Frontend can recover progress after refresh by polling persisted events.\n\n## Planned Next Hardening\n\n- Add migration tool (Alembic) for schema versioning.\n- Add retries/backoff with `next_retry_at` and dead-letter semantics.\n- Add artifact metadata population and checksum tracking.\n- Add worker concurrency controls and queue metrics endpoints.\n","AGENTS.md":"# AGENTS Guide for MoneyPrinter\n\nThis file is the operating manual for coding agents working in this repository.\nFollow it before making changes.\n\n## 1) Repository Layout\n\n- `Backend/`: Flask API, DB-backed job queue, and video generation pipeline.\n- `Frontend/`: static HTML/JS client served by `python -m http.server`.\n- `docs/`: source-of-truth setup and runtime docs.\n- `fonts/`, `Songs/`, `subtitles/`, `temp/`: runtime assets/output folders.\n- Root output artifact: `output.mp4`.\n\n## 2) Source of Truth and Existing Rules\n\n- No `.cursor/rules/` directory found.\n- No `.cursorrules` file found.\n- No `.github/copilot-instructions.md` file found.\n- If any of the above appear later, treat them as higher-priority constraints and update this file.\n\n## 3) Environment and Setup Commands\n\n- Python version: `>=3.11` (from `pyproject.toml`).\n- Dependency manager used in docs: `uv`.\n- Create local env file: `cp .env.example .env`.\n- Install dependencies: `uv sync`.\n- Run backend: `uv run python Backend/main.py`.\n- Run worker (new terminal): `uv run python Backend/worker.py`.\n- Run frontend (new terminal): `python3 -m http.server 3000 --directory Frontend`.\n- Docker workflow: `docker compose up --build`.\n\n## 4) Build, Lint, and Test Commands\n\nThis project has a baseline `pytest` setup for backend repository tests.\nUse the commands below as the expected agent workflow.\n\n### 4.1 Build / Runtime Verification\n\n- Backend syntax check: `uv run python -m compileall Backend`.\n- Frontend syntax sanity (lightweight): open `Frontend/index.html` in browser and run generation flow.\n- API smoke check after backend start: `curl http://localhost:8080/api/models`.\n- Queue smoke check: `curl -X POST http://localhost:8080/api/generate -H \"Content-Type: application/json\" -d '{\"videoSubject\":\"test\",\"voice\":\"en_us_001\",\"paragraphNumber\":1,\"customPrompt\":\"\"}'`.\n- Full local run: backend + worker + frontend servers, then generate a short sample video.\n\n### 4.2 Lint / Formatting (Recommended)\n\n- There is no enforced formatter in-repo today.\n- Follow existing style and keep diffs minimal.\n- If linting is requested, prefer adding tooling in a separate PR.\n- Suggested ad-hoc checks when available locally:\n  - `uv run python -m py_compile Backend/*.py`\n  - `uv run python -m compileall Backend`\n\n### 4.3 Test Commands (Current and Future)\n\n- Run all tests: `uv run pytest`\n- Run one file: `uv run pytest tests/test_file.py`\n- Run a single test: `uv run pytest tests/test_file.py::test_name`\n- Run a single class test: `uv run pytest tests/test_file.py::TestClass::test_name`\n- Current suite location: `tests/`.\n\n## 5) High-Confidence Conventions from Existing Code\n\nThese conventions are inferred from current source and should guide new changes.\n\n### 5.1 Python Imports\n\n- Prefer standard library imports first, then third-party, then local modules.\n- Use one import per line for readability in long modules.\n- Avoid wildcard imports in new code (`from module import *`), even if legacy files use them.\n- Prefer explicit local imports, e.g. `from utils import ENV_FILE, TEMP_DIR`.\n\n### 5.2 Formatting and Structure\n\n- Use 4-space indentation in Python.\n- Keep line length readable; split long calls across multiple lines.\n- Favor small helper functions for distinct pipeline stages.\n- Keep side-effectful startup logic near application boot (`load_dotenv`, env checks).\n\n### 5.3 Typing and Signatures\n\n- Add type hints to all new/modified function signatures.\n- Reuse `Optional`, `List`, `Tuple`, `dict` typing already used in backend.\n- Prefer explicit return types (`-> str`, `-> None`, `-> Tuple[...]`).\n- Use `Path` for filesystem paths where practical.\n\n### 5.4 Naming Conventions\n\n- Python functions/variables: `snake_case`.\n- Constants/env keys: `UPPER_SNAKE_CASE`.\n- JS variables/functions in frontend: `camelCase`.\n- Keep API route names simple and verb-oriented (`/api/generate`, `/api/cancel`).\n\n### 5.5 Error Handling and Logging\n\n- Fail fast on missing critical env vars (current code exits early in startup checks).\n- Catch exceptions at boundary layers (HTTP handlers, external API calls, file IO).\n- Return user-safe JSON error messages from Flask endpoints.\n- Log actionable context with existing logger/log-stream helpers.\n- Do not swallow exceptions silently; at minimum emit error logs.\n\n### 5.6 Filesystem and Path Safety\n\n- Prefer `pathlib.Path` operations.\n- Ensure directories exist before writing (`mkdir(parents=True, exist_ok=True)`).\n- Sanitize uploaded filenames (`os.path.basename`) before save.\n- Avoid hardcoded OS-specific paths; rely on env vars and `Path.resolve()`.\n\n### 5.7 Backend API Patterns\n\n- Keep endpoint payloads consistent with `{\"status\": \"success|error\", ...}`.\n- Use appropriate HTTP status codes for conflict/client errors (e.g., `409`, `400`).\n- Long-running work should run in worker process from DB queue, not on request thread.\n- Preserve cancellation semantics using per-job cancellation and persisted job events.\n\n### 5.8 Frontend Patterns\n\n- Use centralized API helper (`apiRequest`) for backend calls.\n- Validate required fields before firing requests.\n- Keep user feedback explicit via toasts and status area toggles.\n- Preserve localStorage key patterns (`<fieldId>Value`).\n\n## 6) Change Scope Rules for Agents\n\n- Make minimal, targeted edits.\n- Do not rename files/modules unless required by task.\n- Do not introduce new frameworks/toolchains without request.\n- Keep backward compatibility for existing API payload shape when possible.\n- Update docs in `docs/` when setup, env vars, or runtime behavior changes.\n\n## 7) Validation Checklist Before Finishing\n\n- Ran relevant command(s) from section 4.\n- Confirmed backend still starts (`uv run python Backend/main.py`).\n- Confirmed worker still starts (`uv run python Backend/worker.py`).\n- Confirmed frontend still loads (`python3 -m http.server 3000 --directory Frontend`).\n- Verified changed endpoints still return JSON and preserve `status` field.\n- Checked no secrets were added to tracked files.\n\n## 8) Notes for Future Tooling PRs\n\n- Keep tests standardized on `pytest` and document exact paths/selectors here.\n- If adding linting, prefer `ruff` for lint + format and commit config files.\n- If adding type checks, document command and strictness level (`mypy` or equivalent).\n- Keep this file updated whenever workflow commands change.\n\n## 9) Agent Workflow Expectations\n\n- Prefer minimal diffs and preserve current behavior unless the task requires changes.\n- Keep API responses machine-parseable and consistent for frontend consumers.\n- Avoid checking in generated media/output artifacts unless explicitly requested.\n- Before returning work, include what was validated and what was not validated.\n- When adding commands or tooling, update this file and `docs/` together.\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nMoneyPrinter automates YouTube Shorts creation from text topics. It uses Ollama for script generation, TikTok TTS for voiceover, Pexels for stock footage, and moviepy/ImageMagick for video composition. Output: a 9:16 vertical video (`output.mp4`).\n\n## Commands\n\n### Setup\n```bash\ncp .env.example .env        # then fill in API keys\nuv sync                     # install dependencies\nollama serve                # start Ollama (separate terminal)\nollama pull llama3.1:8b     # pull default model\n```\n\n### Run (local)\n```bash\nuv run python Backend/main.py                              # API on :8080\nuv run python Backend/worker.py                            # queue worker\npython3 -m http.server 3000 --directory Frontend           # frontend on :3000\n```\n\n### Run (Docker)\n```bash\ndocker compose up --build   # frontend :8001, backend :8080, postgres :5432\n```\n\n### Verify\n```bash\nuv run python -m compileall Backend          # syntax check\ncurl http://localhost:8080/api/models         # API smoke test\n```\n\n### Tests\nNo test suite exists yet. If added, use pytest:\n```bash\nuv run pytest -q                                           # all tests\nuv run pytest tests/test_file.py::test_name -q             # single test\n```\n\n## Architecture\n\n### Video Generation Pipeline (end-to-end flow)\n\n```\nUser input (Frontend) → POST /api/generate → generation_jobs (Postgres queue)\n  → worker.py claims queued job\n  → gpt.py: generate_script() via Ollama\n  → gpt.py: get_search_terms() → JSON keywords\n  → search.py: Pexels API → download stock clips to temp/\n  → tiktokvoice.py: TTS per sentence → MP3 chunks (threaded)\n  → video.py: generate_subtitles() → .srt (AssemblyAI or local timestamps)\n  → video.py: combine_videos() → concatenate/crop to 9:16\n  → video.py: generate_video() → burn subtitles via ImageMagick, merge audio\n  → (optional) mix background music from Songs/ at 10% volume\n  → (optional) youtube.py: OAuth2 upload\n  → output.mp4\n```\n\n### Frontend ↔ Backend Communication\n- **REST**: JSON payloads to Flask endpoints (`/api/generate`, `/api/jobs/:id`, `/api/jobs/:id/events`, `/api/jobs/:id/cancel`, `/api/models`, `/api/upload-songs`)\n- **Polling**: frontend polls job status and persisted generation events.\n\n### Key Backend Modules\n| File | Responsibility |\n|------|---------------|\n| `main.py` | Flask app and queue/job endpoints |\n| `worker.py` | Job consumer that executes generation pipeline |\n| `db.py`/`models.py`/`repository.py` | DB engine, schema, queue/event persistence |\n| `gpt.py` | Ollama client: script generation, search terms, YouTube metadata |\n| `video.py` | Video processing: combine clips, burn subtitles, merge audio |\n| `search.py` | Pexels stock video search and download |\n| `tiktokvoice.py` | TikTok TTS API (60+ voices, 300-char chunking, threaded) |\n| `youtube.py` | YouTube upload via Google API with OAuth2 |\n| `utils.py` | Path constants, env validation, ImageMagick detection |\n| `pipeline.py` | Reusable generation pipeline used by worker |\n\n### Frontend\n- `index.html`: UI with inline CSS, form fields, live log viewer\n- `app.js`: API client (`apiRequest()`), job polling UI, localStorage persistence\n\n### Runtime Directories\n- `temp/`: intermediate video/audio files (cleared each generation)\n- `subtitles/`: generated .srt files (cleared each generation)\n- `Songs/`: user-uploaded background music MP3s\n- `fonts/`: subtitle font (`bold_font.ttf`)\n\n## Required Environment Variables\n\n- `TIKTOK_SESSION_ID` — TikTok cookie for TTS\n- `PEXELS_API_KEY` — stock video API\n- `IMAGEMAGICK_BINARY` — leave empty to auto-detect from PATH\n\nOptional: `OLLAMA_BASE_URL`, `OLLAMA_MODEL`, `ASSEMBLY_AI_API_KEY`, `DATABASE_URL`\n\n## Conventions\n\n- **Python**: 4-space indent, `snake_case`, type hints on all new/modified signatures, `pathlib.Path` for filesystem ops\n- **JS**: `camelCase`, centralized API calls via `apiRequest()`\n- **API responses**: `{\"status\": \"success|error\", ...}` with proper HTTP codes\n- **Long-running work**: database-backed queue and separate worker process\n- **Concurrency**: multiple jobs can be queued; worker processes them safely via DB locking\n- Update `docs/` when setup, env vars, or runtime behavior changes\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/FujiwaraChoki/MoneyPrinter/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS Guide for MoneyPrinter\n\nThis file is the operating manual for coding agents working in this repository.\nFollow it before making changes.\n\n## 1) Repository Layout\n\n- `Backend/`: Flask API, DB-backed job queue, and video generation pipeline.\n- `Frontend/`: static HTML/JS client served by `python -m http.server`.\n- `docs/`: source-of-truth setup and runtime docs.\n- `fonts/`, `Songs/`, `subtitles/`, `temp/`: runtime assets/output folders.\n- Root output artifact: `output.mp4`.\n\n## 2) Source of Truth and Existing Rules\n\n- No `.cursor/rules/` directory found.\n- No `.cursorrules` file found.\n- No `.github/copilot-instructions.md` file found.\n- If any of the above appear later, treat them as higher-priority constraints and update this file.\n\n## 3) Environment and Setup Commands\n\n- Python version: `>=3.11` (from `pyproject.toml`).\n- Dependency manager used in docs: `uv`.\n- Create local env file: `cp .env.example .env`.\n- Install dependencies: `uv sync`.\n- Run backend: `uv run python Backend/main.py`.\n- Run worker (new terminal): `uv run python Backend/worker.py`.\n- Run frontend (new terminal): `python3 -m http.server 3000 --directory Frontend`.\n- Docker workflow: `docker compose up --build`.\n\n## 4) Build, Lint, and Test Commands\n\nThis project has a baseline `pytest` setup for backend repository tests.\nUse the commands below as the expected agent workflow.\n\n### 4.1 Build / Runtime Verification\n\n- Backend syntax check: `uv run python -m compileall Backend`.\n- Frontend syntax sanity (lightweight): open `Frontend/index.html` in browser and run generation flow.\n- API smoke check after backend start: `curl http://localhost:8080/api/models`.\n- Queue smoke check: `curl -X POST http://localhost:8080/api/generate -H \"Content-Type: application/json\" -d '{\"videoSubject\":\"test\",\"voice\":\"en_us_001\",\"paragraphNumber\":1,\"customPrompt\":\"\"}'`.\n- Full local run: backend + worker + frontend servers, then generate a short sample video.\n\n### 4.2 Lint / Formatting (Recommended)\n\n- There is no enforced formatter in-repo today.\n- Follow existing style and keep diffs minimal.\n- If linting is requested, prefer adding tooling in a separate PR.\n- Suggested ad-hoc checks when available locally:\n  - `uv run python -m py_compile Backend/*.py`\n  - `uv run python -m compileall Backend`\n\n### 4.3 Test Commands (Current and Future)\n\n- Run all tests: `uv run pytest`\n- Run one file: `uv run pytest tests/test_file.py`\n- Run a single test: `uv run pytest tests/test_file.py::test_name`\n- Run a single class test: `uv run pytest tests/test_file.py::TestClass::test_name`\n- Current suite location: `tests/`.\n\n## 5) High-Confidence Conventions from Existing Code\n\nThese conventions are inferred from current source and should guide new changes.\n\n### 5.1 Python Imports\n\n- Prefer standard library imports first, then third-party, then local modules.\n- Use one import per line for readability in long modules.\n- Avoid wildcard imports in new code (`from module import *`), even if legacy files use them.\n- Prefer explicit local imports, e.g. `from utils import ENV_FILE, TEMP_DIR`.\n\n### 5.2 Formatting and Structure\n\n- Use 4-space indentation in Python.\n- Keep line length readable; split long calls across multiple lines.\n- Favor small helper functions for distinct pipeline stages.\n- Keep side-effectful startup logic near application boot (`load_dotenv`, env checks).\n\n### 5.3 Typing and Signatures\n\n- Add type hints to all new/modified function signatures.\n- Reuse `Optional`, `List`, `Tuple`, `dict` typing already used in backend.\n- Prefer explicit return types (`-> str`, `-> None`, `-> Tuple[...]`).\n- Use `Path` for filesystem paths where practical.\n\n### 5.4 Naming Conventions\n\n- Python functions/variables: `snake_case`.\n- Constants/env keys: `UPPER_SNAKE_CASE`.\n- JS variables/functions in frontend: `camelCase`.\n- Keep API route names simple and verb-oriented (`/api/generate`, `/api/cancel`).\n\n### 5.5 Error Handling and Logging\n\n- Fail fast on missing critical env vars (current code exits early in startup checks).\n- Catch exceptions at boundary layers (HTTP handlers, external API calls, file IO).\n- Return user-safe JSON error messages from Flask endpoints.\n- Log actionable context with existing logger/log-stream helpers.\n- Do not swallow exceptions silently; at minimum emit error logs.\n\n### 5.6 Filesystem and Path Safety\n\n- Prefer `pathlib.Path` operations.\n- Ensure directories exist before writing (`mkdir(parents=True, exist_ok=True)`).\n- Sanitize uploaded filenames (`os.path.basename`) before save.\n- Avoid hardcoded OS-specific paths; rely on env vars and `Path.resolve()`.\n\n### 5.7 Backend API Patterns\n\n- Keep endpoint payloads consistent with `{\"status\": \"success|error\", ...}`.\n- Use appropriate HTTP status codes for conflict/client errors (e.g., `409`, `400`).\n- Long-running work should run in worker process from DB queue, not on request thread.\n- Preserve cancellation semantics using per-job cancellation and persisted job events.\n\n### 5.8 Frontend Patterns\n\n- Use centralized API helper (`apiRequest`) for backend calls.\n- Validate required fields before firing requests.\n- Keep user feedback explicit via toasts and status area toggles.\n- Preserve localStorage key patterns (`<fieldId>Value`).\n\n## 6) Change Scope Rules for Agents\n\n- Make minimal, targeted edits.\n- Do not rename files/modules unless required by task.\n- Do not introduce new frameworks/toolchains without request.\n- Keep backward compatibility for existing API payload shape when possible.\n- Update docs in `docs/` when setup, env vars, or runtime behavior changes.\n\n## 7) Validation Checklist Before Finishing\n\n- Ran relevant command(s) from section 4.\n- Confirmed backend still starts (`uv run python Backend/main.py`).\n- Confirmed worker still starts (`uv run python Backend/worker.py`).\n- Confirmed frontend still loads (`python3 -m http.server 3000 --directory Frontend`).\n- Verified changed endpoints still return JSON and preserve `status` field.\n- Checked no secrets were added to tracked files.\n\n## 8) Notes for Future Tooling PRs\n\n- Keep tests standardized on `pytest` and document exact paths/selectors here.\n- If adding linting, prefer `ruff` for lint + format and commit config files.\n- If adding type checks, document command and strictness level (`mypy` or equivalent).\n- Keep this file updated whenever workflow commands change.\n\n## 9) Agent Workflow Expectations\n\n- Prefer minimal diffs and preserve current behavior unless the task requires changes.\n- Keep API responses machine-parseable and consistent for frontend consumers.\n- Avoid checking in generated media/output artifacts unless explicitly requested.\n- Before returning work, include what was validated and what was not validated.\n- When adding commands or tooling, update this file and `docs/` together.\n","isInternal":false,"tokens":1558,"sizeBytes":6787},{"name":"architecture.md","path":"docs/architecture.md","rawUrl":"https://raw.githubusercontent.com/FujiwaraChoki/MoneyPrinter/HEAD/docs/architecture.md","title":"docs - System Architecture & Module Boundaries","category":"project-spec","format":"markdown","content":"# Architecture\n\nMoneyPrinter now uses a database-backed queue architecture designed for reliability, restart safety, and future scaling.\n\n## Overview\n\n- `Frontend` submits generation requests and polls job status/events.\n- `API (Flask)` validates input and enqueues jobs in Postgres.\n- `Worker` claims queued jobs and runs the generation pipeline.\n- `Postgres` is the source of truth for job state, progress events, and artifacts.\n\n```mermaid\nflowchart LR\n    U[User] --> F[Frontend\\nindex.html + app.js]\n    F -->|POST /api/generate| A[API\\nBackend/main.py]\n    F -->|GET /api/jobs/:id| A\n    F -->|GET /api/jobs/:id/events| A\n    F -->|POST /api/jobs/:id/cancel| A\n\n    A -->|insert job| DB[(Postgres)]\n    A -->|read status/events| DB\n\n    W[Worker\\nBackend/worker.py] -->|claim queued job| DB\n    W -->|write logs/events| DB\n    W -->|update final state| DB\n    W --> P[Pipeline\\nBackend/pipeline.py]\n    P --> FS[(temp/subtitles/output files)]\n```\n\n## Runtime Services (Docker)\n\n```mermaid\nflowchart TB\n    subgraph Compose\n      FE[frontend]\n      API[backend]\n      WK[worker]\n      PG[(postgres)]\n    end\n\n    FE --> API\n    API --> PG\n    WK --> PG\n    WK --> API\n```\n\n## Generation Lifecycle\n\n```mermaid\nstateDiagram-v2\n    [*] --> queued\n    queued --> running: worker claims job\n    queued --> cancelled: cancel before claim\n    running --> completed: success\n    running --> failed: unrecoverable error\n    running --> cancelled: cancellation requested\n    completed --> [*]\n    failed --> [*]\n    cancelled --> [*]\n```\n\n## API + Worker Sequence\n\n```mermaid\nsequenceDiagram\n    participant UI as Frontend\n    participant API as Flask API\n    participant DB as Postgres\n    participant WK as Worker\n    participant PL as Pipeline\n\n    UI->>API: POST /api/generate\n    API->>DB: INSERT generation_jobs(status=queued)\n    API-->>UI: { status: success, jobId }\n\n    loop Polling\n      UI->>API: GET /api/jobs/:id\n      API->>DB: SELECT job\n      API-->>UI: job state\n      UI->>API: GET /api/jobs/:id/events?after=n\n      API->>DB: SELECT events > n\n      API-->>UI: event list\n    end\n\n    WK->>DB: claim queued job\n    WK->>DB: UPDATE status=running + INSERT event\n    WK->>PL: run generation pipeline\n    PL-->>WK: result path OR error\n    WK->>DB: UPDATE status + INSERT terminal event\n\n    UI->>API: POST /api/jobs/:id/cancel\n    API->>DB: set cancel_requested=true\n    WK->>DB: observes cancel and marks cancelled\n```\n\n## Data Model (Current Core)\n\n```mermaid\nerDiagram\n    projects ||--o{ generation_jobs : contains\n    generation_jobs ||--o{ generation_events : has\n    generation_jobs ||--o{ scripts : produces\n    generation_jobs ||--o{ artifacts : produces\n\n    projects {\n      int id PK\n      string name\n      datetime created_at\n    }\n\n    generation_jobs {\n      string id PK\n      int project_id FK\n      string status\n      json payload\n      boolean cancel_requested\n      int attempt_count\n      int max_attempts\n      string result_path\n      text error_message\n      datetime created_at\n      datetime started_at\n      datetime completed_at\n      datetime updated_at\n    }\n\n    generation_events {\n      int id PK\n      string job_id FK\n      string event_type\n      string level\n      text message\n      json payload\n      datetime created_at\n    }\n\n    scripts {\n      int id PK\n      string job_id FK\n      string model_name\n      text content\n      datetime created_at\n    }\n\n    artifacts {\n      int id PK\n      string job_id FK\n      string artifact_type\n      string path\n      json metadata_json\n      datetime created_at\n    }\n```\n\n## Current Guarantees\n\n- API is fast and non-blocking for generation requests.\n- Job state and logs survive API/worker restarts.\n- Cancellation is job-scoped (`cancel_requested`) and checked during processing.\n- Frontend can recover progress after refresh by polling persisted events.\n\n## Planned Next Hardening\n\n- Add migration tool (Alembic) for schema versioning.\n- Add retries/backoff with `next_retry_at` and dead-letter semantics.\n- Add artifact metadata population and checksum tracking.\n- Add worker concurrency controls and queue metrics endpoints.\n","isInternal":false,"tokens":1036,"sizeBytes":4131},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/FujiwaraChoki/MoneyPrinter/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nMoneyPrinter automates YouTube Shorts creation from text topics. It uses Ollama for script generation, TikTok TTS for voiceover, Pexels for stock footage, and moviepy/ImageMagick for video composition. Output: a 9:16 vertical video (`output.mp4`).\n\n## Commands\n\n### Setup\n```bash\ncp .env.example .env        # then fill in API keys\nuv sync                     # install dependencies\nollama serve                # start Ollama (separate terminal)\nollama pull llama3.1:8b     # pull default model\n```\n\n### Run (local)\n```bash\nuv run python Backend/main.py                              # API on :8080\nuv run python Backend/worker.py                            # queue worker\npython3 -m http.server 3000 --directory Frontend           # frontend on :3000\n```\n\n### Run (Docker)\n```bash\ndocker compose up --build   # frontend :8001, backend :8080, postgres :5432\n```\n\n### Verify\n```bash\nuv run python -m compileall Backend          # syntax check\ncurl http://localhost:8080/api/models         # API smoke test\n```\n\n### Tests\nNo test suite exists yet. If added, use pytest:\n```bash\nuv run pytest -q                                           # all tests\nuv run pytest tests/test_file.py::test_name -q             # single test\n```\n\n## Architecture\n\n### Video Generation Pipeline (end-to-end flow)\n\n```\nUser input (Frontend) → POST /api/generate → generation_jobs (Postgres queue)\n  → worker.py claims queued job\n  → gpt.py: generate_script() via Ollama\n  → gpt.py: get_search_terms() → JSON keywords\n  → search.py: Pexels API → download stock clips to temp/\n  → tiktokvoice.py: TTS per sentence → MP3 chunks (threaded)\n  → video.py: generate_subtitles() → .srt (AssemblyAI or local timestamps)\n  → video.py: combine_videos() → concatenate/crop to 9:16\n  → video.py: generate_video() → burn subtitles via ImageMagick, merge audio\n  → (optional) mix background music from Songs/ at 10% volume\n  → (optional) youtube.py: OAuth2 upload\n  → output.mp4\n```\n\n### Frontend ↔ Backend Communication\n- **REST**: JSON payloads to Flask endpoints (`/api/generate`, `/api/jobs/:id`, `/api/jobs/:id/events`, `/api/jobs/:id/cancel`, `/api/models`, `/api/upload-songs`)\n- **Polling**: frontend polls job status and persisted generation events.\n\n### Key Backend Modules\n| File | Responsibility |\n|------|---------------|\n| `main.py` | Flask app and queue/job endpoints |\n| `worker.py` | Job consumer that executes generation pipeline |\n| `db.py`/`models.py`/`repository.py` | DB engine, schema, queue/event persistence |\n| `gpt.py` | Ollama client: script generation, search terms, YouTube metadata |\n| `video.py` | Video processing: combine clips, burn subtitles, merge audio |\n| `search.py` | Pexels stock video search and download |\n| `tiktokvoice.py` | TikTok TTS API (60+ voices, 300-char chunking, threaded) |\n| `youtube.py` | YouTube upload via Google API with OAuth2 |\n| `utils.py` | Path constants, env validation, ImageMagick detection |\n| `pipeline.py` | Reusable generation pipeline used by worker |\n\n### Frontend\n- `index.html`: UI with inline CSS, form fields, live log viewer\n- `app.js`: API client (`apiRequest()`), job polling UI, localStorage persistence\n\n### Runtime Directories\n- `temp/`: intermediate video/audio files (cleared each generation)\n- `subtitles/`: generated .srt files (cleared each generation)\n- `Songs/`: user-uploaded background music MP3s\n- `fonts/`: subtitle font (`bold_font.ttf`)\n\n## Required Environment Variables\n\n- `TIKTOK_SESSION_ID` — TikTok cookie for TTS\n- `PEXELS_API_KEY` — stock video API\n- `IMAGEMAGICK_BINARY` — leave empty to auto-detect from PATH\n\nOptional: `OLLAMA_BASE_URL`, `OLLAMA_MODEL`, `ASSEMBLY_AI_API_KEY`, `DATABASE_URL`\n\n## Conventions\n\n- **Python**: 4-space indent, `snake_case`, type hints on all new/modified signatures, `pathlib.Path` for filesystem ops\n- **JS**: `camelCase`, centralized API calls via `apiRequest()`\n- **API responses**: `{\"status\": \"success|error\", ...}` with proper HTTP codes\n- **Long-running work**: database-backed queue and separate worker process\n- **Concurrency**: multiple jobs can be queued; worker processes them safely via DB locking\n- Update `docs/` when setup, env vars, or runtime behavior changes\n","isInternal":false,"tokens":1091,"sizeBytes":4359}],"systemPromptSnippet":"<yakaai_skills repo=\"FujiwaraChoki/MoneyPrinter\">\n<!-- File: AGENTS.md (Tokens: ~1558 | Category: root-instruction) -->\n# AGENTS Guide for MoneyPrinter\n\nThis file is the operating manual for coding agents working in this repository.\nFollow it before making changes.\n\n## 1) Repository Layout\n\n- `Backend/`: Flask API, DB-backed job queue, and video generation pipeline.\n- `Frontend/`: static HTML/JS client served by `python -m http.server`.\n- `docs/`: source-of-truth setup and runtime docs.\n- `fonts/`, `Songs/`, `subtitles/`, `temp/`: runtime assets/output folders.\n- Root output artifact: `output.mp4`.\n\n## 2) Source of Truth and Existing Rules\n\n- No `.cursor/rules/` directory found.\n- No `.cursorrules` file found.\n- No `.github/copilot-instructions.md` file found.\n- If any of the above appear later, treat them as higher-priority constraints and update this file.\n\n## 3) Environment and Setup Commands\n\n- Python version: `>=3.11` (from `pyproject.toml`).\n- Dependency manager used in docs: `uv`.\n- Create local env file: `cp .env.example .env`.\n- Install dependencies: `uv sync`.\n- Run backend: `uv run python Backend/main.py`.\n- Run worker (new terminal): `uv run python Backend/worker.py`.\n- Run frontend (new terminal): `python3 -m http.server 3000 --directory Frontend`.\n- Docker workflow: `docker compose up --build`.\n\n## 4) Build, Lint, and Test Commands\n\nThis project has a baseline `pytest` setup for backend repository tests.\nUse the commands below as the expected agent workflow.\n\n### 4.1 Build / Runtime Verification\n\n- Backend syntax check: `uv run python -m compileall Backend`.\n- Frontend syntax sanity (lightweight): open `Frontend/index.html` in browser and run generation flow.\n- API smoke check after backend start: `curl http://localhost:8080/api/models`.\n- Queue smoke check: `curl -X POST http://localhost:8080/api/generate -H \"Content-Type: application/json\" -d '{\"videoSubject\":\"test\",\"voice\":\"en_us_001\",\"paragraphNumber\":1,\"customPrompt\":\"\"}'`.\n- Full local run: backend + worker + frontend servers, then generate a short sample video.\n\n### 4.2 Lint / Formatting (Recommended)\n\n- There is no enforced formatter in-repo today.\n- Follow existing style and keep diffs minimal.\n- If linting is requested, prefer adding tooling in a separate PR.\n- Suggested ad-hoc checks when available locally:\n  - `uv run python -m py_compile Backend/*.py`\n  - `uv run python -m compileall Backend`\n\n### 4.3 Test Commands (Current and Future)\n\n- Run all tests: `uv run pytest`\n- Run one file: `uv run pytest tests/test_file.py`\n- Run a single test: `uv run pytest tests/test_file.py::test_name`\n- Run a single class test: `uv run pytest tests/test_file.py::TestClass::test_name`\n- Current suite location: `tests/`.\n\n## 5) High-Confidence Conventions from Existing Code\n\nThese conventions are inferred from current source and should guide new changes.\n\n### 5.1 Python Imports\n\n- Prefer standard library imports first, then third-party, then local modules.\n- Use one import per line for readability in long modules.\n- Avoid wildcard imports in new code (`from module import *`), even if legacy files use them.\n- Prefer explicit local imports, e.g. `from utils import ENV_FILE, TEMP_DIR`.\n\n### 5.2 Formatting and Structure\n\n- Use 4-space indentation in Python.\n- Keep line length readable; split long calls across multiple lines.\n- Favor small helper functions for distinct pipeline stages.\n- Keep side-effectful startup logic near application boot (`load_dotenv`, env checks).\n\n### 5.3 Typing and Signatures\n\n- Add type hints to all new/modified function signatures.\n- Reuse `Optional`, `List`, `Tuple`, `dict` typing already used in backend.\n- Prefer explicit return types (`-> str`, `-> None`, `-> Tuple[...]`).\n- Use `Path` for filesystem paths where practical.\n\n### 5.4 Naming Conventions\n\n- Python functions/variables: `snake_case`.\n- Constants/env keys: `UPPER_SNAKE_CASE`.\n- JS variables/functions in frontend: `camelCase`.\n- Keep API route names simple and verb-oriented (`/api/generate`, `/api/cancel`).\n\n### 5.5 Error Handling and Logging\n\n- Fail fast on missing critical env vars (current code exits early in startup checks).\n- Catch exceptions at boundary layers (HTTP handlers, external API calls, file IO).\n- Return user-safe JSON error messages from Flask endpoints.\n- Log actionable context with existing logger/log-stream helpers.\n- Do not swallow exceptions silently; at minimum emit error logs.\n\n### 5.6 Filesystem and Path Safety\n\n- Prefer `pathlib.Path` operations.\n- Ensure directories exist before writing (`mkdir(parents=True, exist_ok=True)`).\n- Sanitize uploaded filenames (`os.path.basename`) before save.\n- Avoid hardcoded OS-specific paths; rely on env vars and `Path.resolve()`.\n\n### 5.7 Backend API Patterns\n\n- Keep endpoint payloads consistent with `{\"status\": \"success|error\", ...}`.\n- Use appropriate HTTP status codes for conflict/client errors (e.g., `409`, `400`).\n- Long-running work should run in worker process from DB queue, not on request thread.\n- Preserve cancellation semantics using per-job cancellation and persisted job events.\n\n### 5.8 Frontend Patterns\n\n- Use centralized API helper (`apiRequest`) for backend calls.\n- Validate required fields before firing requests.\n- Keep user feedback explicit via toasts and status area toggles.\n- Preserve localStorage key patterns (`<fieldId>Value`).\n\n## 6) Change Scope Rules for Agents\n\n- Make minimal, targeted edits.\n- Do not rename files/modules unless required by task.\n- Do not introduce new frameworks/toolchains without request.\n- Keep backward compatibility for existing API payload shape when possible.\n- Update docs in `docs/` when setup, env vars, or runtime behavior changes.\n\n## 7) Validation Checklist Before Finishing\n\n- Ran relevant command(s) from section 4.\n- Confirmed backend still starts (`uv run python Backend/main.py`).\n- Confirmed worker still starts (`uv run python Backend/worker.py`).\n- Confirmed frontend still loads (`python3 -m http.server 3000 --directory Frontend`).\n- Verified changed endpoints still return JSON and preserve `status` field.\n- Checked no secrets were added to tracked files.\n\n## 8) Notes for Future Tooling PRs\n\n- Keep tests standardized on `pytest` and document exact paths/selectors here.\n- If adding linting, prefer `ruff` for lint + format and commit config files.\n- If adding type checks, document command and strictness level (`mypy` or equivalent).\n- Keep this file updated whenever workflow commands change.\n\n## 9) Agent Workflow Expectations\n\n- Prefer minimal diffs and preserve current behavior unless the task requires changes.\n- Keep API responses machine-parseable and consistent for frontend consumers.\n- Avoid checking in generated media/output artifacts unless explicitly requested.\n- Before returning work, include what was validated and what was not validated.\n- When adding commands or tooling, update this file and `docs/` together.\n\n<!-- File: docs/architecture.md (Tokens: ~1036 | Category: project-spec) -->\n# Architecture\n\nMoneyPrinter now uses a database-backed queue architecture designed for reliability, restart safety, and future scaling.\n\n## Overview\n\n- `Frontend` submits generation requests and polls job status/events.\n- `API (Flask)` validates input and enqueues jobs in Postgres.\n- `Worker` claims queued jobs and runs the generation pipeline.\n- `Postgres` is the source of truth for job state, progress events, and artifacts.\n\n```mermaid\nflowchart LR\n    U[User] --> F[Frontend\\nindex.html + app.js]\n    F -->|POST /api/generate| A[API\\nBackend/main.py]\n    F -->|GET /api/jobs/:id| A\n    F -->|GET /api/jobs/:id/events| A\n    F -->|POST /api/jobs/:id/cancel| A\n\n    A -->|insert job| DB[(Postgres)]\n    A -->|read status/events| DB\n\n    W[Worker\\nBackend/worker.py] -->|claim queued job| DB\n    W -->|write logs/events| DB\n    W -->|update final state| DB\n    W --> P[Pipeline\\nBackend/pipeline.py]\n    P --> FS[(temp/subtitles/output files)]\n```\n\n## Runtime Services (Docker)\n\n```mermaid\nflowchart TB\n    subgraph Compose\n      FE[frontend]\n      API[backend]\n      WK[worker]\n      PG[(postgres)]\n    end\n\n    FE --> API\n    API --> PG\n    WK --> PG\n    WK --> API\n```\n\n## Generation Lifecycle\n\n```mermaid\nstateDiagram-v2\n    [*] --> queued\n    queued --> running: worker claims job\n    queued --> cancelled: cancel before claim\n    running --> completed: success\n    running --> failed: unrecoverable error\n    running --> cancelled: cancellation requested\n    completed --> [*]\n    failed --> [*]\n    cancelled --> [*]\n```\n\n## API + Worker Sequence\n\n```mermaid\nsequenceDiagram\n    participant UI as Frontend\n    participant API as Flask API\n    participant DB as Postgres\n    participant WK as Worker\n    participant PL as Pipeline\n\n    UI->>API: POST /api/generate\n    API->>DB: INSERT generation_jobs(status=queued)\n    API-->>UI: { status: success, jobId }\n\n    loop Polling\n      UI->>API: GET /api/jobs/:id\n      API->>DB: SELECT job\n      API-->>UI: job state\n      UI->>API: GET /api/jobs/:id/events?after=n\n      API->>DB: SELECT events > n\n      API-->>UI: event list\n    end\n\n    WK->>DB: claim queued job\n    WK->>DB: UPDATE status=running + INSERT event\n    WK->>PL: run generation pipeline\n    PL-->>WK: result path OR error\n    WK->>DB: UPDATE status + INSERT terminal event\n\n    UI->>API: POST /api/jobs/:id/cancel\n    API->>DB: set cancel_requested=true\n    WK->>DB: observes cancel and marks cancelled\n```\n\n## Data Model (Current Core)\n\n```mermaid\nerDiagram\n    projects ||--o{ generation_jobs : contains\n    generation_jobs ||--o{ generation_events : has\n    generation_jobs ||--o{ scripts : produces\n    generation_jobs ||--o{ artifacts : produces\n\n    projects {\n      int id PK\n      string name\n      datetime created_at\n    }\n\n    generation_jobs {\n      string id PK\n      int project_id FK\n      string status\n      json payload\n      boolean cancel_requested\n      int attempt_count\n      int max_attempts\n      string result_path\n      text error_message\n      datetime created_at\n      datetime started_at\n      datetime completed_at\n      datetime updated_at\n    }\n\n    generation_events {\n      int id PK\n      string job_id FK\n      string event_type\n      string level\n      text message\n      json payload\n      datetime created_at\n    }\n\n    scripts {\n      int id PK\n      string job_id FK\n      string model_name\n      text content\n      datetime created_at\n    }\n\n    artifacts {\n      int id PK\n      string job_id FK\n      string artifact_type\n      string path\n      json metadata_json\n      datetime created_at\n    }\n```\n\n## Current Guarantees\n\n- API is fast and non-blocking for generation requests.\n- Job state and logs survive API/worker restarts.\n- Cancellation is job-scoped (`cancel_requested`) and checked during processing.\n- Frontend can recover progress after refresh by polling persisted events.\n\n## Planned Next Hardening\n\n- Add migration tool (Alembic) for schema versioning.\n- Add retries/backoff with `next_retry_at` and dead-letter semantics.\n- Add artifact metadata population and checksum tracking.\n- Add worker concurrency controls and queue metrics endpoints.\n\n<!-- File: CLAUDE.md (Tokens: ~1091 | Category: claude-rule) -->\n# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nMoneyPrinter automates YouTube Shorts creation from text topics. It uses Ollama for script generation, TikTok TTS for voiceover, Pexels for stock footage, and moviepy/ImageMagick for video composition. Output: a 9:16 vertical video (`output.mp4`).\n\n## Commands\n\n### Setup\n```bash\ncp .env.example .env        # then fill in API keys\nuv sync                     # install dependencies\nollama serve                # start Ollama (separate terminal)\nollama pull llama3.1:8b     # pull default model\n```\n\n### Run (local)\n```bash\nuv run python Backend/main.py                              # API on :8080\nuv run python Backend/worker.py                            # queue worker\npython3 -m http.server 3000 --directory Frontend           # frontend on :3000\n```\n\n### Run (Docker)\n```bash\ndocker compose up --build   # frontend :8001, backend :8080, postgres :5432\n```\n\n### Verify\n```bash\nuv run python -m compileall Backend          # syntax check\ncurl http://localhost:8080/api/models         # API smoke test\n```\n\n### Tests\nNo test suite exists yet. If added, use pytest:\n```bash\nuv run pytest -q                                           # all tests\nuv run pytest tests/test_file.py::test_name -q             # single test\n```\n\n## Architecture\n\n### Video Generation Pipeline (end-to-end flow)\n\n```\nUser input (Frontend) → POST /api/generate → generation_jobs (Postgres queue)\n  → worker.py claims queued job\n  → gpt.py: generate_script() via Ollama\n  → gpt.py: get_search_terms() → JSON keywords\n  → search.py: Pexels API → download stock clips to temp/\n  → tiktokvoice.py: TTS per sentence → MP3 chunks (threaded)\n  → video.py: generate_subtitles() → .srt (AssemblyAI or local timestamps)\n  → video.py: combine_videos() → concatenate/crop to 9:16\n  → video.py: generate_video() → burn subtitles via ImageMagick, merge audio\n  → (optional) mix background music from Songs/ at 10% volume\n  → (optional) youtube.py: OAuth2 upload\n  → output.mp4\n```\n\n### Frontend ↔ Backend Communication\n- **REST**: JSON payloads to Flask endpoints (`/api/generate`, `/api/jobs/:id`, `/api/jobs/:id/events`, `/api/jobs/:id/cancel`, `/api/models`, `/api/upload-songs`)\n- **Polling**: frontend polls job status and persisted generation events.\n\n### Key Backend Modules\n| File | Responsibility |\n|------|---------------|\n| `main.py` | Flask app and queue/job endpoints |\n| `worker.py` | Job consumer that executes generation pipeline |\n| `db.py`/`models.py`/`repository.py` | DB engine, schema, queue/event persistence |\n| `gpt.py` | Ollama client: script generation, search terms, YouTube metadata |\n| `video.py` | Video processing: combine clips, burn subtitles, merge audio |\n| `search.py` | Pexels stock video search and download |\n| `tiktokvoice.py` | TikTok TTS API (60+ voices, 300-char chunking, threaded) |\n| `youtube.py` | YouTube upload via Google API with OAuth2 |\n| `utils.py` | Path constants, env validation, ImageMagick detection |\n| `pipeline.py` | Reusable generation pipeline used by worker |\n\n### Frontend\n- `index.html`: UI with inline CSS, form fields, live log viewer\n- `app.js`: API client (`apiRequest()`), job polling UI, localStorage persistence\n\n### Runtime Directories\n- `temp/`: intermediate video/audio files (cleared each generation)\n- `subtitles/`: generated .srt files (cleared each generation)\n- `Songs/`: user-uploaded background music MP3s\n- `fonts/`: subtitle font (`bold_font.ttf`)\n\n## Required Environment Variables\n\n- `TIKTOK_SESSION_ID` — TikTok cookie for TTS\n- `PEXELS_API_KEY` — stock video API\n- `IMAGEMAGICK_BINARY` — leave empty to auto-detect from PATH\n\nOptional: `OLLAMA_BASE_URL`, `OLLAMA_MODEL`, `ASSEMBLY_AI_API_KEY`, `DATABASE_URL`\n\n## Conventions\n\n- **Python**: 4-space indent, `snake_case`, type hints on all new/modified signatures, `pathlib.Path` for filesystem ops\n- **JS**: `camelCase`, centralized API calls via `apiRequest()`\n- **API responses**: `{\"status\": \"success|error\", ...}` with proper HTTP codes\n- **Long-running work**: database-backed queue and separate worker process\n- **Concurrency**: multiple jobs can be queued; worker processes them safely via DB locking\n- Update `docs/` when setup, env vars, or runtime behavior changes\n</yakaai_skills>"}