feat: Added command

This commit is contained in:
2026-06-20 18:40:57 +05:30
parent 0978403fa2
commit bad324a5cd
16 changed files with 182 additions and 218 deletions

View File

@@ -9,7 +9,7 @@ This skill provides everything needed to add a new installer to the bootstrap pr
## Project Overview
Bootstrap CLI (`b`) is a bash-based tool installer and system bootstrapper. Users run `b <name>` to install tools (e.g., `b nvim`, `b bat`). The project lives at the workspace root.
Bootstrap CLI (`b`) is a bash-based tool installer and system bootstrapper. Users run `b <name>` or `b ware <name>` to install or edit tools (e.g., `b nvim`, `b ware bat`). The project lives at the workspace root.
### Key Directories
@@ -54,7 +54,10 @@ Make **two** edits to `routes.sh`:
### Step 3: Verify (optional)
Run `bash routes.sh` or `b all` to confirm the new installer appears in the help output.
Verify that the installer works and appears in the help output:
- Run `b all` to confirm it appears in the help list.
- Run `b ware <name> -y` to test direct installation.
- Run `b ware <name>` to test the interactive editing flow.
---

View File

@@ -1 +1 @@
1.0.12
1.1.1

32
b.sh
View File

@@ -77,7 +77,7 @@ _b_completion() {
# If completing the first argument after 'b'
if [ "$COMP_CWORD" -eq 1 ]; then
opts="all con bye up"
opts="all con bye up ware"
local routes_file="$HOME/.config/bootstrap/routes.sh"
if [ -f "$routes_file" ]; then
@@ -111,6 +111,36 @@ _b_completion() {
return 0
fi
# If completing arguments for 'b ware <tool>'
if [ "$COMP_CWORD" -eq 2 ] && [ "$prev" = "ware" ]; then
local routes_file="$HOME/.config/bootstrap/routes.sh"
local installer_keys=""
if [ -f "$routes_file" ]; then
installer_keys=$(grep -E "^INSTALLER_KEYS=" "$routes_file" 2>/dev/null | sed -E 's/INSTALLER_KEYS=\(([^)]+)\)/\1/' 2>/dev/null)
fi
[ -z "$installer_keys" ] && installer_keys="agy bat node nvim pnpm rust starship yay yazi zoxide"
# Support comma-separated completions (e.g. b ware nvim,ya<TAB>)
if [[ "$cur" == *,* ]]; then
local prefix="${cur%,*}"
local last="${cur##*,}"
local matches
matches=$(compgen -W "$installer_keys" -- "$last")
if [ -n "$matches" ]; then
COMPREPLY=()
for m in $matches; do
if [[ ",$prefix," != *",$m,"* ]]; then
COMPREPLY+=("${prefix},${m}")
fi
done
fi
return 0
fi
COMPREPLY=( $(compgen -W "$installer_keys" -- "$cur") )
return 0
fi
# If completing arguments for 'b con <config_dir>'
if [ "$COMP_CWORD" -eq 2 ] && [ "$prev" = "con" ]; then
# List of directories in ~/.config/ to choose from

View File

@@ -6,6 +6,7 @@ echo "Available bootstrap commands:"
printf " %-6s - %s\n" "all" "List all available commands"
printf " %-6s - %s\n" "con" "Edit config (e.g. b con nvim)"
printf " %-6s - %s\n" "up" "Check for updates and update Bootstrap CLI"
printf " %-6s - %s\n" "ware" "Edit and run an installer (e.g. b ware nvim)"
printf " %-6s - %s\n" "bye" "Uninstall Bootstrap CLI helper"
# Installers second

View File

@@ -32,15 +32,6 @@ install_agy() {
if [ -f "$BINARY_PATH" ]; then
log_info "Notice: 'agy' is already installed at $BINARY_PATH."
log_info "The Antigravity CLI automatically self-updates in the background during regular runs."
if ! confirm "Do you want to perform a fresh reinstall/upgrade anyway?"; then
log_info "Skipping Antigravity CLI installation."
return 0
fi
else
if ! confirm "Install Antigravity CLI (agy)?"; then
log_info "Skipping Antigravity CLI installation."
return 0
fi
fi
# Detect Architecture (map uname -m to amd64 / arm64)

View File

@@ -35,51 +35,16 @@ install_bat() {
if [ "$distro" = "arch" ]; then
log_info "Arch Linux detected"
if has_command bat; then
if ! confirm "Bat is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Bat installation."
return
fi
else
if ! confirm "Install Bat?"; then
log_info "Skipping Bat installation."
return
fi
fi
log_info "Installing Bat..."
pkg_install bat
elif [ "$distro" = "fedora" ]; then
log_info "Fedora detected"
if has_command bat; then
if ! confirm "Bat is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Bat installation."
return
fi
else
if ! confirm "Install Bat?"; then
log_info "Skipping Bat installation."
return
fi
fi
log_info "Installing Bat..."
pkg_install bat
elif [ "$distro" = "debian" ]; then
log_info "Debian/Ubuntu detected"
if has_command bat; then
if ! confirm "Bat is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Bat installation."
return
fi
else
if ! confirm "Install Bat?"; then
log_info "Skipping Bat installation."
return
fi
fi
pkg_install curl wget

View File

@@ -31,15 +31,7 @@ trap cleanup EXIT
install_nvm() {
if has_command nvm || [ -s "$HOME/.nvm/nvm.sh" ]; then
if ! confirm "NVM is already installed. Reinstall/Upgrade?"; then
log_info "Skipping NVM installation."
return 0
fi
else
if ! confirm "Install NVM (Node Version Manager)?"; then
log_info "Skipping NVM installation."
return 0
fi
log_info "NVM is already installed."
fi
# Ensure required commands are installed
@@ -116,17 +108,6 @@ install_node() {
if has_command node; then
log_info "Currently installed Node.js version: $(node --version)"
if ! confirm "Install/Update to latest Node.js LTS version?"; then
log_info "Skipping Node.js installation."
set -u
return 0
fi
else
if ! confirm "Install Node.js LTS version?"; then
log_info "Skipping Node.js installation."
set -u
return 0
fi
fi
log_info "Installing Node.js LTS version..."

View File

@@ -35,27 +35,8 @@ cleanup() {
trap cleanup EXIT
check_config_dir() {
if [[ -d "$NVIM_CONFIG_DIR" ]]; then
if confirm "$NVIM_CONFIG_DIR already exists. Replace it?"; then
log_info "Existing configuration will be removed during setup."
rm -rf "$NVIM_CONFIG_DIR"
else
while true; do
read -r -p "Enter an alternative directory to clone the configuration into: " alt_dir </dev/tty || true
# Expand tilde (~) to $HOME if the user uses it
alt_dir="${alt_dir/#\~/$HOME}"
if [[ -z "$alt_dir" ]]; then
log_warn "Directory path cannot be empty. Please try again."
continue
fi
NVIM_CONFIG_DIR="$alt_dir"
break
done
fi
fi
# Skip prompt, handled during config clone
return 0
}
install_packages() {
@@ -85,19 +66,9 @@ install_nvim() {
return
fi
log_info "Detected Neovim ${current_version}"
if ! confirm "Upgrade to Neovim v${NVIM_VERSION}?"; then
log_info "Skipping Neovim upgrade."
return
fi
log_info "Detected Neovim ${current_version}. Upgrading to v${NVIM_VERSION}..."
else
log_info "Neovim not installed."
if ! confirm "Install Neovim v${NVIM_VERSION}?"; then
log_info "Skipping Neovim installation."
return
fi
log_info "Installing Neovim v${NVIM_VERSION}..."
fi
# Detect architecture to resolve the release binary name (Fix 4)
@@ -131,14 +102,14 @@ install_nvim() {
}
install_config() {
if [[ -d "$NVIM_CONFIG_DIR" ]]; then
log_info "Neovim configuration directory $NVIM_CONFIG_DIR already exists. Skipping config clone."
return
fi
# Ensure parent directory for the chosen config path exists
mkdir -p "$(dirname "$NVIM_CONFIG_DIR")"
# Quick check if the alternative folder exists and clear it out
if [[ -d "$NVIM_CONFIG_DIR" ]]; then
rm -rf "$NVIM_CONFIG_DIR"
fi
log_info "Cloning configuration to $NVIM_CONFIG_DIR..."
git clone "$NVIM_CONFIG_REPO" "$NVIM_CONFIG_DIR"
log_success "Configuration installed."

View File

@@ -125,15 +125,7 @@ detect_pnpm_arch() {
install_pnpm() {
if has_command pnpm; then
if ! confirm "pnpm is already installed ($(pnpm --version)). Reinstall/Upgrade?"; then
log_info "Skipping pnpm installation."
return
fi
else
if ! confirm "Install pnpm?"; then
log_info "Skipping pnpm installation."
return
fi
log_info "pnpm is already installed ($(pnpm --version))."
fi
local arch libc_suffix version_json version major_version asset_base

View File

@@ -65,15 +65,7 @@ detect_target_triple() {
install_rust() {
if has_command rustup || [ -f "$HOME/.cargo/bin/rustup" ]; then
if ! confirm "Rust (rustup) is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Rust installation."
return
fi
else
if ! confirm "Install Rust (rustup)?"; then
log_info "Skipping Rust installation."
return
fi
log_info "Rust (rustup) is already installed."
fi
install_downloader

View File

@@ -31,15 +31,7 @@ trap cleanup EXIT
install_starship() {
if has_command starship || [ -f "$HOME/.local/bin/starship" ]; then
if ! confirm "Starship is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Starship installation."
return
fi
else
if ! confirm "Install Starship?"; then
log_info "Skipping Starship installation."
return
fi
log_info "Starship is already installed."
fi
# Ensure curl or wget is installed

View File

@@ -35,15 +35,7 @@ install_yay() {
fi
if has_command yay; then
if ! confirm "Yay is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Yay installation."
return
fi
else
if ! confirm "Install Yay?"; then
log_info "Skipping Yay installation."
return
fi
log_info "Yay is already installed."
fi
local needs_install=false

View File

@@ -65,15 +65,7 @@ install_yazi() {
if [ "$distro" = "arch" ]; then
log_info "Arch Linux detected"
if has_command yazi; then
if ! confirm "Yazi is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Yazi installation."
return
fi
else
if ! confirm "Install Yazi and its dependencies?"; then
log_info "Skipping Yazi installation."
return
fi
log_info "Yazi is already installed."
fi
log_info "Installing Yazi..."
@@ -84,15 +76,7 @@ install_yazi() {
elif [ "$distro" = "debian" ]; then
log_info "Debian/Ubuntu detected"
if has_command yazi; then
if ! confirm "Yazi is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Yazi installation."
return
fi
else
if ! confirm "Install Yazi and its dependencies?"; then
log_info "Skipping Yazi installation."
return
fi
log_info "Yazi is already installed."
fi
pkg_install curl wget git
@@ -124,15 +108,7 @@ install_yazi() {
elif [ "$distro" = "fedora" ]; then
log_info "Fedora detected"
if has_command yazi; then
if ! confirm "Yazi is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Yazi installation."
return
fi
else
if ! confirm "Install Yazi and its dependencies?"; then
log_info "Skipping Yazi installation."
return
fi
log_info "Yazi is already installed."
fi
log_info "Installing dnf-plugins-core..."

View File

@@ -42,15 +42,7 @@ install_fzf() {
install_zoxide() {
if has_command zoxide || [ -f "$HOME/.local/bin/zoxide" ]; then
if ! confirm "Zoxide is already installed. Reinstall/Upgrade?"; then
log_info "Skipping Zoxide installation."
return
fi
else
if ! confirm "Install Zoxide?"; then
log_info "Skipping Zoxide installation."
return
fi
log_info "Zoxide is already installed."
fi
install_curl

View File

@@ -41,6 +41,23 @@ b yazi
b nvim,yazi
```
### Inspecting and Editing Installers (`b ware`)
If you want to inspect and edit an installer script before running it (for example, to change version numbers, paths, or customize the logic), you can use the intermediate `b ware` command:
```bash
b ware nvim
b ware starship,zoxide
```
This opens the installer script in your preferred `$EDITOR` (defaulting to standard terminal editors if `$EDITOR` is unset). After you edit and close the file, the modified script runs automatically.
To bypass the editor and install the tool directly using the `ware` command, append the `-y` flag:
```bash
b ware nvim -y
```
You can also edit configurations located in your `~/.config/` directory by running:
```bash

149
routes.sh
View File

@@ -31,6 +31,96 @@ declare -A INSTALLERS=(
# Order in which installers should be displayed
INSTALLER_KEYS=(agy bat node nvim pnpm rust starship yay yazi zoxide)
# Helper function to run/edit installer scripts
run_ware() {
local tool="$1"
shift
# Check if -y is in the remaining arguments
local bypass_edit=false
local cmd_args=()
for arg in "$@"; do
if [ "$arg" = "-y" ]; then
bypass_edit=true
else
cmd_args+=("$arg")
fi
done
# Capitalize first letter for display (e.g. nvim -> Neovim)
local display_name="$(echo "${tool:0:1}" | tr '[:lower:]' '[:upper:]')${tool:1}"
# Check for local installer first
local local_installer="$BOOTSTRAP_DIR/installers/install_${tool}.sh"
local temp_script
temp_script=$(mktemp --suffix=".sh" 2>/dev/null || mktemp)
if [ -f "$local_installer" ]; then
cp "$local_installer" "$temp_script"
else
BOOTSTRAP_BASE_URL="${BOOTSTRAP_BASE_URL:-https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master}"
BOOTSTRAP_FALLBACK_URL="${BOOTSTRAP_FALLBACK_URL:-https://raw.githubusercontent.com/sortedcord/bootstrap/refs/heads/master}"
local installer_path="installers/install_${tool}.sh"
local download_status=0
log_info "Downloading ${display_name} installer..."
if has_command curl; then
curl -fsSL "${BOOTSTRAP_BASE_URL}/${installer_path}" -o "$temp_script"
download_status=$?
if [ "$download_status" -ne 0 ]; then
log_warn "Failed to download installer from primary URL, trying fallback..."
curl -fsSL "${BOOTSTRAP_FALLBACK_URL}/${installer_path}" -o "$temp_script"
download_status=$?
fi
elif has_command wget; then
wget -qO "$temp_script" "${BOOTSTRAP_BASE_URL}/${installer_path}"
download_status=$?
if [ "$download_status" -ne 0 ]; then
log_warn "Failed to download installer from primary URL, trying fallback..."
wget -qO "$temp_script" "${BOOTSTRAP_FALLBACK_URL}/${installer_path}"
download_status=$?
fi
else
log_error "Neither curl nor wget is installed to download the installer."
rm -f "$temp_script"
exit 1
fi
if [ "$download_status" -ne 0 ]; then
log_error "Failed to download the installer from both primary and fallback URLs."
rm -f "$temp_script"
exit 1
fi
fi
# Edit if bypass_edit is false
if [ "$bypass_edit" = "false" ]; then
local editor="${EDITOR:-}"
if [ -z "$editor" ]; then
if has_command nvim; then
editor="nvim"
elif has_command vim; then
editor="vim"
elif has_command nano; then
editor="nano"
else
editor="vi"
fi
fi
log_info "Opening ${display_name} installer for editing using $editor..."
$editor "$temp_script"
fi
# Run the script (edited or unchanged)
log_info "Running ${display_name} installer..."
bash "$temp_script" "${cmd_args[@]}"
local run_status=$?
# Cleanup
rm -f "$temp_script"
return "$run_status"
}
SCRIPT_NAMES="${1:-}"
if [ -z "$SCRIPT_NAMES" ] || [ "$SCRIPT_NAMES" = "-h" ] || [ "$SCRIPT_NAMES" = "--help" ]; then
SCRIPT_NAMES="all"
@@ -47,46 +137,7 @@ IFS=',' read -ra SCRIPTS <<< "$SCRIPT_NAMES"
for script in "${SCRIPTS[@]}"; do
# Check if it is a registered installer
if [[ -n "${INSTALLERS[$script]:-}" ]]; then
# Capitalize first letter for display (e.g. nvim -> Neovim)
display_name="$(echo "${script:0:1}" | tr '[:lower:]' '[:upper:]')${script:1}"
log_info "Launching ${display_name} installer..."
# Check for local installer first, fallback to curl
local_installer="$BOOTSTRAP_DIR/installers/install_${script}.sh"
if [ -f "$local_installer" ]; then
bash "$local_installer" "$@"
else
BOOTSTRAP_BASE_URL="${BOOTSTRAP_BASE_URL:-https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master}"
BOOTSTRAP_FALLBACK_URL="${BOOTSTRAP_FALLBACK_URL:-https://raw.githubusercontent.com/sortedcord/bootstrap/refs/heads/master}"
installer_path="installers/install_${script}.sh"
download_status=0
if has_command curl; then
curl -fsSL "${BOOTSTRAP_BASE_URL}/${installer_path}" | bash -s -- "$@"
download_status="${PIPESTATUS[0]}"
if [ "$download_status" -ne 0 ]; then
log_warn "Failed to download installer from primary URL, trying fallback..."
curl -fsSL "${BOOTSTRAP_FALLBACK_URL}/${installer_path}" | bash -s -- "$@"
download_status="${PIPESTATUS[0]}"
fi
elif has_command wget; then
wget -qO- "${BOOTSTRAP_BASE_URL}/${installer_path}" | bash -s -- "$@"
download_status="${PIPESTATUS[0]}"
if [ "$download_status" -ne 0 ]; then
log_warn "Failed to download installer from primary URL, trying fallback..."
wget -qO- "${BOOTSTRAP_FALLBACK_URL}/${installer_path}" | bash -s -- "$@"
download_status="${PIPESTATUS[0]}"
fi
else
log_error "Neither curl nor wget is installed to download the installer."
exit 1
fi
if [ "$download_status" -ne 0 ]; then
log_error "Failed to download the installer from both primary and fallback URLs."
exit 1
fi
fi
run_ware "$script" -y "$@"
else
# Handle non-installer commands
@@ -115,6 +166,24 @@ for script in "${SCRIPTS[@]}"; do
exit 1
fi
;;
ware)
tools_arg="${1:-}"
if [ -z "$tools_arg" ]; then
log_error "Usage: b ware <tool1,tool2,...> [-y]"
exit 1
fi
shift
IFS=',' read -ra WARE_TOOLS <<< "$tools_arg"
for tool in "${WARE_TOOLS[@]}"; do
if [[ -z "${INSTALLERS[$tool]:-}" ]]; then
log_error "Unknown tool '$tool'."
exit 1
fi
done
for tool in "${WARE_TOOLS[@]}"; do
run_ware "$tool" "$@"
done
;;
bye)
if [ -f "$BOOTSTRAP_DIR/commands/uninstall.sh" ]; then
. "$BOOTSTRAP_DIR/commands/uninstall.sh"