feat: colored installer output with status indicators and next steps

- Green ✓ for success, yellow ⚠ for warnings, red ✗ for errors
- Bold section headings (Installing, Post-install, PATH, Summary)
- Summary block with numbered next steps (source shell profile, mosaic init)
- Suppressed noisy sub-script output — only status lines shown
- Colors auto-disabled when not running in a terminal (piped output)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-19 13:05:10 -06:00
parent 1f2bb6ef77
commit b886b3d3c2
2 changed files with 115 additions and 46 deletions

View File

@@ -9,10 +9,16 @@ $ErrorActionPreference = "Stop"
$SourceDir = $PSScriptRoot
$TargetDir = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
function Write-Ok { param([string]$Msg) Write-Host "" -ForegroundColor Green -NoNewline; Write-Host $Msg }
function Write-Warn { param([string]$Msg) Write-Host "" -ForegroundColor Yellow -NoNewline; Write-Host $Msg }
function Write-Fail { param([string]$Msg) Write-Host "" -ForegroundColor Red -NoNewline; Write-Host $Msg }
function Write-Step { param([string]$Msg) Write-Host ""; Write-Host $Msg -ForegroundColor White -BackgroundColor DarkGray }
# ── Install framework ────────────────────────────────────────
Write-Step " Installing Mosaic framework "
if (-not (Test-Path $TargetDir)) { New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null }
# Sync files: remove old content, copy new
Write-Host "[mosaic-install] Copying framework to $TargetDir..."
Get-ChildItem $TargetDir -Exclude ".git" | Remove-Item -Recurse -Force
Get-ChildItem $SourceDir -Exclude ".git" | ForEach-Object {
$dest = Join-Path $TargetDir $_.Name
@@ -24,67 +30,89 @@ Get-ChildItem $SourceDir -Exclude ".git" | ForEach-Object {
}
}
Write-Host "[mosaic-install] Installed framework to $TargetDir"
Write-Ok "Framework installed to $TargetDir"
# ── Post-install tasks ───────────────────────────────────────
Write-Step " Post-install tasks "
# Run post-install scripts (PowerShell versions)
$binDir = Join-Path $TargetDir "bin"
Write-Host "[mosaic-install] Linking runtime compatibility assets"
try {
& "$binDir\mosaic-link-runtime-assets.ps1"
& "$binDir\mosaic-link-runtime-assets.ps1" *>$null
Write-Ok "Runtime assets linked"
}
catch {
Write-Host "[mosaic-install] WARNING: runtime asset linking failed (framework install still complete)" -ForegroundColor Yellow
Write-Warn "Runtime asset linking failed (non-fatal)"
}
Write-Host "[mosaic-install] Syncing universal skills"
if ($env:MOSAIC_SKIP_SKILLS_SYNC -eq "1") {
Write-Host "[mosaic-install] Skipping skills sync (MOSAIC_SKIP_SKILLS_SYNC=1)"
Write-Ok "Skills sync skipped (MOSAIC_SKIP_SKILLS_SYNC=1)"
}
else {
try {
& "$binDir\mosaic-sync-skills.ps1"
& "$binDir\mosaic-sync-skills.ps1" *>$null
Write-Ok "Skills synced"
}
catch {
Write-Host "[mosaic-install] WARNING: skills sync failed (framework install still complete)" -ForegroundColor Yellow
Write-Warn "Skills sync failed (non-fatal)"
}
}
Write-Host "[mosaic-install] Migrating runtime-local skills to Mosaic junctions"
try {
& "$binDir\mosaic-migrate-local-skills.ps1" -Apply
& "$binDir\mosaic-migrate-local-skills.ps1" -Apply *>$null
Write-Ok "Local skills migrated"
}
catch {
Write-Host "[mosaic-install] WARNING: local skill migration failed (framework install still complete)" -ForegroundColor Yellow
Write-Warn "Local skill migration failed (non-fatal)"
}
Write-Host "[mosaic-install] Running health audit"
try {
& "$binDir\mosaic-doctor.ps1"
& "$binDir\mosaic-doctor.ps1" *>$null
Write-Ok "Health audit passed"
}
catch {
Write-Host "[mosaic-install] WARNING: doctor reported issues (run mosaic-doctor.ps1 -FailOnWarn)" -ForegroundColor Yellow
Write-Warn "Health audit reported issues run 'mosaic doctor' for details"
}
# Ensure mosaic bin is in User PATH persistently
# ── PATH configuration ───────────────────────────────────────
Write-Step " PATH configuration "
$mosaicBin = Join-Path $TargetDir "bin"
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
$pathChanged = $false
if ($userPath -and $userPath.Split(";") -contains $mosaicBin) {
Write-Host "[mosaic-install] PATH: $mosaicBin already in User PATH"
Write-Ok "Already in User PATH"
}
else {
$newPath = if ($userPath) { "$mosaicBin;$userPath" } else { $mosaicBin }
[Environment]::SetEnvironmentVariable("Path", $newPath, "User")
$env:Path = "$mosaicBin;$env:Path"
Write-Host "[mosaic-install] PATH: Added $mosaicBin to User PATH"
Write-Host "[mosaic-install] Open a new terminal for PATH changes to take effect."
Write-Ok "Added to User PATH"
$pathChanged = $true
}
Write-Host "[mosaic-install] Done."
# ── Summary ──────────────────────────────────────────────────
Write-Host ""
Write-Host " Mosaic installed successfully." -ForegroundColor Green
Write-Host ""
$nextSteps = @()
if ($pathChanged) {
$nextSteps += "Open a new terminal (or log out and back in) to activate PATH."
}
$soulPath = Join-Path $TargetDir "SOUL.md"
if (-not (Test-Path $soulPath)) {
Write-Host ""
Write-Host "[mosaic-install] Set up your agent identity by running: mosaic init"
Write-Host "[mosaic-install] This generates SOUL.md - the universal behavioral contract for all agent sessions."
$nextSteps += "Run 'mosaic init' to set up your agent identity (SOUL.md)."
}
if ($nextSteps.Count -gt 0) {
Write-Host " Next steps:" -ForegroundColor White
for ($i = 0; $i -lt $nextSteps.Count; $i++) {
Write-Host " $($i + 1). " -NoNewline
Write-Host $nextSteps[$i] -ForegroundColor Cyan
}
Write-Host ""
}

View File

@@ -4,6 +4,21 @@ set -euo pipefail
SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TARGET_DIR="${MOSAIC_HOME:-$HOME/.config/mosaic}"
# Colors (disabled if not a terminal)
if [[ -t 1 ]]; then
GREEN='\033[0;32m' YELLOW='\033[0;33m' RED='\033[0;31m'
CYAN='\033[0;36m' BOLD='\033[1m' RESET='\033[0m'
else
GREEN='' YELLOW='' RED='' CYAN='' BOLD='' RESET=''
fi
ok() { echo -e " ${GREEN}${RESET} $1"; }
warn() { echo -e " ${YELLOW}${RESET} $1" >&2; }
fail() { echo -e " ${RED}${RESET} $1" >&2; }
step() { echo -e "\n${BOLD}$1${RESET}"; }
step "Installing Mosaic framework"
mkdir -p "$TARGET_DIR"
if command -v rsync >/dev/null 2>&1; then
@@ -16,33 +31,40 @@ fi
chmod +x "$TARGET_DIR"/bin/*
chmod +x "$TARGET_DIR"/install.sh
echo "[mosaic-install] Installed framework to $TARGET_DIR"
ok "Framework installed to $TARGET_DIR"
echo "[mosaic-install] Linking runtime compatibility assets"
if ! "$TARGET_DIR/bin/mosaic-link-runtime-assets"; then
echo "[mosaic-install] WARNING: runtime asset linking failed (framework install still complete)" >&2
step "Post-install tasks"
if "$TARGET_DIR/bin/mosaic-link-runtime-assets" >/dev/null 2>&1; then
ok "Runtime assets linked"
else
warn "Runtime asset linking failed (non-fatal)"
fi
echo "[mosaic-install] Syncing universal skills"
if [[ "${MOSAIC_SKIP_SKILLS_SYNC:-0}" == "1" ]]; then
echo "[mosaic-install] Skipping skills sync (MOSAIC_SKIP_SKILLS_SYNC=1)"
ok "Skills sync skipped (MOSAIC_SKIP_SKILLS_SYNC=1)"
else
if ! "$TARGET_DIR/bin/mosaic-sync-skills"; then
echo "[mosaic-install] WARNING: skills sync failed (framework install still complete)" >&2
if "$TARGET_DIR/bin/mosaic-sync-skills" >/dev/null 2>&1; then
ok "Skills synced"
else
warn "Skills sync failed (non-fatal)"
fi
fi
echo "[mosaic-install] Migrating runtime-local skills to Mosaic links"
if ! "$TARGET_DIR/bin/mosaic-migrate-local-skills" --apply; then
echo "[mosaic-install] WARNING: local skill migration failed (framework install still complete)" >&2
if "$TARGET_DIR/bin/mosaic-migrate-local-skills" --apply >/dev/null 2>&1; then
ok "Local skills migrated"
else
warn "Local skill migration failed (non-fatal)"
fi
echo "[mosaic-install] Running health audit"
if ! "$TARGET_DIR/bin/mosaic-doctor"; then
echo "[mosaic-install] WARNING: doctor reported issues (run ~/.config/mosaic/bin/mosaic-doctor --fail-on-warn)" >&2
if "$TARGET_DIR/bin/mosaic-doctor" >/dev/null 2>&1; then
ok "Health audit passed"
else
warn "Health audit reported issues — run 'mosaic doctor' for details"
fi
# Ensure ~/.config/mosaic/bin is in PATH persistently
step "PATH configuration"
PATH_LINE="export PATH=\"$TARGET_DIR/bin:\$PATH\""
# Find the right shell profile
@@ -56,20 +78,39 @@ else
SHELL_PROFILE="$HOME/.profile"
fi
PATH_CHANGED=false
if grep -qF "$TARGET_DIR/bin" "$SHELL_PROFILE" 2>/dev/null; then
echo "[mosaic-install] PATH: $TARGET_DIR/bin already in $SHELL_PROFILE"
ok "Already in PATH via $SHELL_PROFILE"
else
{
echo ""
echo "# Mosaic agent framework"
echo "$PATH_LINE"
} >> "$SHELL_PROFILE"
echo "[mosaic-install] PATH: Added $TARGET_DIR/bin to $SHELL_PROFILE"
echo "[mosaic-install] Run 'source $SHELL_PROFILE' or open a new terminal to activate."
ok "Added to PATH in $SHELL_PROFILE"
PATH_CHANGED=true
fi
# ── Summary ──────────────────────────────────────────────────
echo ""
echo -e "${GREEN}${BOLD} Mosaic installed successfully.${RESET}"
echo ""
# Collect next steps
NEXT_STEPS=()
if [[ "$PATH_CHANGED" == "true" ]]; then
NEXT_STEPS+=("Run ${CYAN}source $SHELL_PROFILE${RESET} or log out and back in to activate PATH.")
fi
if [[ ! -f "$TARGET_DIR/SOUL.md" ]]; then
echo ""
echo "[mosaic-install] Set up your agent identity by running: mosaic init"
echo "[mosaic-install] This generates SOUL.md — the universal behavioral contract for all agent sessions."
NEXT_STEPS+=("Run ${CYAN}mosaic init${RESET} to set up your agent identity (SOUL.md).")
fi
if [[ ${#NEXT_STEPS[@]} -gt 0 ]]; then
echo -e " ${BOLD}Next steps:${RESET}"
for i in "${!NEXT_STEPS[@]}"; do
echo -e " $((i+1)). ${NEXT_STEPS[$i]}"
done
echo ""
fi