basectl Quick Reference

September 1, 2026 ยท View on GitHub

Status: maintained command reference Last reviewed: 2026-07-25

This page is a compact lookup table for the current basectl command surface. Run basectl help <nested path> or append --help to that path for the same leaf-specific usage. Run basectl --help for the journey-oriented command map.

Use space-separated values for long options, for example --format json. Base rejects --option=value syntax before command delegation. Arguments after -- belong to the delegated project command and may use that command's native syntax.

For report commands documented with text|csv|tsv|yaml|json, an omitted --format (or --format text) is a pretty table on a terminal and headerless TSV when stdout is redirected. See Output formats for stable field order, JSON/YAML compatibility, stderr behavior, and the command-specific exceptions.

basectl exposes -v as the public command-level debug switch. Direct base_cli package standard options such as --debug, --quiet, --log-file, --config and --environment are private to Python package execution and are rejected by basectl. Use basectl --keep-temp <command> when temporary run files must be preserved for diagnosis; they are removed by default.

Stability Tiers

Commands documented here are stable public CLI unless a focused feature document explicitly marks the command, flag, output shape, or generated artifact as experimental. Prefer documented --format json payloads for automation and avoid scripting against human-readable tables, logs, or private base_cli package options.

See Base Stability Tiers for the full stable, experimental, and internal support contract. The four read-only control-plane payloads using the shared v1 envelope are defined in Inspection JSON.

Source Control And Forge Boundary

Base assumes Git as the source-control system. Non-Git SCMs such as Mercurial, Perforce, and Subversion are out of scope.

Base is GitHub-primary today. Local project commands work for non-GitHub Git repositories once they are checked out locally and declare base_manifest.yaml. Repository creation, cloning, configuration, issue, pull-request, Project, and release automation are GitHub-specific unless a command explicitly says otherwise. See Source Control And Forge Support for the full compatibility contract.

Install And Bootstrap

CommandWhat it doesImportant flags
basectl setup [project]Install or reconcile Base and optional project artifacts. Project-originated IDE app, extension, and user-setting mutations require separate approval.--ci, --format <text|json>, --profile <dev,sre,ai>, --dry-run, --manifest <path>, --allow-project-ide-mutations, --recreate-venv, --upgrade-pip, --notify, --no-notify
basectl update-profileCreate, refresh, or remove Base-managed Bash and Zsh startup snippets, backing up existing dotfiles before changes.--defaults, --no-defaults, --remove, --dry-run
basectl update [project]Update a Base-managed project checkout through Git, or update Base through Homebrew when Base is Homebrew-managed, then run setup for the selected project.--dry-run
basectl onboard [project]Guide first-run setup through check, setup, shell profile, doctor, project discovery, and read-only manifest trust status. Defaults to base.--profile <list>, --dry-run, --yes, --allow-project-ide-mutations, --no-profile
basectl versionShow the installed Base version.none

Daily Project Loop

CommandWhat it doesImportant flags
basectl projects listDiscover Base-managed projects under the workspace root.--workspace <path>, --format <text|csv|tsv|yaml|json>
basectl activate <project>Start an interactive Base Bash runtime shell for a project.--workspace <path>, --no-cd
basectl test [project]Run the project's declared test command from the project root.--project <name>, --workspace <path>, --dry-run, -- <args>
basectl run [project] <command>Run a named manifest command from the project root.--project <name>, --workspace <path>, --dry-run, -- <args>
basectl run [project] --listList runnable commands declared by a project manifest.--project <name>, --workspace <path>, --format <text|csv|tsv|yaml|json>
basectl build [project] [target...]Run declared build targets, or build.default when no target is provided.--project <name>, --workspace <path>, --dry-run, -- <args>
basectl build [project] --listList build targets declared by a project manifest.--project <name>, --workspace <path>, --format <text|csv|tsv|yaml|json>
basectl demo [project]Run a project-owned demo script.--project <name>, --workspace <path>, --dry-run, -- <args>
basectl devcontainer [project]Preview or write .devcontainer/devcontainer.json from a Base manifest. Dry-run is the default.--workspace <path>, --format <text|json>, --write
basectl devenv-report [project]Classify Base manifest fields for Nix/devenv planning without generating files or requiring Nix.--workspace <path>, --format <text|json>
basectl trust status [project]Show one project's manifest trust status, or all discovered command-bearing projects.--workspace <path>, --format <text|csv|tsv|yaml|json>
basectl trust allow <project>Approve the current manifest command contract on this machine.--workspace <path>, --manifest-sha256 <sha256>
basectl trust revoke <project>Remove local manifest command approval.--workspace <path>

Manifest-declared test, run, build, demo, and activation surfaces are project-owned code executed from the project root. Review manifests from unfamiliar repositories before running them; use --dry-run or --list where available and inspect activate.source directly before activation.

These four lifecycle commands use one project-selection order: --project <name>, then a backward-compatible first positional value when it names a registered project, then the nearest base_manifest.yaml from the current directory. If none applies, Base returns a controlled error. --workspace changes where named projects are discovered; it does not replace nearest- manifest traversal. From a workspace root with no project manifest, pass --project <name> or a registered positional project.

For run and build, a registered first positional value keeps its legacy project meaning even when the current manifest declares a command or target with the same name. Select the current project explicitly to disambiguate, for example basectl run --project current api or basectl build --project current api. Bash and Zsh completion use the same read-only resolution rules.

basectl run --list --format json and basectl build --list --format json are stable, side-effect-free automation contracts. Each object has schema_version: 1, a project object (name, root, manifest_path), and an ordered commands or targets array. Each command item has name, command, and runner (string or null). Each target item has name, working_dir, command, description (string or null), and runner (string or null). These keys are always present. Listing and completion read manifest metadata only: they do not execute project commands or grant manifest trust.

Diagnostics And Logs

CommandWhat it doesImportant flags
basectl setup --ci [project]Run setup with CI-safe defaults. Does not run tests or create runners/VMs.--format <text|json>, --manifest <path>, --profile <list>, --recreate-venv, --upgrade-pip
basectl check [project]Check Base readiness and, when selected by project name or --manifest, manifest-declared project requirements. It does not install or repair prerequisites, modify project files, or run tests. Normal runs write local logs/history; project checks also record ~/.base.d/<project>/checks/last.json.--ci, --profile <list>, --format <text|json>, --manifest <path>, --remote-network
basectl doctor [project]Explain Base and optional project findings with stable finding IDs and fixes.--ci, --profile <list>, --format <text|json>, --manifest <path>, --remote-network, --no-color
basectl doctor explain <finding-id>Print local, deterministic guidance for a stable finding ID.--format <text|json>
basectl logsList recent Base CLI runtime logs.--command <name[,name...]>, --limit <count>
basectl logs last-failedPrint the latest failed command metadata plus a bounded redacted log tail.--command <name[,name...]>, --lines <count>, --format <text|csv|tsv|yaml|json>
basectl logs --latestPrint the newest matching log path only.--command <name[,name...]>
basectl historyList one record per public Base command invocation.--project <name>, --command <name[,name...]>, --status <ok|warn|error>, --limit <count>, --format <text|csv|tsv|yaml|json>, --oldest-first, --last <duration>, --since <time>, --until <time>, --local-time
basectl history --reportPrint a local Markdown or JSON activity report from history and log metadata.--limit <count>, --format <markdown|json>, --oldest-first, --last <duration>, --since <time>, --until <time>, --local-time
basectl logs --openOpen the newest matching log in PAGER or EDITOR.--command <name[,name...]>
basectl logs --tailTail and follow the newest matching log.--command <name[,name...]>, --lines <count>
basectl cleanPreview cleanup of completed Base run bundles and component caches; use --yes to delete matches. Active runs are retained and reported.--older-than <age>, --keep-last <count>, --dry-run, --yes
basectl config pathPrint the local Base config path.none
basectl config showShow local Base config as redacted JSON.none
basectl config doctorDiagnose local Base config.none

Workspace

CommandWhat it doesImportant flags
basectl workspace statusShow read-only workspace project status and latest recorded project check dates. Uses workspace.manifest from user config unless --manifest is supplied.--workspace <path>, --manifest <path>, --format <text|csv|tsv|yaml|json>
basectl workspace checkRender check-oriented readiness state across workspace projects. Text output summarizes check names and messages; JSON keeps the diagnostic envelope. Uses workspace.manifest from user config unless --manifest is supplied.--workspace <path>, --manifest <path>, --format <text|csv|tsv|yaml|json>
basectl workspace doctorRender actionable workspace diagnostics with stable finding IDs and fix guidance. Uses workspace.manifest from user config unless --manifest is supplied.--workspace <path>, --manifest <path>, --format <text|csv|tsv|yaml|json>
basectl workspace onboardingSummarize expected-repository first-day state and next actions without cloning or setup. Requires a configured or explicit workspace manifest.--workspace <path>, --manifest <path>, --format <text|csv|tsv|yaml|json>
basectl workspace agent-briefReport local baseline, agent-guidance, AI-context, environment, and validation evidence for expected and extra Base-managed repositories without mutation or network calls. Requires a configured or explicit workspace manifest.--workspace <path>, --manifest <path>, --format <text|csv|tsv|yaml|json>
basectl workspace cloneClone or validate expected repositories from a workspace manifest. Missing-repository materialization is GitHub-only today because this path delegates to repo clone. Uses workspace.manifest from user config unless --manifest is supplied.--workspace <path>, --manifest <path>, --include-optional, --dry-run
basectl workspace pullExplicitly fetch and validate a canonical workspace manifest source before updating the local workspace manifest. Uses workspace.manifest_source and workspace.manifest from user config unless flags are supplied.--source <url-or-path>, --manifest <path>, --dry-run
basectl workspace updateRun git pull --ff-only across present repositories in manifest order, including the active Base checkout when it is the manifest's base target. Continues after failures, skips missing optional repositories, treats missing required repositories as failures, and reports updated/unchanged/skipped/failed counts.--workspace <path>, --manifest <path>, --dry-run
basectl workspace init <workspace-source>Initialize a workspace from a workspace configuration repository, update local workspace config, and optionally materialize member repositories.--owner <owner>, --path <path>, --workspace <path>, --manifest <path>, --include-optional, --dry-run
basectl workspace configureApply the existing repo configure repair path across discovered Base-managed workspace repositories or an explicit workspace manifest. Skips missing, non-Base-managed, or non-GitHub repos and continues after per-repo failures.--workspace <path>, --manifest <path>, --dry-run
basectl workspace setupSet up eligible repositories from a workspace manifest in manifest order by delegating to each repository's local basectl setup command. Skips ineligible repositories, continues after per-repo failures, and reports setup/skipped/failed counts.--workspace <path>, --manifest <path>, --dry-run, --yes

Repository And GitHub Workflow

This section is intentionally GitHub-specific except for local baseline inspection. Use ordinary Git to clone non-GitHub repositories, then use the daily project loop commands from the local checkout.

CommandWhat it doesImportant flags
basectl repo init <name>Create a Base-managed repository baseline, including .github/base-project.yml, and optionally create/configure the GitHub repo. Use --path . for the current checkout. If --repo creates a new remote, init attaches origin, creates an initial commit, and pushes; existing remotes are never implicitly pushed. Use --pr --issue <number> for an explicit baseline PR. Real PR runs derive the issue category; offline --pr --dry-run also requires --category <name>. Use --agent-ready to seed AGENTS.md and skills.md with the baseline. Use repeatable --language <csv> values to seed normalized project.languages metadata; selecting python also writes python.manager: uv.--path <path>, --repo <owner/name>, --issue <number>, --category <name>, --language <csv>, --description <text>, --license <SPDX>, --public, --private, --pr, --agent-ready, --project <title>, --project-owner <login>, --project-schema <schema>, --copy-project-fields-from <title>, --initiative-option <name>, --no-configure, --no-project, --no-protect-default-branch, --dry-run
basectl repo clone <name-or-owner/name>Clone one GitHub repository into the configured Base workspace, treating matching existing checkouts as already satisfied.--owner <owner>, --path <path>, --dry-run
basectl repo check [path]Verify the local repository baseline. Stable inspection JSON uses the shared v1 envelope.--agent-guidance, --agent-ready, --release, --format <text|json>
basectl repo configure [path]Apply Base-managed GitHub repository settings, labels, default branch protection, non-default branch naming enforcement, the trusted issue/category branch policy workflow, and repo Project metadata. After a default-branch dispatch produces a recent trusted success, its GitHub-Actions-bound PR-head status becomes required. Reads .github/base-project.yml to seed options and fill missing issue defaults when present.--repo <owner/name>, --project <title>, --project-owner <login>, --project-schema <schema>, --copy-project-fields-from <title>, --initiative-option <name>, --replace-project, --no-project, --no-protect-default-branch, --dry-run
basectl repo agent-guidance [path]Seed optional repo-local agent guidance files, optionally through a draft PR. Real PR runs derive the issue category; offline --pr --dry-run also requires --category <name>.--repo <owner/name>, --repo-name <name>, --default-branch <name>, --validation-command <cmd>, --issue <number>, --category <name>, --pr, --dry-run
basectl repo installer-template [path]Write the maintained project installer starter script to a path, defaulting to ./install.sh, optionally through a draft PR. Real PR runs derive the issue category; offline --pr --dry-run also requires --category <name>.--print, --repo <owner/name>, --issue <number>, --category <name>, --pr, --dry-run
basectl gh issue listList GitHub issues through gh.passes through gh options
basectl gh issue createCreate an issue with Base category conventions, assign it, and add repo Project metadata when the repo is known. Defaults to --category enhancement and Project Size=S when omitted. Project updates are limited to Projects linked to the issue repository unless --allow-cross-repo is explicitly supplied.--category <bug|enhancement|documentation|ci|security>, --title <title>, --body <body>, --repo <owner/name>, --project <title>, --project-owner <login>, --size <T|S|M|L>, --no-project, --allow-cross-repo
basectl gh issue readiness <number>Check whether an issue has the required body sections and, when Project coordinates are supplied, Base Project fields before assignment. Omitting Project coordinates reports a partial result. Stable inspection JSON uses the shared v1 envelope.--repo <owner/name>, --project-owner <login>, --project-number <number>, --format <text|json>
basectl gh issue start <number>Start the issue-backed branch workflow after verifying the issue has exactly one standard category; an explicit --category must match that label. The issue repository resolves from an explicit selector, then GH_REPO, then origin.--category <category>, --title <title>, --repo <owner/name>, -R <owner/name>
basectl gh auth statusInspect GitHub authentication state without displaying token values. Warns when an environment token takes precedence over stored credentials and distinguishes network failures from unavailable login.--hostname <host>
basectl gh auth refreshExplicitly refresh the stored GitHub credential and optionally request additional OAuth scopes. It does not alter GH_TOKEN or other environment-provided credentials.--hostname <host>, repeatable --scope <scope>, --scopes <scope,...>, --clipboard
basectl gh pr create/status/checks/ready/mergeCreate and manage pull requests through Base's workflow wrapper. pr create rejects a noncanonical current branch before invoking GitHub, auto-injects Fixes #<issue> unless --no-fixes is passed, and uses github.pr from base_manifest.yaml when present.passes through gh options; pr create also accepts --no-fixes
basectl gh branch staleReport stale local branches. Stable inspection JSON uses the shared v1 envelope.--days <days>, --format <text|json>
basectl gh branch prunePrune safe merged branches.--dry-run, --yes, --remote
basectl gh worktree prunePrune stale merged worktrees.--dry-run, --yes
basectl gh project doctorInspect GitHub Project metadata against the Base Project schema.--project <title>, --owner <login>, --schema base-project
basectl gh project configureCreate or repair Base-managed Project metadata.--project <title>, --owner <login>, --repo <owner/name>, --schema base-project, --config <path>, --copy-fields-from <title>, --replace-project, --initiative-option <name>, --dry-run
basectl gh project issue set-fields <number>Add an issue to the Project if needed and update metadata fields. The target Project must be linked to the issue repository unless the intentional cross-repository exception is enabled.--project <title>, --repo <owner/name>, --config <path>, --allow-cross-repo, field options

Release And Context

CommandWhat it doesImportant flags
basectl release check --version <version>Inspect release readiness without publishing. Supports all five report formats; JSON uses the shared v1 inspection envelope.--manifest <path>, --format <text|csv|tsv|yaml|json>
basectl release plan --version <version>Print the release plan and downstream handoff details.--manifest <path>
basectl release notes --version <version>Extract release notes for the requested version.--manifest <path>
basectl release publish --version <version>Create the annotated Git tag and GitHub Release only after the configured repository, origin fetch/push URLs, live remote default branch, and local full HEAD SHA match; recheck before tagging and verify the local, pushed, and GitHub tag SHAs.--manifest <path>, --dry-run, --yes
basectl docsOpen the Base documentation home page on GitHub.--show-url
basectl export-context [project]Export a project's .ai-context/ directory as Markdown or Zip.--workspace <path>, --format <markdown|zip>, --output <path>, --print, --list-files
basectl prompt listList repo-owned Markdown prompts that Base can render for AI-assisted workflows.none
basectl prompt product-self-reviewPrint the periodic Base product self-review prompt with current Base metadata.--output <path>

Detailed Product Layers And Shipped Commands

+## Product Layers And Shipped Commands

Deep reference: This section is intentionally skippable on a first read. It preserves the detailed command and runtime reference for contributors and evaluators; start with Quickstart, then use the focused Command Quick Reference and Technical Overview when you need command detail.

Base's primary product outcome is readiness and handoff. The command and runtime details below preserve discovery of the shipped execution contract, workflow packs, and adapters that support that outcome.

1. Core Outcome And Enabling Execution Contract

Base should give the user one entry point for setting up and validating a project or a workspace that contains multiple project repositories.

Current implemented commands include:

  • basectl setup [project]
  • basectl check
  • basectl doctor
  • basectl <setup|check|doctor> --ci [project]
  • basectl clean --older-than <age>
  • basectl clean --keep-last <count>
  • basectl config path
  • basectl config show
  • basectl config doctor
  • basectl update-profile
  • basectl update
  • basectl projects list
  • basectl workspace <status|check|doctor|onboarding|agent-brief|clone|pull|update|init|configure|setup>
  • basectl trust status [project]
  • basectl trust <allow|revoke> <project>
  • basectl repo init <name>
  • basectl repo clone <name-or-owner/name>
  • basectl repo check [path]
  • basectl repo configure [path]
  • basectl repo agent-guidance [path]
  • basectl repo installer-template [path]
  • basectl gh <area> <command>
  • basectl release check --version <version>
  • basectl release plan --version <version>
  • basectl release notes --version <version>
  • basectl release publish --version <version>
  • basectl prompt list
  • basectl prompt product-self-review
  • basectl activate <project>
  • basectl test [project]
  • basectl build [project] [target...]
  • basectl demo [project]
  • basectl run [project] <command>
  • basectl export-context [project]
  • basectl devcontainer [project]
  • basectl devenv-report [project]
  • basectl docs
  • basectl onboard
  • basectl history [--report]
  • basectl version

Use basectl --help for the journey-oriented command map. For a group or leaf, basectl help <nested path> and basectl <nested path> --help show the same public usage without exposing private Python runtime options.

--ci runs setup, check, and doctor with CI-safe defaults such as non-interactive behavior and JSON-capable output. The deprecated basectl ci compatibility alias remains available for v1.x consumers; use the flag on the underlying command for new scripts. The CI-safe lifecycle commands do not run project tests, launch GitHub Actions locally, or create Ubuntu/Multipass VMs. Use basectl test for a project's declared test command and bin/base-test for Base's full source-checkout validation suite. See CI-safe mode for the CI contract, and Command Quick Reference for a scannable command lookup table.

The important idea is that the user should not need to memorize a different bootstrap story for every repository in the workspace.

Base should be able to discover participating project repositories checked out under a shared workspace root, for example:

~/work/
  base/
  banyanlabs/
  bankbuddy/
  blend/
  brew/

Over time, each project repo can declare how Base should interact with it, likely through a small project manifest or well-defined conventions.

The first version of that manifest is base_manifest.yaml at a project repo root. It declares the project name and the project contracts Base should orchestrate:

schema_version: 1

project:
  name: example

brewfile: Brewfile

mise: .mise.toml

artifacts:
  - type: python-package
    name: requests
    version: latest

health:
  required_env:
    - DATABASE_URL
    - REDIS_URL
  required_ports:
    - name: postgres
      host: 127.0.0.1
      port: 5432
      state: listening
    - name: app
      port: 8000
      state: free

activate:
  source:
    - .base/activate.sh

test:
  command: pytest tests/

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

schema_version is optional for existing manifests and defaults to 1. It is an integer compatibility marker for the manifest contract, not a Base release number. Base rejects manifests with a newer schema version than it understands and asks the user to upgrade Base.

The manifest intentionally describes what the project needs and which project-owned commands Base should expose. Base's direction is delegation-first: use mature tools for the domains they already own, and keep Base responsible for participation semantics, readiness diagnostics, explicit execution trust, lifecycle guidance, onboarding, and handoff evidence. Project environments and command execution remain owned by their declared substrates.

Manifest-declared commands are trusted project code. Base executes test.command, build.targets.*.command, commands.*, demo.script, and activate.source entries from the project root. Review manifests from unfamiliar repositories before running basectl test, basectl build, basectl run, basectl demo, or manifest-backed basectl activate; use --dry-run and --list first for command surfaces that support read-only inspection, and inspect activate.source entries directly before activation. basectl check <project> and basectl doctor <project> include advisory command-lint warnings for obvious missing executables or project scripts; those warnings do not make an untrusted manifest safe to run. See Manifest Command Trust for the local allow flow before first execution of unfamiliar manifest commands.

The optional top-level brewfile field points to a Homebrew Brewfile relative to the project root. When present, basectl setup runs brew bundle --file=<project-root>/<brewfile> before reconciling artifacts. Use this for ordinary Homebrew formulae and casks instead of adding every Homebrew package to Base's hand-curated artifact registry.

The optional top-level health.required_env list declares environment variables the project needs in the local shell. basectl check <project> and basectl doctor <project> report whether those variables are present and non-empty. Base only checks presence; it never reads, prints, or logs the variable values.

The optional top-level health.required_ports list declares local TCP ports the project expects to be either listening or free. Each entry must include port and state; host defaults to 127.0.0.1, and name is an optional display label. Base checks whether a TCP connection succeeds on the declared endpoint. It does not start or stop services, inspect process ownership, or perform Docker Compose health checks.

The optional top-level activate.source list declares project-root-relative shell scripts to source when basectl activate <project> starts the runtime shell. Base sources those scripts after the Base runtime and project virtual environment are ready, rejects paths outside the project root, reports missing scripts clearly, and logs only the sourced script path.

Future manifest fields should follow the same rule. A mise field causes Base to run mise install from the project root when a project chooses that substrate. A test field gives basectl test a single project-owned command to run. A commands map gives basectl run named project commands that run from the project root with the same Base project environment contract as basectl test. Projects that keep tasks in mise can declare test.mise instead:

test:
  mise: test

commands:
  dev: mise run dev
  lint: mise run lint

Commands may declare a generic runner. The first supported runner is uv:

test:
  command: pytest
  runner: uv

commands:
  taxbuddy:
    command: taxbuddy
    runner: uv

runner: uv routes that command through uv run -- .... It is independent of the project-level Python manager, so composite projects can use uv for one Python utility while keeping other commands in Go, Node, shell, or mise.

For a polyglot project such as banyanlabs, keep Base at the workspace orchestration layer and let the language-native tools own their usual files. Base should see a small manifest contract:

schema_version: 1

project:
  name: banyanlabs

brewfile: Brewfile

mise: .mise.toml

test:
  mise: test

Then .mise.toml can pin the project runtimes and expose the task Base should delegate to:

[tools]
go = "1.22"
java = "temurin-21"

[tasks.test]
run = "go test ./... && ./gradlew test"

Use the Brewfile for ordinary workstation tools such as Maven, Gradle, golangci-lint, protobuf, or Docker-related CLIs when Homebrew is the right installer. Keep Go dependencies in go.mod/go.sum and Java dependencies in Maven or Gradle project files. Base does not need first-class go-package or java-package artifact types until it has a Base-specific behavior to add on top of those native ecosystems.

Base does not run arbitrary setup hooks from the manifest. Projects should use typed Base contracts or project-owned installers/tasks until there is an explicit, reviewable hook contract for when hooks run, where they run, whether they are interactive, and how dry-run/check/doctor report them. See Setup Hooks Boundary.

The curated built-in artifact registry lives in lib/base/artifact-registry.yaml using schema version 1, and cli/python/base_setup/registry.py loads and validates that data before setup, check, or doctor use it. The registry should stay small and Base-aware. python-package artifacts are pass-through PyPI package names and install into the project virtual environment at <project-root>/.venv for non-Base projects by default. Projects that need the historical external location can declare python.venv_location: external. Homebrew-managed tool artifacts currently support version: latest; basectl check and basectl doctor treat an installed but outdated Homebrew package as unhealthy, and basectl setup upgrades it. Ordinary Homebrew tools should move toward Brewfile delegation. Pinned Homebrew versions fail clearly until Base grows explicit versioned tool support. The registry boundary is captured in Artifact Adapter Registry.

The optional structured python: manifest section supports uv-managed Python projects:

python:
  manager: uv

For uv-managed projects, Base delegates setup to uv sync, uses the project-local .venv for activation and project commands, and skips Base-managed python-package reconciliation. See Python Manifest Section. Projects without a top-level python: section or any python-package artifacts are treated as shell-only for setup and diagnostics. Base parses and reconciles those manifests from its own runtime, does not create a project .venv for its control plane, and reports workspace venv state as not_applicable. An explicit python: {} keeps the existing Base-managed project venv contract; project.languages: [python] remains taxonomy only. Use basectl check <project> --format json for detailed runtime diagnostics and basectl workspace status --format json to compare actual project Python versions across a workspace.

Artifacts may include bootstrap: true when they are part of the minimum Python runtime contract needed before Base can reconcile a project's remaining artifacts. Base currently uses this marker in lib/base/default_manifest.yaml for click, PyYAML, and tomli for Python 3.10 TOML parsing.

You can inspect the projects Base can see with:

basectl projects list
basectl projects list --format json
basectl workspace status
basectl workspace status --format json
basectl workspace status --manifest ~/work/workspace.yaml
basectl workspace check
basectl workspace doctor
basectl workspace onboarding --manifest ~/work/workspace.yaml
basectl workspace agent-brief --manifest ~/work/workspace.yaml --format json
basectl workspace init basefoundry/base-workspace --dry-run
basectl workspace clone --manifest ~/work/workspace.yaml --dry-run
basectl workspace configure --dry-run
basectl workspace setup --manifest ~/work/workspace.yaml --dry-run
basectl workspace update --manifest ~/work/workspace.yaml --dry-run

By default this scans workspace.root from ~/.base.d/config.yaml when that value is configured. If it is not configured, Base falls back to the parent directory of BASE_HOME, which matches the source-checkout sibling-repo layout. Use --workspace <path> to inspect a different workspace root for one command. Project list output is tab-separated as <project-name><TAB><path>. In a source checkout, basectl projects list can run before basectl setup when the ambient python3 has Base's bootstrap Python dependencies available; otherwise it reports a targeted setup diagnostic. basectl projects list and the read-only workspace status, doctor, onboarding, and agent-brief commands support --format json for machine-readable output. Workspace clone, pull, init, configure, and setup use text output only. Status reports each discovered project's manifest validity, whether the Base-managed project virtual environment is present, and the latest recorded basectl check <project> or basectl workspace check date when one exists. Check records live under ~/.base.d/<project>/checks/last.json; status JSON includes the full timestamp and recorded check status. Check and doctor run project diagnostics across discovered projects and keep invalid project manifests visible as per-project findings. Workspace check also refreshes each checked project's last-check record after rendering its report; record-write failures are logged without changing the diagnostic result.

basectl workspace onboarding is also shipped. It summarizes first-day workspace onboarding from a workspace manifest without cloning repositories or running setup. It reports ready, needs-setup, invalid-manifest, missing-required, and missing-optional repository states with next actions as a read-only text or JSON view.

basectl workspace agent-brief turns the same manifest and local repository state into a handoff-readiness view. It includes expected repositories and extra locally discovered Base-managed projects, then reports repository baseline, agent-guidance, .ai-context, environment, and validation evidence. Readiness is structural: a ready repository has a valid manifest, an executable interpreter file at the expected project-environment path, complete Base baseline and agent-guidance file contracts, and an available validation path. The executable interpreter is reported as present_unverified; the brief never executes it. The recommended repository check and validation commands still need to run separately and may fail. .ai-context is reported as useful context, not required by the existing agent-ready repository contract. Present repositories without a Base manifest remain unmanaged; the brief reports generic guidance, context, and validation evidence when available but does not recommend Base adoption. The command does not clone, run setup or validation, mutate repository checkouts, update workspace manifests, write repo guidance or context, or make network calls.

Set workspace.manifest in ~/.base.d/config.yaml, or use --manifest <path> with basectl workspace status, check, doctor, onboarding, or agent-brief, to include expected repositories from a local workspace manifest. The command-line --manifest value takes precedence over the configured manifest. Missing required repositories are errors, missing optional repositories are warnings, and Base-managed projects outside the manifest stay visible as warnings.

Use basectl workspace clone --manifest <path>, or configure workspace.manifest, to materialize the missing required GitHub repositories from that manifest. The command keeps existing repositories visible, delegates each repository operation to basectl repo clone, and supports --dry-run for a no-write preview. Optional repositories are reported but skipped unless --include-optional is supplied. Workspace manifests may list non-GitHub Git URLs for reporting, but automatic materialization through workspace clone is GitHub-only today; clone GitLab, Bitbucket, internal Git, or local repositories with ordinary Git first, then let Base discover the local checkout.

An external multi-repository manager may materialize repositories before Base discovers opted-in projects. Base does not currently import or synchronize mani.yaml, the clone configuration emitted by gita freeze, .repos, Android Repo manifests, or west.yml. Until a separately designed adapter exists, either let the external tool remain the only repository-set authority and use Base's local discovery, or maintain a deliberate Base workspace manifest for Base-specific expected-set semantics.

Use basectl workspace init <workspace-source> for first-run bootstrap from a workspace configuration repository. The source can be a local path, GitHub URL, owner/repo, or a short repository name resolved with --owner <owner> or github.default_owner. --path <path> controls where the workspace configuration repo is checked out or read. --workspace <path> controls where member repositories are cloned. Init validates workspace.yaml before materializing member repositories and then delegates those clones through basectl workspace clone.

Use basectl workspace pull, or basectl workspace pull --dry-run, when workspace.manifest_source and workspace.manifest are configured to refresh a local workspace manifest explicitly. --source <url-or-path> and --manifest <path> override those configured values for one command. Pull validates the fetched manifest before writing and never mutates project repositories.

Use basectl workspace update --dry-run to preview running git pull --ff-only across the existing repositories in manifest order, then run basectl workspace update to apply it. Update never clones, resets, or changes the workspace manifest. It continues after individual Git failures, reports updated/unchanged/skipped/failed counts, skips missing optional repositories, and treats missing required repositories as failures. If the manifest points at the active BASE_HOME/base checkout, that control plane is skipped; a separate workspace checkout of base is updated normally. Text output uses a stable repository/action/result table; raw Git output is retained for debug diagnostics, and failures include concise repository and exit details.

Use basectl workspace configure --dry-run to preview applying basectl repo configure across Base-managed repositories in the workspace, then run basectl workspace configure to apply the repair path. With --manifest <path>, Base walks the expected repository set, skips missing or non-Base-managed repositories, and continues after per-repo failures. Without a manifest, Base scans discovered local Base-managed projects under the workspace root. This is the fastest way to roll out shared repo or Project schema repairs across a local repository set while keeping each repository's repo configure behavior idempotent.

Use basectl workspace setup --dry-run to preview project setup across the expected repositories, then run basectl workspace setup to execute it. Setup walks the manifest in order, skips the active base control plane and repositories that are not eligible for Base setup, and delegates each eligible repository to its local basectl setup --manifest <path> <project> command. Use --yes to forward setup confirmation to each delegated command. A setup failure does not prevent later repositories from running; the final counts report setup, skipped, and failed repositories and the command exits nonzero when any setup target fails. Required missing checkouts and invalid required manifests are also reported as failures during a dry run, so the preview can be used as a CI gate without modifying repositories.

Start a new Base-managed repository with:

basectl repo init example --repo basefoundry/example

This creates the local repository baseline: README, version, changelog, contributing guide, Apache-2.0 license, .gitignore, base_manifest.yaml, a tests/validate.sh contract, and a GitHub Actions workflow that runs it. By default, repo init creates the repository under workspace.root from ~/.base.d/config.yaml; if that is not configured, it falls back to the parent directory of BASE_HOME. Use --path <path> for an explicit location. When refreshing the current checkout, pass the repository name plus --path .; . is a path value, not the repo init name. repo init also creates the GitHub repository when needed and then standardizes its settings when --repo <owner/name> is provided or when an existing origin remote can be inferred. Newly created GitHub repositories are private by default; pass --public when a public repository is intentional. When repo init creates the remote, it also attaches origin, creates an initial commit, and pushes the current branch. Existing remotes are never implicitly pushed. Use --pr --issue <number> on an existing clean Git worktree to commit baseline changes on a canonical issue-backed branch, push that branch to origin, and open a pull request. Use --no-configure to skip the GitHub step, or rerun it later with basectl repo configure. The generated license defaults to Apache-2.0, matching Base. Real PR runs derive and verify the issue category; offline --pr --dry-run previews also require --category <name>. Add --agent-ready when a new baseline should also include AGENTS.md and skills.md for repo-local agent workflow guidance. Use repeatable --language <csv> values to record an explicit, normalized polyglot profile in project.languages; selecting python also generates the explicit python.manager: uv manifest contract.

Clone an existing GitHub repository into the configured workspace with:

basectl repo clone basefoundry/example
basectl repo clone example --owner basefoundry

Short names can use github.default_owner from ~/.base.d/config.yaml. Without --path, repo clone writes to <workspace.root>/<repo>, and --dry-run prints the resolved repository, destination, clone tool, and clone URL without touching the filesystem. Existing matching checkouts are treated as already satisfied; conflicting destinations fail with guidance.

repo clone and repo configure are GitHub automation surfaces. For non-GitHub Git repositories, use the forge's normal Git clone path and then use Base's local project loop from the resulting checkout.

Check and repair the repo baseline with:

basectl repo check ~/work/example
basectl repo check ~/work/example --format json
basectl repo configure ~/work/example --repo basefoundry/example

The JSON form is a stable v1 inspection contract for automation. The same envelope is available from release readiness, issue readiness, and stale-branch inspection; see Inspection JSON.

Seed optional repo-local agent guidance with:

basectl repo init example --repo basefoundry/example --agent-ready
basectl repo agent-guidance ~/work/example --repo-name example
basectl repo agent-guidance ~/work/example --repo-name example --issue 123 --category enhancement --pr --dry-run
basectl repo check ~/work/example --agent-guidance
basectl repo check ~/work/example --agent-ready

Use repo init --agent-ready for new baselines that should include agent guidance from the first pull request. Use repo agent-guidance to add or repair that optional layer in an existing repository. Use repo check --agent-ready when a repo should satisfy the baseline-integrated agent readiness contract.

Use --pr --issue <number> on repo agent-guidance or repo installer-template when the generated helper files should go through review first. The target must be a clean Git worktree, the GitHub repository is inferred from origin unless --repo <owner/name> is provided, and the opened pull request is a draft on the canonical issue-backed branch. Real PR runs derive and verify the issue's standard category label; offline --pr --dry-run previews require --category <name> explicitly.

repo configure is intentionally idempotent. It enables Issues and Projects, standardizes merge settings, deletes branches after merge, applies the Base-managed default branch protection and branch naming rulesets, seeds the trusted Issue Branch Policy workflow, configures a repo-named GitHub Project copied from base-project-template, and creates the standard GitHub labels documented in Repository Baseline. Once that workflow is active and a default-branch dispatch has produced a recent trusted success, rerunning repo configure makes its GitHub-Actions-bound base/issue-branch-policy PR-head status required without weakening an existing requirement when run history expires. When .github/base-project.yml exists, repo configure also adds missing shared Project field options, adds repo-specific Area and Initiative Project options from that file, and applies its issue_defaults to Project issue items that are missing those values. repo init also seeds .github/workflows/project-intake.yml, a visible fallback for issues created outside basectl gh issue create. repo configure creates the workflow when it is missing from older Base-managed repositories. The baseline also includes .github/workflows/issue-branch-policy.yml, which does not require a secret, never checks out pull-request code, and automatically queues default-branch revalidation for matching open pull requests when an issue category label changes. Set a BASE_PROJECT_TOKEN Actions secret with Project write access so that workflow can add issue items and apply the repo Project defaults on issue open, reopen, and close events. repo configure checks for that secret when Project support is enabled and prints a gh secret set BASE_PROJECT_TOKEN command when the required secret is missing. Pass --no-protect-default-branch when a repository intentionally skips that ruleset. Pass --no-project when a repository intentionally skips Base-managed Project metadata, or --project, --project-owner, and --initiative-option when the default Project title or Initiative values need to vary by repository. During Project migration, pass --copy-project-fields-from <title> to copy missing issue item field values from an existing Project into the repo Project without overwriting values that are already set. When an existing repo Project has the right fields and issue items but the wrong GitHub view layout, pass --replace-project to replace it from base-project-template. Base renames and closes the old Project as a legacy archive, creates a fresh Project with the original title, links it to the repo, backfills repo issues, and copies missing issue item fields from the legacy Project before applying repo defaults. The repaired Project gets a new Project number and URL. If the existing Project already has the standard Base views, --replace-project leaves it intact and continues normal metadata repair.

Run a discovered project's declared test command with:

basectl test example

When the current directory is inside a Base-managed project, the project name can be omitted:

basectl test

Base runs the manifest test.command or mise run <test.mise> from the project root, exports BASE_PROJECT, BASE_PROJECT_ROOT, BASE_PROJECT_MANIFEST, and BASE_PROJECT_VENV_DIR, prepends the project virtual environment when it exists, and returns the command's exit status. Use --dry-run to inspect the resolved command without running it.

Pass additional arguments to the project's test command after --:

basectl test example -- -k focused_case

For test.mise, Base passes those arguments after mise run <task> --.

Run a discovered project's declared build targets with:

basectl build
basectl build example
basectl build example api worker
basectl build --project example api worker

The build contract is intentionally declarative. Base does not infer how to compile Go, Java, C++, Node.js, or any other language. The project declares the targets it owns:

build:
  default:
    - api
    - worker
  targets:
    api:
      description: Build the API service.
      working_dir: services/api
      command: go build ./cmd/api
    worker:
      description: Build the worker service.
      working_dir: services/worker
      command: go build ./cmd/worker

basectl build [project] runs build.default sequentially. basectl build [project] <target> [target...] runs only the named targets. Base exports the same project environment variables as basectl test, prepends the project virtual environment when it exists, changes into each target's working_dir, and returns the first failing build command's exit status.

Use --list or --dry-run to inspect the manifest contract:

basectl build example --list
basectl build --list --format json
basectl build example --dry-run

Run other manifest-declared project commands with:

basectl run dev
basectl run example dev
basectl run example lint
basectl run --project example dev

The commands map is intentionally small and declarative:

commands:
  dev: uvicorn app:app --reload
  audit:
    command: pytest tests/audit
    runner: uv
  lint: ruff check .
  format: ruff format .

basectl run [project] <command> runs the command from the project root, exports the same BASE_PROJECT, BASE_PROJECT_ROOT, BASE_PROJECT_MANIFEST, and BASE_PROJECT_VENV_DIR variables as basectl test, prepends the project virtual environment when it exists, and returns the command's exit status. Use basectl run [project] --list to see a project's runnable commands. When the current directory is inside a Base-managed project, basectl run --list lists that project.

run, build, test, and demo select projects in one order: explicit --project <name>, a backward-compatible first positional project when that name is registered, then the nearest base_manifest.yaml. At a workspace root with no nearest manifest, pass --project or a registered positional project. --workspace controls named-project discovery and does not scan arbitrary directories. If a current command or build target has the same name as a registered project, the legacy project interpretation wins; use --project <current-name> to select the current command or target explicitly.

basectl run --list --format json and basectl build --list --format json return stable schema_version: 1 objects for automation. These list paths only read manifest metadata; they do not execute commands or grant manifest trust.

Pass additional arguments after --:

basectl run example lint -- --fix

The command name test is reserved for the top-level test contract, so basectl run example test delegates to the same command as basectl test example.

Export a project's AI context pack with:

basectl export-context example
basectl export-context example --format zip --output /tmp/example-ai-context.zip
basectl export-context --print
basectl export-context --list-files

basectl export-context reads .ai-context/ from the current or named Base-managed project. Markdown exports combine context Markdown files with stable source headings, using .ai-context/INDEX.md order when available and falling back to deterministic filename order for unlisted files. Zip exports contain only files from .ai-context/ so they can be uploaded manually. Exports fail closed on a symlinked context root, symlinked descendants, and special files; only regular files stored inside the real context directory are eligible.

Preview a Dev Containers configuration from a project manifest with:

basectl devcontainer example
basectl devcontainer example --format json
basectl devcontainer example --write

basectl devcontainer is dry-run by default and reports unsupported or ambiguous manifest fields instead of guessing container behavior. --write creates .devcontainer/devcontainer.json only when that file does not already exist.

Inspect Nix/devenv compatibility without generating files with:

basectl devenv-report example
basectl devenv-report example --format json

basectl devenv-report classifies present manifest fields as supported, unsupported, lossy, or project-owned so teams can evaluate Nix/devenv adoption without installing or invoking Nix.

Open Base's documentation home page on GitHub with:

basectl docs
basectl docs --show-url

basectl docs opens the GitHub README because the README is the starting point for the rest of Base's documentation. Use --show-url to print the URL without opening a browser.

Print repo-owned AI workflow prompts with:

basectl prompt list
basectl prompt product-self-review
basectl prompt product-self-review --output /tmp/base-product-self-review.md

basectl prompt renders maintained Markdown prompts from Base's repo-visible prompt library. The command prints prompts to stdout by default and can write rendered Markdown to a path with --output; Base does not run the review or send the prompt to any provider. The first built-in prompt, product-self-review, is the periodic product assessment ritual for revisiting Base's originality, usefulness, adoption potential, creator-skill evidence, risks, and next directions.

Once a project is discoverable, activate it with:

basectl activate example

Activation spawns a project-specific Bash runtime shell, changes to the project root, sets BASE_PROJECT and related project variables, adds project-owned commands from $PROJECT_ROOT/bin when that directory exists, and activates the project virtual environment at <project-root>/.venv by default. If the manifest declares activate.source, Base then sources each declared script in order. Exit that shell to return to the original environment.

The activated runtime shell is always Bash, even when the user's login shell is Zsh. BASE_ACTIVATE_SHELL may point to another Bash executable, but it must not point to Zsh or another non-Bash shell. Zsh-specific aliases, options, completions, and prompt customizations are not loaded inside the activated Base runtime shell.

Use basectl activate example --no-cd to keep the caller's current directory while still loading the selected project's Base runtime environment.

Invoking basectl with no arguments in a terminal starts the default interactive Base shell. It uses the nearest base_manifest.yaml above the current directory to choose the active project, then preserves the current directory. If no project manifest is found, it falls back to the base project.

Clean old Base CLI runtime logs, retained temp files, and cache entries with:

basectl clean --older-than 30d --dry-run
basectl clean --older-than 30d
basectl clean --keep-last 20
basectl clean --older-than 30d --keep-last 20

Cleanup only targets runtime artifacts under the Base cache root, which defaults to ~/Library/Caches/base on macOS. Set BASE_CACHE_DIR to override it. Durable state such as ~/.base.d/config.yaml, Base's own venv, and project virtual environments are outside this scope.

Show recent Base CLI logs with:

basectl logs
basectl logs --command setup,check
basectl logs --latest
basectl logs --open
basectl logs --tail
basectl logs -v

basectl logs is read-only. It lists the newest runtime logs under the Base cache root so failed Python-layer runs can be inspected without rerunning with debug output enabled. It supports -v/--debug for its own diagnostics without creating a new default log entry for the inspection run.

Show recent structured Base command history with:

basectl history
basectl history --project base
basectl history --command check --status error
basectl history --format json
basectl history --report
basectl history --report --format json
basectl history --oldest-first
basectl history --last 2h --oldest-first
basectl history --since 2026-07-17 --until 2026-07-18
basectl history --local-time

basectl history reads the local Base history index at <base-cache-root>/base/history/runs.jsonl. Each invocation also has a run-oriented bundle under <base-cache-root>/base/runs/<run-id>/, while project-native commands use <base-cache-root>/projects/<project>/<checkout>/. The default view shows one row per public basectl command. Delegated Python and resolver steps share that invocation's run ID and logs/primary.log; they are not separate history records. History records point to raw logs instead of replacing them, and malformed or legacy internal rows are ignored while listing recent runs. --report prints a privacy-conscious local activity summary with recent commands, failure counts, common failing command families, and log file locations. Use --oldest-first for chronological display, --last 2h for a relative window, or --since/--until for explicit bounds. Text and Markdown timestamps use UTC by default; --local-time renders those views in the host's local timezone. JSON retains canonical UTC timestamps. Reports do not include raw log contents, compact home paths to ~, and redact secret-looking arguments and URL credentials. The broader local diagnostic report model is described in docs/observability.md.

Inspect machine-local Base config with:

basectl config path
basectl config show
basectl config doctor

Base creates ~/.base.d/config.yaml with a small first-run default when the file is missing, then leaves user edits and symlinks alone. Base owns the meaning of that file, but users own how it is edited, backed up, or synced. config show prints redacted JSON for routine inspection; Base config is not a secret store. See docs/local-config.md.

Inspect release readiness for a Base-managed repository with:

basectl release check --version 1.8.0
basectl release check --version 1.8.0 --format json
basectl release plan --version 1.8.0
basectl release notes --version 1.8.0
basectl release publish --version 1.8.0 --dry-run
basectl release publish --version 1.8.0 --yes

basectl release check|plan|notes are read-only. They validate the manifest release contract, version file, changelog section, Git worktree state, GitHub CLI authentication, local and remote tag availability, and planned downstream handoffs. basectl release publish reuses those checks, requires confirmation unless --yes is supplied, creates an annotated tag, pushes the tag, and creates the GitHub Release from the matching changelog section. Homebrew tap updates remain a manual handoff printed by the command.

Use --keep-last <count> to retain the newest completed run bundles per owner namespace. --older-than removes completed bundles and persistent component caches by age; active bundles and durable ~/.base.d state are never removed.

Use basectl doctor when you want a human-oriented diagnosis with suggested fixes. Each finding includes a stable identifier that automation can use instead of matching on human-readable messages; see docs/doctor-findings.md. basectl check and basectl doctor validate virtual environment integrity, not just path existence, and recommend --recreate-venv when a Base-managed venv is broken.

basectl doctor
basectl doctor --profile dev
basectl doctor --profile sre

basectl check <project> and basectl doctor <project> extend those checks to a project's base_manifest.yaml artifacts after verifying the Base bootstrap environment:

basectl check example
basectl doctor example

basectl onboard [project] provides a guided checklist for technically-adjacent users who want a first Base setup flow around check, setup, profile refresh, doctor, and project discovery. It defaults to base, and can target another Base-managed project for the check/setup/doctor steps. Product-specific onboarding should still live in project installers that call Base internally. See docs/basectl-onboard.md.

Today, basectl workspace agent-brief, onboarding output, stable diagnostics, basectl history --report, and basectl export-context provide local evidence for a manual handoff. The separate issue-oriented handoff bundle remains planned in #1562; Base does not yet package branch, issue, history, diagnostics, and context exports into a single artifact.

Base can also bootstrap supported IDEs for participating projects through the optional ide: manifest section. It currently supports VS Code and Cursor app installation, extension installation, additive user settings, and check/doctor diagnostics. See docs/ide-bootstrapping.md.

2. Enabling Execution Contract: Shell Environment

Base should manage shell environments at two levels:

  • global environment shared across the whole workspace
  • project-specific environment layered on top for an individual repo

That includes things like:

  • common shell initialization
  • PATH management
  • shared environment variables
  • host and OS detection
  • project-local activation hooks
  • predictable loading order

The goal is to make shell behavior explicit, inspectable, and repeatable instead of depending on a fragile mix of ad hoc dotfiles and one-off scripts.

3. Enabling Execution Contract: Libraries And Wrappers

Base should provide a stable foundation for controlled CLI execution.

That includes:

  • shell libraries for logging, errors, files, Git, networking, and standard helpers
  • Python wrappers for running Python-based tooling with the right environment
  • shell wrappers for sourcing shared libraries and normalizing execution context
  • a consistent convention for passing arguments, setting environment variables, and reporting failures

The wrapper model matters because it keeps command behavior predictable. A CLI should run inside a known environment instead of relying on whoever happened to invoke it from whatever shell state they already had.