What Is the Difference Between `runtime-opencode-config-store` and Environment Variable Config Injection?
The runtime-opencode-config-store provides a mutable, SQLite-backed configuration store that applications can read from and write to during execution, while environment variable config injection supplies static, immutable values loaded from process.env when the Node.js process starts.
The different-ai/openwork repository supports two distinct configuration strategies for managing OpenCode settings: a dynamic runtime store for mutable data and static environment variables for deployment-specific secrets. Understanding the architectural differences between these approaches ensures you select the correct method for dynamic provider credentials versus immutable deployment parameters.
Core Architectural Differences
Mutable Runtime Configuration
The runtime-opencode-config-store persists configuration in a lightweight SQLite database located in the runtime's data directory. Implemented in dev/apps/server/src/runtime-opencode-config-store.ts, this module exports readRuntimeOpencodeConfig and writeRuntimeOpencodeConfig functions that enable on-demand configuration updates without requiring process restarts. This approach supports dynamic features such as live plugin installation, real-time provider credential rotation, and user-driven MCP (Model Context Protocol) management.
Static Environment Variable Injection
Environment variable config injection relies on Node.js process.env values captured immediately upon process initialization. These values remain immutable during execution—modifying them requires restarting the process with a new environment. This method is ideal for sensitive secrets like OPENWORK_API_KEY or feature flags that must remain constant throughout the application lifecycle, as referenced in openwork-runtime-config.ts.
Implementation Details in OpenWork
The Runtime Store Module
In dev/apps/server/src/runtime-opencode-config-store.ts, the store implements a read-write interface against SQLite:
import {
readRuntimeOpencodeConfig,
writeRuntimeOpencodeConfig,
} from "./runtime-opencode-config-store.js";
// Example: Adding a new provider at runtime
async function addProvider(name: string, apiKey: string) {
const cfg = await readRuntimeOpencodeConfig();
cfg.providers ??= {};
cfg.providers[name] = { apiKey };
await writeRuntimeOpencodeConfig(cfg);
}
The SQLite file resides in the runtime's data directory, allowing the application to persist changes across sessions while maintaining ACID guarantees for concurrent operations.
Environment Variable Handling
Configuration via environment variables occurs before any OpenWork modules execute. The openwork-runtime-config.ts file handles the initial parsing of process.env values:
// Values loaded at startup from process.env
const apiKey = process.env.OPENWORK_API_KEY!;
const model = process.env.OPENWORK_MODEL ?? "openai/gpt-4";
const logLevel = process.env.OPENWORK_LOG_LEVEL ?? "info";
Since these values are frozen at startup, they provide a secure baseline for constants that should not change during execution, including credentials injected by CI/CD pipelines.
When to Use Each Approach
Use the runtime-opencode-config-store when:
- Configuration must evolve without restarting the server
- Implementing user-facing features like plugin management or dynamic MCP configuration
- Running integration tests that need to inspect or modify configuration state, as demonstrated in
runtime-opencode-config-store.test.ts
Use environment variable config injection when:
- Storing sensitive secrets that should never be writable by the application code itself
- Defining static feature flags or model overrides (
OPENWORK_MODEL_OVERRIDES) - Operating in containerized environments where configuration is determined at deployment time
Practical Code Examples
Dynamic Updates with the Runtime Store
// File: dev/apps/server/src/runtime-opencode-config-store.ts
const cfg = await readRuntimeOpencodeConfig();
cfg.providers.anthropic.apiKey = "sk-new-key";
await writeRuntimeOpencodeConfig(cfg); // Immediately persisted to SQLite
Components like cloud-provider-sync.ts consume this store to synchronize provider credentials dynamically.
Static Configuration via Environment
// In .env file
OPENWORK_API_KEY=abc123
OPENWORK_MODEL=anthropic/claude-v2
// In application bootstrap code
const apiKey = process.env.OPENWORK_API_KEY!;
// Value remains constant for this process lifetime
The end-to-end tests in runtime-config-migrate.e2e.test.ts demonstrate migration patterns from environment-based to runtime-store configuration.
Summary
- Mutability: The runtime store allows dynamic updates via
writeRuntimeOpencodeConfig, while environment variables are immutable after process start - Persistence: Runtime configuration writes to a SQLite database; environment variables exist only in process memory
- Timing: Runtime store reads occur on-demand during execution; environment variables load exactly once at startup
- Use Cases: Use the store for dynamic provider management and plugins; use environment variables for secrets and static deployment configuration
- Key Files: Core implementation resides in
dev/apps/server/src/runtime-opencode-config-store.ts, while environment handling appears inopenwork-runtime-config.ts
Frequently Asked Questions
Can I modify environment variables after the OpenWork server starts?
No. Environment variables are captured when the Node.js process initializes and remain static throughout execution. To change configuration values loaded from process.env, you must restart the server with updated environment variables or migrate to the runtime store pattern shown in runtime-config-migrate.e2e.test.ts.
How does the runtime store handle concurrent writes?
The runtime-opencode-config-store leverages SQLite's built-in concurrency mechanisms to handle simultaneous read and write operations safely. The writeRuntimeOpencodeConfig function ensures atomic updates to the configuration file, preventing data corruption during concurrent access.
Where is the runtime configuration physically stored?
According to the source code in dev/apps/server/src/runtime-opencode-config-store.ts, the runtime store persists data in a SQLite database file located within the runtime's data directory. This ensures configuration survives individual requests but remains scoped to the specific deployment instance.
Should I use environment variables or the runtime store for API keys?
Store sensitive API keys in environment variables for security immutability, but reference them through the runtime store if your application requires dynamic key rotation without restarts. The test suite in runtime-config-global-providers.test.ts demonstrates secure patterns for combining both approaches.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →