# Security Best Practices for API Key Storage and Environment Handling in Claude-Video

> Secure your Claude-Video API keys with robust storage and environment handling. Discover best practices like 0600 permissions and runtime validation to prevent exposure.

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

---

**Claude-Video implements a defense-in-depth strategy for API credentials by enforcing 0600 file permissions, validating access controls at runtime, and prioritizing environment variables over dot-env files to prevent accidental key exposure.**

The `bradautomates/claude-video` repository demonstrates production-grade security patterns for managing sensitive credentials like Groq and OpenAI Whisper API keys. By combining restricted filesystem permissions with runtime validation and environment-first loading patterns, the codebase ensures that secrets remain protected throughout the application lifecycle.

## Defense-in-Depth Architecture for Secret Storage

Claude-Video employs multiple layers of protection to ensure API keys never leak through filesystem access or version control.

### Restricted File Permissions and Isolated Config Locations

The installer in [`skills/watch/scripts/setup.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/setup.py) creates a dedicated configuration directory at `~/.config/watch/` and immediately sets permissions to `0o700` (owner-only access). When scaffolding the `.env` file, it applies mode `0600` (read/write for owner only) through explicit `os.chmod` calls (lines 31-38). This prevents group members or other system users from reading the file, even if they possess filesystem access.

### Empty Placeholder Pattern

Rather than prompting for and writing actual API keys to disk, the installer only creates empty placeholders (`GROQ_API_KEY=` and `OPENAI_API_KEY=`) in the scaffolded file (lines 52-54). This ensures that real credentials never touch the filesystem unless the user explicitly adds them manually, eliminating the risk of accidental commits or logs containing sensitive data.

## Runtime Permission Validation

Before reading any configuration, the `_check_file_permissions` function in [`setup.py`](https://github.com/bradautomates/claude-video/blob/main/setup.py) (lines 73-87) validates that the `.env` file is not world-readable or group-readable. If permissive permissions are detected, the system warns the user immediately, preventing scenarios where secrets might be exposed through misconfigured file sharing or backup processes.

## Environment Variable Precedence

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-73) implements a strict hierarchy: it first checks `os.environ` for `GROQ_API_KEY` or `OPENAI_API_KEY`, and only falls back to the dot-env locations (`~/.config/watch/.env` and a local `.env`) if environment variables are unset. This pattern supports CI/CD pipelines and containerized deployments where injecting secrets via environment variables is standard practice.

## Safe Configuration Parsing

The `read_env_file` function in [`skills/watch/scripts/config.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/config.py) (lines 36-44) safely strips inline comments while preserving `#` characters inside quoted values. This prevents accidental corruption of API keys that might contain hash symbols or base64-encoded strings, ensuring that the parsed configuration exactly matches the user's intent.

## Idempotent Setup and Optional Key Handling

After successful installation, the setup script appends `SETUP_COMPLETE=true` to the `.env` file (lines 42-60) with the same restrictive permissions. This flag enables idempotent behavior, preventing the installer from re-prompting users on subsequent runs while maintaining the security boundary of the configuration file. As documented in the README, these keys remain optional—leaving them blank disables the Whisper integration entirely, allowing users to run the application without storing any third-party credentials.

## Practical Implementation Examples

To load an API key with the environment-first fallback pattern used by the Whisper integration:

```python
from whisper import load_api_key

backend, api_key = load_api_key()          # prefers Groq, falls back to OpenAI

if not api_key:
    raise RuntimeError("No Whisper API key found")

```

To safely read configuration values with proper comment handling:

```python
from config import read_env_file

env = read_env_file()                      # reads ~/.config/watch/.env

detail = env.get("WATCH_DETAIL", "balanced")

```

To manually create a secure configuration file with proper permissions:

```bash
mkdir -p ~/.config/watch
cat > ~/.config/watch/.env <<EOF
GROQ_API_KEY=your-groq-key
OPENAI_API_KEY=your-openai-key
WATCH_DETAIL=balanced
EOF
chmod 600 ~/.config/watch/.env

```

## Summary

- **Create files with mode 0600**: The installer explicitly sets owner-only permissions on `~/.config/watch/.env` during creation.
- **Validate permissions at runtime**: The `_check_file_permissions` function warns if the file is accessible to group or other users.
- **Prefer environment variables**: The `load_api_key` function checks `os.environ` before falling back to dot-env files.
- **Never auto-populate secrets**: The installer only writes empty placeholders, requiring manual user intervention for real keys.
- **Parse comments safely**: The `read_env_file` function handles inline comments without corrupting values containing hash symbols.

## Frequently Asked Questions

### Where does Claude-Video store API keys?

Claude-Video stores API keys in `~/.config/watch/.env` with mode 0600 permissions, ensuring only the file owner can read or write the configuration. According to the source code in [`skills/watch/scripts/setup.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/setup.py), this location is created with explicit `os.chmod` calls to prevent group or other access.

### How does Claude-Video prevent accidental key exposure?

The repository prevents exposure through the **empty placeholder pattern**: the installer never writes user-provided keys to disk, only scaffolding empty variables like `GROQ_API_KEY=`. Combined with runtime permission checks in `_check_file_permissions` and strict file mode 0600, this ensures credentials cannot be leaked through filesystem access or version control.

### Can I use environment variables instead of the .env file?

Yes. The `load_api_key` function in [`skills/watch/scripts/whisper.py`](https://github.com/bradautomates/claude-video/blob/main/skills/watch/scripts/whisper.py) explicitly checks `os.environ` for `GROQ_API_KEY` and `OPENAI_API_KEY` before reading from `~/.config/watch/.env`. This environment-first approach allows secure deployment in containers and CI/CD pipelines without writing secrets to disk.

### What happens if the .env file has insecure permissions?

If the `.env` file is group-readable or world-readable, the `_check_file_permissions` function in [`setup.py`](https://github.com/bradautomates/claude-video/blob/main/setup.py) (lines 73-87) detects the permissive mode and emits a warning before proceeding. This runtime validation acts as a safety net against accidental permission changes or overly permissive umask settings.