This is the canonical reference for user-facing Shipper environment variables. Internal IPC,
build-time, Electron, cache, and worktree implementation variables are intentionally excluded except
for the Shipper orchestrator handoff and the workflow-stage color controls documented below.
| Field | Value |
|---|
| Set by | User, container runtime, or CI environment. |
| Read by | GitHub CLI (gh) for API and git auth; Shipper preflight detects it before gh auth setup-git. |
| Default when unset | Shipper relies on gh auth login or the existing GitHub CLI authentication available to the process. |
| Accepted values | Any non-empty GitHub token string with the repository access needed for the Shipper operation. |
| Example | GH_TOKEN=<token> shipper next S#123 |
| Field | Value |
|---|
| Set by | User, container runtime, or GitHub Actions. |
| Read by | GitHub CLI (gh) for API and git auth; Shipper preflight detects it after GH_TOKEN. |
| Default when unset | Same as GH_TOKEN; if both variables are set, Shipper’s own token detection checks GH_TOKEN first. |
| Accepted values | Any non-empty GitHub token string with the repository access needed for the Shipper operation. |
| Example | GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} shipper next S#123 |
| Field | Value |
|---|
| Set by | Shipper developers or users acting under support direction. |
| Read by | Shipper’s browser sign-in and license-validation requests. |
| Default when unset | https://shipper.baremetallabs.ai |
| Accepted values | Alternate licensing-service base URL supplied for development or support. |
| Example | SHIPPER_LICENSE_API_URL=http://localhost:8787 shipper auth login |
This is a development/support endpoint override. Normal end users never need to set it.
| Field | Value |
|---|
| Set by | MCP client configuration or the operator starting shipper-mcp. |
| Read by | shipper-mcp at startup when resolving the target repository. |
| Default when unset | The MCP process startup working directory is used. |
| Accepted values | Path to a Git repository; relative paths resolve against the MCP process startup working directory. |
| Example | SHIPPER_REPO_DIR=/path/to/repo shipper-mcp |
| Field | Value |
|---|
| Set by | Developers or operators running development builds or non-standard installs where the bundled docs corpus snapshot is unavailable. |
| Read by | MCP docs corpus resolution after workspace docs and bundled docs lookup fail. |
| Default when unset | Normal workspace/bundled docs discovery is used; end users on a normal install do not need to set this variable. |
| Accepted values | Absolute path to an existing docs corpus directory; relative paths and missing directories are ignored. |
| Example | SHIPPER_DOCS_PATH=/path/to/shipper/packages/docs/src/content/docs shipper-mcp |
The MCP server’s corpus-unavailable error message names SHIPPER_DOCS_PATH when this fallback
may be needed.
| Field | Value |
|---|
| Set by | Shipper-owned orchestrating hosts that can relay deferred questions and return answers. |
| Read by | Generalized core/CLI orchestrator gate for the headless question-file (defer-by-exit) loop. |
| Default when unset | Question loop disabled; headless grooming cannot surface questions to an orchestrator. |
| Accepted values | Exactly 1; every other value behaves as unset. |
| Example | Set internally by a Shipper orchestrating host; users should not set it as a feature flag. |
Color behavior in a workflow-stage agent session follows the concrete execution mode Shipper
resolved for that run, not whether anyone happens to be watching the output.
Shipper applies no color policy to a terminal-attended interactive workflow session. It neither
forces color on nor suppresses it: your inherited environment, the terminal’s capabilities, the
selected agent, and the commands run inside the session decide how output is rendered. Values you
already export — including ones that disable color and ones that force it — reach the session
unchanged, and this is true for every supported agent CLI and every workflow stage that can run
interactively.
Shipper runs every headless workflow-stage agent session in a color-free environment, so the build,
test, lint, and package-manager output the agent captures is plain text rather than raw escape
sequences. Shipper applies these five operations to the spawned session’s environment:
| Operation | Value |
|---|
NO_COLOR | 1 |
FORCE_COLOR | 0 |
CLICOLOR | 0 |
NPM_CONFIG_COLOR | false |
CLICOLOR_FORCE | Removed from the environment rather than set. |
| Field | Value |
|---|
| Set by | Shipper, when it spawns a headless workflow-stage agent session. |
| Read by | The agent CLI and every shell command it launches, which inherit the session environment. |
| Default when unset | Not applicable — Shipper always applies these values to headless workflow-stage sessions. |
| Accepted values | Not configurable. There is no setting, flag, or opt-out. |
| Example | Applied internally whenever Shipper runs a headless workflow stage; users should not set these variables to influence it. |
Shipper applies these values after both the inherited environment and any caller-supplied values, so
they take precedence over an operator environment that already forces color on.
Desktop, MCP, automation, and background execution are all headless, and they are suppressed on that
basis alone. Capturing a session’s output to a log does not change its execution mode: a captured run
is suppressed only when it is headless. Live visibility never makes a headless session interactive.
Retained output from a terminal-attended interactive session may contain the native escape sequences
its agent and child commands emitted, because Shipper stores the session’s bytes as produced.
Retained output from a headless session stays color-free under the suppression policy above.
The following are excluded and keep their current coloring:
shipper new
shipper setup
- The Shipper CLI’s own terminal output
- The desktop application’s own interface
shipper new and shipper setup are attended operator experiences, so the headless suppression
never applies to them. The desktop’s session view relays the output of a headless agent run, which is
plain for that reason — that is expected, not a defect; only the desktop’s own interface is excluded.
Sandboxed temporary storage is sandboxed-only and applies on macOS, Linux, and WSL2.
For a sandboxed Codex child, Shipper creates a fresh unique real directory named
/tmp/shipper-cx-<24 lowercase hex> (on macOS, /private/tmp/shipper-cx-<24 lowercase hex> after
canonicalization). That short path preserves Unix-domain socket path headroom. These values are the
final environment source, after the inherited environment and all worktreeEnv values:
| Variable | Value |
|---|
TMPDIR | The Shipper-managed unique /tmp/shipper-cx-<24 lowercase hex> path |
TMP | The same value as TMPDIR |
TEMP | The same value as TMPDIR |
There is no setting, flag, or opt-out. The override exists only in the sandboxed Codex child
process and commands it launches; Shipper does not mutate process.env or the operator’s shell.
Sandboxed Claude uses native per-session temporary storage and receives no Shipper TMPDIR,
TMP, or TEMP override. Unsandboxed commands and other agents retain their existing temporary
environment.
Shipper deletes current and abandoned sandboxed Codex directories only when exact ownership is
proven. Matching path, owner, device, and inode is insufficient because a successor directory may
reuse them. For abandoned reclamation, both the Shipper process and Codex child must also be proven
dead. When exact ownership cannot be proven, Shipper preserves the candidate, warns with its
specific location, and continues the requested stage with fresh isolated storage. Preparation
failure that makes isolated storage unsafe prevents launch with a standalone temporary-storage
error. Cleanup failures warn with the affected location and do not change the stage result or fall
back to shared or uncertain storage.
Shipper does not add --add-dir /tmp or widen Codex’s default writable roots, and does not promise
exact-directory confinement. Codex may independently permit other system temporary directories
through its own sandbox.
| Field | Value |
|---|
| Set by | Operator, per shell or per launch, to run a second fully independent Shipper instance (for example a dogfood instance beside the stable one). |
| Read by | Core path resolution for every Shipper-home location (issue-state store, daemon socket and ownership, repository registry, Auto-ship state, worktrees, logs, license, installed launcher), the installer for its install root, and Desktop, which keeps its Electron userData at <home>/desktop/user-data. |
| Default when unset | The Shipper home is ~/.shipper. |
| Accepted values | An absolute path to an existing directory that is not a symlink and has no group or world permission bits. Empty or whitespace-only behaves as unset. Any other value fails the command; Shipper never falls back to ~/.shipper from an invalid override. |
| Example | mkdir -m 700 ~/.shipper-dev && SHIPPER_HOME=$HOME/.shipper-dev shipper status |
The override relocates the whole home, so every process of that instance must carry the same
value: the daemon, its workers, and Desktop child processes inherit it from whichever process
launched them. The installer honors it too (SHIPPER_HOME=/abs/dir sh install.sh), creates the
missing root with owner-only permissions and rejects an existing symlink, non-directory, or
group/world-accessible root without changing its permissions. It trims surrounding whitespace
just like the runtime and prints safely quoted SHIPPER_HOME and PATH exports that put the
selected installation first, instead of editing the login-shell profile. Alternate-home installs
skip automatic user-wide MCP registration and print a home-bound launcher command and OpenCode
configuration for a separate client profile with a distinct entry name. A packaged macOS Desktop receives it through
open -n --env SHIPPER_HOME=/abs/dir /path/to/Shipper.app; -n starts a second instance beside
the default one. Shipper never expands ~ in the value. withShipperHome scopes and Vitest
isolation take precedence over this variable, and the Vitest harness scrubs it from every test.
| Field | Value |
|---|
| Set by | User as a temporary escape hatch. |
| Read by | Core version freshness checks. |
| Default when unset | Shipper enforces the runtime version check, except existing development/dogfood bypass behavior. |
| Accepted values | Exactly 1; any other value behaves as unset. |
| Example | SHIPPER_SKIP_VERSION_CHECK=1 shipper next S#123 |
These variables are retained only so older operator configurations fail softly.
| Field | Value |
|---|
| Set by | Older MCP operator configs; new configs should remove it. |
| Read by | shipper-mcp startup compatibility notice code only. |
| Default when unset | No obsolete-variable notice is shown; grooming tools remain registered and the unconfigured groom mode remains interactive. |
| Accepted values | Any defined value, including empty string, 0, false, or no, triggers one obsolete-variable notice for that server start; it controls neither registration nor mode. |
| Example | Remove SHIPPER_EXPERIMENTAL_MCP_GROOMING from MCP client configuration. |
| Field | Value |
|---|
| Set by | Older MCP operator configs; new configs should remove it. |
| Read by | shipper-mcp startup compatibility notice code only. |
| Default when unset | No obsolete-variable notice is shown; shipper_switch_repo is still registered after successful MCP initialization. |
| Accepted values | Any defined value, including empty string, 0, false, or no, triggers one obsolete-variable notice for that server start; it does not control registration. |
| Example | Remove SHIPPER_EXPERIMENTAL_MCP_REPO_SWITCH from MCP client configuration. |
| Field | Value |
|---|
| Set by | Older user, CI, or desktop launch configurations; new configurations should remove it. |
| Read by | shipper design compatibility notice code only. |
| Default when unset | No obsolete-variable notice is emitted. Adversarial design review resolves from the adversarialDesignReview setting or a direct one-run override. |
| Accepted values | Any defined value, including empty string, 0, false, or no, emits one obsolete-and-ignored notice for each design run. The value cannot enable adversarial review and the notice never fails the run. |
| Example | Remove the variable, set adversarialDesignReview through shipper settings, or use shipper design --enable-adversarial-review / shipper design --disable-adversarial-review for a single invocation. |
| Field | Value |
|---|
| Set by | Shipper for stage hooks and worktree lifecycle hooks. |
| Read by | User-authored hook scripts. |
| Default when unset | Outside Shipper hook execution, Shipper does not provide it. |
| Accepted values | Current stage string such as groom, design, plan, implement, pr-open, pr-review, new, or merge; worktree hook contexts may provide an empty string when no stage applies. |
| Example | printf '%s\n' "$SHIPPER_STAGE" |
| Field | Value |
|---|
| Set by | Shipper for stage hooks and worktree lifecycle hooks; hook contexts without an issue number receive an empty string. |
| Read by | User-authored hook scripts. |
| Default when unset | Outside Shipper hook execution, Shipper does not provide it; for the new stage, it is an empty string because no issue exists yet; other hooks without issue context may also receive an empty string. |
| Accepted values | GitHub issue number string or empty string. |
| Example | test -n "$SHIPPER_ISSUE_NUMBER" |
| Field | Value |
|---|
| Set by | Shipper for hooks when branch context exists. |
| Read by | User-authored hook scripts. |
| Default when unset | Outside Shipper hook execution, Shipper does not provide it; in hooks without branch context, it may be empty. |
| Accepted values | Git branch name or empty string. |
| Example | printf '%s\n' "$SHIPPER_BRANCH_NAME" |
| Field | Value |
|---|
| Set by | Shipper for worktree-setup and worktree-teardown hooks. |
| Read by | User-authored worktree hook scripts. |
| Default when unset | Not supplied to plain stage hooks and not provided outside worktree hook execution. |
| Accepted values | Absolute path of the temporary worktree. |
| Example | cd "$SHIPPER_WORKTREE_PATH" |