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 to local or cloud
  • LLM_URL: Specifies the endpoint URL for cloud connections
  • GPU_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 .env file with MODEL_PROVIDER, LLM_URL, and GPU_BACKEND keys to determine runtime behavior.
  • Dynamic container orchestration: The scripts/resolve-compose-stack.sh generates appropriate Docker Compose configurations, adding docker-compose.cloud-proxy.yml for cloud mode or GPU-specific overlays for local mode.
  • Ergonomic CLI interface: Commands like dream-cli config set MODEL_PROVIDER local modify configuration permanently, while the --cloud flag enables temporary overrides.
  • Strict validation: The Bash implementation with set -euo pipefail and the error helper 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →