# How OpenClaude Handles Out‑of‑Process Teammate Routing During Startup

> Discover how OpenClaude manages out-of-process teammate routing at startup. Learn about its efficient flag parsing and environment variable detection for early provider setup.

- Repository: [Gitlawb/openclaude](https://github.com/Gitlawb/openclaude)
- Tags: internals
- Published: 2026-09-02

---

**Out‑of‑process teammate routing in OpenClaude happens before the main UI loads, using eager flag parsing in [`src/utils/settings/flagSettings.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/settings/flagSettings.ts) and environment variable detection in [`src/utils/teammate.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/teammate.ts) to identify teammates and wire up the correct provider early.**

OpenClaude's multi‑agent architecture allows teammates to run in separate terminal windows via tmux or iTerm2 panes. The routing mechanism that determines whether a process is the leader or an out‑of‑process teammate operates during the bootstrap phase—**before [`main.tsx`](https://github.com/Gitlawb/openclaude/blob/main/main.tsx) is even imported**—ensuring minimal startup overhead and correct communication channel setup.

## Early Flag Parsing in flagSettings.ts

The routing decision begins with **eager CLI flag parsing**. The `eagerLoadSettingsFromArgs` function in [`src/utils/settings/flagSettings.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/settings/flagSettings.ts) executes immediately when the process starts, parsing `--settings` and `--setting-sources` flags at lines 23‑24:

```ts
// src/utils/settings/flagSettings.ts
// This is needed by bootstrap paths that inspect getInitialSettings()
// before main.tsx is imported, including out-of-process teammate provider routing.
export function eagerLoadSettingsFromArgs(argv = process.argv) {
  const settingsFile = eagerParseCliFlag('--settings', argv);
  if (settingsFile) loadSettingsFromFlag(settingsFile);
  // …additional flag handling…
  return { ok: true };
}

```

This function returns settings that downstream routing logic consumes **before any heavy UI code runs**. The comment explicitly notes this timing requirement for out‑of‑process teammate provider routing.

## Environment Variable Detection in teammate.ts

Once flags are loaded, OpenClaude checks for **teammate identity markers** via environment variables. When a launcher spawns an out‑of‑process teammate, it injects `CLAUDE_CODE_AGENT_ID` and `CLAUDE_CODE_TEAM_NAME`. The helpers in [`src/utils/teammate.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/teammate.ts) read these variables:

```ts
// src/utils/teammate.ts
export function getAgentId(): string | undefined { … }
export function getTeamName(): string | undefined { … }

export function isRunningAsOutOfProcessTeammate(): boolean {
  return !!process.env.CLAUDE_CODE_AGENT_ID && !!process.env.CLAUDE_CODE_TEAM_NAME;
}

```

These functions fall back to `AsyncLocalStorage` context for in‑process teammates, making the detection mechanism **dual‑mode**: environment variables for out‑of‑process, async context for in‑process.

## Background Task Registration in spawnMultiAgent.ts

After detection, the leader must **register communication channels** for the teammate. The `spawnMultiAgent` utility in [`src/tools/shared/spawnMultiAgent.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/tools/shared/spawnMultiAgent.ts) creates a background‑task entry at line 828:

```ts
// src/tools/shared/spawnMultiAgent.ts
// Register a background task entry for an out-of-process (tmux/iTerm2) teammate.
function registerBackgroundTask(taskInfo) {
  backgroundTaskRegistry.add(taskInfo);
}

```

This registry entry tells the leader's message router to **listen for IPC or mailbox messages** from the specific teammate ID, ensuring requests reach the correct provider instance.

## Optional Startup Profiling

Developers can measure routing overhead using [`src/utils/startupProfiler.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/startupProfiler.ts). This utility records timing for:

- `eagerLoadSettingsFromArgs` execution
- Environment variable detection
- Provider instantiation

Profiling helps identify latency introduced by complex flag configurations or slow teammate detection.

## Final Wiring to main.tsx

With settings resolved and teammate identity confirmed, the bootstrap calls `getInitialSettings()` and proceeds to [`src/main.tsx`](https://github.com/Gitlawb/openclaude/blob/main/src/main.tsx). The main UI creates the appropriate `Provider`:

- **In‑process provider** — Uses `AsyncLocalStorage` from [`src/utils/teammateContext.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/teammateContext.ts)
- **Out‑of‑process provider** — Uses IPC channels or mailbox routing via the background task registry

## Complete Startup Command Examples

Launch the leader normally:

```bash
openclaude --settings ./my-settings.json

```

Launch an out‑of‑process teammate that triggers early routing:

```bash
openclaude --settings ./my-settings.json \
           --agent-id teammate-01 \
           --team-name my-team

```

The presence of `CLAUDE_CODE_AGENT_ID` and `CLAUDE_CODE_TEAM_NAME` in the environment (typically set by the launcher before these commands) causes the routing code to select the out‑of‑process path.

## Key Files in the Routing Chain

| File | Routing Role |
|------|--------------|
| [`src/utils/settings/flagSettings.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/settings/flagSettings.ts) | **First entry point** — eager flag parsing before UI load |
| [`src/utils/teammate.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/teammate.ts) | Environment variable detection and teammate identity |
| [`src/tools/shared/spawnMultiAgent.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/tools/shared/spawnMultiAgent.ts) | Background task registration for cross‑process messaging |
| [`src/utils/teammateContext.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/teammateContext.ts) | In‑process `AsyncLocalStorage` counterpart |
| [`src/utils/startupProfiler.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/utils/startupProfiler.ts) | Optional latency measurement |
| [`src/main.tsx`](https://github.com/Gitlawb/openclaude/blob/main/src/main.tsx) | Final provider instantiation based on resolved settings |

## Summary

- **Eager parsing in [`flagSettings.ts`](https://github.com/Gitlawb/openclaude/blob/main/flagSettings.ts)** runs before [`main.tsx`](https://github.com/Gitlawb/openclaude/blob/main/main.tsx) import to prepare settings early
- **Environment variables (`CLAUDE_CODE_AGENT_ID`, `CLAUDE_CODE_TEAM_NAME`)** identify out‑of‑process teammates via [`teammate.ts`](https://github.com/Gitlawb/openclaude/blob/main/teammate.ts) helpers
- **[`spawnMultiAgent.ts`](https://github.com/Gitlawb/openclaude/blob/main/spawnMultiAgent.ts)** registers background tasks enabling leader‑to‑teammate message routing
- **Startup profiler** tracks routing overhead for optimization
- **Final wiring** in [`main.tsx`](https://github.com/Gitlawb/openclaude/blob/main/main.tsx) instantiates the correct provider based on pre‑resolved identity

## Frequently Asked Questions

### What happens if `CLAUDE_CODE_AGENT_ID` is set but `CLAUDE_CODE_TEAM_NAME` is missing?

The `isRunningAsOutOfProcessTeammate()` function requires both variables to return `true`. If either is missing, the process falls back to single‑agent or in‑process routing. This safety check prevents partial teammate configuration from causing routing failures.

### Can I use the same `--settings` file for leader and teammate processes?

Yes. The `--settings` flag is parsed early by `eagerLoadSettingsFromArgs` in both cases. The routing differentiation happens through environment variables, not settings files, so shared configuration is supported and common in practice.

### Why does routing need to happen before [`main.tsx`](https://github.com/Gitlawb/openclaude/blob/main/main.tsx) loads?

Heavy UI initialization including React rendering, terminal UI setup, and provider instantiation occurs in [`main.tsx`](https://github.com/Gitlawb/openclaude/blob/main/main.tsx). Determining teammate identity **before** this step avoids wasted work if the process needs a different provider type, and ensures the correct communication channels exist before any messages are sent.

### How does the leader know which teammates are active?

The `backgroundTaskRegistry` in [`spawnMultiAgent.ts`](https://github.com/Gitlawb/openclaude/blob/main/spawnMultiAgent.ts) tracks registered tasks by `agentId`. When a teammate spawns, its registration entry includes the ID and communication endpoint. The leader queries this registry when routing messages, matching incoming requests to the correct teammate handler.