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

> Understand the difference between session-only and persistent configuration in the Forge ZSH plugin. Learn how Forge stores temporary and permanent settings to optimize your shell environment. Read our complete guide.

- Repository: [Forge Code/forgecode](https://github.com/antinomyhq/forgecode)
- Tags: how-to-guide
- Published: 2026-04-08

---

**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`](https://github.com/antinomyhq/forgecode/blob/main/shell-plugin/lib/config.zsh) (lines 32-40) using the `typeset -h` attribute to keep them internal to the shell:

```zsh
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`](https://github.com/antinomyhq/forgecode/blob/main/shell-plugin/lib/actions/config.zsh)). This function writes the selected IDs directly into session variables without calling the `forge config` CLI:

```zsh
_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:

```zsh
_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`](https://github.com/antinomyhq/forgecode/blob/main/shell-plugin/lib/actions/config.zsh)):

```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`](https://github.com/antinomyhq/forgecode/blob/main/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:

```zsh
forge :model  # Select from fzf - sets _FORGE_SESSION_MODEL only

```

Commit a model change permanently:

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

```

Reset to global defaults after experimenting:

```zsh
forge config reload  # Clears all session overrides

```

Check which layer is active:

```zsh
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`](https://github.com/antinomyhq/forgecode/blob/main/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`](https://github.com/antinomyhq/forgecode/blob/main/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.