How the Dream CLI Switches Between Local and Cloud AI Models
The Dream CLI switches between local and cloud AI models by persisting the MODEL_PROVIDER variable to a .env file and dynamically regenerating the Docker Compose stack to either initialize local GPU containers or deploy a cloud-proxy service.
The Dream CLI is the Bash-based command-line interface for the Light-Heart-Labs/DreamServer project. It enables seamless switching between self-hosted local models running on your own hardware and external cloud providers through a three-layer architecture involving environment configuration, compose-stack generation, and runtime flags.
Architecture Overview
The CLI orchestrates model switching through three tightly coupled layers that work together to reconfigure the entire stack. When you change the model provider, the system validates the configuration, updates the environment file, and rebuilds the container orchestration to match the selected backend.
Environment Configuration Layer
The foundation of model switching resides in the .env file located at dream-server/.env.example. This file stores the critical configuration keys that determine runtime behavior:
MODEL_PROVIDER: Sets the active mode tolocalorcloudLLM_URL: Specifies the endpoint URL for cloud connectionsGPU_BACKEND: Declares the hardware acceleration type (AMD, NVIDIA, or Apple)CLOUD_FALLBACK: Enables automatic fallback to cloud when local resources are unavailable
The CLI loads these values on startup (lines 28-33 of dream-server/dream-cli) and exposes helper functions to manipulate them. The _env_set function writes key-value pairs to the environment file, while _env_get_raw retrieves current settings without default fallbacks.
Dynamic Compose-Stack Generation
The scripts/resolve-compose-stack.sh script acts as the orchestration engine that translates environment variables into running containers. This script evaluates the MODEL_PROVIDER value and conditionally assembles the Docker Compose configuration.
When MODEL_PROVIDER=local, the resolver merges docker-compose.base.yml with GPU-specific overlays such as docker-compose.amd.yml or docker-compose.nvidia.yml. When MODEL_PROVIDER=cloud, the script appends docker-compose.cloud-proxy.yml to the stack, which defines a proxy container that forwards API calls to external providers like Claude-3-Opus.
# scripts/resolve-compose-stack.sh (simplified logic)
provider=$(grep '^MODEL_PROVIDER=' "$INSTALL_DIR/.env" | cut -d= -f2)
if [[ "$provider" == "cloud" ]]; then
COMPOSE_FILES+=("-f" "docker-compose.cloud-proxy.yml")
fi
docker compose -f docker-compose.base.yml "${COMPOSE_FILES[@]}" up -d
CLI Commands and Runtime Flags
The Dream CLI provides ergonomic commands to modify configuration without manual file editing.
Permanent Provider Switching
Use the config set subcommand to persistently change the model provider. This invokes _env_set and automatically triggers the compose-stack resolver to recreate services:
# Switch to local model (e.g., Qwen-3-Coder-Next)
dream-cli config set MODEL_PROVIDER local
# Switch to cloud model (e.g., Claude-3-Opus)
dream-cli config set MODEL_PROVIDER cloud
Behind the scenes, the CLI executes:
# In dream-server/dream-cli
_env_set() {
local key="$1" val="$2" file="$INSTALL_DIR/.env"
# Writes key=value into .env
}
if [[ "$1" == "config" && "$2" == "set" ]]; then
_env_set "$3" "$4"
scripts/resolve-compose-stack.sh
fi
Temporary Runtime Overrides
For experimental workflows, the --cloud flag temporarily overrides the stored configuration for a single command execution without persisting changes to the .env file:
# Execute against cloud backend without changing default configuration
dream-cli --cloud run-agent "Explain the code base"
Configuration Inspection
Verify the current mode using the config get command:
dream-cli config get MODEL_PROVIDER
# Output: local (or cloud)
Error Handling and Validation
The Dream CLI is written in Bash with strict set -euo pipefail settings that ensure immediate failure on undefined variables or pipe errors. When you attempt to set an invalid provider, the built-in error helper aborts the process with a descriptive message, preventing accidental misconfiguration that could leave the system in an inconsistent state.
Summary
- Configuration-driven switching: The Dream CLI uses a
.envfile withMODEL_PROVIDER,LLM_URL, andGPU_BACKENDkeys to determine runtime behavior. - Dynamic container orchestration: The
scripts/resolve-compose-stack.shgenerates appropriate Docker Compose configurations, addingdocker-compose.cloud-proxy.ymlfor cloud mode or GPU-specific overlays for local mode. - Ergonomic CLI interface: Commands like
dream-cli config set MODEL_PROVIDER localmodify configuration permanently, while the--cloudflag enables temporary overrides. - Strict validation: The Bash implementation with
set -euo pipefailand theerrorhelper prevents invalid configuration states.
Frequently Asked Questions
How do I temporarily test a cloud model without changing my default configuration?
Use the --cloud runtime flag before any subcommand. This overrides the MODEL_PROVIDER value stored in .env for that single execution only. For example: dream-cli --cloud run-agent "Analyze this function".
What files control the container composition when switching providers?
The scripts/resolve-compose-stack.sh script reads MODEL_PROVIDER from .env and assembles the appropriate stack. For local models, it combines docker-compose.base.yml with GPU-specific files like docker-compose.nvidia.yml. For cloud models, it additionally includes docker-compose.cloud-proxy.yml to route API calls.
Where does the Dream CLI store the current model provider setting?
The CLI stores the active provider in the MODEL_PROVIDER key within the .env file located in the installation directory. Helper functions _env_set and _env_get_raw in dream-server/dream-cli manage read and write operations to this file.
What happens if I specify an invalid provider name?
The CLI validates inputs using strict Bash settings (set -euo pipefail). If you attempt to set an unrecognized provider, the error helper function prints a clear diagnostic message and terminates the process immediately, preventing the system from launching with misconfigured services.
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 →