Base Runtime Environment

August 24, 2026 ยท View on GitHub

Status: maintained runtime contract Last reviewed: 2026-07-25

This page is the canonical reference for Base-managed shell environment variables. It covers variables that are part of the runtime contract, command dispatch, project activation, and user-facing configuration knobs.

Test-only variables such as BASE_TEST_*, private implementation variables such as _BASE_*, and local variables that are not exported are intentionally excluded.

Ownership Rules

Base-owned variables are derived by Base and describe where Base is installed, which command is running, or which project runtime is active. Users should not change them after Base sets them. In Bash runtime contexts, Base marks these variables readonly when the shell can enforce that safely.

User-tunable variables are knobs. Users may set them in the environment, in ~/.baserc when they are shell-startup-safe, or in CI/test wrappers when the specific command documents that behavior.

~/.base.d/profile.conf is different from ~/.baserc: it is generated by basectl update-profile and should not be hand-edited.

User Baserc

~/.baserc is an optional, user-managed file for simple Base preferences that must be visible during shell startup. The main intended use today is:

BASE_DEBUG=1

Base-managed Bash and Zsh dotfile snippets source ~/.baserc when it exists. The Base runtime Bash rcfile also sources it before loading base_init.sh. This lets BASE_DEBUG=1 trace early startup code that runs before Base's full Bash standard library is available.

~/.baserc is not a second .bashrc or .zshrc. It should not contain PATH rewrites, command execution, virtual environment activation, aliases, prompt logic, or project-specific setup. Put ordinary interactive shell behavior in the normal shell dotfiles.

The Bash and Zsh baserc guards source ~/.baserc at most once per shell. They also snapshot Base-owned variables before sourcing the file, reject any attempt to change those variables, restore the previous value, and return an error. That guard protects startup configuration. It is not a general security boundary.

~/.baserc may set user knobs such as BASE_DEBUG. It must not set Base-owned runtime or profile variables such as BASE_HOME, BASE_BIN_DIR, BASE_LIB_DIR, BASE_OS, BASE_PLATFORM, BASE_HOST_ENV, BASE_HOST, BASE_SHELL, BASE_BASH_LIBS_DIR, BASE_BASH_LIBS_SOURCE, BASE_PLATFORM_TOOLS_HOME, BASE_PLATFORM_TOOLS_BIN_DIR, BASE_PROFILE_VERSION, BASE_ENABLE_BASH_DEFAULTS, or BASE_ENABLE_ZSH_DEFAULTS. It must also not set command or project metadata such as BASE_BASH_COMMAND_SCRIPT, BASE_PROJECT, BASE_PROJECT_ROOT, or BASE_PROJECT_VENV_DIR.

Base Runtime Contract

base_init.sh sets this contract when basectl runs a Base command, runs an explicit Bash script, or starts a Base runtime Bash shell.

VariableOwnerMeaning and impactUser changes
BASE_HOMEBaseCanonical Base install or checkout root. All other Base paths derive from it. basectl seeds it before base_init.sh; direct base_init.sh sourcing may also start from an existing value.May be provided only before runtime bootstrap to select the Base root. Readonly after base_init.sh.
BASE_BIN_DIRBase$BASE_HOME/bin. Added to PATH for Base command launchers.Do not set. Readonly after base_init.sh.
BASE_CLI_DIRBase$BASE_HOME/cli, the in-tree Base CLI implementation root.Do not set. Readonly after base_init.sh.
BASE_CLI_SOURCE_DIRBaseExplicit source root for the extracted base_cli package. When set before a Base Python command starts, it must contain base_cli/__init__.py.May be provided only before runtime bootstrap for tests or nonstandard source worktrees.
BASE_BASH_DIRBase$BASE_HOME/cli/bash. Root for Bash command implementations.Do not set. Readonly after base_init.sh.
BASE_BASH_COMMANDS_DIRBase$BASE_BASH_DIR/commands. Directory used by command dispatch.Do not set. Readonly after base_init.sh.
BASE_LIB_DIRBase$BASE_HOME/lib. Root for shared Base libraries.Do not set. Readonly after base_init.sh.
BASE_BASH_LIB_DIRBase$BASE_HOME/lib/bash. Base-specific Bash helper root, including runtime and version helpers.Do not set. Readonly after base_init.sh.
BASE_BASH_LIBS_DIRBaseResolved reusable Bash library root used for stdlib loading and import_base_lib. It can point at an explicit BASE_BASH_LIBS_DIR, a sibling base-bash-libs checkout, or a Homebrew base-bash-libs package next to Homebrew Base. Base requires the v2 base_ API; the final coordinated cutover applies the 2.0.0 version floor.May be provided only before runtime bootstrap to force a compatible reusable library root. Readonly after base_init.sh.
BASE_BASH_LIBS_SOURCEBaseSource category for BASE_BASH_LIBS_DIR: explicit, sibling, or homebrew. basectl check and basectl doctor use this to report how Base is consuming external reusable Bash libraries.Do not set. Readonly after base_init.sh.
BASE_CLI_SOURCEBaseResolved base_cli provider: explicit, sibling, or pip after the standalone package is installed.Do not set. Derived by Base before Python runtime startup.
BASE_SHELL_DIRBase$BASE_HOME/lib/shell. Root for managed shell startup snippets and completions.Do not set. Readonly after base_init.sh.
BASE_OSBaseNormalized host OS metadata such as macos or linux. Used by runtime decisions and diagnostics.Do not set. Readonly after base_init.sh.
BASE_PLATFORMBaseNormalized runtime platform metadata such as macos, linux-debian, or linux-unknown. Used when Base needs distribution-family behavior without overloading BASE_OS.Do not set. Readonly after base_init.sh.
BASE_HOST_ENVBaseHost-environment metadata layered on BASE_PLATFORM, currently native or wsl2. Ubuntu/Debian under WSL2 remains BASE_PLATFORM=linux-debian; this variable only clarifies host context and does not imply native Windows support.Do not set. Readonly after base_init.sh.
BASE_HOSTBaseShort host name from hostname -s. Used by runtime metadata and prompts.Do not set. Readonly after base_init.sh.
BASE_SHELLBaseLegacy runtime marker. Plain base_init.sh defaults it to bash; Base runtime shells seed it as 1 before base_init.sh. New code should avoid adding new meanings to it.Do not set in user config. Readonly after base_init.sh.

BASE_BASH_LIBS_DIR and BASE_BASH_LIBS_SOURCE are part of the external Bash library contract. For the full resolution order, standalone install path, and post-migration boundary, see Base Bash Libraries.

The standalone Python base_cli package follows the same provider pattern. Base checks BASE_CLI_SOURCE_DIR first, then a sibling checkout at $BASE_HOME/../base-cli/lib/python. If neither source checkout is present, Base leaves base_cli to normal Python environment resolution and expects the base-cli distribution to be installed in the selected Base virtual environment. An explicit or sibling checkout that exists but is malformed is an error; Base does not silently fall back to a different provider. Base no longer carries an in-tree copy of the package.

CI Runtime Variables

basectl setup --ci, basectl check --ci, and basectl doctor --ci set these variables while running the existing setup, check, and doctor paths. They are scoped to that command invocation and are not part of the readonly base_init.sh runtime contract. The canonical lifecycle commands set these variables when invoked with --ci.

VariableOwnerMeaning and impactUser changes
BASE_CIBaseSet to true by --ci so Base setup and diagnostics can choose non-interactive CI-safe behavior, including the runtime-only Linux system-Python fallback gate.Do not set directly; use --ci on setup, check, or doctor.
CIBase/tooling conventionSet to true by --ci for compatibility with common CI-aware tools.CI systems may already set this. Base sets it for delegated commands when using --ci.

Command Dispatch Variables

bin/basectl sets these before sourcing the selected Bash command or explicit script path. They describe the script being dispatched, not the user's project.

VariableOwnerMeaning and impactUser changes
BASE_BASH_COMMAND_NAMEBaseNormalized command name, such as basectl or a script basename without .sh.Do not set. Readonly before the command script is sourced.
BASE_BASH_COMMAND_DIRBasePhysical directory containing the dispatched Bash script.Do not set. Readonly before the command script is sourced.
BASE_BASH_COMMAND_SCRIPTBasePhysical path of the dispatched Bash script.Do not set. Readonly before the command script is sourced.
BASE_BASH_LIBS_BOOTSTRAP_SOURCEBaseInternal transient override used while base_init.sh initializes the Bash stdlib so the v2 runtime source directory resolves to the command script.Do not set. It is unset immediately after bootstrap and is not part of the public runtime contract.

Cache And Run Variables

The cache root is user-tunable; ownership and run identity are assigned by the launcher. See Cache Ownership And Layout for the resulting directory tree.

VariableOwnerMeaning and impactUser changes
BASE_CACHE_DIRUserOverrides the platform default Base cache root.May be set before invoking Base.
BASE_CLI_RUNTIME_OWNERBase/project launcherbase for Base control-plane processes or project for a project-native process.Do not set manually; launchers establish it.
BASE_CLI_RUN_ROOTParent launcherPoints a Base-internal child at its parent run bundle so it reuses the parent's run ID and logs/primary.log. Reuse requires an internal Base context, matching run and parent IDs, running metadata, and a real direct child of the active cache's base/runs/ directory. Invalid inherited state is scrubbed before Base creates a fresh bundle. Project launchers deliberately unset it before creating a project-owned bundle.Do not set manually.
BASE_CLI_HISTORY_PARENT_RUN_IDParent launcherLinks internal or project history records to the public Base invocation.Do not set manually.

Project Runtime Variables

Project runtime variables are set after Base resolves a project from an explicit project name, the configured workspace, or the current directory. They are available to project commands, runtime shells, and activation scripts.

VariableOwnerMeaning and impactUser changes
BASE_PROJECTBaseResolved project name. Used by Base wrappers, prompts, logs, and project command dispatch.Do not change after project resolution. Readonly in interactive Base runtime Bash shells.
BASE_PROJECT_ROOTBasePhysical project root directory. Project commands run from this directory.Do not change after project resolution. Readonly in interactive Base runtime Bash shells.
BASE_PROJECT_MANIFESTBasePhysical path to the project's base_manifest.yaml.Do not change after project resolution. Readonly in interactive Base runtime Bash shells.
BASE_PROJECT_VENV_DIRSharedProject virtual environment directory. Users may set it before basectl activate, basectl run, or basectl demo to override the default. Base defaults non-Base projects to <project-root>/.venv; Base itself stays at ~/.base.d/base/.venv. A non-Base manifest can opt into the historical external project venv with python.venv_location: external.May be set before project resolution. Do not change after Base resolves the project. Readonly in interactive Base runtime Bash shells.

Readonly shell attributes do not cross arbitrary process boundaries. For example, basectl run exports project variables to the project command process, but a non-Bash command receives normal environment variables. Treat the values as read-only contract values even when the operating shell cannot enforce that.

Optional Companion Repository Variables

Base can integrate with the optional base-platform-tools repository when it is checked out next to Base. Detection is intentionally local and conservative: the sibling directory must be named base-platform-tools and must contain both base_manifest.yaml and bin/.

These variables are set only when that checkout is detected by ordinary Bash/Zsh startup snippets or by a Base runtime Bash shell. Plain base_init.sh command dispatch does not require the optional repository.

VariableOwnerMeaning and impactUser changes
BASE_PLATFORM_TOOLS_HOMEBasePhysical path to the optional sibling base-platform-tools checkout.Do not set. Derived during shell startup when the optional repo is present.
BASE_PLATFORM_TOOLS_BIN_DIRBase$BASE_PLATFORM_TOOLS_HOME/bin. Added to PATH after $BASE_HOME/bin and before project bin/ directories.Do not set. Derived during shell startup when the optional repo is present.

Dotfile And Profile Variables

These variables are involved in normal shell startup rather than the full base_init.sh runtime.

VariableOwnerMeaning and impactUser changes
BASE_PROFILE_VERSIONBaseSchema version written to ~/.base.d/profile.conf by basectl update-profile. Reserved for future migrations.Do not edit. Managed by Base.
BASE_ENABLE_BASH_DEFAULTSBaseGenerated preference controlling optional Base Bash defaults.Change with basectl update-profile --defaults or --no-defaults, not by editing files directly.
BASE_ENABLE_ZSH_DEFAULTSBaseGenerated preference controlling optional Base Zsh defaults.Change with basectl update-profile --defaults or --no-defaults, not by editing files directly.
BASE_DEBUGUserEnables debug traces in Base-managed shell startup snippets and the runtime Bash rcfile.Safe to set in ~/.baserc or as a one-off environment variable.
LOG_DEBUGBase wrapper compatibilityInternal debug signal exported by wrapper/debug paths before the full runtime exists. The Python config layer treats 1 or true as a fallback for BASE_CLI_LOG_LEVEL=debug when BASE_CLI_LOG_LEVEL is unset.Do not set directly; use --debug-wrapper or BASE_CLI_LOG_LEVEL=debug for Python CLI logs.
LOG_UTCBase wrapper compatibilityWhen set to 1, switches Bash and Python CLI log presentation to UTC. It is set by basectl --utc-wrapper; persisted metadata is UTC regardless.Prefer basectl --utc-wrapper for one-off CI or diagnostic runs.
BASE_CLI_COLORBase wrapper compatibilityInternal signal exported by basectl --color so Python-backed child commands use the same terminal log colors as Bash.Do not set directly; use basectl --color. NO_COLOR still disables colors.

The ordinary Bash/Zsh dotfile snippets derive BASE_HOME and add $BASE_HOME/bin to PATH so basectl is available in new terminals. When a valid sibling base-platform-tools checkout is present, those same snippets add its bin/ directory immediately after Base's own bin/. They do not source base_init.sh, so they do not establish the full readonly runtime contract.

User-Tunable Command Knobs

These variables are intentionally mutable inputs. They should not be marked readonly by Base.

VariableScopeMeaning
BASE_CACHE_DIRPython CLI/runtime cacheOverrides the cache, log, and temp root. Defaults are platform-specific.
BASE_PROJECT_PYTHON_BINProject Python runtime selectionOverrides the interpreter candidate used when Base creates or checks a project virtual environment. The path must point to a supported Python interpreter.
BASE_CLI_ENVIRONMENTPython CLI configSelects the CLI environment value used by base_cli.
BASE_CLI_LOG_LEVELPython CLI configSets the Python CLI user-stream log level.
BASE_CLI_KEEP_TEMPPython CLI configKeeps temp directories for inspection when true.
BASE_CLI_TEMP_RETENTION_DAYSPython CLI configRetention window for pruned temp directories.
BASE_ACTIVATE_SHELLbasectl activateOverrides the Bash executable used for the activated runtime shell.
BASE_ACTIVATE_PRESERVE_CWDbasectl activateTest/user override equivalent to --no-cd when set to 1.
BASE_SETUP_PROFILESbasectl setupComma-separated setup profiles such as dev,sre.
BASE_SETUP_NOTIFYbasectl setupEnables or disables setup completion notifications.
BASE_SETUP_NOTIFY_MIN_SECONDSbasectl setupMinimum setup duration before completion notification.
BASE_SETUP_PYTHON_FORMULAbasectl setupOverrides the Homebrew Python formula.
BASE_SETUP_UPGRADE_PIPbasectl setup --upgrade-pipInternal setup flag requesting an explicit pip upgrade in the selected Base-managed or pip-managed virtual environment.
BASE_INSTALL_DIRinstall.shOverrides the default source install directory.
BASE_BOOTSTRAP_MODEbootstrap.shSelects bootstrap mode when no command-line mode overrides it.

The clean-slate ownership boundary and implemented run-oriented layout for BASE_CACHE_DIR are documented in Cache Ownership And Layout. That document is the runtime contract for the owner-aware cache tree.

Additional setup and bootstrap BASE_SETUP_*, BASE_BOOTSTRAP_*, and BASE_INSTALL_* variables exist for tests, CI, and narrow command overrides. Those are command-specific inputs, not shell runtime contract variables.

Activated Shell Contract

basectl activate <project> starts an interactive Base Bash runtime shell with Base's runtime rcfile. The caller's login shell can be Bash, Zsh, or another shell, but activation itself is Bash so Base can load the Bash standard library, project virtual environment, manifest-declared activate.source scripts, and runtime prompt consistently.

The activated shell inherits the activate invocation's run context only while its rcfile performs startup, so startup diagnostics stay in the activation run bundle. The rcfile clears launcher-only run and history variables before the prompt; recordable basectl commands entered interactively therefore follow the normal policy for independent run bundles and history rows. When the shell exits, the waiting activation launcher finalizes the activation bundle with the shell's exit status and records the single activate history row.

BASE_ACTIVATE_SHELL may point to a different Bash executable, such as a Homebrew-managed Bash. It must not point to Zsh or another non-Bash shell. Base rejects non-Bash values before launch so users see a direct configuration error instead of a Bash-rcfile failure from the target shell.

Zsh-specific aliases, options, completions, and prompt customizations are not loaded in the activated Base runtime shell. Put shell-neutral shared settings in ~/.baserc or project activation scripts when they need to apply to Base runtime activation.