How to Configure Lieutenant Backend and Override Options in SwarmForge

TL;DR: SwarmForge configures the lieutenant AI backend through a line-based config file at swarmforge/swarmforge.conf, falling back to the SWARMFORGE_LIEUTENANT_AGENT environment variable or defaulting to grok if neither is set.

SwarmForge uses a lightweight configuration system to determine which AI backend powers the lieutenant role. According to the unclebob/swarm-forge source code, this configuration is handled by the parse-lieutenant-config function in swarmforge/scripts/swarmforge.bb (lines 887-904). Understanding how to configure the lieutenant backend and override its options lets you switch between agents like grok, claude, or codex without modifying the core codebase.

Configuration File Location and Format

SwarmForge reads lieutenant settings from swarmforge/swarmforge.conf at startup. This file uses a simple line-based format:

  • Comment lines start with # or are blank
  • Active configuration lines contain space-separated fields
  • The lieutenant keyword (case-insensitive) triggers backend selection

A valid lieutenant line requires at least two fields:


Lieutenant <agent-name> [extra-args...]

  • Field 1: The literal word lieutenant
  • Field 2: The agent name (validated against known-agents)
  • Field 3+: Optional arguments passed verbatim to the agent

Example configuration:


# swarmforge/swarmforge.conf

Lieutenant claude --temperature 0.7 --max-tokens 1024

Priority of Configuration Methods

SwarmForge resolves the lieutenant backend through a three-tier fallback system:

Priority Method When Applied
1 (Highest) swarmforge.conf lieutenant line Used whenever present and valid
2 SWARMFORGE_LIEUTENANT_AGENT environment variable Used when config file lacks a lieutenant line
3 (Lowest) Default agent grok Used when neither config nor env-var is set

Method 1: Edit swarmforge.conf

Add or modify the lieutenant line directly in your configuration file:


# swarmforge/swarmforge.conf

Lieutenant codex --verbose

This takes precedence over all other methods.

Method 2: Environment Variable Override

Export SWARMFORGE_LIEUTENANT_AGENT before running SwarmForge:

export SWARMFORGE_LIEUTENANT_AGENT=claude
./swarm

The environment variable only applies when swarmforge.conf contains no lieutenant line.

Method 3: Default Behavior

With no configuration, SwarmForge launches:

{:agent "grok" :extra-args nil}

Code Flow: How Configuration Becomes Execution

The lieutenant backend selection follows this execution path in swarmforge/scripts/swarmforge.bb:

  1. run-host! or run-project! builds the context ctx
  2. lieutenant-row calls parse-lieutenant-config with ctx
  3. parse-lieutenant-config returns a map {:agent "..." :extra-args "..."}
  4. window-row constructs a tmux session specification using these values
  5. launch-command spawns the lieutenant pane with the final agent command

The parse-lieutenant-config function implements the full fallback logic:

;; swarmforge/scripts/swarmforge.bb (lines 887-904)
(defn parse-lieutenant-config [ctx]
  (let [file (:config-file ctx)
        fallback (str/lower-case 
                  (or (not-empty (System/getenv "SWARMFORGE_LIEUTENANT_AGENT")) 
                      "grok"))]
    (if-not (fs/regular-file? file)
      {:agent fallback :extra-args nil}
      (or (some (fn [raw]
                  (let [line (str/trim raw)]
                    (when-not (skip-config-line? line)
                      (let [fields (str/split line #"\s+")]
                        (when (and (>= (count fields) 2)
                                   (= (str/lower-case (first fields)) "lieutenant"))
                          (let [agent (str/lower-case (second fields))]
                            (reject-if (not (known-agents agent))
                                       (str "Unsupported agent '" (second fields)
                                            "' for lieutenant"))
                            {:agent agent
                             :extra-args (extra-args-str (drop 2 fields))}))))))
                (str/split-lines (slurp (str file))))
          {:agent fallback :extra-args nil}))))

Key behaviors in this implementation:

  • Agent validation: Unknown agents trigger an error via reject-if against the known-agents whitelist
  • Case insensitivity: Both LIEUTENANT and lieutenant are valid
  • Extra args preservation: All fields after the agent name are joined and passed through extra-args-str

Practical Configuration Examples

Default grok with No Configuration


# swarmforge/swarmforge.conf

# (no lieutenant line)

Result: Lieutenant launches with grok and no extra arguments.

Claude with Temperature Control


# swarmforge/swarmforge.conf

Lieutenant claude --temperature 0.7 --max-tokens 1024

Result: The tmux pane executes approximately:

claude --temperature 0.7 --max-tokens 1024 ...

Environment Override for Temporary Switching


# Ensure no lieutenant line in swarmforge.conf

export SWARMFORGE_LIEUTENANT_AGENT=codex
./swarm my-project

Result: Uses codex without modifying configuration files.

Combined Documentation and Active Config


# swarmforge/swarmforge.conf

# Development: use claude with relaxed constraints

Lieutenant claude --thought

# Production (commented out):

# Lieutenant grok --strict

Key Files Reference

File Purpose Location in Repository
swarmforge/swarmforge.conf User-editable configuration with optional lieutenant line [swarmforge/swarmforge.conf](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/swarmforge.conf)
swarmforge/scripts/swarmforge.bb Core script containing parse-lieutenant-config and launch logic swarmforge/scripts/swarmforge.bb
swarmforge/roles/lieutenant.prompt Prompt template read by the lieutenant at session start swarmforge/roles/lieutenant.prompt

Summary

  • Primary configuration happens in swarmforge/swarmforge.conf using a lieutenant <agent> [args...] line format
  • Environment variable SWARMFORGE_LIEUTENANT_AGENT serves as fallback when no config line exists
  • Default agent is grok when neither source provides a value
  • The parse-lieutenant-config function in swarmforge.bb enforces agent validation against known-agents
  • Extra arguments pass through verbatim to the agent command, enabling backend-specific tuning

Frequently Asked Questions

What happens if I specify an unsupported agent in swarmforge.conf?

SwarmForge validates the agent name against a whitelist (known-agents). If you specify an unknown agent, parse-lieutenant-config calls reject-if and throws an error with the message "Unsupported agent '<name>' for lieutenant". The session will not start until you correct the configuration.

Can I use multiple lieutenant configurations for different projects?

The current implementation uses a single global configuration file at swarmforge/swarmforge.conf. For per-project overrides, use the SWARMFORGE_LIEUTENANT_AGENT environment variable in project-specific wrapper scripts, or maintain separate config files and symlink them before running ./swarm.

Why does my environment variable not take effect?

The SWARMFORGE_LIEUTENANT_AGENT variable only applies when swarmforge.conf contains no lieutenant line. Check that your config file does not have an active lieutenant entry, as explicit configuration always wins over environment variables according to the priority rules in parse-lieutenant-config.

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 →