CLAUDE.md · git:20260327.e1f1dd8 · 2026-03-27 · sha256 1cd5c8e7277d2ad3
CLAUDE.md git:20260327.e1f1dd8A
Immutable. This exact content never changes and is served at /api/v1/blob/1cd5c8e7277d2ad3.
# Flash (runpod-flash)
> Auto-generated by /analyze-repos on 2026-02-22. Manual edits will be overwritten on next analysis.
## Project Overview
runpod-flash (v1.3.0, PyPI: `runpod-flash`, MIT, Python >=3.10 <3.13). Python SDK for distributed inference and serving on RunPod serverless. Provides `@remote` decorator, CLI (`flash init/run/build/deploy`), runtime for serialization, endpoint provisioning, cross-endpoint routing, and load-balanced HTTP serving.
Package: `runpod_flash` (src layout). Key deps: cloudpickle, runpod, pydantic>=2.0, rich>=14.0, typer>=0.12.
## Architecture
### Key Abstractions
1. **ServerlessResource** (`src/runpod_flash/core/resources/serverless.py:93`) -- Base Pydantic model for all serverless endpoint configs. Extends DeployableResource with config hashing, drift detection, deployment lifecycle.
2. **ResourceManager** (`src/runpod_flash/core/resources/resource_manager.py:22`) -- Singleton managing dynamic provisioning, persistence, config drift detection, concurrent deployment locking.
3. **ServiceRegistry** (`src/runpod_flash/runtime/service_registry.py:21`) -- Runtime service discovery for cross-endpoint function routing. Loads `flash_manifest.json`, queries State Manager.
4. **remote() decorator** (`src/runpod_flash/client.py:48`) -- Primary public API. Three modes: stub creation, local execution in deployed env, LB route handler.
5. **stub_resource() singledispatch** (`src/runpod_flash/stubs/registry.py:22`) -- Polymorphic stub factory. Dispatches on resource type to create execution stubs.
### Entry Points
- **CLI**: `src/runpod_flash/cli/main.py:30` (`flash = runpod_flash.cli.main:app`). Commands: `init`, `run`, `build`, `deploy`, `env`, `app`, `undeploy`
- **Module entry**: `src/runpod_flash/cli/main.py:89`
- **Programmatic**: `src/runpod_flash/__init__.py` exports `remote`, `LiveServerless`, etc.
### Module Structure
```
src/runpod_flash/
__init__.py # Package root; lazy imports, dotenv, logging
client.py # @remote decorator (3 modes: stub/local/LB)
config.py # FlashPaths NamedTuple
execute_class.py # RemoteClassWrapper, class serialization
logger.py # SensitiveDataFilter, setup_logging()
cli/ # CLI layer (Typer-based)
main.py # CLI app definition
commands/
init.py # flash init
run.py # flash run (dev server codegen + uvicorn)
build.py # flash build (artifact packaging)
deploy.py # flash deploy (build + upload + provision)
preview.py # flash deploy --preview (Docker Compose)
env.py, apps.py, undeploy.py
_run_server_helpers.py # lb_execute, make_input_model
build_utils/
scanner.py # AST-based @remote detection for API key analysis
manifest.py # flash_manifest.json generation
handler_generator.py, lb_handler_generator.py, resource_config_generator.py
utils/ # app.py, conda.py, deployment.py, formatting.py, ignore.py, skeleton.py
core/ # Core business logic
deployment.py # DeploymentOrchestrator
discovery.py # ResourceDiscovery (AST scanning)
exceptions.py, validation.py
api/runpod.py # RunpodGraphQLClient, RunpodRESTClient (899 lines)
resources/ # All resource types, ResourceManager, GPU/CPU enums, constants
utils/ # backoff, constants, file_lock, http, lru_cache, singleton, user_agent
runtime/ # Deployed runtime (runs inside workers)
service_registry.py # Cross-endpoint routing via manifest
production_wrapper.py # Production handler wrapper
lb_handler.py # Load balancer FastAPI handler
circuit_breaker.py, models.py, config.py, context.py
serialization.py, state_manager_client.py
resource_provisioner.py, retry_manager.py, metrics.py, reliability_config.py
stubs/ # Execution dispatch
registry.py # singledispatch stub factory
live_serverless.py, serverless.py, load_balancer_sls.py, dependency_resolver.py
protos/ # FunctionRequest dataclass, protobuf definitions
```
## Public API Surface
**20 symbols via `__all__`:**
| Symbol | Type | Purpose |
|--------|------|---------|
| `remote` | decorator | Primary API -- marks functions for remote execution |
| `LiveServerless` | resource config | GPU serverless endpoint |
| `CpuLiveServerless` | resource config | CPU serverless endpoint |
| `LiveLoadBalancer` | resource config | GPU load-balanced endpoint |
| `CpuLiveLoadBalancer` | resource config | CPU load-balanced endpoint |
| `LoadBalancerSlsResource` | resource config | LB serverless resource |
| `CpuLoadBalancerSlsResource` | resource config | CPU LB serverless resource |
| `ServerlessEndpoint` | resource config | Serverless endpoint |
| `CpuServerlessEndpoint` | resource config | CPU serverless endpoint |
| `GpuGroup` | enum | GPU type groupings |
| `GpuType` | enum | Specific GPU types |
| `CpuInstanceType` | enum | CPU instance types |
| `CudaVersion` | enum | CUDA version selection |
| `DataCenter` | enum | Data center selection |
| `PodTemplate` | model | Pod template config |
| `NetworkVolume` | model | Network volume config |
| `ServerlessScalerType` | enum | Scaler type selection |
| `ServerlessType` | enum | Serverless type selection |
| `ResourceManager` | singleton | Dynamic provisioning manager |
| `FlashApp` | model | Application definition |
**Key environment variables:** `RUNPOD_API_KEY`, `RUNPOD_API_BASE_URL`, `RUNPOD_REST_API_URL`, `RUNPOD_ENDPOINT_ID`, `RUNPOD_POD_ID`, `FLASH_RESOURCE_NAME`, `FLASH_ENVIRONMENT_ID`, `FLASH_IMAGE_TAG`, `FLASH_GPU_IMAGE`, `FLASH_CPU_IMAGE`, `FLASH_LB_IMAGE`, `FLASH_CPU_LB_IMAGE`, `LOG_LEVEL`, `FLASH_FILE_LOGGING_ENABLED`, `FLASH_CIRCUIT_BREAKER_ENABLED`, `FLASH_LB_STRATEGY`, `FLASH_RETRY_ENABLED`, `CONSOLE_BASE_URL`.
## Cross-Repo Dependencies
### Depends On
- **runpod-python** (`runpod` package) -- `runpod.endpoint.runner.Job` (internal path, fragile), `runpod.api_key` (mutable global), `runpod.endpoint_url_base`. Pinned to git main (unstable).
### Depended On By
- **flash-worker** -- imports `FunctionRequest`/`FunctionResponse` protocol from `runpod_flash.protos`, `ServiceRegistry`, `StateManagerClient`
- **flash-examples** -- all 18 worker files import from `runpod_flash`. High risk: `remote` (all break), `LiveServerless` (9 break), `GpuGroup` (7 break)
### Interface Contracts
- **FunctionRequest/FunctionResponse protocol** (`protos/`) -- shared with flash-worker. Field changes require coordinated releases.
- **@remote decorator signature** (`client.py:48`) -- any parameter changes break all flash-examples files.
- **`_hashed_fields` changes** on resource models break drift detection for deployed endpoints.
- **Manifest schema** (`flash_manifest.json`) -- changes break deployed workers that parse it at runtime.
- **Docker image names** hardcoded in `core/resources/constants.py` -- must match flash-worker Docker Hub tags.
### Dependency Chain
```
flash-examples --> flash (runpod_flash) --> runpod-python (runpod)
flash-worker --> flash (protocols) --> runpod-python (serverless.start)
```
### Known Drift
- Python version: runpod-python supports 3.8+, flash requires 3.10+
- Coverage thresholds: runpod-python 90%, flash 35%, flash-examples none
- runpod pinned to git main instead of stable release
## Development Commands
### Setup
```bash
uv venv && source .venv/bin/activate
uv sync --all-groups
```
### Testing
```bash
make test # All tests
make test-unit # Unit tests only
make test-integration # Integration tests only
make test-coverage # Tests with coverage report
```
### Quality
```bash
make quality-check # REQUIRED BEFORE ALL COMMITS (format + lint + typecheck + tests + coverage)
make quality-check-strict # Stricter threshold
make lint # Ruff linter
make lint-fix # Auto-fix lint issues
make format # Ruff formatter
make format-check # Check formatting
make typecheck # mypy type checking
```
### Build and Deploy
```bash
make build # Build wheel/sdist
make validate-wheel # Validate built packages
make dev # Install in dev mode
```
### Code Intelligence
```bash
make index # Rebuild MCP code intelligence index
make query SYMBOL=name # Query index for a symbol
```
## Code Health
### High Severity
- **20 functions exceed 50 lines.** Worst offenders:
- `_generate_flash_server`: 322 lines (`cli/commands/run.py:268`) -- codegen monolith, needs extraction
- `remote()`: 185 lines (`client.py:48`) -- three modes jammed into one function
- `reconcile_and_provision_resources`: 184 lines -- deployment orchestration
- `install_dependencies`: 179 lines -- build step
- `run_build`: 170 lines -- build orchestration
### Medium Severity
- 6 TODOs without assignee/date (`gpu.py`, `serverless.py`, `app.py`, `network_volume.py`, `runpod.py`)
- `ResourceManager` uses class-level mutable dicts (acceptable for singleton pattern but fragile in tests)
- `runpod` dependency pinned to git main -- no stable release guarantee
### Low Severity
- Commented-out code at `cli/main.py:42` and `logger.py:141` -- delete or restore
- No mutable defaults, no bare except, no raw `print()` -- clean
## Testing
### Structure
- `tests/unit/` -- fast, isolated component tests
- `tests/integration/` -- external dependency tests
- `tests/conftest.py` -- shared fixtures
- Coverage threshold: 35% minimum
### Coverage Gaps
These files have zero or near-zero test coverage:
| File | Lines | Risk |
|------|-------|------|
| `core/api/runpod.py` | 899 | HIGH -- all GraphQL/REST calls untested |
| `config.py` | -- | LOW |
| `core/utils/backoff.py` | -- | MEDIUM -- retry logic |
| `core/utils/lru_cache.py` | -- | LOW |
| `core/utils/singleton.py` | -- | LOW |
| `cli/utils/ignore.py` | -- | LOW |
| `cli/utils/app.py` | -- | LOW |
| `cli/utils/conda.py` | -- | LOW |
| `runtime/metrics.py` | -- | MEDIUM |
| `runtime/api_key_context.py` | -- | MEDIUM -- security path |
### Patterns
- Arrange-Act-Assert in all tests
- Mock external services (RunPod API), trust internal code
- Both `tests/unit/cli/commands/test_run.py` and `tests/unit/cli/test_run.py` test codegen -- update BOTH when changing `_generate_flash_server` output
- Test `_check_makes_remote_calls()` by writing manifest to `Path.cwd() / "flash_manifest.json"`
### Key Testing Gotchas
- `@remote` on classes returns `RemoteClassWrapper` -- `inspect.signature()` gives `*args, **kwargs`, not original params. Fix: use `instance._class_type.method` for the unwrapped signature.
- QB routes only expose `/run_sync` (no `/run`) in dev server
- LB codegen imports both config variable and function: `from module import config_var, func`
## Code Intelligence (MCP)
**Server:** `flash-code-intel`
**Always prefer MCP tools over Grep/Glob for semantic code searches.**
| Tool | Use Case | Example |
|------|----------|---------|
| `find_symbol(symbol)` | Find classes, functions, methods by name | `find_symbol("ResourceManager")` |
| `list_classes()` | Get all classes in codebase | Exploring class hierarchy |
| `get_class_interface(class_name)` | Inspect class methods/properties without reading full file | `get_class_interface("ServerlessResource")` |
| `list_file_symbols(file_path)` | View file structure without reading content | `list_file_symbols("src/runpod_flash/client.py")` |
| `find_by_decorator(decorator)` | Find decorated items | `find_by_decorator("remote")` |
**When to use Grep instead:** Content searches (error messages, string literals, log statements, env var usage).
---
*Last analyzed: 2026-02-22*