# Security Model for Storing Whisper API Keys in claude-video: External Config and Strict Permissions

> Discover the secure Whisper API key storage model in claude-video. Learn how external config and strict permissions protect your credentials, keeping them out of version control.

- Repository: [bradautomates/claude-video](https://github.com/bradautomates/claude-video)
- Tags: security-best-practices
- Published: 2026-08-05

---

**claude-video stores Whisper API credentials outside version control in a user-specific configuration directory with `0600` permissions, loading them via environment variables or a protected `~/.config/watch/.env` file.**

The `bradautomates/claude-video` repository implements a defense-in-depth approach to protecting sensitive API tokens. By following a "no secrets in source control" principle and utilizing hierarchical configuration precedence, the project ensures that Whisper API keys remain accessible only to the invoking user while supporting multiple backend providers. This article examines the complete security model for storing Whisper API keys in claude-video based on the actual implementation in the Python source files.

## Configuration Directory Architecture

All runtime configuration lives under the user's home directory to ensure portability and security across different development environments.

In [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py) (lines 9–11), the repository defines the configuration path using constants named `CONFIG_DIR` and `CONFIG_FILE`:

```python

# From skills/watch/scripts/config.py

CONFIG_DIR = Path.home() / ".config" / "watch"
CONFIG_FILE = CONFIG_DIR / ".env"

```

This externalizes sensitive data from the project repository, ensuring that `.env` files are never accidentally committed to version control.

## Filesystem Permission Hardening

When the configuration file is first created, the [`setup.py`](https://github.com/bradautomates/claude-video/blob/main/setup.py) script enforces strict access controls. The file is initialized with mode `0600`, granting read and write permissions exclusively to the file owner.

This prevents other users on the same system from reading API credentials, even if they have access to the filesystem. The permission model follows Unix security best practices for sensitive credential storage.

## Hierarchical API Key Loading

The `load_api_key` function in [`skills/watch/scripts/whisper.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/whisper.py) (lines 65–102) implements a three-tier precedence system for discovering API credentials:

1. **Environment variables** – Checks for `GROQ_API_KEY` or `OPENAI_API_KEY` via `os.environ`
2. **User-specific config** – Reads from `~/.config/watch/.env`
3. **Project-local `.env`** – Falls back to `./.env` for reproducible development environments

```python

# Example: Load the Whisper backend and key

from skills.watch.scripts.whisper import load_api_key

backend, api_key = load_api_key()  # Prefers GROQ, falls back to OpenAI

if backend is None:
    raise RuntimeError("No Whisper API key found")
print(f"Using {backend} backend")

```

You can manually scaffold the secure config file using standard Unix commands:

```bash
mkdir -p ~/.config/watch
printf "GROQ_API_KEY=your_groq_key_here\n" > ~/.config/watch/.env
chmod 600 ~/.config/watch/.env

```

## Backend Selection Logic

If both API keys are present in the environment, claude-video prefers the **Groq** backend because it offers lower cost and faster inference. The `load_api_key` function checks for `GROQ_API_KEY` before falling back to `OPENAI_API_KEY`, ensuring optimal performance when both credentials are available.

## Graceful Failure Handling

When no valid key is found, the `transcribe_video` function (lines 29–34 in [`skills/watch/scripts/whisper.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/whisper.py)) aborts execution with a `SystemExit` and provides clear instructions directing the user to set environment variables or edit the user-config file. This prevents the application from running with missing credentials and failing downstream with cryptic API errors.

```python

# The transcribe_video function validates key presence before processing

from skills.watch.scripts.whisper import transcribe_video
from pathlib import Path

segments, used_backend = transcribe_video(
    video_path="example.mp4",
    audio_out=Path("audio.mp3"),
)
print(f"Transcribed with {used_backend}")

```

## Summary

- **External storage**: API keys live in `~/.config/watch/.env`, outside the repository path
- **Strict permissions**: Config files are created with `0600` mode (owner read/write only)
- **No repository secrets**: `.env` files are excluded from version control via `.gitignore`
- **Precedence hierarchy**: Environment variables take priority, followed by user config, then project-local files
- **Backend preference**: Groq is prioritized over OpenAI for cost and speed optimization
- **Clear errors**: Missing credentials trigger immediate `SystemExit` with actionable guidance

## Frequently Asked Questions

### Where does claude-video store Whisper API keys?

The application stores credentials in `~/.config/watch/.env` within the user's home directory, or reads them from environment variables (`GROQ_API_KEY` or `OPENAI_API_KEY`). This location is defined in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py) and ensures secrets remain outside the git repository.

### What file permissions protect the API key storage?

The setup script initializes the configuration file with Unix mode `0600`, meaning only the file owner can read or write the credentials. Other users on the system cannot access the API keys even if they have filesystem access.

### Which API provider takes precedence if both keys are configured?

**Groq** is preferred over OpenAI. The `load_api_key` function checks for `GROQ_API_KEY` first because the Groq backend is cheaper and faster for Whisper transcription tasks. If the Groq key is absent, the function falls back to `OPENAI_API_KEY`.

### What happens if I run claude-video without configuring an API key?

The `transcribe_video` function raises a `SystemExit` with a descriptive error message (implemented at lines 29–34 of [`skills/watch/scripts/whisper.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/whisper.py)). The message directs you to either set environment variables or edit the `~/.config/watch/.env` file, preventing the script from attempting API calls with invalid credentials.