Skip to content

Instantly share code, notes, and snippets.

@lastknight
Last active March 26, 2026 13:26
Show Gist options
  • Select an option

  • Save lastknight/f21271d761a86a5ab2b6a5f2e73256d5 to your computer and use it in GitHub Desktop.

Select an option

Save lastknight/f21271d761a86a5ab2b6a5f2e73256d5 to your computer and use it in GitHub Desktop.
clouded-bootstrap: one-curl Claude Code setup with skills
#!/usr/bin/env bash
# clouded-bootstrap.sh — Setup/migrazione Claude Code su qualsiasi macchina
# Idempotente: funziona su macchina nuova E su macchina esistente da aggiornare.
# Usage: curl -fsSL https://gist.githubusercontent.com/lastknight/f21271d761a86a5ab2b6a5f2e73256d5/raw/clouded-bootstrap.sh | bash
set -euo pipefail
# ── colori ────────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BOLD='\033[1m'; NC='\033[0m'
log() { echo -e "${GREEN}▸${NC} $*"; }
warn() { echo -e "${YELLOW}⚠${NC} $*"; }
err() { echo -e "${RED}✗${NC} $*" >&2; exit 1; }
ok() { echo -e "${GREEN}✓${NC} $*"; }
REPO="lastknight/claude-skills"
SKILLS_DIR="$HOME/.claude/skills"
REPO_DIR="$HOME/.claude-skills-repo"
HOSTNAME_SHORT="$(hostname -s 2>/dev/null || hostname)"
CMD_NAME="clouded"
MEMORY_DIR="$HOME/.claude/projects/$(echo "$HOME" | sed 's|/|-|g')/memory"
# rsync exclusions — MUST match sync.md (single source of truth)
RSYNC_EXCLUDES=(
--exclude='.git' --exclude='.DS_Store' --exclude='.gitignore'
--exclude='README.md' --exclude='README.pdf' --exclude='CLAUDE.md'
--exclude='memory/' --exclude='agents/' --exclude='rules/'
--exclude='sessions/' --exclude='hooks/' --exclude='scripts/'
--exclude='config/' --exclude='settings.json'
--exclude='clouded-bootstrap.sh'
)
# rileva se siamo su server headless (SSH senza display)
HAS_DISPLAY=false
if [ -n "${DISPLAY:-}" ] || [ -n "${WAYLAND_DISPLAY:-}" ] || [[ "$(uname)" == "Darwin" ]]; then
HAS_DISPLAY=true
fi
# rileva se siamo root
IS_ROOT=false
[ "$(id -u)" = "0" ] && IS_ROOT=true
echo -e "\n${BOLD}clouded bootstrap${NC} — macchina: ${YELLOW}${HOSTNAME_SHORT}${NC}\n"
# ── 1. prerequisiti base ──────────────────────────────────────────────────────
log "Controllo prerequisiti..."
check_cmd() {
command -v "$1" &>/dev/null && return 0
return 1
}
# funzione per installare pacchetti di sistema (apt o brew)
install_pkg() {
if check_cmd apt-get; then
apt-get install -y "$@" 2>/dev/null || warn "Impossibile installare $* (serve root?)"
elif check_cmd brew; then
brew install "$@"
else
warn "Impossibile installare $* — installa manualmente"
fi
}
# claude
if ! check_cmd claude; then
warn "Claude Code non trovato. Provo ad installarlo..."
if check_cmd npm; then
npm install -g @anthropic-ai/claude-code
elif check_cmd brew; then
brew install claude
else
err "npm non trovato. Installa Node.js prima:\n https://nodejs.org\nPoi: npm install -g @anthropic-ai/claude-code"
fi
fi
ok "claude $(claude --version 2>/dev/null | head -1)"
# gh CLI
if ! check_cmd gh; then
warn "GitHub CLI (gh) non trovato. Provo ad installarlo..."
if check_cmd brew; then
brew install gh
elif check_cmd apt-get; then
(type -p curl >/dev/null || apt install curl -y) && \
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg 2>/dev/null && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
apt update && apt install gh -y
else
err "Installa gh manualmente: https://cli.github.com"
fi
fi
ok "gh $(gh --version 2>/dev/null | head -1 | awk '{print $3}')"
# rsync, git, tmux, curl
for tool in rsync git tmux curl; do
if ! check_cmd "$tool"; then
warn "$tool non trovato. Installo..."
install_pkg "$tool"
fi
check_cmd "$tool" && ok "$tool" || warn "$tool non disponibile"
done
# ── 1b. dipendenze Python e system ───────────────────────────────────────────
log "Installazione dipendenze Python e system tools..."
# poppler-utils (per lettura PDF)
if ! check_cmd pdftotext; then
log "Installo poppler-utils (lettura PDF)..."
install_pkg poppler-utils
fi
check_cmd pdftotext && ok "poppler-utils (pdftotext)" || warn "poppler-utils non installato"
# Python3 packages per md-to-docx e conversioni
if check_cmd python3; then
ok "python3 $(python3 --version 2>&1 | awk '{print $2}')"
# controlla se i pacchetti sono già installati
MISSING_PY=""
python3 -c "import yaml" 2>/dev/null || MISSING_PY="$MISSING_PY python3-yaml"
python3 -c "import markdown" 2>/dev/null || MISSING_PY="$MISSING_PY python3-markdown"
python3 -c "import bs4" 2>/dev/null || MISSING_PY="$MISSING_PY python3-bs4"
python3 -c "import docx" 2>/dev/null || MISSING_PY="$MISSING_PY python3-docx"
if [ -n "$MISSING_PY" ]; then
log "Installo pacchetti Python:$MISSING_PY"
if check_cmd apt-get; then
apt-get install -y $MISSING_PY 2>/dev/null || \
pip3 install --break-system-packages pyyaml python-docx markdown beautifulsoup4 2>/dev/null || \
warn "Impossibile installare pacchetti Python (serve root?)"
elif check_cmd pip3; then
pip3 install pyyaml python-docx markdown beautifulsoup4
elif check_cmd brew; then
pip3 install pyyaml python-docx markdown beautifulsoup4
fi
fi
# verifica
python3 -c "import yaml, markdown, bs4, docx" 2>/dev/null && ok "Python packages (yaml, markdown, bs4, docx)" || warn "Alcuni pacchetti Python mancanti"
else
warn "python3 non trovato — md-to-docx non funzionerà"
fi
# ── 2. autenticazione gh ──────────────────────────────────────────────────────
log "Verifica autenticazione GitHub..."
if ! gh auth status &>/dev/null; then
warn "Non autenticato con gh. Avvio autenticazione..."
gh auth login
fi
ok "GitHub autenticato"
gh auth setup-git 2>/dev/null || true
# ── 3. skills ─────────────────────────────────────────────────────────────────
log "Download skills da ${REPO}..."
git config --global --add safe.directory "$REPO_DIR" 2>/dev/null || true
if [ -d "$REPO_DIR/.git" ] && [ "$(stat -c '%u' "$REPO_DIR" 2>/dev/null || stat -f '%u' "$REPO_DIR" 2>/dev/null)" = "$(id -u)" ]; then
cd "$REPO_DIR" && git pull --quiet
else
rm -rf "$REPO_DIR"
gh repo clone "$REPO" "$REPO_DIR" -- --quiet
fi
mkdir -p "$SKILLS_DIR"
# ── 3a. CLEANUP — rimuovi directory che non devono stare sotto skills/ ───────
log "Cleanup directory obsolete..."
CLEANED=0
# Skill deprecate (migrate a /self nel marzo 2026)
for old_dir in warmup sogna coherence person-decode skills; do
if [ -d "$SKILLS_DIR/$old_dir" ]; then
rm -rf "$SKILLS_DIR/$old_dir"
ok "Rimosso: $old_dir/ (migrato a /self)"
CLEANED=$((CLEANED + 1))
fi
done
# Directory del repo finite in skills/ per errore (vecchi rsync senza esclusioni)
for stray_dir in agents hooks rules memory sessions scripts config; do
if [ -d "$SKILLS_DIR/$stray_dir" ]; then
rm -rf "$SKILLS_DIR/$stray_dir"
ok "Rimosso: $stray_dir/ (non deve stare in skills/)"
CLEANED=$((CLEANED + 1))
fi
done
# File del repo finiti in skills/ per errore
for stray_file in clouded-bootstrap.sh settings.json README.pdf README.md; do
if [ -f "$SKILLS_DIR/$stray_file" ]; then
rm -f "$SKILLS_DIR/$stray_file"
ok "Rimosso: $stray_file (non deve stare in skills/)"
CLEANED=$((CLEANED + 1))
fi
done
[ "$CLEANED" -gt 0 ] && ok "Cleanup: $CLEANED elementi rimossi" || ok "Nessun residuo trovato"
# ── 3b. salva stile attivo se esiste ─────────────────────────────────────────
ACTIVE_STYLE=""
if [ -L "$SKILLS_DIR/ACTIVE_STYLE.md" ]; then
ACTIVE_STYLE="$(readlink "$SKILLS_DIR/ACTIVE_STYLE.md")"
fi
# ── 3c. rsync skills (con esclusioni corrette) ──────────────────────────────
rsync -a --delete "${RSYNC_EXCLUDES[@]}" "$REPO_DIR/" "$SKILLS_DIR/"
ok "Skills sincronizzate"
# ── 3d. agents, rules ────────────────────────────────────────────────────────
mkdir -p "$HOME/.claude/agents" "$HOME/.claude/rules"
[ -d "$REPO_DIR/agents" ] && rsync -a "$REPO_DIR/agents/" "$HOME/.claude/agents/"
[ -d "$REPO_DIR/rules" ] && rsync -a "$REPO_DIR/rules/" "$HOME/.claude/rules/"
ok "Agents e rules sincronizzati"
# ── 3e. CLAUDE.md globale ────────────────────────────────────────────────────
[ -f "$REPO_DIR/CLAUDE.md" ] && cp "$REPO_DIR/CLAUDE.md" "$HOME/.claude/CLAUDE.md"
ok "CLAUDE.md aggiornato"
# ── 3f. hooks ────────────────────────────────────────────────────────────────
if [ -d "$REPO_DIR/hooks" ]; then
mkdir -p "$HOME/.claude/hooks"
cp "$REPO_DIR/hooks/"*.sh "$HOME/.claude/hooks/" 2>/dev/null
chmod +x "$HOME/.claude/hooks/"*.sh 2>/dev/null
ok "Hooks sincronizzati"
fi
# ── 3g. settings.json ───────────────────────────────────────────────────────
[ -f "$REPO_DIR/settings.json" ] && cp "$REPO_DIR/settings.json" "$HOME/.claude/settings.json"
# ── 3h. ripristina stile ────────────────────────────────────────────────────
if [ -n "$ACTIVE_STYLE" ]; then
ln -sf "$ACTIVE_STYLE" "$SKILLS_DIR/ACTIVE_STYLE.md"
elif [ -f "$SKILLS_DIR/styles/tf-corporate.md" ]; then
ln -sf "styles/tf-corporate.md" "$SKILLS_DIR/ACTIVE_STYLE.md"
fi
ok "Stile attivo: $(readlink "$SKILLS_DIR/ACTIVE_STYLE.md" 2>/dev/null || echo 'nessuno')"
# ── 3i. memory ───────────────────────────────────────────────────────────────
log "Sincronizzazione memorie..."
mkdir -p "$MEMORY_DIR"
if [ -d "$REPO_DIR/memory" ]; then
rsync -a "$REPO_DIR/memory/" "$MEMORY_DIR/"
ok "Memorie sincronizzate in $MEMORY_DIR"
else
warn "Nessuna directory memory nel repo — skip"
fi
# ── 3j. copia repo in /tmp per sync futuro ───────────────────────────────────
if [ ! -d /tmp/claude-skills/.git ]; then
cp -a "$REPO_DIR" /tmp/claude-skills
ok "Repo copiato in /tmp/claude-skills per /self update"
fi
# ── 4. comando 'clouded' ──────────────────────────────────────────────────────
log "Installazione comando '${CMD_NAME}'..."
# sceglie la directory di installazione
if [ -w /usr/local/bin ]; then
INSTALL_DIR="/usr/local/bin"
elif [ -d "$HOME/.local/bin" ]; then
INSTALL_DIR="$HOME/.local/bin"
else
mkdir -p "$HOME/.local/bin"
INSTALL_DIR="$HOME/.local/bin"
fi
CMD_PATH="$INSTALL_DIR/$CMD_NAME"
cat > "$CMD_PATH" << 'ENDOFSCRIPT'
#!/usr/bin/env bash
# clouded — Claude Code con tmux persistente + Telegram
SESSION="clouded"
CLAUDE_CMD="claude --dangerously-skip-permissions --channels plugin:telegram@claude-plugins-official"
if command -v tmux &>/dev/null; then
if tmux has-session -t "$SESSION" 2>/dev/null; then
exec tmux attach-session -t "$SESSION"
else
tmux new-session -d -s "$SESSION" "while true; do $CLAUDE_CMD; echo 'Claude uscito. Riavvio in 2s... (Ctrl+C per fermare)'; sleep 2; done"
exec tmux attach-session -t "$SESSION"
fi
else
exec $CLAUDE_CMD
fi
ENDOFSCRIPT
chmod +x "$CMD_PATH"
ok "Comando installato: $CMD_PATH (con Telegram)"
# ── 5. PATH check ─────────────────────────────────────────────────────────────
if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
warn "$INSTALL_DIR non è nel PATH."
SHELL_RC=""
case "${SHELL:-}" in
*/zsh) SHELL_RC="$HOME/.zshrc" ;;
*/bash) SHELL_RC="$HOME/.bashrc" ;;
esac
if [ -n "$SHELL_RC" ] && ! grep -q "$INSTALL_DIR" "$SHELL_RC" 2>/dev/null; then
echo "" >> "$SHELL_RC"
echo "# clouded" >> "$SHELL_RC"
echo "export PATH=\"$INSTALL_DIR:\$PATH\"" >> "$SHELL_RC"
ok "PATH aggiunto a $SHELL_RC"
fi
fi
# ── 5b. scripts operativi ────────────────────────────────────────────────────
if [ -d "$REPO_DIR/scripts" ]; then
mkdir -p "$INSTALL_DIR"
cp "$REPO_DIR/scripts/"*.sh "$INSTALL_DIR/" 2>/dev/null
chmod +x "$INSTALL_DIR/"*.sh 2>/dev/null
ok "Scripts operativi installati"
fi
# ── 5c. sogna-nightly + cron (restart notturno) ──────────────────────────────
log "Installazione sogna-nightly (consolidamento memoria + restart)..."
NIGHTLY_PATH="$INSTALL_DIR/sogna-nightly.sh"
CLAUDE_CMD_NIGHTLY="claude --dangerously-skip-permissions --channels plugin:telegram@claude-plugins-official"
cat > "$NIGHTLY_PATH" << ENDOFNIGHTLY
#!/usr/bin/env bash
# sogna-nightly — consolida memoria + push + restart clouded
# Cron: 0 23 * * * (23:00 UTC = ~mezzanotte Italia)
LOG="\$HOME/.claude/sogna-nightly.log"
SESSION="clouded"
CLAUDE_CMD="$CLAUDE_CMD_NIGHTLY"
echo "\$(date -Iseconds) — sogna-nightly started" >> "\$LOG"
# 1. Dream + push in una sessione claude dedicata
echo "\$(date -Iseconds) — running /self dream --force + push" >> "\$LOG"
echo -e '/self dream --force\n/self update push' | claude --dangerously-skip-permissions --print 2>&1 | tail -30 >> "\$LOG"
echo "\$(date -Iseconds) — dream + push completed" >> "\$LOG"
# 2. Killa la sessione tmux clouded
if tmux has-session -t "\$SESSION" 2>/dev/null; then
echo "\$(date -Iseconds) — killing tmux session \$SESSION" >> "\$LOG"
tmux kill-session -t "\$SESSION" 2>/dev/null
sleep 3
fi
# 3. Riavvia clouded con sessione fresca
echo "\$(date -Iseconds) — restarting clouded" >> "\$LOG"
tmux new-session -d -s "\$SESSION" \\
"while true; do \$CLAUDE_CMD; echo 'Claude uscito. Riavvio in 2s...'; sleep 2; done"
echo "\$(date -Iseconds) — sogna-nightly completed, clouded restarted" >> "\$LOG"
ENDOFNIGHTLY
chmod +x "$NIGHTLY_PATH"
ok "sogna-nightly.sh installato: $NIGHTLY_PATH"
# installa cron (23:00 UTC = ~mezzanotte Italia)
if check_cmd crontab; then
(crontab -l 2>/dev/null | grep -v sogna-nightly; echo "0 23 * * * $NIGHTLY_PATH") | crontab -
ok "Cron installato: ogni giorno alle 23:00 UTC (dream + push + restart clouded)"
else
warn "crontab non disponibile — installa cron manualmente"
fi
# ── 6. MCP: Microsoft 365 Calendar (globale, non npx) ─────────────────────────
echo ""
log "Configurazione Microsoft 365 Calendar..."
# installa globalmente (NON npx — il token si perde con npx)
if ! check_cmd ms-365-mcp-server; then
log "Installo ms-365-mcp-server globalmente..."
npm install -g @softeria/ms-365-mcp-server 2>/dev/null || warn "Impossibile installare ms-365-mcp-server (serve root per npm global?)"
fi
if check_cmd ms-365-mcp-server; then
ok "ms-365-mcp-server installato globalmente"
# chmod per permettere scrittura token dall'utente claude
MS365_DIR="$(npm root -g 2>/dev/null)/@softeria/ms-365-mcp-server"
if [ -d "$MS365_DIR" ] && $IS_ROOT; then
chmod 777 "$MS365_DIR" 2>/dev/null || true
ok "Permessi token directory impostati"
elif [ -d "$MS365_DIR" ]; then
warn "Token directory potrebbe non essere scrivibile (serve chmod 777 da root su $MS365_DIR)"
fi
# autenticazione (device code flow — funziona anche headless)
echo ""
log "Autenticazione Microsoft 365 (device code flow)..."
echo -e "${YELLOW}Verrà mostrato un URL e un codice. Apri l'URL in un browser qualsiasi e inserisci il codice.${NC}"
read -r -p "Procedere? [y/N] " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
ms-365-mcp-server --login --org-mode && ok "Microsoft 365 autenticato" || warn "Autenticazione saltata"
else
warn "Autenticazione saltata. Quando vuoi: ms-365-mcp-server --login --org-mode"
fi
else
warn "ms-365-mcp-server non installato — calendario non disponibile"
fi
# ── 7. Gmail: gog CLI ─────────────────────────────────────────────────────────
echo ""
log "Configurazione Gmail (gog)..."
if ! check_cmd gog; then
warn "gog non trovato. Provo ad installarlo..."
if check_cmd brew; then
brew install steipete/tap/gogcli
else
GOG_VERSION="0.12.0"
ARCH="$(uname -m)"
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
case "$ARCH" in
x86_64) ARCH="amd64" ;;
aarch64|arm64) ARCH="arm64" ;;
esac
GOG_URL="https://github.com/steipete/gogcli/releases/download/v${GOG_VERSION}/gogcli_${GOG_VERSION}_${OS}_${ARCH}.tar.gz"
if [ -w /usr/local/bin ]; then
curl -fsSL "$GOG_URL" | tar -xz -C /usr/local/bin gog
chmod +x /usr/local/bin/gog
else
mkdir -p "$HOME/.local/bin"
curl -fsSL "$GOG_URL" | tar -xz -C "$HOME/.local/bin" gog
chmod +x "$HOME/.local/bin/gog"
fi
fi
fi
check_cmd gog && ok "gog $(gog --version 2>/dev/null | head -1)" || warn "gog non installato — Gmail non disponibile"
# registra credenziali e token
if check_cmd gog; then
GOG_CREDS="$REPO_DIR/config/gog-credentials.json"
GOG_TOKEN="$REPO_DIR/config/gog-token.json"
if [ -f "$GOG_CREDS" ]; then
gog auth credentials set "$GOG_CREDS" 2>/dev/null && ok "Credenziali Gmail registrate"
else
warn "gog-credentials.json non trovato — skip"
fi
if [ -f "$GOG_TOKEN" ]; then
export GOG_KEYRING_PASSWORD=clouded
gog auth keyring file 2>/dev/null || true
gog auth tokens import "$GOG_TOKEN" 2>/dev/null && ok "Token Gmail importato"
grep -q GOG_KEYRING_PASSWORD "$HOME/.bashrc" 2>/dev/null || echo 'export GOG_KEYRING_PASSWORD=clouded' >> "$HOME/.bashrc"
else
if $HAS_DISPLAY; then
read -r -p "Autenticarsi con Gmail ora? (richiede browser) [y/N] " choice
[[ "$choice" =~ ^[Yy]$ ]] && gog auth add mf@matteoflora.com && ok "Gmail autenticato"
else
warn "Server headless: esegui 'gog auth tokens import <file>' per autenticare Gmail"
fi
fi
fi
# ── 8. utente 'claude' per SSH (solo se root) ─────────────────────────────────
if $IS_ROOT; then
echo ""
log "Creazione utente 'claude' per SSH..."
if ! id claude &>/dev/null; then
useradd -m -s /bin/bash claude
ok "Utente 'claude' creato"
else
ok "Utente 'claude' già esistente"
fi
# copia le authorized_keys di root
mkdir -p /home/claude/.ssh
if [ -f /root/.ssh/authorized_keys ]; then
cp /root/.ssh/authorized_keys /home/claude/.ssh/authorized_keys
chown -R claude:claude /home/claude/.ssh
chmod 700 /home/claude/.ssh
chmod 600 /home/claude/.ssh/authorized_keys
ok "Chiavi SSH copiate da root"
fi
# installa skills per l'utente claude
CLAUDE_HOME="/home/claude"
mkdir -p "$CLAUDE_HOME/.claude/skills" "$CLAUDE_HOME/.claude/agents" "$CLAUDE_HOME/.claude/rules"
rsync -a --delete "${RSYNC_EXCLUDES[@]}" "$REPO_DIR/" "$CLAUDE_HOME/.claude/skills/"
# cleanup anche per utente claude
for old_dir in warmup sogna coherence person-decode skills agents hooks rules memory sessions scripts config; do
rm -rf "$CLAUDE_HOME/.claude/skills/$old_dir"
done
[ -d "$HOME/.claude/agents" ] && rsync -a "$HOME/.claude/agents/" "$CLAUDE_HOME/.claude/agents/"
[ -d "$HOME/.claude/rules" ] && rsync -a "$HOME/.claude/rules/" "$CLAUDE_HOME/.claude/rules/"
[ -f "$HOME/.claude/CLAUDE.md" ] && cp "$HOME/.claude/CLAUDE.md" "$CLAUDE_HOME/.claude/CLAUDE.md"
[ -f "$HOME/.claude/settings.json" ] && cp "$HOME/.claude/settings.json" "$CLAUDE_HOME/.claude/settings.json"
# hooks per utente claude
if [ -d "$HOME/.claude/hooks" ]; then
mkdir -p "$CLAUDE_HOME/.claude/hooks"
cp "$HOME/.claude/hooks/"*.sh "$CLAUDE_HOME/.claude/hooks/" 2>/dev/null
chmod +x "$CLAUDE_HOME/.claude/hooks/"*.sh 2>/dev/null
fi
# memory per l'utente claude
CLAUDE_MEMORY_DIR="$CLAUDE_HOME/.claude/projects/$(echo "$CLAUDE_HOME" | sed 's|/|-|g')/memory"
mkdir -p "$CLAUDE_MEMORY_DIR"
[ -d "$REPO_DIR/memory" ] && rsync -a "$REPO_DIR/memory/" "$CLAUDE_MEMORY_DIR/"
chown -R claude:claude "$CLAUDE_HOME/.claude"
# GOG_KEYRING_PASSWORD per l'utente claude
grep -q GOG_KEYRING_PASSWORD "$CLAUDE_HOME/.bashrc" 2>/dev/null || echo 'export GOG_KEYRING_PASSWORD=clouded' >> "$CLAUDE_HOME/.bashrc"
warn "Connettiti con: ssh claude@${HOSTNAME_SHORT}"
fi
# ── done ──────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}${GREEN}Setup completato!${NC}"
echo ""
echo -e " Macchina: ${YELLOW}${HOSTNAME_SHORT}${NC}"
echo -e " Comando: ${BOLD}${CMD_NAME}${NC} (tmux + Telegram)"
echo -e " Skills: $SKILLS_DIR"
echo -e " Memory: $MEMORY_DIR"
echo -e " Agents: $HOME/.claude/agents/"
echo -e " Rules: $HOME/.claude/rules/"
echo -e " CLAUDE.md: $HOME/.claude/CLAUDE.md"
echo -e " Calendar: ms-365-mcp-server (globale)"
echo -e " Gmail: gog CLI (mf@matteoflora.com)"
echo -e " Python: yaml, markdown, bs4, docx"
echo -e " PDF: poppler-utils (pdftotext)"
echo ""
echo -e "Prossimo passo: ${BOLD}${CMD_NAME}${NC} poi ${BOLD}/self dream --force${NC} per consolidare le sessioni"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment