Files
blackroad/bin/br-pack
Alexa Amundson 78fbe80f2a Initial monorepo — everything BlackRoad in one place
bin/       230 CLI tools (ask-*, br-*, agent-*, roadid, carpool)
scripts/   99 automation scripts
fleet/     Node configs and deployment
workers/   Cloudflare Worker sources (roadpay, road-search, squad webhooks)
roadc/     RoadC programming language
roadnet/   Mesh network (5 APs, WireGuard)
operator/  Memory system scripts
config/    System configs
dotfiles/  Shell configs
docs/      Documentation

BlackRoad OS — Pave Tomorrow.

RoadChain-SHA2048: d1a24f55318d338b
RoadChain-Identity: alexa@sovereign
RoadChain-Full: d1a24f55318d338b24b60bad7be39286379c76ae5470817482100cb0ddbbcb97e147d07ac7243da0a9f0363e4e5c833d612b9c0df3a3cd20802465420278ef74875a5b77f55af6fe42a931b8b635b3d0d0b6bde9abf33dc42eea52bc03c951406d8cbe49f1a3d29b26a94dade05e9477f34a7d4d4c6ec4005c3c2ac54e73a68440c512c8e83fd9b1fe234750b898ef8f4032c23db173961fe225e67a0432b5293a9714f76c5c57ed5fdf35b9fb40fd73c03ebf88b7253c6a0575f5afb6a6b49b3bda310602fb1ef676859962dad2aebbb2875814b30eee0a8ba195e482d4cbc91d8819e7f38f6db53e8063401649c77bb994371473cabfb917fb53e8cbe73d60
2026-03-14 17:08:41 -05:00

291 lines
7.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# br-pack - BlackRoad OS Script Pack Manager
# Install, list, and remove modular script packs
# Usage: br-pack <install|remove|list|create|info> [pack-name]
set -euo pipefail
source "$HOME/.blackroad/config/nodes.sh" 2>/dev/null || true
PACKS_DIR="$HOME/.blackroad/packs"
BIN_DIR="$HOME/bin"
INSTALLED_FILE="$PACKS_DIR/.installed"
mkdir -p "$PACKS_DIR"
touch "$INSTALLED_FILE"
usage() {
cat <<EOF
${PINK}br-pack${RESET} - BlackRoad OS Script Pack Manager
${BLUE}USAGE:${RESET}
br-pack install <pack> Install a script pack
br-pack remove <pack> Remove a script pack
br-pack list List available packs
br-pack installed List installed packs
br-pack create <name> Create a new empty pack
br-pack info <pack> Show pack details
br-pack deploy <pack> [node] Deploy pack to a fleet node
${AMBER}EXAMPLES:${RESET}
br-pack create ai-tools
br-pack install monitoring
br-pack deploy monitoring cecilia
EOF
}
cmd_list() {
printf '%b%-20s %-12s %s%b\n' "$BLUE" "PACK" "STATUS" "DESCRIPTION" "$RESET"
printf '%-20s %-12s %s\n' "────" "──────" "───────────"
for dir in "$PACKS_DIR"/*/; do
[[ -d "$dir" ]] || continue
name=$(basename "$dir")
[[ "$name" == "." ]] && continue
if [[ -f "$dir/pack.yaml" ]]; then
desc=$(grep '^description:' "$dir/pack.yaml" 2>/dev/null | sed 's/^description: *//' | head -1)
else
desc="(no pack.yaml)"
fi
if grep -qx "$name" "$INSTALLED_FILE" 2>/dev/null; then
status="${GREEN}installed${RESET}"
else
status="available"
fi
printf '%-20s %-20b %s\n' "$name" "$status" "${desc:-}"
done
}
cmd_installed() {
if [[ ! -s "$INSTALLED_FILE" ]]; then
echo "No packs installed."
return
fi
printf '%bInstalled packs:%b\n' "$GREEN" "$RESET"
while IFS= read -r pack; do
echo " - $pack"
done < "$INSTALLED_FILE"
}
cmd_create() {
local name="$1"
local pack_dir="$PACKS_DIR/$name"
if [[ -d "$pack_dir" ]]; then
echo "Pack '$name' already exists at $pack_dir"
return 1
fi
mkdir -p "$pack_dir"/{bin,config,hooks}
cat > "$pack_dir/pack.yaml" <<YAML
name: $name
version: 1.0.0
description: Custom script pack
author: blackroad
requires: [] # other packs this depends on
# Hardware requirements (optional)
hardware:
min_ram: 512M
requires: [] # e.g., [hailo, nvme, gpio]
platforms: [pi5, pi4, pi400, x86, mac]
# Scripts to symlink into ~/bin on install
scripts:
# - bin/my-tool
# Config files to copy on install
configs:
# - config/my-config.yaml -> ~/.blackroad/my-config.yaml
# Hooks
hooks:
post_install: hooks/post-install.sh
pre_remove: hooks/pre-remove.sh
health_check: hooks/health.sh
# cron: "*/5 * * * *" # optional cron schedule
YAML
cat > "$pack_dir/hooks/post-install.sh" <<'HOOK'
#!/bin/bash
# Post-install hook for this pack
echo "Pack installed successfully."
HOOK
cat > "$pack_dir/hooks/health.sh" <<'HOOK'
#!/bin/bash
# Health check for this pack — exit 0 if healthy, 1 if degraded, 2 if critical
exit 0
HOOK
chmod +x "$pack_dir/hooks/"*.sh
printf '%bCreated pack: %s%b\n' "$GREEN" "$pack_dir" "$RESET"
printf 'Edit %s/pack.yaml and add scripts to %s/bin/\n' "$pack_dir" "$pack_dir"
}
cmd_install() {
local name="$1"
local pack_dir="$PACKS_DIR/$name"
if [[ ! -d "$pack_dir" ]]; then
echo "Pack '$name' not found in $PACKS_DIR"
return 1
fi
if grep -qx "$name" "$INSTALLED_FILE" 2>/dev/null; then
echo "Pack '$name' already installed."
return 0
fi
printf '%bInstalling pack: %s%b\n' "$AMBER" "$name" "$RESET"
# Link scripts
if [[ -d "$pack_dir/bin" ]]; then
for script in "$pack_dir/bin/"*; do
[[ -f "$script" ]] || continue
chmod +x "$script"
local target="$BIN_DIR/$(basename "$script")"
if [[ -e "$target" ]]; then
printf ' %bskip%b %s (exists)\n' "$AMBER" "$RESET" "$(basename "$script")"
else
ln -sf "$script" "$target"
printf ' %blink%b %s\n' "$GREEN" "$RESET" "$(basename "$script")"
fi
done
fi
# Copy configs
if [[ -d "$pack_dir/config" ]]; then
for cfg in "$pack_dir/config/"*; do
[[ -f "$cfg" ]] || continue
local dest="$HOME/.blackroad/$(basename "$cfg")"
if [[ ! -e "$dest" ]]; then
cp "$cfg" "$dest"
printf ' %bconfig%b %s\n' "$BLUE" "$RESET" "$(basename "$cfg")"
fi
done
fi
# Run post-install hook
if [[ -x "$pack_dir/hooks/post-install.sh" ]]; then
"$pack_dir/hooks/post-install.sh"
fi
echo "$name" >> "$INSTALLED_FILE"
printf '%bPack %s installed.%b\n' "$GREEN" "$name" "$RESET"
}
cmd_remove() {
local name="$1"
local pack_dir="$PACKS_DIR/$name"
if ! grep -qx "$name" "$INSTALLED_FILE" 2>/dev/null; then
echo "Pack '$name' is not installed."
return 1
fi
printf '%bRemoving pack: %s%b\n' "$AMBER" "$name" "$RESET"
# Run pre-remove hook
if [[ -x "$pack_dir/hooks/pre-remove.sh" ]]; then
"$pack_dir/hooks/pre-remove.sh"
fi
# Unlink scripts
if [[ -d "$pack_dir/bin" ]]; then
for script in "$pack_dir/bin/"*; do
[[ -f "$script" ]] || continue
local target="$BIN_DIR/$(basename "$script")"
if [[ -L "$target" ]]; then
rm -f "$target"
printf ' %bunlink%b %s\n' "$RED" "$RESET" "$(basename "$script")"
fi
done
fi
# Remove from installed list
grep -vx "$name" "$INSTALLED_FILE" > "$INSTALLED_FILE.tmp" && mv "$INSTALLED_FILE.tmp" "$INSTALLED_FILE"
printf '%bPack %s removed.%b\n' "$GREEN" "$name" "$RESET"
}
cmd_info() {
local name="$1"
local pack_dir="$PACKS_DIR/$name"
if [[ ! -d "$pack_dir" ]]; then
echo "Pack '$name' not found."
return 1
fi
printf '%b=== %s ===%b\n' "$PINK" "$name" "$RESET"
if [[ -f "$pack_dir/pack.yaml" ]]; then
cat "$pack_dir/pack.yaml"
fi
echo ""
if [[ -d "$pack_dir/bin" ]]; then
printf '%bScripts:%b\n' "$BLUE" "$RESET"
ls "$pack_dir/bin/" 2>/dev/null | sed 's/^/ /'
fi
}
cmd_deploy() {
local name="$1"
local node="${2:-}"
local pack_dir="$PACKS_DIR/$name"
if [[ ! -d "$pack_dir" ]]; then
echo "Pack '$name' not found."
return 1
fi
local targets=()
if [[ -n "$node" ]]; then
targets=("$node")
else
targets=("${PI_NODES[@]}")
fi
for target in "${targets[@]}"; do
printf '%bDeploying %s to %s...%b\n' "$AMBER" "$name" "$target" "$RESET"
local ssh_target
ssh_target="$(br_ssh_target "$target" 2>/dev/null)" || {
printf ' %bskip%b unknown node\n' "$RED" "$RESET"
continue
}
if ! br_ssh_up "$target" 2>/dev/null; then
printf ' %boffline%b\n' "$RED" "$RESET"
continue
fi
# Create remote pack directory
br_ssh "$target" "mkdir -p /opt/blackroad/packs/$name/bin" 2>/dev/null || continue
# Copy pack files
scp -q -r "$pack_dir/bin/"* "$ssh_target:/opt/blackroad/packs/$name/bin/" 2>/dev/null || true
scp -q "$pack_dir/pack.yaml" "$ssh_target:/opt/blackroad/packs/$name/" 2>/dev/null || true
# Make scripts executable and link them
br_ssh "$target" "chmod +x /opt/blackroad/packs/$name/bin/* 2>/dev/null; for f in /opt/blackroad/packs/$name/bin/*; do ln -sf \"\$f\" /opt/blackroad/bin/\$(basename \"\$f\") 2>/dev/null; done" || true
printf ' %bdeployed%b\n' "$GREEN" "$RESET"
done
}
# Main
case "${1:-}" in
install) cmd_install "${2:?pack name required}" ;;
remove) cmd_remove "${2:?pack name required}" ;;
list) cmd_list ;;
installed) cmd_installed ;;
create) cmd_create "${2:?pack name required}" ;;
info) cmd_info "${2:?pack name required}" ;;
deploy) cmd_deploy "${2:?pack name required}" "${3:-}" ;;
-h|--help|help|"") usage ;;
*) echo "Unknown: $1"; usage; exit 1 ;;
esac