Session-Only vs Persistent Configuration in the Forge ZSH Plugin: A Complete Guide

The Forge ZSH plugin maintains two distinct configuration layers: temporary session-only variables stored in hidden shell parameters like _FORGE_SESSION_MODEL, and permanent settings written to ~/.forge/.forge.toml that persist across reboots.

The antinomyhq/forgecode repository provides a ZSH integration that manages AI model interactions through the forge CLI. Understanding the difference between session-only and persistent configuration in the Forge ZSH plugin allows you to quickly test different models without altering your global defaults, while ensuring long-term preferences remain intact across terminal sessions.

How the Configuration Layers Work

The plugin implements a two-tiered system where session-only values always take precedence over persistent ones, but disappear when you close the shell or explicitly reload the configuration.

Layer Storage Lifetime Precedence
Session-only Hidden ZSH variables (_FORGE_SESSION_*) Current shell session only Highest (overrides persistent)
Persistent TOML file (~/.forge/.forge.toml) Permanent, user-wide Fallback when session is empty

Session-Only Configuration

Session-only configuration allows you to temporarily override the default model, provider, or reasoning effort without touching any files on disk. These values exist purely in memory for the current interactive shell.

Declaring Session Variables

The plugin declares hidden session variables in shell-plugin/lib/config.zsh (lines 32-40) using the typeset -h attribute to keep them internal to the shell:

typeset -h _FORGE_SESSION_MODEL
typeset -h _FORGE_SESSION_PROVIDER
typeset -h _FORGE_SESSION_REASONING_EFFORT

Setting Temporary Overrides

When you select a model for the current session only—typically via forge :model or an fzf interface—the plugin invokes _forge_action_session_model (lines 301-349 in shell-plugin/lib/actions/config.zsh). This function writes the selected IDs directly into session variables without calling the forge config CLI:

_FORGE_SESSION_MODEL="$model_id"
_FORGE_SESSION_PROVIDER="$provider_id"

Every subsequent forge invocation checks these variables and automatically appends --model $value --provider $value flags, ensuring your temporary selection overrides the global config.

Clearing Session State

To revert to persistent settings without closing the terminal, run forge config reload (bound to ⌃R). This triggers _forge_action_config_reload (lines 52-68), which empties all session variables:

_FORGE_SESSION_MODEL=""
_FORGE_SESSION_PROVIDER=""
_FORGE_SESSION_REASONING_EFFORT=""

Once cleared, the plugin stops injecting override flags, causing the CLI to fall back to the TOML configuration.

Persistent Configuration

Persistent configuration stores your default model, provider, and reasoning preferences in a global TOML file that survives shell restarts and system reboots.

The Global Config File

The canonical location for persistent settings is ~/.forge/.forge.toml. This file is managed exclusively through the forge config subcommand or direct editing via forge config edit.

Managing Permanent Settings

The plugin provides specific actions for modifying the global config. The forge config set command writes values directly to the TOML file, while forge config edit opens the file in your $EDITOR (implemented in _forge_action_config_edit, lines 53-88 of shell-plugin/lib/actions/config.zsh):


# Set a permanent default model

forge config set model 0123456789abcdef

# Edit the file directly

forge config edit  # Opens ${HOME}/.forge/.forge.toml

Changes made through either method immediately affect all new shell sessions and existing sessions that have no active session-only overrides.

Layer Interaction and Precedence

The plugin resolves configuration at runtime in forge.theme.zsh through a strict precedence chain:

  1. Check session variables: If _FORGE_SESSION_MODEL or _FORGE_SESSION_PROVIDER is non-empty, the plugin prepends --model $value --provider $value to the CLI arguments.
  2. Inject reasoning effort: Similarly, if _FORGE_SESSION_REASONING_EFFORT is set, it exports FORGE_REASONING__EFFORT to the environment.
  3. CLI parsing: The forge binary reads these flags/environment variables before loading ~/.forge/.forge.toml, ensuring session values always win.
  4. Fallback: When session variables are empty, the CLI uses the values stored in the persistent TOML file.

This architecture guarantees that session-only configurations are strictly temporary while persistent settings provide the global baseline.

Practical Usage Examples

Switch models temporarily for the current terminal tab:

forge :model  # Select from fzf - sets _FORGE_SESSION_MODEL only

Commit a model change permanently:

forge config set provider anthropic
forge config set model claude-3-opus-20240229

Reset to global defaults after experimenting:

forge config reload  # Clears all session overrides

Check which layer is active:

echo "Session model: ${_FORGE_SESSION_MODEL:-'using persistent config'}"

Summary

  • Session-only configuration uses hidden ZSH variables (_FORGE_SESSION_MODEL, _FORGE_SESSION_PROVIDER, _FORGE_SESSION_REASONING_EFFORT) declared in shell-plugin/lib/config.zsh to provide temporary overrides that last until config reload or shell exit.
  • Persistent configuration stores defaults in ~/.forge/.forge.toml and is managed via forge config set or forge config edit.
  • The plugin enforces precedence by injecting session values as CLI flags (--model, --provider) before the global config is read.
  • Use session variables for temporary experimentation and persistent storage for long-term workflow defaults.

Frequently Asked Questions

How do I determine which configuration layer is currently active?

Run echo $_FORGE_SESSION_MODEL in your terminal. If the output is empty, the plugin is using the persistent configuration from ~/.forge/.forge.toml. If a model ID is displayed, that session-only value is overriding your global defaults until you run forge config reload.

Will closing my terminal window clear session-only settings?

Yes. Because session-only variables are declared with typeset -h in the current shell process, they are destroyed when the interactive shell exits. New terminal windows or tabs initialize with empty session variables, immediately falling back to the persistent TOML configuration.

Can I mix session-only and persistent configurations?

Absolutely. The antinomyhq/forgecode plugin tracks session overrides for models, providers, and reasoning effort independently. You can set a session-only model while keeping a persistent provider, or vice versa. Each variable is injected separately into the CLI invocation based on its presence in the session state.

Why does the plugin use hidden variables for session state?

The typeset -h declaration in shell-plugin/lib/config.zsh prevents the _FORGE_SESSION_* variables from appearing in the public environment or being inherited by subprocesses unnecessarily. This design keeps your shell environment clean while allowing the ZSH plugin to maintain internal state for temporary configuration overrides.

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 →