Skip to content

Environment variables

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.

FieldValue
Set byUser, container runtime, or CI environment.
Read byGitHub CLI (gh) for API and git auth; Shipper preflight detects it before gh auth setup-git.
Default when unsetShipper relies on gh auth login or the existing GitHub CLI authentication available to the process.
Accepted valuesAny non-empty GitHub token string with the repository access needed for the Shipper operation.
ExampleGH_TOKEN=<token> shipper next S#123
FieldValue
Set byUser, container runtime, or GitHub Actions.
Read byGitHub CLI (gh) for API and git auth; Shipper preflight detects it after GH_TOKEN.
Default when unsetSame as GH_TOKEN; if both variables are set, Shipper’s own token detection checks GH_TOKEN first.
Accepted valuesAny non-empty GitHub token string with the repository access needed for the Shipper operation.
ExampleGITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} shipper next S#123
FieldValue
Set byShipper developers or users acting under support direction.
Read byShipper’s browser sign-in and license-validation requests.
Default when unsethttps://shipper.baremetallabs.ai
Accepted valuesAlternate licensing-service base URL supplied for development or support.
ExampleSHIPPER_LICENSE_API_URL=http://localhost:8787 shipper auth login

This is a development/support endpoint override. Normal end users never need to set it.

FieldValue
Set byMCP client configuration or the operator starting shipper-mcp.
Read byshipper-mcp at startup when resolving the target repository.
Default when unsetThe MCP process startup working directory is used.
Accepted valuesPath to a Git repository; relative paths resolve against the MCP process startup working directory.
ExampleSHIPPER_REPO_DIR=/path/to/repo shipper-mcp
FieldValue
Set byDevelopers or operators running development builds or non-standard installs where the bundled docs corpus snapshot is unavailable.
Read byMCP docs corpus resolution after workspace docs and bundled docs lookup fail.
Default when unsetNormal workspace/bundled docs discovery is used; end users on a normal install do not need to set this variable.
Accepted valuesAbsolute path to an existing docs corpus directory; relative paths and missing directories are ignored.
ExampleSHIPPER_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.

FieldValue
Set byShipper-owned orchestrating hosts that can relay deferred questions and return answers.
Read byGeneralized core/CLI orchestrator gate for the headless question-file (defer-by-exit) loop.
Default when unsetQuestion loop disabled; headless grooming cannot surface questions to an orchestrator.
Accepted valuesExactly 1; every other value behaves as unset.
ExampleSet 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:

OperationValue
NO_COLOR1
FORCE_COLOR0
CLICOLOR0
NPM_CONFIG_COLORfalse
CLICOLOR_FORCERemoved from the environment rather than set.
FieldValue
Set byShipper, when it spawns a headless workflow-stage agent session.
Read byThe agent CLI and every shell command it launches, which inherit the session environment.
Default when unsetNot applicable — Shipper always applies these values to headless workflow-stage sessions.
Accepted valuesNot configurable. There is no setting, flag, or opt-out.
ExampleApplied 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:

VariableValue
TMPDIRThe Shipper-managed unique /tmp/shipper-cx-<24 lowercase hex> path
TMPThe same value as TMPDIR
TEMPThe 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.

FieldValue
Set byOperator, per shell or per launch, to run a second fully independent Shipper instance (for example a dogfood instance beside the stable one).
Read byCore 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 unsetThe Shipper home is ~/.shipper.
Accepted valuesAn 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.
Examplemkdir -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.

FieldValue
Set byUser as a temporary escape hatch.
Read byCore version freshness checks.
Default when unsetShipper enforces the runtime version check, except existing development/dogfood bypass behavior.
Accepted valuesExactly 1; any other value behaves as unset.
ExampleSHIPPER_SKIP_VERSION_CHECK=1 shipper next S#123

These variables are retained only so older operator configurations fail softly.

FieldValue
Set byOlder MCP operator configs; new configs should remove it.
Read byshipper-mcp startup compatibility notice code only.
Default when unsetNo obsolete-variable notice is shown; grooming tools remain registered and the unconfigured groom mode remains interactive.
Accepted valuesAny defined value, including empty string, 0, false, or no, triggers one obsolete-variable notice for that server start; it controls neither registration nor mode.
ExampleRemove SHIPPER_EXPERIMENTAL_MCP_GROOMING from MCP client configuration.
FieldValue
Set byOlder MCP operator configs; new configs should remove it.
Read byshipper-mcp startup compatibility notice code only.
Default when unsetNo obsolete-variable notice is shown; shipper_switch_repo is still registered after successful MCP initialization.
Accepted valuesAny defined value, including empty string, 0, false, or no, triggers one obsolete-variable notice for that server start; it does not control registration.
ExampleRemove SHIPPER_EXPERIMENTAL_MCP_REPO_SWITCH from MCP client configuration.
FieldValue
Set byOlder user, CI, or desktop launch configurations; new configurations should remove it.
Read byshipper design compatibility notice code only.
Default when unsetNo obsolete-variable notice is emitted. Adversarial design review resolves from the adversarialDesignReview setting or a direct one-run override.
Accepted valuesAny 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.
ExampleRemove the variable, set adversarialDesignReview through shipper settings, or use shipper design --enable-adversarial-review / shipper design --disable-adversarial-review for a single invocation.
FieldValue
Set byShipper for stage hooks and worktree lifecycle hooks.
Read byUser-authored hook scripts.
Default when unsetOutside Shipper hook execution, Shipper does not provide it.
Accepted valuesCurrent 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.
Exampleprintf '%s\n' "$SHIPPER_STAGE"
FieldValue
Set byShipper for stage hooks and worktree lifecycle hooks; hook contexts without an issue number receive an empty string.
Read byUser-authored hook scripts.
Default when unsetOutside 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 valuesGitHub issue number string or empty string.
Exampletest -n "$SHIPPER_ISSUE_NUMBER"
FieldValue
Set byShipper for hooks when branch context exists.
Read byUser-authored hook scripts.
Default when unsetOutside Shipper hook execution, Shipper does not provide it; in hooks without branch context, it may be empty.
Accepted valuesGit branch name or empty string.
Exampleprintf '%s\n' "$SHIPPER_BRANCH_NAME"
FieldValue
Set byShipper for worktree-setup and worktree-teardown hooks.
Read byUser-authored worktree hook scripts.
Default when unsetNot supplied to plain stage hooks and not provided outside worktree hook execution.
Accepted valuesAbsolute path of the temporary worktree.
Examplecd "$SHIPPER_WORKTREE_PATH"