Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,25 @@ Flash requires [Python 3.10+](https://www.python.org/downloads/), and is current

### Authentication

Before you can use Flash, you need to authenticate with your Runpod account:
Before you can use Flash, you need a Runpod API key. The simplest way:

```bash
flash login
```

This saves your API key securely and allows you to use the Flash CLI and run `@Endpoint` functions.
This opens a browser auth flow and saves your key to `~/.runpod/config.toml`.

You can also provide a key via environment variable or `.env` file:

```bash
# Environment variable
export RUNPOD_API_KEY=your_api_key_here

# Or .env file in project root
echo "RUNPOD_API_KEY=your_api_key_here" > .env
```

Flash checks these sources in order: env var, `.env` file, then credentials file. See the [flash login docs](src/runpod_flash/cli/docs/flash-login.md) for details.

### Coding agent integration (optional)

Expand Down
10 changes: 1 addition & 9 deletions src/runpod_flash/cli/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,11 @@ def init_command(

steps_table.add_row(f"{step_num}.", "pip install -r requirements.txt")
step_num += 1
steps_table.add_row(f"{step_num}.", "cp .env.example .env")
step_num += 1
steps_table.add_row(
f"{step_num}.", "Add your RUNPOD_API_KEY to .env (or run flash login)"
)
steps_table.add_row(f"{step_num}.", "flash login")
step_num += 1
steps_table.add_row(f"{step_num}.", "flash run")

console.print(steps_table)

console.print("\n[bold]Get your API key:[/bold]")
console.print(" https://docs.runpod.io/get-started/api-keys")
console.print("\n[bold]Or authenticate with flash:[/bold]")
console.print(" flash login")
console.print("\nVisit http://localhost:8888/docs after running")
console.print("\nCheck out the README.md for more")
6 changes: 5 additions & 1 deletion src/runpod_flash/cli/commands/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
from rich.console import Console

from runpod_flash.core.api.runpod import RunpodGraphQLClient
from runpod_flash.core.credentials import save_api_key
from runpod_flash.core.credentials import (
check_and_migrate_legacy_credentials,
save_api_key,
)
from runpod_flash.core.resources.constants import CONSOLE_BASE_URL

console = Console()
Expand Down Expand Up @@ -55,6 +58,7 @@ async def _login(open_browser: bool, timeout_seconds: float) -> None:
api_key = status_payload.get("apiKey")

if api_key and status in {"APPROVED", "CONSUMED"}:
check_and_migrate_legacy_credentials()
path = save_api_key(api_key)
console.print(
f"[green]Logged in.[/green] Credentials saved to [dim]{path}[/dim]"
Expand Down
8 changes: 6 additions & 2 deletions src/runpod_flash/cli/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ cd my-project
uv sync # or: pip install -r requirements.txt
```

Authenticate with Runpod:
Authenticate with Runpod (saves API key to `~/.runpod/config.toml`):
```bash
flash login
```

Or add your Runpod API key to `.env`:
Alternatively, set your API key via environment variable or `.env` file:
```bash
# Shell environment variable (highest priority)
export RUNPOD_API_KEY=your_api_key_here

# Or .env file in project root (second priority)
echo "RUNPOD_API_KEY=your_api_key_here" > .env
```

Expand Down
118 changes: 118 additions & 0 deletions src/runpod_flash/cli/docs/flash-login.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# flash login

Authenticate with Runpod via browser and save your API key locally.

## Overview

The `flash login` command opens a browser-based authentication flow with Runpod. On approval, your API key is saved to `~/.runpod/config.toml` -- the same credentials file used by runpod-python. This is the recommended way to authenticate for local development.

### When to use this command
- First-time setup after installing Flash
- Switching between Runpod accounts
- Re-authenticating after revoking an API key

## Usage

```bash
flash login [OPTIONS]
```

## Options

- `--force`: Re-authenticate even if valid credentials already exist
- `--no-open`: Print the auth URL instead of opening the browser
- `--timeout`: Maximum wait time in seconds (default: 600)

## Examples

```bash
# Standard login (opens browser)
flash login

# Re-authenticate with a different account
flash login --force

# Login on a headless server (copy URL manually)
flash login --no-open
```

## How It Works

1. Flash creates an auth request and prints a URL
2. You approve the request in your browser at runpod.io
3. Flash polls for approval, then saves the API key to `~/.runpod/config.toml`
4. File permissions are set to `0600` (owner read/write only)

If you already have valid credentials on file, `flash login` detects this and exits early. Use `--force` to bypass this check and re-authenticate.

## Credential Resolution Order

Flash checks for an API key in this order, using the first one found:

| Priority | Source | How to set |
|----------|--------|------------|
| 1 | `RUNPOD_API_KEY` environment variable | `export RUNPOD_API_KEY=your_key` |
| 2 | `RUNPOD_API_KEY` in `.env` file | `echo "RUNPOD_API_KEY=your_key" >> .env` |
| 3 | `~/.runpod/config.toml` credentials file | `flash login` |

The `.env` file is loaded into the environment automatically via `python-dotenv` at startup, so priorities 1 and 2 both resolve through `os.getenv("RUNPOD_API_KEY")`. An explicitly exported shell variable takes precedence over a `.env` value.

### Scope of `flash login`

`flash login` manages **only the credentials file** (priority 3). It does not read or write environment variables or `.env` files. The pre-flight check that detects existing credentials also only checks the file -- if your key comes from an env var or `.env`, `flash login` will not see it and will proceed with the browser flow.

This separation means you can use `flash login` for persistent, machine-wide credentials while still overriding per-project or per-session with env vars.

## Credentials File Format

Flash delegates credential storage to runpod-python. The file uses TOML with a `[default]` profile:

```toml
[default]
api_key = "your_api_key_here"
```

**Location:** `~/.runpod/config.toml` (shared with runpod-python CLI)

This means `runpod config` and `flash login` write to the same file. A key saved by either tool is visible to both.

## Troubleshooting

### "Already logged in" but I want to re-authenticate

```bash
flash login --force
```

### Login works but `flash deploy` says key is missing

Check which source your key is coming from:

```bash
# Is the env var set?
echo $RUNPOD_API_KEY

# Is there a .env file?
cat .env | grep RUNPOD_API_KEY

# Is the credentials file present?
cat ~/.runpod/config.toml
```

If the env var or `.env` has a stale key, it takes precedence over the credentials file. Remove or update it.

### Headless server / SSH session

Use `--no-open` to get a URL you can copy to another machine's browser:

```bash
flash login --no-open
```

### Timeout during login

The default timeout is 10 minutes. Increase it for slow connections:

```bash
flash login --timeout 1200
```
21 changes: 15 additions & 6 deletions src/runpod_flash/cli/utils/skeleton_template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Set up the project:
```bash
uv venv && source .venv/bin/activate
uv sync
cp .env.example .env # Add your RUNPOD_API_KEY
flash login # Authenticate with Runpod
flash run
```

Expand All @@ -24,7 +24,7 @@ Or with pip:
```bash
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # Add your RUNPOD_API_KEY
flash login # Authenticate with Runpod
flash run
```

Expand All @@ -34,9 +34,6 @@ Use `flash run --auto-provision` to pre-deploy all endpoints on startup, elimina

When you stop the server with Ctrl+C, all endpoints provisioned during the session are automatically cleaned up.

Get your API key from [Runpod Settings](https://www.runpod.io/console/user/settings).
Learn more about it from our [Documentation](https://docs.runpod.io/get-started/api-keys).

## Test the API

```bash
Expand Down Expand Up @@ -182,10 +179,22 @@ Pass a CPU instance type string to `cpu=`:

Or use `CpuInstanceType` enum values.

## Authentication

Run `flash login` to authenticate via browser. This stores your API key in `~/.runpod/config.toml`.

Alternatively, set the `RUNPOD_API_KEY` environment variable or add it to `.env`:
```bash
cp .env.example .env # Then edit .env with your key
```

Get your API key from [Runpod Settings](https://www.runpod.io/console/user/settings).
Learn more from our [Documentation](https://docs.runpod.io/get-started/api-keys).

## Environment Variables

```bash
# Required
# Authentication (optional if using flash login)
RUNPOD_API_KEY=your_api_key

# Optional
Expand Down
Loading
Loading