202 lines
7.3 KiB
PowerShell
202 lines
7.3 KiB
PowerShell
# mosaic.ps1 — Unified agent launcher and management CLI (Windows)
|
|
#
|
|
# AGENTS.md is the single source of truth for all agent sessions.
|
|
# The launcher injects it into every runtime consistently.
|
|
#
|
|
# Usage:
|
|
# mosaic claude [args...] Launch Claude Code with AGENTS.md injected
|
|
# mosaic opencode [args...] Launch OpenCode with AGENTS.md injected
|
|
# mosaic codex [args...] Launch Codex with AGENTS.md injected
|
|
# mosaic init [args...] Generate SOUL.md interactively
|
|
# mosaic doctor [args...] Health audit
|
|
# mosaic sync [args...] Sync skills
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
|
|
$Version = "0.1.0"
|
|
|
|
function Show-Usage {
|
|
Write-Host @"
|
|
mosaic $Version - Unified agent launcher
|
|
|
|
Usage: mosaic <command> [args...]
|
|
|
|
Agent Launchers:
|
|
claude [args...] Launch Claude Code with AGENTS.md injected
|
|
opencode [args...] Launch OpenCode with AGENTS.md injected
|
|
codex [args...] Launch Codex with AGENTS.md injected
|
|
|
|
Management:
|
|
init [args...] Generate SOUL.md (agent identity contract)
|
|
doctor [args...] Audit runtime state and detect drift
|
|
sync [args...] Sync skills from canonical source
|
|
bootstrap <path> Bootstrap a repo with Mosaic standards
|
|
upgrade [mode] [args] Upgrade release (default) or project files
|
|
upgrade check Check release upgrade status (no changes)
|
|
release-upgrade [...] Upgrade installed Mosaic release
|
|
project-upgrade [...] Clean up stale SOUL.md/CLAUDE.md in a project
|
|
|
|
Options:
|
|
-h, --help Show this help
|
|
-v, --version Show version
|
|
"@
|
|
}
|
|
|
|
function Assert-MosaicHome {
|
|
if (-not (Test-Path $MosaicHome)) {
|
|
Write-Host "[mosaic] ERROR: ~/.config/mosaic not found." -ForegroundColor Red
|
|
Write-Host "[mosaic] Install with: irm https://git.mosaicstack.dev/mosaic/bootstrap/raw/branch/main/remote-install.ps1 | iex"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
function Assert-AgentsMd {
|
|
$agentsPath = Join-Path $MosaicHome "AGENTS.md"
|
|
if (-not (Test-Path $agentsPath)) {
|
|
Write-Host "[mosaic] ERROR: ~/.config/mosaic/AGENTS.md not found." -ForegroundColor Red
|
|
Write-Host "[mosaic] Re-run the installer."
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
function Assert-Soul {
|
|
$soulPath = Join-Path $MosaicHome "SOUL.md"
|
|
if (-not (Test-Path $soulPath)) {
|
|
Write-Host "[mosaic] SOUL.md not found. Running mosaic init..."
|
|
& (Join-Path $MosaicHome "bin\mosaic-init.ps1")
|
|
}
|
|
}
|
|
|
|
function Assert-Runtime {
|
|
param([string]$Cmd)
|
|
if (-not (Get-Command $Cmd -ErrorAction SilentlyContinue)) {
|
|
Write-Host "[mosaic] ERROR: '$Cmd' not found in PATH." -ForegroundColor Red
|
|
Write-Host "[mosaic] Install $Cmd before launching."
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
function Ensure-RuntimeConfig {
|
|
param([string]$Dst)
|
|
$src = Join-Path $MosaicHome "AGENTS.md"
|
|
$parent = Split-Path $Dst -Parent
|
|
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent -Force | Out-Null }
|
|
$srcHash = (Get-FileHash $src -Algorithm SHA256).Hash
|
|
$dstHash = if (Test-Path $Dst) { (Get-FileHash $Dst -Algorithm SHA256).Hash } else { "" }
|
|
if ($srcHash -ne $dstHash) {
|
|
Copy-Item $src $Dst -Force
|
|
}
|
|
}
|
|
|
|
if ($args.Count -eq 0) {
|
|
Show-Usage
|
|
exit 0
|
|
}
|
|
|
|
$command = $args[0]
|
|
$remaining = if ($args.Count -gt 1) { $args[1..($args.Count - 1)] } else { @() }
|
|
|
|
switch ($command) {
|
|
"claude" {
|
|
Assert-MosaicHome
|
|
Assert-AgentsMd
|
|
Assert-Soul
|
|
Assert-Runtime "claude"
|
|
# Claude supports --append-system-prompt for direct injection
|
|
$agentsContent = Get-Content (Join-Path $MosaicHome "AGENTS.md") -Raw
|
|
Write-Host "[mosaic] Launching Claude Code..."
|
|
& claude --append-system-prompt $agentsContent @remaining
|
|
}
|
|
"opencode" {
|
|
Assert-MosaicHome
|
|
Assert-AgentsMd
|
|
Assert-Soul
|
|
Assert-Runtime "opencode"
|
|
# OpenCode reads from ~/.config/opencode/AGENTS.md
|
|
Ensure-RuntimeConfig (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md")
|
|
Write-Host "[mosaic] Launching OpenCode..."
|
|
& opencode @remaining
|
|
}
|
|
"codex" {
|
|
Assert-MosaicHome
|
|
Assert-AgentsMd
|
|
Assert-Soul
|
|
Assert-Runtime "codex"
|
|
# Codex reads from ~/.codex/instructions.md
|
|
Ensure-RuntimeConfig (Join-Path $env:USERPROFILE ".codex\instructions.md")
|
|
Write-Host "[mosaic] Launching Codex..."
|
|
& codex @remaining
|
|
}
|
|
"init" {
|
|
Assert-MosaicHome
|
|
& (Join-Path $MosaicHome "bin\mosaic-init.ps1") @remaining
|
|
}
|
|
"doctor" {
|
|
Assert-MosaicHome
|
|
& (Join-Path $MosaicHome "bin\mosaic-doctor.ps1") @remaining
|
|
}
|
|
"sync" {
|
|
Assert-MosaicHome
|
|
& (Join-Path $MosaicHome "bin\mosaic-sync-skills.ps1") @remaining
|
|
}
|
|
"bootstrap" {
|
|
Assert-MosaicHome
|
|
Write-Host "[mosaic] NOTE: mosaic-bootstrap-repo requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
|
& (Join-Path $MosaicHome "bin\mosaic-bootstrap-repo") @remaining
|
|
}
|
|
"upgrade" {
|
|
Assert-MosaicHome
|
|
if ($remaining.Count -eq 0) {
|
|
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1")
|
|
break
|
|
}
|
|
|
|
$mode = $remaining[0]
|
|
$tail = if ($remaining.Count -gt 1) { $remaining[1..($remaining.Count - 1)] } else { @() }
|
|
|
|
switch -Regex ($mode) {
|
|
"^release$" {
|
|
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @tail
|
|
}
|
|
"^check$" {
|
|
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") -DryRun @tail
|
|
}
|
|
"^project$" {
|
|
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
|
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @tail
|
|
}
|
|
"^(--all|--root)$" {
|
|
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
|
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
|
|
}
|
|
"^(--dry-run|--ref|--keep|--overwrite|-y|--yes)$" {
|
|
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
|
|
}
|
|
"^-.*" {
|
|
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
|
|
}
|
|
default {
|
|
Write-Host "[mosaic] NOTE: treating positional argument as project path." -ForegroundColor Yellow
|
|
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
|
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
|
|
}
|
|
}
|
|
}
|
|
"release-upgrade" {
|
|
Assert-MosaicHome
|
|
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
|
|
}
|
|
"project-upgrade" {
|
|
Assert-MosaicHome
|
|
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
|
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
|
|
}
|
|
{ $_ -in "help", "-h", "--help" } { Show-Usage }
|
|
{ $_ -in "version", "-v", "--version" } { Write-Host "mosaic $Version" }
|
|
default {
|
|
Write-Host "[mosaic] Unknown command: $command" -ForegroundColor Red
|
|
Write-Host "[mosaic] Run 'mosaic --help' for usage."
|
|
exit 1
|
|
}
|
|
}
|