Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .ai-context/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ Important Python packages include:
- `base_logs` - runtime log inspection.
- `base_clean` - runtime cache/log/temp cleanup.
- `base_release` - release check/plan/notes/publish support.
- `base_dev` - developer profile setup/check/doctor/onboard support.
- `base_dev` - prerequisite profile setup/check/doctor/onboard support,
including dev, sre, ai, and linux-lab.
- `base_export_context` - deterministic local Markdown and Zip exports from a
project's `.ai-context/` directory. Provider uploads are intentionally out of
scope.
Expand Down
3 changes: 3 additions & 0 deletions .ai-context/DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ architecture discussion.
hardcoded inside `basectl build`.
- New tool families such as AI developer tools should stay explicit and
opt-in.
- Host VM tooling should stay explicit and opt-in. The `linux-lab` profile may
install and check Multipass on macOS hosts, but Base setup should not create
or mutate VM instances automatically.
- AI agent harnesses such as Codex CLI, Claude Code, Cursor agents, Omnigent,
and Pi-like tools are optional adjacent tools. Base may help install or check
explicit AI prerequisites, export portable context, render repo-owned prompts,
Expand Down
4 changes: 4 additions & 0 deletions .ai-context/STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ The current command surface covers:
- repo-owned prompt rendering through `basectl prompt`
- documentation entrypoint opening through `basectl docs`
- explicit `ai` prerequisite profile for Codex CLI and Claude Code
- explicit `linux-lab` prerequisite profile for host-side Multipass checks and
setup
- Ubuntu/Debian runtime checks, diagnostics, and source-checkout validation

## Active Development Direction
Expand Down Expand Up @@ -69,6 +71,8 @@ Recent released work includes:
- newcomer orientation presentation docs
- optional project Git remote reachability diagnostics
- explicit `ai` prerequisite profile
- explicit host-scoped `linux-lab` prerequisite profile for Multipass checks
and setup
- portable project Git workflow guidance from `basectl repo init`
- Homebrew upgrade path preservation for explicit `BASE_HOME` and shell startup
snippets
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,17 @@ and Base versions are tracked in the repo-root `VERSION` file.

## [Unreleased]

### Added

- Added an explicit `linux-lab` prerequisite profile that checks and installs
Multipass via Homebrew cask for local Ubuntu lab VMs without creating VM
instances during Base setup.

### Fixed

- Replaced stray shell `run` calls in setup's virtualenv and apt install paths
with direct command execution so spawned `basectl setup` runs do not depend on
a test-harness helper.
- Stopped default project checks from failing Ubuntu/Linux acceptance solely
because manifest-declared IDE extension CLIs such as `code` are not on `PATH`;
IDE extension diagnostics now run with the developer profile.
Expand Down
10 changes: 6 additions & 4 deletions FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,12 @@ to operate.

### Why can setup fail on a Homebrew `brew link` conflict?

Prerequisite profiles install ordinary Homebrew tools. A tool can pull a
Homebrew dependency that needs to be linked into Homebrew's prefix. If files such
as `/usr/local/bin/python3`, `/usr/local/bin/pip3`, or `/usr/local/bin/idle3`
already point at another Python installation, Homebrew may stop with:
Prerequisite profiles can install ordinary Homebrew tools and, for explicitly
selected host profiles, Homebrew casks such as Multipass. A tool can pull a
Homebrew dependency that needs to be linked into Homebrew's prefix. If files
such as `/usr/local/bin/python3`, `/usr/local/bin/pip3`, or
`/usr/local/bin/idle3` already point at another Python installation, Homebrew
may stop with:

```text
Error: The `brew link` step did not complete successfully
Expand Down
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1055,24 +1055,31 @@ installs Base bootstrap Python packages into that environment. For project
artifact setup, Base first seeds the target project venv with `bootstrap: true`
default artifacts and then invokes the Python project setup layer through
`base-wrapper --project <project>`.
Prerequisite profiles are opt-in and manifest-driven. Use `--profile dev` to
install Base contributor tools such as BATS, the GitHub CLI, and ShellCheck from
Prerequisite profiles are opt-in. Use `--profile dev` to install Base
contributor tools such as BATS, the GitHub CLI, and ShellCheck from
`lib/base/dev_manifest.yaml`. Use `--profile sre` for the initial
site-reliability profile in `lib/base/sre_manifest.yaml`, which installs local
diagnostic tools such as `kubectl`, `helm`, `k9s`, `httpie`, `grpcurl`, `jq`,
`yq`, `nmap`, and `mtr`. Use `--profile ai` for optional AI coding tools:
Codex CLI and Claude Code. Profiles compose with a comma-separated list.
Codex CLI and Claude Code. Use `--profile linux-lab` on a macOS host to install
and check Multipass for local Ubuntu lab VMs. Profiles compose with a
comma-separated list.

```bash
basectl setup --profile dev
basectl setup --profile sre
basectl setup --profile ai
basectl setup --profile linux-lab --dry-run
basectl setup --profile linux-lab
basectl setup --profile dev,sre
basectl setup --profile dev,ai
basectl setup --profile dev,linux-lab
basectl check --profile sre
basectl check --profile ai
basectl check --profile linux-lab
basectl doctor --profile sre
basectl doctor --profile ai
basectl doctor --profile linux-lab
```

AI coding tools are intentionally not part of the plain `dev` or `sre` profile.
Expand All @@ -1081,6 +1088,12 @@ profile is explicitly requested. Base checks tool presence and version output,
but it does not manage accounts, credentials, model access, or organization
policy.

The `linux-lab` profile is intentionally host-scoped. It installs or checks the
Multipass CLI on macOS through `brew install --cask multipass`, but Base does
not create, start, mount, or delete Multipass instances during setup. Review
the planned install with `--dry-run`, then create lab VMs with
`multipass launch` when you are ready.

For the allowed Homebrew, Codex CLI, and Claude Code installer URLs, dry-run
behavior, non-interactive behavior, and managed-device guidance, see
[Remote Installer Policy](docs/remote-installer-policy.md).
Expand Down
9 changes: 5 additions & 4 deletions cli/bash/commands/basectl/subcommands/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Usage:
basectl check [project] [options]

Options:
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai.
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai, linux-lab.
--format <text|json> Select output format. Defaults to text.
--manifest <path> Use a specific base_manifest.yaml path for project checks.
--remote-network Opt in to bounded project Git origin reachability checks.
Expand All @@ -23,9 +23,10 @@ Options:

Profiles:
Profile lists are comma-separated, for example: --profile dev,sre.
dev - Base development tooling for this repository.
sre - production/SRE prerequisite tooling.
ai - AI coding assistant tooling.
dev - Base development tooling for this repository.
sre - production/SRE prerequisite tooling.
ai - AI coding assistant tooling.
linux-lab - Multipass tooling for local Ubuntu lab VMs on macOS hosts.

Purpose:
Verify the local Base CLI environment and, when provided, project artifacts on supported platforms without making changes.
Expand Down
9 changes: 5 additions & 4 deletions cli/bash/commands/basectl/subcommands/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ Usage:
Options:
--format <text|json> Select output format. Defaults to text.
--manifest <path> Use a specific base_manifest.yaml path.
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai.
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai, linux-lab.
--recreate-venv Back up and recreate the project virtual environment during setup.
-v Enable DEBUG logging for this subcommand.
-h, --help Show this help text.

Profiles:
Profile lists are comma-separated, for example: --profile dev,sre.
dev - Base development tooling for this repository.
sre - production/SRE prerequisite tooling.
ai - AI coding assistant tooling.
dev - Base development tooling for this repository.
sre - production/SRE prerequisite tooling.
ai - AI coding assistant tooling.
linux-lab - Multipass tooling for local Ubuntu lab VMs on macOS hosts.

Purpose:
Run Base setup, checks, and diagnostics in a non-interactive CI environment.
Expand Down
9 changes: 5 additions & 4 deletions cli/bash/commands/basectl/subcommands/doctor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Usage:
basectl doctor [project] [options]

Options:
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai.
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai, linux-lab.
--format <text|json> Select output format. Defaults to text.
--manifest <path> Use a specific base_manifest.yaml path for project diagnostics.
--remote-network Opt in to bounded project Git origin reachability diagnostics.
Expand All @@ -24,9 +24,10 @@ Options:

Profiles:
Profile lists are comma-separated, for example: --profile dev,sre.
dev - Base development tooling for this repository.
sre - production/SRE prerequisite tooling.
ai - AI coding assistant tooling.
dev - Base development tooling for this repository.
sre - production/SRE prerequisite tooling.
ai - AI coding assistant tooling.
linux-lab - Multipass tooling for local Ubuntu lab VMs on macOS hosts.

Purpose:
Diagnose the local Base CLI environment and, when provided, project artifacts.
Expand Down
2 changes: 1 addition & 1 deletion cli/bash/commands/basectl/subcommands/onboard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Usage:
basectl onboard [project] [options]

Options:
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai.
--profile <list> Include named prerequisite profiles. Known profiles: dev, sre, ai, linux-lab.
--dry-run Explain planned onboarding steps without making changes.
--yes Accept default answers for setup and shell profile prompts.
--no-profile Skip shell profile updates.
Expand Down
9 changes: 5 additions & 4 deletions cli/bash/commands/basectl/subcommands/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Usage:
basectl setup [options] [project]

Options:
--profile <list> Install named prerequisite profiles. Known profiles: dev, sre, ai.
--profile <list> Install named prerequisite profiles. Known profiles: dev, sre, ai, linux-lab.
--dry-run Log what would happen without making changes.
--manifest <path> Use a specific base_manifest.yaml path.
--notify Force a best-effort macOS notification when setup ends.
Expand All @@ -26,9 +26,10 @@ Options:

Profiles:
Profile lists are comma-separated, for example: --profile dev,sre.
dev - Base development tooling for this repository.
sre - production/SRE prerequisite tooling.
ai - AI coding assistant tooling.
dev - Base development tooling for this repository.
sre - production/SRE prerequisite tooling.
ai - AI coding assistant tooling.
linux-lab - Multipass tooling for local Ubuntu lab VMs on macOS hosts.

Purpose:
Prepare the local Base CLI environment on supported setup platforms.
Expand Down
28 changes: 17 additions & 11 deletions cli/bash/commands/basectl/subcommands/setup_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ setup_enable_debug_logging() {
}

setup_supported_profiles() {
printf '%s\n' "dev sre ai"
printf '%s\n' "dev sre ai linux-lab"
}

setup_supported_profiles_display() {
printf '%s\n' "dev, sre, ai"
printf '%s\n' "dev, sre, ai, linux-lab"
}

setup_epoch_seconds() {
Expand All @@ -87,7 +87,7 @@ setup_profile_supported() {
local profile="$1"

case "$profile" in
dev|sre|ai)
dev|sre|ai|linux-lab)
return 0
;;
*)
Expand Down Expand Up @@ -326,7 +326,7 @@ setup_backup_existing_venv_path() {
fi

log_info "Moving $description '$venv_dir' to '$backup_path'."
run mv "$venv_dir" "$backup_path"
mv "$venv_dir" "$backup_path" || fatal_error "Unable to move $description '$venv_dir' to '$backup_path'."
}

setup_python_formula() {
Expand Down Expand Up @@ -727,7 +727,12 @@ setup_install_homebrew() {

if [[ -n "${BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT:-}" ]]; then
setup_reject_test_hook_if_disallowed BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT
run "$BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT"
"$BASE_SETUP_HOMEBREW_INSTALLER_SCRIPT"
exit_code=$?
if ((exit_code)); then
log_error "$(setup_recovery_homebrew)"
fi
exit_if_error "$exit_code" "Homebrew installation failed."
else
command -v curl >/dev/null 2>&1 || fatal_error "curl is required to install Homebrew. Install curl or install Homebrew manually from https://brew.sh/, then rerun 'basectl setup'."
/bin/bash -c "$(curl -fsSL "$installer_url")"
Expand Down Expand Up @@ -772,7 +777,7 @@ setup_install_xcode_tools() {
fi

log_info "Installing Xcode Command Line Tools."
run --no-exit xcode-select --install
xcode-select --install || true

timeout="$(setup_xcode_wait_timeout_seconds)"
interval="$(setup_xcode_wait_interval_seconds)"
Expand Down Expand Up @@ -815,7 +820,7 @@ setup_install_python() {
brew_bin="$(setup_find_brew_bin)" || fatal_error "Homebrew is required to install Python formula '$formula'. $(setup_recovery_homebrew)"

log_info "Installing Python formula '$formula' via Homebrew."
run "$brew_bin" install "$formula"
"$brew_bin" install "$formula" || fatal_error "Homebrew failed to install Python formula '$formula'."
}

setup_find_python_bin() {
Expand Down Expand Up @@ -974,7 +979,7 @@ setup_create_virtualenv() {

safe_mkdir -p "$(dirname "$venv_dir")"
log_info "Creating Python virtual environment at '$venv_dir'."
run "$python_bin" -m venv "$venv_dir"
"$python_bin" -m venv "$venv_dir"
}

setup_base_venv_python_bin() {
Expand Down Expand Up @@ -1019,7 +1024,8 @@ setup_install_base_python_package() {
python_bin="$(setup_base_venv_python_bin "$venv_dir")" || fatal_error "Base virtual environment Python was not found at '$venv_dir/bin/python'. $(setup_recovery_venv)"

log_info "Installing Python package '$package' in the Base virtual environment."
run "$python_bin" -m pip install --disable-pip-version-check "$package"
"$python_bin" -m pip install --disable-pip-version-check "$package" ||
fatal_error "Unable to install Python package '$package' in the Base virtual environment."
}

setup_install_pyyaml() {
Expand Down Expand Up @@ -2649,8 +2655,8 @@ setup_run_linux_debian_apt_prerequisites() {
fi

log_info "Installing Ubuntu/Debian apt prerequisites."
run sudo apt-get update || return $?
run sudo apt-get install -y "${package_args[@]}"
sudo apt-get update || return $?
sudo apt-get install -y "${package_args[@]}"
}

setup_run_linux_debian_install() {
Expand Down
13 changes: 7 additions & 6 deletions cli/bash/commands/basectl/tests/check.bats
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ load ./setup_helpers.bash
[[ "$output" != *"--dev"* ]]
[[ "$output" == *"--profile <list>"* ]]
[[ "$output" == *"Profile lists are comma-separated, for example: --profile dev,sre."* ]]
[[ "$output" == *"dev - Base development tooling for this repository."* ]]
[[ "$output" == *"sre - production/SRE prerequisite tooling."* ]]
[[ "$output" == *"ai - AI coding assistant tooling."* ]]
[[ "$output" == *"dev - Base development tooling for this repository."* ]]
[[ "$output" == *"sre - production/SRE prerequisite tooling."* ]]
[[ "$output" == *"ai - AI coding assistant tooling."* ]]
[[ "$output" == *"linux-lab - Multipass tooling for local Ubuntu lab VMs on macOS hosts."* ]]
[[ "$output" == *"--remote-network"* ]]
[[ "$output" == *"Verify the local Base CLI environment and, when provided, project artifacts on supported platforms without making changes."* ]]
[[ "$output" == *"Use check for a quick pass/fail result; use doctor for finding IDs and fix hints."* ]]
Expand Down Expand Up @@ -302,18 +303,18 @@ EOF
touch "$TEST_STATE_DIR/click-installed"
create_base_venv_stub "$venv_dir"

run_base_command check --profile dev,SRE,AI
run_base_command check --profile dev,SRE,AI,LINUX-LAB

[ "$status" -eq 1 ]
[ "$(cat "$TEST_STATE_DIR/dev-args")" = "$(printf '%s\n' check --profile dev,sre,ai)" ]
[ "$(cat "$TEST_STATE_DIR/dev-args")" = "$(printf '%s\n' check --profile dev,sre,ai,linux-lab)" ]
[[ "$output" == *"Base CLI environment check found missing requirements."* ]]
}

@test "basectl check rejects unknown profiles" {
run_base_command check --profile ops

[ "$status" -eq 2 ]
[[ "$output" == *"Unsupported profile 'ops'. Expected one of: dev, sre, ai."* ]]
[[ "$output" == *"Unsupported profile 'ops'. Expected one of: dev, sre, ai, linux-lab."* ]]
}

@test "basectl check rejects empty profile list entries" {
Expand Down
7 changes: 4 additions & 3 deletions cli/bash/commands/basectl/tests/ci.bats
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ prepare_ci_runtime() {
[[ "$output" == *"--format <text|json>"* ]]
[[ "$output" == *"--profile <list>"* ]]
[[ "$output" == *"Profile lists are comma-separated, for example: --profile dev,sre."* ]]
[[ "$output" == *"dev - Base development tooling for this repository."* ]]
[[ "$output" == *"sre - production/SRE prerequisite tooling."* ]]
[[ "$output" == *"ai - AI coding assistant tooling."* ]]
[[ "$output" == *"dev - Base development tooling for this repository."* ]]
[[ "$output" == *"sre - production/SRE prerequisite tooling."* ]]
[[ "$output" == *"ai - AI coding assistant tooling."* ]]
[[ "$output" == *"linux-lab - Multipass tooling for local Ubuntu lab VMs on macOS hosts."* ]]
[[ "$output" == *"BASE_CI=true"* ]]
}

Expand Down
4 changes: 2 additions & 2 deletions cli/bash/commands/basectl/tests/completions.bats
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ EOF
[[ "$output" == *"update_projects=base demo"* ]]
[[ "$output" == *"check_options=--profile --format --manifest --remote-network"* ]]
[[ "$output" == *"update_options=--dry-run"* ]]
[[ "$output" == *"check_profiles=dev sre ai dev,sre dev,ai sre,ai dev,sre,ai"* ]]
[[ "$output" == *"check_profiles=dev sre ai linux-lab dev,sre dev,ai dev,linux-lab sre,ai sre,linux-lab ai,linux-lab dev,sre,ai dev,sre,linux-lab dev,ai,linux-lab sre,ai,linux-lab dev,sre,ai,linux-lab"* ]]
[[ "$output" == *"test_options=--workspace --dry-run"* ]]
[[ "$output" == *"build_options=--workspace --dry-run --list"* ]]
[[ "$output" == *"run_options=--workspace --dry-run --list"* ]]
Expand All @@ -243,7 +243,7 @@ EOF
[[ "$output" == *"workspace_configure_options=--workspace --manifest --dry-run"* ]]
[[ "$output" == *"onboard_options=--profile --dry-run --yes --no-profile"* ]]
[[ "$output" == *"onboard_projects=base demo"* ]]
[[ "$output" == *"onboard_profiles=dev sre ai dev,sre dev,ai sre,ai dev,sre,ai"* ]]
[[ "$output" == *"onboard_profiles=dev sre ai linux-lab dev,sre dev,ai dev,linux-lab sre,ai sre,linux-lab ai,linux-lab dev,sre,ai dev,sre,linux-lab dev,ai,linux-lab sre,ai,linux-lab dev,sre,ai,linux-lab"* ]]
[[ "$output" == *"prompt_names=list product-self-review"* ]]
[[ "$output" == *"prompt_options=--help"* ]]
[[ "$output" == *"docs_options=--show-url"* ]]
Expand Down
Loading
Loading