mirror of
https://github.com/gnekt/My-Brain-Is-Full-Crew.git
synced 2026-09-07 22:36:26 +00:00
Architecture change: complex multi-step flows (onboarding, email triage, transcription, etc.) are now skills that run in the main conversation context instead of agent subprocesses. This fixes the state/context loss that caused agents to skip phases during multi-turn conversations. Skills created (13): - Architect: /onboarding, /create-agent, /manage-agent, /defrag - Postman: /email-triage, /meeting-prep, /weekly-agenda, /deadline-radar - Transcriber: /transcribe - Librarian: /vault-audit, /deep-clean, /tag-garden - Sorter: /inbox-triage Agent changes: - architect.md: -70% (1554 → 473 lines) - transcriber.md: -72% (530 → 147 lines) - postman.md: -42%, librarian.md: -37%, sorter.md: -11% - All agents: explicit post-it create-if-not-exists Scripts: - launchme.sh/updateme.sh: copy skills/ directly, remove generate-skills.py Docs updated: - README.md: new Skills section, mermaid diagrams, routing - getting-started.md, examples.md: skill references - docs/agents/*.md: capability tables with skill vs agent routing - references/agents.md, agent-orchestration.md, agents-registry.md, agent-template.md: skill registry, skill-first routing protocol
263 lines
12 KiB
Bash
Executable File
263 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# My Brain Is Full - Crew :: Updater
|
|
# =============================================================================
|
|
# After pulling new changes from the repo, run this to update the agents
|
|
# in your vault:
|
|
#
|
|
# cd /path/to/your-vault/My-Brain-Is-Full-Crew
|
|
# git pull
|
|
# bash scripts/updateme.sh
|
|
#
|
|
# =============================================================================
|
|
|
|
set -eo pipefail
|
|
|
|
# ── Colors ──────────────────────────────────────────────────────────────────
|
|
if [[ -t 1 ]]; then
|
|
GREEN='\033[0;32m'; CYAN='\033[0;36m'; YELLOW='\033[1;33m'
|
|
RED='\033[0;31m'; BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m'
|
|
else
|
|
GREEN=''; CYAN=''; YELLOW=''; RED=''; BOLD=''; DIM=''; NC=''
|
|
fi
|
|
|
|
info() { echo -e " ${CYAN}>${NC} $*"; }
|
|
success() { echo -e " ${GREEN}✓${NC} $*"; }
|
|
warn() { echo -e " ${YELLOW}!${NC} $*"; }
|
|
die() { echo -e "\n ${RED}Error: $*${NC}\n" >&2; exit 1; }
|
|
|
|
# ── Find paths ──────────────────────────────────────────────────────────────
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
VAULT_DIR="$(cd "$REPO_DIR/.." && pwd)"
|
|
|
|
[[ -d "$REPO_DIR/agents" ]] || die "Can't find agents/ — are you running this from the repo?"
|
|
|
|
# ── Check vault has been set up ─────────────────────────────────────────────
|
|
if [[ ! -d "$VAULT_DIR/.claude/agents" ]]; then
|
|
die "No .claude/agents/ found in $VAULT_DIR — run launchme.sh first"
|
|
fi
|
|
|
|
# ── Banner ──────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
echo -e "${BOLD}╔══════════════════════════════════════════╗${NC}"
|
|
echo -e "${BOLD}║ My Brain Is Full - Crew :: Update ║${NC}"
|
|
echo -e "${BOLD}╚══════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
# ── Confirm overwrite ────────────────────────────────────────────────────
|
|
echo -e "${BOLD}This will overwrite core agent files, references, and CLAUDE.md.${NC}"
|
|
echo -e " ${DIM}Custom agent files in .claude/agents/ will not be deleted or overwritten.${NC}"
|
|
echo -e " ${DIM}Custom agent entries in registry/directory will be preserved during update.${NC}"
|
|
echo -e " ${DIM}Your vault notes are never touched.${NC}"
|
|
echo ""
|
|
echo -e " ${BOLD}c)${NC} Continue"
|
|
echo -e " ${BOLD}q)${NC} Quit"
|
|
if ! read -r -p " > " UPDATE_ANSWER 2>/dev/null; then UPDATE_ANSWER=""; fi
|
|
if [[ ! "$UPDATE_ANSWER" =~ ^[Cc]$ ]]; then
|
|
echo ""
|
|
info "Update cancelled."
|
|
echo ""
|
|
exit 0
|
|
fi
|
|
echo ""
|
|
|
|
# ── Deprecate removed core agents ─────────────────────────────────────────
|
|
# Read the OLD manifest first (before rewriting it) so we know which files
|
|
# were previously installed as core. Agents removed from the repo will still
|
|
# be in the old manifest and can be correctly deprecated.
|
|
MANIFEST="$VAULT_DIR/.claude/agents/.core-manifest"
|
|
DEPRECATED_COUNT=0
|
|
for vault_agent in "$VAULT_DIR/.claude/agents/"*.md; do
|
|
[[ -f "$vault_agent" ]] || continue
|
|
name="$(basename "$vault_agent")"
|
|
# Skip if it still exists in repo
|
|
[[ -f "$REPO_DIR/agents/$name" ]] && continue
|
|
# Skip if already deprecated
|
|
[[ "$name" == *"-DEPRECATED"* ]] && continue
|
|
# Require manifest to distinguish core from custom agents
|
|
if [[ ! -f "$MANIFEST" ]]; then
|
|
continue
|
|
fi
|
|
# Skip custom agents: only deprecate if listed in the manifest
|
|
if ! grep -qxF "$name" "$MANIFEST"; then
|
|
continue
|
|
fi
|
|
deprecated_name="${name%.md}-DEPRECATED.md"
|
|
mkdir -p "$VAULT_DIR/.claude/deprecated"
|
|
# Skip if already deprecated in a previous run
|
|
[[ -f "$VAULT_DIR/.claude/deprecated/$deprecated_name" ]] && continue
|
|
mv "$vault_agent" "$VAULT_DIR/.claude/deprecated/$deprecated_name"
|
|
# Prepend deprecation header
|
|
{ echo "########"; echo "DEPRECATED DO NOT USE"; echo "########"; echo ""; cat "$VAULT_DIR/.claude/deprecated/$deprecated_name"; } > "$VAULT_DIR/.claude/deprecated/$deprecated_name.tmp"
|
|
mv "$VAULT_DIR/.claude/deprecated/$deprecated_name.tmp" "$VAULT_DIR/.claude/deprecated/$deprecated_name"
|
|
warn "Deprecated agent: $name -> deprecated/$deprecated_name"
|
|
DEPRECATED_COUNT=$((DEPRECATED_COUNT + 1))
|
|
# Remove deprecated agent from manifest
|
|
if [[ -f "$MANIFEST" ]]; then
|
|
grep -vxF "$name" "$MANIFEST" > "$MANIFEST.tmp" || true
|
|
mv "$MANIFEST.tmp" "$MANIFEST"
|
|
fi
|
|
done
|
|
|
|
# ── Update agents and rewrite manifest ────────────────────────────────────
|
|
AGENT_COUNT=0
|
|
: > "$VAULT_DIR/.claude/agents/.core-manifest"
|
|
for agent in "$REPO_DIR/agents/"*.md; do
|
|
name="$(basename "$agent")"
|
|
basename "$agent" >> "$VAULT_DIR/.claude/agents/.core-manifest"
|
|
if [[ -f "$VAULT_DIR/.claude/agents/$name" ]]; then
|
|
if ! diff -q "$agent" "$VAULT_DIR/.claude/agents/$name" >/dev/null 2>&1; then
|
|
cp "$agent" "$VAULT_DIR/.claude/agents/"
|
|
info "Updated $name"
|
|
AGENT_COUNT=$((AGENT_COUNT + 1))
|
|
fi
|
|
else
|
|
cp "$agent" "$VAULT_DIR/.claude/agents/"
|
|
info "Added $name (new agent)"
|
|
AGENT_COUNT=$((AGENT_COUNT + 1))
|
|
fi
|
|
done
|
|
|
|
# ── Deprecate removed references ──────────────────────────────────────────
|
|
# Read the old manifest before rewriting, same logic as agents.
|
|
REF_MANIFEST="$VAULT_DIR/.claude/references/.core-manifest"
|
|
for vault_ref in "$VAULT_DIR/.claude/references/"*.md; do
|
|
[[ -f "$vault_ref" ]] || continue
|
|
name="$(basename "$vault_ref")"
|
|
[[ -f "$REPO_DIR/references/$name" ]] && continue
|
|
[[ "$name" == *"-DEPRECATED"* ]] && continue
|
|
# Require manifest to distinguish core from user-created references
|
|
if [[ ! -f "$REF_MANIFEST" ]]; then
|
|
continue
|
|
fi
|
|
# Skip user-created references: only deprecate if listed in the manifest
|
|
if ! grep -qxF "$name" "$REF_MANIFEST"; then
|
|
continue
|
|
fi
|
|
deprecated_name="${name%.md}-DEPRECATED.md"
|
|
mkdir -p "$VAULT_DIR/.claude/deprecated"
|
|
[[ -f "$VAULT_DIR/.claude/deprecated/$deprecated_name" ]] && continue
|
|
mv "$vault_ref" "$VAULT_DIR/.claude/deprecated/$deprecated_name"
|
|
{ echo "########"; echo "DEPRECATED DO NOT USE"; echo "########"; echo ""; cat "$VAULT_DIR/.claude/deprecated/$deprecated_name"; } > "$VAULT_DIR/.claude/deprecated/$deprecated_name.tmp"
|
|
mv "$VAULT_DIR/.claude/deprecated/$deprecated_name.tmp" "$VAULT_DIR/.claude/deprecated/$deprecated_name"
|
|
warn "Deprecated reference: $name -> deprecated/$deprecated_name"
|
|
DEPRECATED_COUNT=$((DEPRECATED_COUNT + 1))
|
|
done
|
|
|
|
# ── Update references and rewrite manifest ────────────────────────────────
|
|
# Files the Architect modifies with user content (custom agent rows/sections).
|
|
# These need special merge logic to preserve the "## Custom Agents" section.
|
|
USER_MUTABLE_REFS="agents-registry.md agents.md"
|
|
|
|
# ── Ensure Meta/states/ exists (agent post-its) ─────────────────────────────
|
|
mkdir -p "$VAULT_DIR/Meta/states"
|
|
|
|
REF_COUNT=0
|
|
mkdir -p "$VAULT_DIR/.claude/references"
|
|
: > "$VAULT_DIR/.claude/references/.core-manifest"
|
|
for ref in "$REPO_DIR/references/"*.md; do
|
|
name="$(basename "$ref")"
|
|
basename "$ref" >> "$VAULT_DIR/.claude/references/.core-manifest"
|
|
vault_copy="$VAULT_DIR/.claude/references/$name"
|
|
|
|
# For user-mutable files: preserve custom agent content
|
|
if [[ " $USER_MUTABLE_REFS " == *" $name "* ]] && [[ -f "$vault_copy" ]]; then
|
|
# Extract user's custom section (from "## Custom Agents" to end of file)
|
|
custom_section=""
|
|
if grep -qn "^## Custom Agents" "$vault_copy"; then
|
|
custom_line=$(grep -n "^## Custom Agents" "$vault_copy" | head -1 | cut -d: -f1)
|
|
custom_section=$(tail -n +"$custom_line" "$vault_copy")
|
|
fi
|
|
|
|
# For agents-registry.md: also extract custom rows from the Registry table
|
|
# Custom rows are table lines whose agent name is NOT a core agent
|
|
custom_table_rows=""
|
|
if [[ "$name" == "agents-registry.md" ]]; then
|
|
CORE_NAMES="architect scribe sorter seeker connector librarian transcriber postman"
|
|
while IFS= read -r row; do
|
|
# Extract agent name from first column: | name | ...
|
|
agent_name=$(echo "$row" | awk -F'|' '{gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2}')
|
|
if [[ -n "$agent_name" ]] && ! echo "$CORE_NAMES" | grep -qw "$agent_name"; then
|
|
custom_table_rows="${custom_table_rows}${row}"$'\n'
|
|
fi
|
|
done < <(grep "^|" "$vault_copy" | grep -v "^|[[:space:]]*Name[[:space:]]*|" | grep -v "^|[-[:space:]]*|")
|
|
fi
|
|
|
|
# Copy the new repo version
|
|
if ! diff -q "$ref" "$vault_copy" >/dev/null 2>&1; then
|
|
cp "$ref" "$vault_copy"
|
|
|
|
# Re-insert custom table rows into the registry table (after the last table row)
|
|
if [[ -n "$custom_table_rows" ]]; then
|
|
# Find the last table row (any line starting with |) — avoids hard-coding a specific agent name
|
|
last_table_line=$(grep -n "^|" "$vault_copy" | tail -1 | cut -d: -f1)
|
|
if [[ -n "$last_table_line" ]]; then
|
|
{ head -n "$last_table_line" "$vault_copy"; printf "%s" "$custom_table_rows"; tail -n +"$((last_table_line + 1))" "$vault_copy"; } > "$vault_copy.tmp"
|
|
mv "$vault_copy.tmp" "$vault_copy"
|
|
fi
|
|
fi
|
|
|
|
# Re-append preserved custom section (replace the repo's empty custom section)
|
|
if [[ -n "$custom_section" ]]; then
|
|
repo_custom_line=$(grep -n "^## Custom Agents" "$vault_copy" | head -1 | cut -d: -f1)
|
|
if [[ -n "$repo_custom_line" ]]; then
|
|
head -n "$((repo_custom_line - 1))" "$vault_copy" > "$vault_copy.tmp"
|
|
printf '%s\n' "$custom_section" >> "$vault_copy.tmp"
|
|
mv "$vault_copy.tmp" "$vault_copy"
|
|
fi
|
|
fi
|
|
info "Updated reference: $name (preserved custom content)"
|
|
REF_COUNT=$((REF_COUNT + 1))
|
|
fi
|
|
continue
|
|
fi
|
|
|
|
if [[ ! -f "$vault_copy" ]] || ! diff -q "$ref" "$vault_copy" >/dev/null 2>&1; then
|
|
cp "$ref" "$vault_copy"
|
|
info "Updated reference: $name"
|
|
REF_COUNT=$((REF_COUNT + 1))
|
|
fi
|
|
done
|
|
|
|
# ── Update skills ────────────────────────────────────────────────────────────
|
|
SKILL_COUNT=0
|
|
if [[ -d "$REPO_DIR/skills" ]]; then
|
|
for skill_dir in "$REPO_DIR/skills/"*/; do
|
|
[[ -f "$skill_dir/SKILL.md" ]] || continue
|
|
skill_name="$(basename "$skill_dir")"
|
|
src="$skill_dir/SKILL.md"
|
|
dst="$VAULT_DIR/.claude/skills/$skill_name/SKILL.md"
|
|
if [[ ! -f "$dst" ]] || ! diff -q "$src" "$dst" >/dev/null 2>&1; then
|
|
mkdir -p "$VAULT_DIR/.claude/skills/$skill_name"
|
|
cp "$src" "$dst"
|
|
info "Updated skill: $skill_name"
|
|
SKILL_COUNT=$((SKILL_COUNT + 1))
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# ── Update CLAUDE.md ──────────────────────────────────────────────────────
|
|
CLAUDE_MD_UPDATED=""
|
|
if [[ -f "$REPO_DIR/CLAUDE.md" ]]; then
|
|
if [[ ! -f "$VAULT_DIR/CLAUDE.md" ]] || ! diff -q "$REPO_DIR/CLAUDE.md" "$VAULT_DIR/CLAUDE.md" >/dev/null 2>&1; then
|
|
cp "$REPO_DIR/CLAUDE.md" "$VAULT_DIR/CLAUDE.md"
|
|
info "Updated CLAUDE.md"
|
|
CLAUDE_MD_UPDATED="1"
|
|
fi
|
|
fi
|
|
|
|
# ── Summary ─────────────────────────────────────────────────────────────────
|
|
echo ""
|
|
if [[ $AGENT_COUNT -eq 0 && $REF_COUNT -eq 0 && $SKILL_COUNT -eq 0 && $DEPRECATED_COUNT -eq 0 && -z "$CLAUDE_MD_UPDATED" ]]; then
|
|
success "Everything is already up to date!"
|
|
else
|
|
success "Updated $AGENT_COUNT agent(s), $SKILL_COUNT skill(s), and $REF_COUNT reference(s)"
|
|
if [[ $DEPRECATED_COUNT -gt 0 ]]; then
|
|
warn "Deprecated $DEPRECATED_COUNT file(s) no longer in the project"
|
|
fi
|
|
fi
|
|
echo ""
|
|
echo -e " ${DIM}Restart Claude Code to pick up the changes.${NC}"
|
|
echo ""
|