refactor: AGENTS.md is the single source of truth for all runtimes
- Create ~/.config/mosaic/AGENTS.md as the canonical universal agent config - Runtime adapters (CLAUDE.md, opencode/AGENTS.md, codex/instructions.md) are now thin pointers that say "READ ~/.config/mosaic/AGENTS.md" - mosaic claude: injects AGENTS.md via --append-system-prompt - mosaic opencode/codex: copies AGENTS.md to runtime config path before launch - mosaic-link-runtime-assets: pushes thin pointers for direct launch fallback AGENTS.md is runtime-agnostic. All runtimes get the same standards. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
47
bin/mosaic
47
bin/mosaic
@@ -3,10 +3,13 @@ set -euo pipefail
|
||||
|
||||
# mosaic — Unified agent launcher and management CLI
|
||||
#
|
||||
# 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 SOUL.md injected
|
||||
# mosaic opencode [args...] Launch OpenCode
|
||||
# mosaic codex [args...] Launch Codex
|
||||
# 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
|
||||
@@ -22,9 +25,9 @@ mosaic $VERSION — Unified agent launcher
|
||||
Usage: mosaic <command> [args...]
|
||||
|
||||
Agent Launchers:
|
||||
claude [args...] Launch Claude Code with SOUL.md injected
|
||||
opencode [args...] Launch OpenCode
|
||||
codex [args...] Launch Codex
|
||||
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)
|
||||
@@ -49,6 +52,14 @@ check_mosaic_home() {
|
||||
fi
|
||||
}
|
||||
|
||||
check_agents_md() {
|
||||
if [[ ! -f "$MOSAIC_HOME/AGENTS.md" ]]; then
|
||||
echo "[mosaic] ERROR: ~/.config/mosaic/AGENTS.md not found." >&2
|
||||
echo "[mosaic] Re-run the installer: cd ~/src/mosaic-bootstrap && bash install.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_soul() {
|
||||
if [[ ! -f "$MOSAIC_HOME/SOUL.md" ]]; then
|
||||
echo "[mosaic] SOUL.md not found. Running mosaic init..."
|
||||
@@ -65,31 +76,51 @@ check_runtime() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Ensure AGENTS.md is present at the runtime's native config path.
|
||||
# Used for runtimes that don't support CLI prompt injection.
|
||||
ensure_runtime_config() {
|
||||
local src="$MOSAIC_HOME/AGENTS.md"
|
||||
local dst="$1"
|
||||
mkdir -p "$(dirname "$dst")"
|
||||
if ! cmp -s "$src" "$dst" 2>/dev/null; then
|
||||
cp "$src" "$dst"
|
||||
fi
|
||||
}
|
||||
|
||||
# Launcher functions
|
||||
launch_claude() {
|
||||
check_mosaic_home
|
||||
check_agents_md
|
||||
check_soul
|
||||
check_runtime "claude"
|
||||
|
||||
# SOUL.md is loaded via ~/.claude/CLAUDE.md directive (pushed by mosaic-link-runtime-assets)
|
||||
# Claude supports --append-system-prompt for direct injection
|
||||
local agents_content
|
||||
agents_content="$(cat "$MOSAIC_HOME/AGENTS.md")"
|
||||
echo "[mosaic] Launching Claude Code..."
|
||||
exec claude "$@"
|
||||
exec claude --append-system-prompt "$agents_content" "$@"
|
||||
}
|
||||
|
||||
launch_opencode() {
|
||||
check_mosaic_home
|
||||
check_agents_md
|
||||
check_soul
|
||||
check_runtime "opencode"
|
||||
|
||||
# OpenCode reads from ~/.config/opencode/AGENTS.md — copy canonical version there
|
||||
ensure_runtime_config "$HOME/.config/opencode/AGENTS.md"
|
||||
echo "[mosaic] Launching OpenCode..."
|
||||
exec opencode "$@"
|
||||
}
|
||||
|
||||
launch_codex() {
|
||||
check_mosaic_home
|
||||
check_agents_md
|
||||
check_soul
|
||||
check_runtime "codex"
|
||||
|
||||
# Codex reads from ~/.codex/instructions.md — copy canonical version there
|
||||
ensure_runtime_config "$HOME/.codex/instructions.md"
|
||||
echo "[mosaic] Launching Codex..."
|
||||
exec codex "$@"
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ for p in "${legacy_paths[@]}"; do
|
||||
remove_legacy_path "$p"
|
||||
done
|
||||
|
||||
# Runtime files are synced as regular files (not symlinks) to reduce path confusion.
|
||||
# Claude-specific runtime files (settings, hooks — NOT CLAUDE.md which is now a thin pointer)
|
||||
for runtime_file in \
|
||||
CLAUDE.md \
|
||||
settings.json \
|
||||
@@ -80,13 +80,13 @@ for runtime_file in \
|
||||
copy_file_managed "$src" "$HOME/.claude/$runtime_file"
|
||||
done
|
||||
|
||||
# OpenCode runtime adapter (optional, copied when present).
|
||||
# OpenCode runtime adapter (thin pointer to AGENTS.md)
|
||||
opencode_adapter="$MOSAIC_HOME/runtime/opencode/AGENTS.md"
|
||||
if [[ -f "$opencode_adapter" ]]; then
|
||||
copy_file_managed "$opencode_adapter" "$HOME/.config/opencode/AGENTS.md"
|
||||
fi
|
||||
|
||||
# Codex runtime adapter (optional, copied when present).
|
||||
# Codex runtime adapter (thin pointer to AGENTS.md)
|
||||
codex_adapter="$MOSAIC_HOME/runtime/codex/instructions.md"
|
||||
if [[ -f "$codex_adapter" ]]; then
|
||||
mkdir -p "$HOME/.codex"
|
||||
|
||||
@@ -77,7 +77,7 @@ foreach ($p in $legacyPaths) {
|
||||
Remove-LegacyPath $p
|
||||
}
|
||||
|
||||
# Sync runtime config files (copy, not link)
|
||||
# Claude-specific runtime files (settings, hooks — CLAUDE.md is now a thin pointer)
|
||||
$runtimeFiles = @("CLAUDE.md", "settings.json", "hooks-config.json", "context7-integration.md")
|
||||
foreach ($rf in $runtimeFiles) {
|
||||
$src = Join-Path $MosaicHome "runtime\claude\$rf"
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# 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 SOUL.md injected
|
||||
# mosaic opencode [args...] Launch OpenCode
|
||||
# mosaic codex [args...] Launch Codex
|
||||
# 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
|
||||
@@ -19,9 +22,9 @@ mosaic $Version - Unified agent launcher
|
||||
Usage: mosaic <command> [args...]
|
||||
|
||||
Agent Launchers:
|
||||
claude [args...] Launch Claude Code with SOUL.md injected
|
||||
opencode [args...] Launch OpenCode
|
||||
codex [args...] Launch Codex
|
||||
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)
|
||||
@@ -43,6 +46,15 @@ function Assert-MosaicHome {
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
@@ -60,6 +72,18 @@ function Assert-Runtime {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -71,23 +95,31 @@ $remaining = if ($args.Count -gt 1) { $args[1..($args.Count - 1)] } else { @() }
|
||||
switch ($command) {
|
||||
"claude" {
|
||||
Assert-MosaicHome
|
||||
Assert-AgentsMd
|
||||
Assert-Soul
|
||||
Assert-Runtime "claude"
|
||||
# SOUL.md is loaded via ~/.claude/CLAUDE.md directive (pushed by mosaic-link-runtime-assets)
|
||||
# Claude supports --append-system-prompt for direct injection
|
||||
$agentsContent = Get-Content (Join-Path $MosaicHome "AGENTS.md") -Raw
|
||||
Write-Host "[mosaic] Launching Claude Code..."
|
||||
& claude @remaining
|
||||
& 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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user