### Install and Run Project Dependencies Source: https://github.com/ttlequals0/minuspod/blob/main/frontend/README.md Use these npm commands to install dependencies, start the development server, build for production, and run the linter. ```bash npm install ``` ```bash npm run dev ``` ```bash npm run build ``` ```bash npm run lint ``` -------------------------------- ### Clone Repository and Start Container Source: https://github.com/ttlequals0/minuspod/blob/main/docs/DEPLOYMENT.md Follow these steps to clone the repository, set up the environment, and start the application container. ```bash # Clone repository git clone https://github.com/ttlequals0/minuspod.git cd minuspod # Create .env file echo "ANTHROPIC_API_KEY=your-key-here" > .env # Start container docker-compose up -d # View logs docker logs -f minuspod ``` -------------------------------- ### Setup whisper.cpp as a Transcription Server Source: https://context7.com/ttlequals0/minuspod/llms.txt Clones whisper.cpp, downloads a model, and starts it as a separate server for GPU-accelerated transcription. The API base URL should then be set to http://whisper-server:8765/v1. ```bash git clone --depth 1 https://github.com/ggml-org/whisper.cpp bash whisper.cpp/models/download-ggml-model.sh large-v3-turbo mkdir -p models && mv whisper.cpp/models/ggml-large-v3-turbo.bin models/ docker compose -f docker-compose.whisper.yml up -d ``` -------------------------------- ### Configure OpenRouter API Key and Start Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Set up the OpenRouter API key in a .env file and start the service using Docker Compose. ```bash # Create .env echo "OPENROUTER_API_KEY=sk-or-v1-your-key-here" > .env # Start docker compose -f docker-compose.openrouter.yml up -d ``` -------------------------------- ### Add OpenRouter to Existing Setup Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Configure environment variables to use OpenRouter as the LLM provider in an existing setup. ```bash LLM_PROVIDER=openrouter OPENROUTER_API_KEY=sk-or-v1-your-key-here ``` -------------------------------- ### Start whisper.cpp Docker Server Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Starts the whisper.cpp transcription server using Docker Compose. Ensure the docker-compose.whisper.yml file is present in the current directory. ```bash docker compose -f docker-compose.whisper.yml up -d ``` -------------------------------- ### Docker Compose Setup with Ollama Source: https://context7.com/ttlequals0/minuspod/llms.txt Docker Compose setup for MinusPod using a local LLM via Ollama. Requires OPENAI_BASE_URL and OPENAI_MODEL to be configured. ```bash cat > .env << 'EOF' \ LLM_PROVIDER=ollama \ OPENAI_BASE_URL=http://host.docker.internal:11434/v1 \ OPENAI_MODEL=qwen3:14b \ BASE_URL=http://localhost:8000 \ APP_PASSWORD=your-password-here \ EOF ``` -------------------------------- ### Start Claude Code Wrapper Service Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Use this command to start the Claude Code Wrapper service using Docker Compose. Ensure Docker and Docker Compose are installed. ```bash docker compose --profile wrapper up -d ``` -------------------------------- ### Get All Settings Source: https://context7.com/ttlequals0/minuspod/llms.txt Retrieves all current runtime configuration settings. ```APIDOC ## GET /api/v1/settings ### Description Retrieves all current runtime configuration settings, including LLM provider, models, and other parameters. ### Method GET ### Endpoint /api/v1/settings ### Response #### Success Response (200) (No specific response schema provided in source) #### Response Example (No example provided in source) ``` -------------------------------- ### Pushover Webhook Configuration Example Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Example selectors for configuring Pushover to extract data from MinusPod's default JSON payload. Pushover evaluates these selectors on its side. ```text Title | `{{podcast.name}} - {{event}}` Body | `{{episode.title}}`
`{{episode.ads_removed}} ads removed. Saved {{episode.time_saved}}. Cost {{episode.llm_cost_display}}` URL | `{{episode.url}}` URL Title | `Open in MinusPod` ``` -------------------------------- ### Docker Compose Setup with Anthropic Claude Source: https://context7.com/ttlequals0/minuspod/llms.txt Minimal Docker Compose setup for MinusPod using Anthropic Claude for LLM processing. Requires an ANTHROPIC_API_KEY and APP_PASSWORD. ```bash cat > .env << 'EOF' \ ANTHROPIC_API_KEY=sk-ant-your-key \ BASE_URL=http://localhost:8000 \ APP_PASSWORD=your-password-here \ MINUSPOD_MASTER_PASSPHRASE=long-random-string-keep-safe \ EOF mkdir -p data docker-compose up -d ``` -------------------------------- ### Example .env for OpenAI-compatible Mode Source: https://github.com/ttlequals0/minuspod/blob/main/README.md This example shows how to configure Minuspod to use any OpenAI-compatible LLM endpoint, including the Claude Code Wrapper. The AI model itself is selected in the Minuspod Settings UI. ```dotenv # LLM Configuration (OpenAI-compatible) LLM_PROVIDER=openai-compatible OPENAI_BASE_URL=http://claude-wrapper:8000/v1 OPENAI_API_KEY=not-needed # Server Configuration BASE_URL=http://localhost:8000 ``` -------------------------------- ### Get All Current Settings Source: https://context7.com/ttlequals0/minuspod/llms.txt Fetch all current runtime configuration settings for the application. This includes LLM providers, models, and other operational parameters. ```bash curl -b cookies.txt http://localhost:8000/api/v1/settings ``` -------------------------------- ### Authenticate Claude Wrapper Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Run this command to authenticate the Claude wrapper with your Claude account. This is a one-time setup step. ```bash docker compose --profile wrapper run --rm claude-wrapper claude auth login ``` -------------------------------- ### Start Application with Cloudflare Tunnel Source: https://github.com/ttlequals0/minuspod/blob/main/docs/DEPLOYMENT.md Configure and start the application using a Cloudflare Tunnel profile for remote access without port forwarding. Ensure the tunnel token is set in the .env file. ```bash # Set tunnel token in .env TUNNEL_TOKEN=your-cloudflare-tunnel-token # Start with tunnel profile docker-compose --profile tunnel up -d ``` -------------------------------- ### Docker Compose Setup with Remote Whisper API Source: https://context7.com/ttlequals0/minuspod/llms.txt Docker Compose setup for MinusPod using a remote Whisper API for transcription. Requires API keys and base URL for the Whisper service. ```bash cat > .env << 'EOF' \ ANTHROPIC_API_KEY=sk-ant-your-key \ WHISPER_BACKEND=openai-api \ WHISPER_API_BASE_URL=https://api.groq.com/openai/v1 \ WHISPER_API_KEY=gsk_your-groq-key \ WHISPER_API_MODEL=whisper-large-v3-turbo \ WHISPER_DEVICE=cpu \ BASE_URL=http://localhost:8000 \ EOF ``` -------------------------------- ### Get All Model Pricing Rates Source: https://context7.com/ttlequals0/minuspod/llms.txt Retrieves a list of all known model pricing rates. Requires authentication via cookies.txt. ```bash curl -b cookies.txt http://localhost:8000/api/v1/system/model-pricing ``` -------------------------------- ### Configure Audio Analysis Module Source: https://github.com/ttlequals0/minuspod/blob/main/CHANGELOG.md Example of enabling and configuring various audio analysis components via database settings. These settings control loudness, music, and speaker detection. ```json { "audio_analysis_enabled": true, "volume_analysis_enabled": true, "music_detection_enabled": true, "speaker_analysis_enabled": true, "volume_threshold_db": -15.0, "music_confidence_threshold": 0.7, "monologue_duration_threshold": 45.0 } ``` -------------------------------- ### Data Fetching with TanStack Query Source: https://github.com/ttlequals0/minuspod/blob/main/frontend/README.md Example of using TanStack Query's `useQuery` hook for fetching data. Ensure `fetchFeeds` is correctly implemented and imported. ```tsx const { data, isLoading, error } = useQuery({ queryKey: ['feeds'], queryFn: () => fetchFeeds(), staleTime: 30000, // 30 seconds }); ``` -------------------------------- ### Liveness Probe Endpoint Source: https://github.com/ttlequals0/minuspod/blob/main/CHANGELOG.md Defines the GET /api/v1/health/live endpoint for liveness checks. Returns a simple status ok. ```python from flask import Blueprint, jsonify health_bp = Blueprint('health', __name__) @health_bp.route('/health/live', methods=['GET']) def liveness_probe(): """Liveness probe endpoint. Returns 200 OK.""" return jsonify({"status": "ok"}), 200 ``` -------------------------------- ### Set HuggingFace Token in Docker Compose Source: https://github.com/ttlequals0/minuspod/blob/main/CHANGELOG.md Example of how to set the HF_TOKEN environment variable in docker-compose.yml for HuggingFace authentication, required for speaker diarization. ```yaml services: app: build: . environment: - HF_TOKEN=YOUR_HUGGINGFACE_TOKEN_HERE ports: - "8000:8000" volumes: - ./data:/app/data ``` -------------------------------- ### Enable legacy peer dependency resolution in npmrc Source: https://github.com/ttlequals0/minuspod/blob/main/CHANGELOG.md This .npmrc file sets the `legacy-peer-deps` flag to `true`. This is a temporary workaround to allow installations with older versions of `vite-plugin-pwa` that have stricter peer dependency requirements with Vite 8. ```ini legacy-peer-deps=true # Remove this flag once vite-plugin-pwa publishes vite 8 support. ``` -------------------------------- ### System Status Endpoint Source: https://github.com/ttlequals0/minuspod/blob/main/CHANGELOG.md Defines the GET /api/v1/system/status endpoint, reporting system security status including crypto readiness and plaintext secret count. ```python from flask import Blueprint, jsonify, current_app import sqlite3 system_bp = Blueprint('system', __name__) @system_bp.route('/system/status', methods=['GET']) def system_status(): """Returns system status, including security information.""" # Assume db_conn is available, e.g., via current_app context db_conn = current_app.config['DB_CONN'] crypto_ready = check_crypto_readiness(db_conn) # Placeholder for actual check plaintext_count = count_plaintext_secrets(db_conn) # Uses the function defined earlier return jsonify({ "status": "ok", "security": { "cryptoReady": crypto_ready, "plaintextSecretsCount": plaintext_count } }) def check_crypto_readiness(db_conn): # Placeholder implementation return True ``` -------------------------------- ### Get Contaminated Patterns Source: https://github.com/ttlequals0/minuspod/blob/main/CHANGELOG.md Retrieves a list of all active patterns that are contaminated, meaning they contain multiple ad transition phrases. This endpoint is useful for identifying merged multi-sponsor ads that require splitting. ```APIDOC ## GET /patterns/contaminated ### Description This endpoint retrieves all active patterns that contain multiple ad transition phrases, indicating merged multi-sponsor ads that should be split. The response includes pattern IDs, sponsors, text lengths, and transition counts. ### Method GET ### Endpoint /patterns/contaminated ### Response #### Success Response (200) - **pattern_id** (integer) - The unique identifier for the pattern. - **sponsors** (array of strings) - A list of sponsor names associated with the pattern. - **text_length** (integer) - The total length of the pattern's text. - **transition_count** (integer) - The number of ad transition phrases detected within the pattern. ### Response Example { "patterns": [ { "pattern_id": 123, "sponsors": ["Sponsor A", "Sponsor B"], "text_length": 500, "transition_count": 3 }, { "pattern_id": 456, "sponsors": ["Sponsor C", "Sponsor D", "Sponsor E"], "text_length": 750, "transition_count": 5 } ] } ``` -------------------------------- ### Create Environment File and Data Directory Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Sets up the necessary environment variables and creates a data directory for the application. Ensure to replace 'your-key-here' and 'long-random-string-you-will-not-lose' with your actual credentials and passphrase. ```bash cat > .env << EOF ANTHROPIC_API_KEY=your-key-here BASE_URL=http://localhost:8000 APP_PASSWORD=your-password MINUSPOD_MASTER_PASSPHRASE=long-random-string-you-will-not-lose EOF mkdir -p data ``` -------------------------------- ### Tailwind CSS Dark Mode Implementation Source: https://github.com/ttlequals0/minuspod/blob/main/frontend/README.md Example of applying dark mode styles using Tailwind CSS. Ensure dark mode is configured in your Tailwind setup. ```tsx
Content
``` -------------------------------- ### Get Processing Status Source: https://context7.com/ttlequals0/minuspod/llms.txt Performs a one-shot poll to get the current real-time processing status. ```APIDOC ## GET /api/v1/status ### Description Retrieves the current processing status of the system, including whether processing is active, the current episode, stage, progress, and queue depth. ### Method GET ### Endpoint /api/v1/status ### Response #### Success Response (200) - **processing** (boolean) - Indicates if processing is currently active. - **episode** (object | null) - Information about the currently processing episode, or null if none. - **title** (string) - The title of the episode. - **slug** (string) - The slug of the podcast. - **episodeId** (string) - The unique ID of the episode. - **stage** (string | null) - The current processing stage (e.g., "Detecting Ads"). - **progress** (integer) - The percentage of progress for the current stage (0-100). - **queueDepth** (integer) - The number of items waiting in the processing queue. #### Response Example ```json { "processing": true, "episode": { "title": "Ep 42: The Answer", "slug": "my-podcast", "episodeId": "abc123" }, "stage": "Detecting Ads", "progress": 45, "queueDepth": 2 } ``` ``` -------------------------------- ### Build Project for Production Source: https://github.com/ttlequals0/minuspod/blob/main/frontend/README.md Command to initiate the production build process. The output will be placed in the `../static/ui/` directory. ```bash npm run build ``` -------------------------------- ### Build and Run whisper.cpp on Apple Silicon Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Build the whisper.cpp server natively on Apple Silicon and configure MinusPod to connect to it. The WHISPER_API_BASE_URL uses host.docker.internal for Docker-to-host communication. ```bash # Download model git clone --depth 1 https://github.com/ggml-org/whisper.cpp bash whisper.cpp/models/download-ggml-model.sh large-v3-turbo # Build and run the server cd whisper.cpp && make -j ./build/bin/whisper-server \ --host 0.0.0.0 --port 8765 \ --model models/ggml-large-v3-turbo.bin \ --inference-path /v1/audio/transcriptions \ --dtw large.v3.turbo # Configure MinusPod WHISPER_BACKEND=openai-api WHISPER_API_BASE_URL=http://host.docker.internal:8765/v1 WHISPER_DEVICE=cpu ``` -------------------------------- ### Restore from Backup Source: https://github.com/ttlequals0/minuspod/blob/main/docs/DEPLOYMENT.md Restore the application's database from a backup file by stopping the container, copying the backup, and restarting the container. ```bash # Stop container docker-compose stop # Restore database cp data/backups/podcast_YYYYMMDD_HHMMSS.db data/podcast.db # Restart docker-compose start ``` -------------------------------- ### Safe HTTP GET Request Source: https://github.com/ttlequals0/minuspod/blob/main/CHANGELOG.md Python function to perform a safe HTTP GET request with configurable trust tiers and redirect handling. Uses read_response_capped to limit response size. ```python class TrustTier(enum.Enum): OPERATOR_CONFIGURED = 1 FEED_CONTENT = 2 class RedirectContext(enum.Enum): NONE = 0 FOLLOWED = 1 DISALLOWED = 2 def safe_get(url: str, trust_tier: TrustTier, max_bytes: int = 1024 * 1024) -> FetchResult: """Performs a safe GET request to the given URL. Respects trust_tier and limits response size with max_bytes. """ try: with httpx.Client(follow_redirects=True, max_redirects=5) as client: response = client.get(url) response.raise_for_status() # Raise an exception for bad status codes return read_response_capped(response, max_bytes) except httpx.HTTPStatusError as e: # Handle HTTP errors return FetchResult(e.response.status_code, dict(e.response.headers), b'') except httpx.RequestError as e: # Handle request errors (e.g., network issues) return FetchResult(503, {}, f"Request error: {e}".encode()) except ResponseTooLargeError as e: # Handle response too large error return FetchResult(413, {}, str(e).encode()) ``` -------------------------------- ### Import OPML Source: https://context7.com/ttlequals0/minuspod/llms.txt Imports podcast subscriptions from an OPML file. The file is uploaded as form data. Returns counts of imported, skipped, and failed feeds. ```bash curl -b cookies.txt -X POST http://localhost:8000/api/v1/feeds/import-opml \ -H "X-CSRF-Token: $CSRF" \ -F "opml=@/path/to/subscriptions.opml" ``` -------------------------------- ### List Webhooks Source: https://context7.com/ttlequals0/minuspod/llms.txt Lists all configured webhooks. Requires authentication via cookies.txt. ```bash curl -b cookies.txt http://localhost:8000/api/v1/settings/webhooks ``` -------------------------------- ### Get Model Pricing Source: https://context7.com/ttlequals0/minuspod/llms.txt Retrieves the pricing rates for all known LLM models. ```APIDOC ## GET /api/v1/system/model-pricing ### Description Retrieves the current pricing rates for all supported LLM models. ### Method GET ### Endpoint /api/v1/system/model-pricing ### Response Example (Schema not provided in source, but expected to contain model identifiers and their associated costs) ``` -------------------------------- ### Project Structure Overview Source: https://github.com/ttlequals0/minuspod/blob/main/frontend/README.md An overview of the frontend project's directory structure, highlighting key directories like api, components, context, hooks, and pages. ```tree src/ ├── api/ # API client and types │ ├── auth.ts # Authentication endpoints │ ├── client.ts # Base fetch API wrapper │ ├── feeds.ts # Feed/episode endpoints │ ├── history.ts # History endpoints │ ├── patterns.ts # Pattern endpoints │ ├── search.ts # Search endpoints │ ├── settings.ts # Settings endpoints │ ├── sponsors.ts # Sponsor endpoints │ └── types.ts # TypeScript interfaces ├── components/ # Reusable components │ ├── EpisodeList.tsx │ ├── FeedCard.tsx │ ├── FeedListItem.tsx │ ├── GlobalStatusBar.tsx │ ├── Layout.tsx │ ├── LoadingSpinner.tsx │ ├── PatternDetailModal.tsx │ └── AdEditor.tsx ├── context/ # React contexts │ ├── AuthContext.tsx │ └── ThemeContext.tsx ├── hooks/ # Custom hooks │ └── useTranscriptKeyboard.ts ├── pages/ # Route pages │ ├── AddFeed.tsx │ ├── Dashboard.tsx │ ├── EpisodeDetail.tsx │ ├── FeedDetail.tsx │ ├── HistoryPage.tsx │ ├── Login.tsx │ ├── PatternsPage.tsx │ ├── Search.tsx │ └── Settings.tsx ├── App.tsx # Route configuration ├── main.tsx # Entry point └── index.css # Global styles ``` -------------------------------- ### Get Episode Transcript Source: https://context7.com/ttlequals0/minuspod/llms.txt Retrieves the transcript for a specific episode. Requires cookies. ```bash curl -b cookies.txt http://localhost:8000/api/v1/feeds/my-podcast/episodes/abc123/transcript ``` -------------------------------- ### Configure Minuspod to Use Claude Wrapper Source: https://github.com/ttlequals0/minuspod/blob/main/README.md Update your .env file to point Minuspod to the Claude wrapper service. This involves setting the LLM provider and the OpenAI compatible base URL. ```bash LLM_PROVIDER=openai-compatible OPENAI_BASE_URL=http://claude-wrapper:8000/v1 OPENAI_API_KEY=not-needed ``` -------------------------------- ### Get Available LLM Models Source: https://context7.com/ttlequals0/minuspod/llms.txt Retrieves a list of LLM models available from the currently configured provider. ```APIDOC ## GET /api/v1/settings/models ### Description Fetches a list of LLM models that are compatible with the currently configured LLM provider. ### Method GET ### Endpoint /api/v1/settings/models ### Response #### Success Response (200) (No specific response schema provided in source) #### Response Example (No example provided in source) ```