Base

August 24, 2026 · View on GitHub

Status: maintained product and technical reference Last reviewed: 2026-08-15

What It Is

Base is a macOS-first local operating contract for developers who work across multiple independent Git repositories checked out side by side under a shared directory (typically ~/work/). Rather than forcing unrelated codebases into a monorepo, Base makes the repository set understandable, locally ready, explicitly trusted, onboardable, and transferable through one inspectable CLI contract.

Its durable product loop is:

inventory -> prepare -> verify -> trust -> onboard -> hand off

The basectl CLI provides the execution surface for that loop, including setup, diagnostics, project discovery, shell activation, test execution, and releases.

The repo you check out once per workspace so all other repos become easier to set up, test, and run.

Why It Exists

Multi-repo development has a recurring problem: every project has a different bootstrap story, and the glue between projects — shared env vars, shared tools, consistent shell environments — lives in fragile ad-hoc dotfiles or one-off scripts. Base formalizes that glue without absorbing project-specific logic.

It gives the repository set a common, inspectable operating contract:

  1. Inventory — identify participating repositories and their declarations.
  2. Prepare — reconcile the tools and environments those declarations need.
  3. Verify and trust — report readiness and require explicit consent before running project-owned commands.
  4. Onboard and hand off — guide first use and preserve local evidence for the next implementer without taking project behavior away from its owner.

Target Workspace Shape

~/work/
  base/           ← Base itself (source checkout or Homebrew install)
  project-a/      ← has base_manifest.yaml
  project-b/      ← has base_manifest.yaml
  infra/          ← another peer repo opted into Base

Projects opt in by placing a base_manifest.yaml at their root. Base discovers them by scanning the workspace root.

Tech Stack

LayerTechnology
OrchestrationBash 4.2+
Data / artifactsPython 3.10+
CLI frameworkClick (wrapped by base_cli)
Manifest formatYAML (base_manifest.yaml)
Package managementHomebrew (tools), pip/venv (Python)
Runtime versioningmise (optional, per-project)
TestingBATS (Bash), pytest (Python)
Static analysisShellCheck, Pylint, Bandit, pip-audit
CIGitHub Actions (tests, lint, skills)

Shell Environment Architecture: Three Layers

These are shell environment layers, not the product responsibility tiers described in the architecture reference.

Shell Layer 1 — Dotfile integration (basectl update-profile)

Manages small marked sections in ~/.bash_profile, ~/.bashrc, ~/.zprofile, and ~/.zshrc. Adds $BASE_HOME/bin to PATH. Never takes over whole dotfiles. Markers look like:

# >>> base: bashrc managed >>>
# ... Base-managed content ...
# <<< base: bashrc managed <<<

Shell Layer 2 — Base runtime (base_init.sh, sourced on every basectl invocation)

Exports BASE_HOME, BASE_BIN_DIR, BASE_BASH_LIB_DIR, BASE_BASH_LIBS_DIR, BASE_BASH_LIBS_SOURCE, BASE_OS, BASE_PLATFORM, BASE_HOST_ENV, BASE_HOST, and BASE_SHELL. Loads the Bash standard library from the resolved reusable library root. Sets up import_base_lib for convention-based library imports from that reusable root. The standalone install path and post-migration contract for those reusable libraries are documented in Base Bash Libraries.

Shell Layer 3 — Project environment (basectl activate <project>)

Spawns a Bash runtime shell, sets BASE_PROJECT, applies the project runtime route, runs activate.source scripts declared in the manifest, and updates the prompt to [project: branch] ~/path $. Python projects activate their selected project venv. Shell-only setup/check/doctor work does not create one solely for Base's runtime. Exit that shell to return to the original environment - no deactivation logic needed.

Design choice — no cd-triggered activation: switching directories does not change environment. Users explicitly activate projects with basectl activate. This is deliberate; auto-activation on cd is ambiguous and error-prone.

Project Manifest Contract

Each project opts into Base with a small declarative YAML file at its root. All fields are optional:

schema_version: 1

project:
  name: example

brewfile: Brewfile          # delegates to brew bundle
mise: .mise.toml            # delegates to mise install

artifacts:                  # Python packages → project venv
  - type: python-package
    name: requests
    version: latest

health:
  required_env: [DATABASE_URL]
  required_ports:
    - { name: postgres, port: 5432, state: listening }

activate:
  source: [.base/activate.sh]

test:
  command: pytest tests/    # or: mise: test

commands:
  dev: uvicorn app:app --reload
  lint: ruff check .

build:
  default: [api]
  targets:
    api:
      command: go build ./cmd/api
      working_dir: services/api

ide:
  vs-code:
    extensions: [ms-python.python]

release:
  version_file: VERSION
  changelog: CHANGELOG.md

Design principle: manifests describe what the project needs, not how to do arbitrary setup. There are no setup hooks. Projects delegate to Homebrew, mise, and their own build systems. See Setup Hooks Boundary.

Key Commands

Install and Bootstrap

CommandWhat it does
basectl setup [project] [--profile dev|sre|ai|linux-lab]Install / reconcile prerequisites
basectl update-profile [--defaults]Wire shell startup files
basectl update [project] [--dry-run]Upgrade Base or a Base-managed project checkout
basectl onboard [project]Guided first-run checklist

Daily Loop

CommandWhat it does
basectl projects list [--format json]Discover all Base-managed projects
basectl activate <project> [--no-cd]Spawn project subshell
basectl test [project] [-- args]Run the declared test command for the explicit, positional, or nearest project
basectl run [project] <cmd> [-- args]Run a named manifest command for the explicit, positional, or nearest project
basectl build [project] [targets] [--list|--dry-run]Run build targets for the explicit, positional, or nearest project
basectl demo [project] [--non-interactive]Run project demo script
basectl export-context [project]Generate AI context pack from .ai-context/
basectl devcontainer [project]Preview or write .devcontainer/devcontainer.json from manifest metadata
basectl devenv-report [project]Classify manifest compatibility for Nix/devenv planning
basectl prompt <list|name>List or render repo-owned AI workflow prompts

Diagnostics

CommandWhat it does
basectl check [project] [--profile]Quick pass/fail readiness check
basectl doctor [project] [--profile]Human-readable findings + fix commands
basectl logs [--tail|--command|--latest|--open]Inspect runtime logs
basectl history [--format json]Inspect structured local command history with ordering and time-window filters
basectl history --report [--format json]Summarize local command history and log metadata without raw log dumps
basectl config path|show|doctorMachine-local config
basectl clean [--older-than|--keep-last] [--yes]Preview completed-run/cache pruning; require --yes to delete and retain active runs

Workspace

CommandWhat it does
basectl workspace status/check/doctor [--manifest] [--format json]Read-only cross-project manifest, venv, Git, check, and diagnostic state
basectl workspace onboarding [--manifest] [--format json]Read-only first-day state and next actions for expected repositories
basectl workspace agent-brief [--manifest] [--format json]Read-only baseline, guidance, context, environment, and validation evidence for expected and extra Base-managed repositories
basectl workspace clone [--manifest] [--dry-run]Explicitly clone or validate expected repositories from a workspace manifest
basectl workspace pull [--source] [--manifest] [--dry-run]Explicitly refresh the local workspace manifest from a validated source
basectl workspace update [--manifest] [--dry-run]Run git pull --ff-only across existing repositories in manifest order
basectl workspace check [--manifest]Cross-project readiness check
basectl workspace doctor [--manifest]Cross-project diagnostic findings

Repository and Release

CommandWhat it does
basectl repo init <name> [--repo owner/name]Create a Base-managed repo baseline; use --agent-ready to include AGENTS.md and skills.md, --language <csv> to seed normalized project.languages metadata, --path . for the current checkout, and --pr --issue <number> when baseline changes should be pushed through a PR
basectl repo check [path] [--format json]Validate repo baseline; use --agent-ready for the baseline-integrated agent guidance contract
basectl repo configure [path]Repair / standardize repo settings
basectl repo agent-guidance [path]Seed AI guidance for a repo
basectl release check [--format json]|plan|notes|publishRelease readiness + guarded publishing

CI

CommandWhat it does
basectl setup|check|doctor --ci [--format json]CI-safe setup/readiness/diagnostics

Prerequisite profiles (compose with commas: --profile dev,linux-lab):

ProfileInstalls
devBATS, GitHub CLI, ShellCheck
srekubectl, helm, k9s, jq, yq, httpie, nmap, mtr
aiCodex CLI, Claude Code
linux-labMultipass for local Ubuntu lab VMs on macOS hosts

Installation Paths

MethodBest for
curl … bootstrap.sh | bashBlank macOS machine; installs Homebrew, Git, Bash, then Base
brew trust basefoundry/base + brew install basefoundry/base/baseUsers wanting Base installed as a managed tool
git clone + basectl setupContributors / Base developers
curl … install.sh | bashSource-install shortcut

Homebrew installs should trust the basefoundry/base tap before installing Base. The tap owns both base and the base-bash-libs dependency, and the trust command is safe to rerun on machines that already trust the tap.

All paths converge on the same daily command surface. After any install, finish with:

basectl setup
basectl update-profile
exec "$SHELL" -l

Key File Locations

PathPurpose
~/.base.d/config.yamlMachine-local config (workspace root, workspace manifest, canonical manifest source, log level)
<project-root>/.venvDefault non-Base project Python virtual environment when the manifest declares python: or python-package artifacts; not created for shell-only control-plane work
~/.base.d/<project>/.venvHistorical external project Python virtual environment when python.venv_location: external is set
~/.base.d/<project>/checks/last.jsonLatest recorded basectl check <project> result used by workspace status
~/Library/Caches/base/Runtime logs, temp files, project discovery cache
~/.basercUser preferences (e.g., BASE_DEBUG=1)
~/.base.d/profile.confShell defaults opt-in state

Testing

LayerToolWhere
Bash unit testsBATScli/bash/commands/basectl/tests/, lib/bash/*/tests/
Python unit testspytestcli/python/*/tests/, lib/python/*/tests/
Integration testsBATStests/integration/base_workflows.bats
Shell static analysisShellCheckAll *.sh files
Python lintPylintcli/python/, lib/python/ (3.10–3.13 matrix)
Python security scanBanditcli/python/, lib/python/
Python dependency auditpip-auditrequirements-dev.txt

Run everything locally with basectl test base or bin/base-test.

Current Status

Base 1.8.0 (August 2026) covers: first-mile bootstrap.sh installation, setup, check, doctor, project discovery, workspace status/check/doctor/clone/pull/init/configure, basectl onboard, project activation (subshell), test execution, build targets, named commands, demo scripts, explicit python.manager: uv project support, standalone and source-checkout base-bash-libs consumption, repository baseline creation, guarded GitHub release publishing, AI context export, repo-owned prompt rendering, local command history, manifest-declared PR policy, Base-managed artifact declarations, --ci mode for non-interactive CI, IDE bootstrapping (VS Code/Cursor), release readiness inspection, the basectl docs documentation shortcut, CI setup JSON output improvements, CI supply-chain policy enforcement, pinned Homebrew installer variables for verified first-mile bootstrap, and apt-backed Ubuntu/Debian setup support.

The setup/check/doctor platform contract is implemented for macOS and Ubuntu/Debian Linux. Broader Linux families, WSL, and native Windows remain outside the supported contract unless a later platform policy explicitly adds them.

Where to Go Next