web analytics

OpenClaw: Guida Completa, Configurazione e Creazione Skills

OpenClaw ha conquistato oltre 100.000 stelle su GitHub in meno di una settimana dal lancio, a gennaio 2026, diventando uno dei repository open-source in più rapida crescita della storia. Non si tratta di un semplice chatbot: è un agente AI personale che gira sul proprio hardware, agisce autonomamente e impara nuove abilità attraverso un sistema di skill modulari.

Questa guida copre tutto — dall'installazione alla configurazione avanzata — con tre esempi pratici di skill pronti all'uso, inclusa una che pubblica automaticamente articoli giornalistici su WordPress tramite WP-CLI.

1. Cos'è OpenClaw e come funziona

OpenClaw (precedentemente noto come MoltBot e ClawdBot) è un framework open-source per agenti AI personali, progettato per girare direttamente sul proprio hardware. A differenza degli assistenti AI tradizionali, non si limita a rispondere a domande: agisce, esegue comandi, automatizza flussi di lavoro e impara nuove abilità in modo autonomo.

Creato da Peter Steinberger (fondatore di PSPDFKit), il progetto si basa su tre principi fondamentali:

  • Local-first — tutti i dati, la memoria e le configurazioni risiedono sul proprio machine, senza dipendenza da servizi cloud.
  • Model-agnostic — supporta Claude (Anthropic), GPT-4, Gemini, Llama e qualsiasi modello compatibile con l'API OpenAI.
  • Community-extensible — le Skill sono file SKILL.md portabili, condivisibili e installabili dal marketplace ClawHub.

Il Loop dell'Agente

Quando si lancia openclaw gateway, si avvia un singolo processo Node.js che gestisce tutto: canali di messaggistica, sessioni, chiamate al modello, esecuzione degli strumenti e persistenza della memoria. Il ciclo agentico si compone di quattro fasi:

  1. Perceive — riceve un input (comando utente, evento cron, webhook, heartbeat).
  2. Plan — l'LLM analizza il contesto, la memoria e le skill disponibili.
  3. Act — esegue strumenti: shell, browser, web fetch, file system, API.
  4. Reflect — aggiorna la memoria, notifica l'utente e attende il prossimo ciclo.

Dove si posiziona rispetto ad altri strumenti

Gli LLM puri (ChatGPT, Claude) sono intelligenti ma non agiscono. Gli strumenti di automazione (n8n, Make, Zapier) agiscono ma richiedono configurazione esplicita. OpenClaw unisce entrambi: l'LLM decide cosa fare, il Gateway lo esegue.


2. Installazione

Requisiti di sistema

Componente Requisito
Node.js ≥ 22.x (LTS raccomandato)
npm/pnpm npm ≥ 10 o pnpm ≥ 9
OS macOS, Linux, Windows (WSL2)
RAM Minimo 2 GB (4 GB+ raccomandati)
Disco ~500 MB per l'installazione base

Installazione via npm

npm install -g openclaw@latest

In alternativa con pnpm:

pnpm add -g openclaw@latest

Verifica l'installazione:

openclaw --version

Installazione via script (Linux/macOS)

curl -fsSL https://clawd.bot/install.sh | bash

⚠️ Sicurezza — Prima di eseguire script via curl, esamina sempre il contenuto su clawd.bot. OpenClaw richiede permessi elevati sulla macchina.

Onboarding Wizard

Dopo l'installazione, avvia il wizard interattivo:

openclaw onboard --install-daemon

Il flag --install-daemon installa il daemon di sistema (launchd su macOS, systemd su Linux) in modo che il Gateway rimanga sempre attivo in background. Il wizard configura: modello LLM, canale di messaggistica, workspace principale e prime skill.

Verifica con Doctor

openclaw doctor

Controlla: stato del daemon, API key configurate, permessi del workspace, policy DM, presenza di binari richiesti dalle skill attive.


3. Configurazione

Il file principale: ~/.openclaw/openclaw.json

{
  "agents": {
    "defaults": {
      "model": "claude-opus-4-6",
      "provider": "anthropic",
      "maxTokens": 8192
    }
  },
  "gateway": {
    "port": 18789,
    "host": "127.0.0.1"
  },
  "skills": {
    "load": {
      "extraDirs": ["/path/to/custom/skills"]
    }
  }
}

Configurazione dei Modelli LLM

OpenClaw supporta qualsiasi provider compatibile OpenAI. I principali:

  • Anthropic (Claude) — raccomandato per resistenza all'injection e long-context
  • OpenAI (GPT-4, GPT-4o)
  • Google (Gemini Flash, Gemini Pro)
  • Provider locali via Ollama o LM Studio

Esempio configurazione Anthropic:

"providers": {
  "anthropic": {
    "apiKey": "sk-ant-...",
    "defaultModel": "claude-opus-4-6"
  }
}

Failover automatico tra modelli:

"modelFailover": [
  "claude-opus-4-6",
  "claude-sonnet-4-6",
  "gpt-4o"
]

💡 Consiglio — Usa claude-opus-4-6 per task complessi (ragionamento, coding, analisi) e Gemini Flash per task semplici (riassunti, lookup veloci). Puoi cambiare modello dal menu Telegram in qualsiasi momento.

Configurazione dei Canali

Telegram — il canale più semplice per iniziare. Crea un bot con @BotFather e ottieni il token:

"channels": {
  "telegram": {
    "enabled": true,
    "token": "YOUR_BOT_TOKEN",
    "ownerIds": [123456789]
  }
}

Slack — richiede una Slack App con permessi chat:write, im:read, im:write, users:read:

"slack": {
  "enabled": true,
  "botToken": "xoxb-...",
  "signingSecret": "...",
  "appToken": "xapp-..."
}

Il file soul.md

Uno degli aspetti più potenti di OpenClaw è il file soul.md — la personalità e le istruzioni permanenti dell'agente. Si trova nel workspace principale e viene caricato come system prompt persistente:

# Il mio Assistente AI Personale

## Personalità
Sei un assistente professionale, preciso e proattivo. Parli italiano.
Anticipi le esigenze e proponi soluzioni prima di essere interrogato.

## Contesto
- Nome: Marco
- Professione: Giornalista digitale
- Sito WordPress: https://miosito.it
- Server: VPS Ubuntu 22.04

## Regole operative
1. Prima di eseguire comandi distruttivi, chiedi conferma.
2. Logga sempre le azioni importanti in ~/logs/agent.log
3. Avvisami su Telegram se qualcosa va storto.

Sicurezza — Best Practice

  • Non installare mai OpenClaw sull'account root di un server di produzione.
  • Usa VM o container dedicati per ambienti ad alto rischio.
  • Configura le Exec Approvals per i comandi shell pericolosi.
  • Imposta spending cap sul dashboard del provider LLM.
  • Esegui openclaw doctor regolarmente.

⚠️ Attenzione — Un agente in loop può consumare molti token rapidamente. Imposta sempre un limite mensile di spesa prima di avviare automazioni autonome.


4. Il Sistema delle Skills

Cos'è una Skill

Una skill in OpenClaw è una cartella contenente un file SKILL.md con frontmatter YAML e istruzioni in linguaggio naturale. Le skill insegnano all'agente come usare strumenti specifici, seguire procedure particolari o automatizzare task ricorrenti.

my-skill/
  SKILL.md         # definizione principale
  scripts/         # script Python/Bash
  config.json      # configurazione opzionale

Anatomia di un SKILL.md

---
name: nome-skill
description: Descrizione breve che appare nel prompt dell'agente
homepage: https://link-documentazione.com
user-invocable: true
disable-model-invocation: false
metadata:
  {"openclaw": {
    "emoji": "🔧",
    "requires": {
      "bins": ["wp", "python3"],
      "env": ["WP_SSH_HOST"],
      "config": ["browser.enabled"]
    }
  }}
---

# Istruzioni per l'agente

Qui vanno le istruzioni dettagliate in linguaggio naturale.
L'agente le leggerà e le seguirà per eseguire il task.

Posizioni e Precedenza

OpenClaw carica le skill da tre posizioni, in ordine di precedenza:

  1. Workspace skills<workspace>/skills → priorità massima
  2. Managed/local skills~/.openclaw/skills → condivise tra tutti gli agenti
  3. Bundled skills — incluse nell'installazione npm → priorità minima

ClawHub — Il Marketplace

ClawHub è il registry pubblico delle skill per OpenClaw. Comandi principali:

# Cerca una skill
clawhub search wordpress

# Installa una skill nel workspace
clawhub install wordpress-publisher

# Aggiorna tutte le skill installate
clawhub update --all

Gating (Filtri al Caricamento)

OpenClaw filtra le skill al caricamento in base ai requisiti dichiarati:

Campo Comportamento
requires.bins I binari devono essere presenti nel PATH
requires.env Le variabili d'ambiente devono esistere
requires.config I path di openclaw.json devono avere valori truthy
os La skill si carica solo sugli OS specificati

Iniezione di Segreti nelle Skill

"skills": {
  "entries": {
    "my-wordpress-skill": {
      "env": {
        "WP_DB_PASS": "secret123",
        "UNSPLASH_KEY": "your-api-key"
      }
    }
  }
}

5. Automazione: Cron, Heartbeat e Webhook

Cron Jobs

"cron": {
  "jobs": [
    {
      "id": "morning-briefing",
      "schedule": "0 8 * * *",
      "prompt": "Prepara il briefing mattutino: meteo, news, calendario.",
      "channel": "telegram"
    },
    {
      "id": "weekly-report",
      "schedule": "0 9 * * 1",
      "prompt": "Genera il report settimanale di analytics WordPress.",
      "channel": "slack"
    }
  ]
}

Heartbeat (Ciclo Autonomo)

"heartbeat": {
  "enabled": true,
  "intervalMinutes": 60,
  "prompt": "Controlla se ci sono task pendenti, aggiorna la memoria, invia notifiche se necessario."
}

💡 Differenza chiave — Il Cron è per task schedulati a orari precisi. Il Heartbeat è per check periodici autonomi. In pratica: usa il Cron per "pubblica alle 9:00", usa il Heartbeat per "controlla ogni ora se c'è qualcosa da fare".

Webhook

"webhooks": {
  "enabled": true,
  "endpoints": [
    {
      "path": "/github-push",
      "secret": "your-webhook-secret",
      "prompt": "Un nuovo push su GitHub. Analizza le modifiche e aggiorna la documentazione."
    }
  ]
}

6. Configurazione Multi-Agent

OpenClaw supporta più agenti sullo stesso Gateway, ognuno con il proprio workspace, soul.md, set di skill e canale dedicato. Architettura ideale per:

  • Separare agenti per ruolo (sviluppo, marketing, giornalismo)
  • Isolare gli ambienti per sicurezza (agente untrusted in sandbox Docker)
  • Condividere skill comuni tra agenti diversi

Routing dei canali:

"routing": {
  "telegram": {
    "workBot": "agent-work",
    "personalBot": "agent-personal"
  }
}

7. Esempi di impostazione Skills OpenClaw


Skill 1 — Web Scraper e Digest Quotidiano delle News

Raccoglie automaticamente notizie da fonti RSS, le aggrega, applica un'analisi editoriale e invia un digest formattato su Telegram ogni mattina.

Struttura della cartella:

~/.openclaw/skills/news-digest/
  SKILL.md
  scripts/
    fetch_rss.py
  sources.json

SKILL.md:

---
name: news-digest
description: Raccoglie news da RSS, le aggrega e invia un digest quotidiano su Telegram
user-invocable: true
metadata:
  {"openclaw": {
    "emoji": "📰",
    "requires": {
      "bins": ["python3"],
      "env": ["TELEGRAM_CHAT_ID"]
    }
  }}
---

# Skill: News Digest Quotidiano

## Trigger
Eseguita automaticamente alle 7:30 via cron job, oppure con /news-digest.

## Procedura

1. Esegui: python3 {baseDir}/scripts/fetch_rss.py > /tmp/raw_news.json

2. Per ogni notizia applica questa analisi:
   - Valuta la rilevanza (1-10): impatto, novità, interesse
   - Scrivi un riassunto di 2-3 righe in italiano
   - Assegna categoria: Tecnologia, Economia, Politica, Scienza, Altro

3. Seleziona le TOP 5 notizie per rilevanza.

4. Formatta il digest:
   🌅 *Buongiorno! Digest News — [DATA]*
   📌 *[TITOLO]*
   [RIASSUNTO]
   🔗 [LINK]

5. Invia su Telegram. Logga in ~/openclaw-logs/news-digest-[DATA].json

scripts/fetch_rss.py:

#!/usr/bin/env python3
import json, feedparser
from datetime import datetime, timedelta

SOURCES = json.load(open('{baseDir}/sources.json'))
articles = []

for src in SOURCES['feeds']:
    feed = feedparser.parse(src['url'])
    for entry in feed.entries[:10]:
        articles.append({
            'title': entry.get('title', ''),
            'summary': entry.get('summary', '')[:400],
            'link': entry.get('link', ''),
            'source': src['name']
        })

print(json.dumps(articles, ensure_ascii=False))

sources.json:

{
  "feeds": [
    {"name": "Ansa",     "url": "https://www.ansa.it/sito/notizie/tecnologia/tecnologia_rss.xml"},
    {"name": "Wired IT", "url": "https://www.wired.it/feed/rss"},
    {"name": "BBC Tech", "url": "https://feeds.bbci.co.uk/news/technology/rss.xml"}
  ]
}

Configurazione cron:

{
  "cron": {
    "jobs": [{
      "id": "morning-news",
      "schedule": "30 7 * * *",
      "prompt": "Esegui la skill news-digest e invia il digest mattutino.",
      "channel": "telegram"
    }]
  }
}

Skill 2 — Monitoraggio e Alert del Server

Monitora periodicamente CPU, RAM, disco e servizi critici di un server Linux, inviando alert proattivi con diagnosi e azioni consigliate su Telegram.

Struttura della cartella:

~/.openclaw/skills/server-monitor/
  SKILL.md
  scripts/
    check_metrics.sh
  thresholds.json

SKILL.md:

---
name: server-monitor
description: Monitora CPU, RAM, disco e servizi del server con alert intelligenti su Telegram
user-invocable: true
metadata:
  {"openclaw": {
    "emoji": "🖥️",
    "requires": {
      "bins": ["df", "free", "top", "systemctl", "python3"],
      "env": ["ALERT_TELEGRAM_CHAT_ID"]
    },
    "os": ["linux"]
  }}
---

# Skill: Server Monitor con Alert Intelligenti

## Esecuzione automatica
Gira ogni 15 minuti via heartbeat.

## Procedura

1. Raccogli metriche:
   bash {baseDir}/scripts/check_metrics.sh > /tmp/metrics.txt

2. Confronta i valori con {baseDir}/thresholds.json

3. Determina la gravità:
   - WARNING (🟡): metrica tra 70% e 85% della soglia critica
   - CRITICAL (🔴): metrica sopra l'85%

4. Genera alert con:
   - Metrica problematica e valore attuale
   - Diagnosi probabile (es. "Possibile memory leak in nginx")
   - Azioni consigliate (comandi specifici)

5. In caso di CRITICAL, esegui automaticamente:
   sudo systemctl restart nginx (se nginx è coinvolto)
   Notifica l'azione intrapresa.

scripts/check_metrics.sh:

#!/bin/bash
echo "=== CPU ==="
top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d'%' -f1

echo "=== RAM ==="
free -m | awk 'NR==2{printf "%.1f\n", $3*100/$2}'

echo "=== DISCO ==="
df -h / | awk 'NR==2{print $5}' | tr -d '%'

echo "=== SERVIZI ==="
for svc in nginx mysql php8.2-fpm; do
  systemctl is-active $svc 2>/dev/null && echo "$svc:OK" || echo "$svc:FAIL"
done

thresholds.json:

{
  "cpu_warning": 70,
  "cpu_critical": 90,
  "ram_warning": 75,
  "ram_critical": 90,
  "disk_warning": 80,
  "disk_critical": 95,
  "services": ["nginx", "mysql", "php8.2-fpm"]
}

⚠️ Sicurezza — Configura sudoers per permettere solo i comandi specifici necessari (es. systemctl restart nginx) senza password, e mai con accesso root completo.


Skill 3 — WordPress Remote News Publisher via SSH + WP-CLI

Versione remota della Skill 3 originale.
Rispetto alla versione locale, questa skill non richiede WP-CLI installato sulla macchina che esegue OpenClaw: tutta l'interazione con WordPress avviene sul server remoto tramite connessione SSH con autenticazione automatica a chiave pubblica. Le immagini vengono scaricate e ottimizzate localmente, trasferite sul server via scp, e poi importate con wp media import eseguito in remoto.


Struttura della cartella

~/.openclaw/skills/wp-remote-publisher/
  SKILL.md
  scripts/
    download_cover.py
    optimize_image.sh
    upload_media_remote.sh
    publish_wp_remote.sh
  config.json

SKILL.md

---
name: wp-remote-publisher
description: Genera e pubblica automaticamente articoli di news su WordPress remoto
            via SSH con autenticazione a chiave pubblica e WP-CLI installato sul server.
            Scarica e ottimizza immagini di copertina da Unsplash, le trasferisce via scp
            e pubblica con metadati SEO Yoast.
user-invocable: true
metadata:
  {"openclaw": {
    "emoji": "📝",
    "requires": {
      "bins": ["ssh", "scp", "python3", "curl", "convert"],
      "env": [
        "WP_SSH_HOST",
        "WP_SSH_USER",
        "WP_SSH_KEY",
        "WP_REMOTE_PATH",
        "UNSPLASH_ACCESS_KEY",
        "WP_AUTHOR_ID"
      ]
    }
  }}
---

#### Skill: WordPress Remote News Publisher

#### IMPORTANTE — Filosofia Editoriale

Ogni articolo DEVE rispettare queste regole:
- Scrivi come un giornalista senior del settore, non come un AI.
- Usa frasi di lunghezza variabile. Alterna periodi brevi a costruzioni articolate.
- Inserisci una tesi editoriale chiara nel primo paragrafo (lede).
- Usa citazioni attribuite a fonti reali quando disponibili.
- EVITA: "è importante notare", "nell'era digitale", "nel mondo di oggi",
  "in conclusione", "ovviamente", "chiaramente", qualsiasi formula AI.
- Il titolo deve essere specifico. Niente clickbait.

#### Variabili d'ambiente richieste

| Variabile           | Descrizione                                             | Esempio                              |
|---------------------|---------------------------------------------------------|--------------------------------------|
| WP_SSH_HOST         | Hostname o IP del server remoto                         | `203.0.113.10` o `miosito.it`        |
| WP_SSH_USER         | Utente SSH sul server remoto                            | `ubuntu` / `www-data` / `deploy`     |
| WP_SSH_KEY          | Path assoluto alla chiave privata SSH locale            | `/home/user/.ssh/id_ed25519_wp`      |
| WP_SSH_PORT         | Porta SSH (default 22)                                  | `22`                                 |
| WP_REMOTE_PATH      | Path assoluto di WordPress sul server remoto            | `/var/www/html/wordpress`            |
| WP_REMOTE_TMP       | Cartella temporanea scrivibile sul server remoto        | `/tmp`                               |
| UNSPLASH_ACCESS_KEY | Access Key API Unsplash                                 | `AbC123...`                          |
| WP_AUTHOR_ID        | ID autore WordPress                                     | `1`                                  |

#### Trigger
Eseguita ogni giorno alle 10:00 e 16:00 (lun-ven) via cron job.
Invocabile manualmente con: /wp-remote-publisher [argomento]

---

#### Procedura Completa

#### FASE 1 — Selezione Argomento
Se non viene fornito un argomento:
1. Leggi {baseDir}/config.json per la lista di topic configurati.
2. Seleziona il topic con la pubblicazione più vecchia (round-robin).

#### FASE 2 — Verifica Connessione SSH
Prima di qualsiasi operazione, verifica che la connessione SSH funzioni:

  ssh -i $WP_SSH_KEY -p ${WP_SSH_PORT:-22} -o StrictHostKeyChecking=no \
      -o BatchMode=yes -o ConnectTimeout=10 \
      $WP_SSH_USER@$WP_SSH_HOST \
      "wp --info --path=$WP_REMOTE_PATH" 2>&1

Se il comando fallisce, interrompi e notifica l'errore su Telegram.

#### FASE 3 — Ricerca e Raccolta Fatti
1. Cerca via web: "[argomento] ultime notizie [mese corrente]"
   Cerca anche in inglese per fonti internazionali.

2. Raccogli SOLO fatti verificabili:
   - Dati numerici con fonte
   - Dichiarazioni di persone reali con nome e ruolo
   - Date ed eventi specifici
   - Evita speculazioni non attribuite

3. Salva i fatti in /tmp/wp_facts.json

#### FASE 4 — Generazione Articolo con Stile Giornalistico

Struttura editoriale obbligatoria:

**TITOLO** (max 65 caratteri)
- Specifico, non generico. Contiene il fatto principale.
- Buono:  "Meta taglia 3.600 posti: addio ai team AI di Base"
- Cattivo: "Meta compie un passo importante per il futuro"

**LEDE** (primo paragrafo, 40-60 parole)
- Risponde a: Chi? Cosa? Quando? Dove? Perché?
- È la notizia più importante in forma densa e precisa.
- Non inizia mai con "Nel mondo di..." o "Negli ultimi anni..."

**CORPO** (600-900 parole totali)
- Paragrafo 2: contesto e background
- Paragrafo 3-4: sviluppo principale con dati e citazioni
- Paragrafo 5: reazioni e posizioni dei protagonisti
- Paragrafo 6: implicazioni e prospettive (attribuite a esperti)
- Paragrafo finale: elemento che chiude il cerchio narrativo

**META DESCRIPTION** (max 155 caratteri)
**TAG SEO** (3-5 tag, senza #)
**KEYWORD PRINCIPALE** (1 keyword)

Salva in /tmp/wp_article.json:
{
  "title": "...",
  "content": "...",
  "excerpt": "...",
  "tags": ["..."],
  "meta_desc": "...",
  "keyword": "...",
  "topic": "..."
}

#### FASE 5 — Immagine di Copertina
1. Determina una keyword visiva (es. "server room technology").
2. Scarica da Unsplash LOCALMENTE:
   python3 {baseDir}/scripts/download_cover.py '[keyword]' /tmp/cover.jpg
3. Ottimizza localmente:
   bash {baseDir}/scripts/optimize_image.sh /tmp/cover.jpg /tmp/cover_opt.jpg
4. Trasferisci sul server remoto e importa in WordPress:
   bash {baseDir}/scripts/upload_media_remote.sh /tmp/cover_opt.jpg
   → ID salvato in /tmp/wp_media_id.txt

#### FASE 6 — Pubblicazione su WordPress Remoto
1. Esegui: bash {baseDir}/scripts/publish_wp_remote.sh
2. Post creato come draft. Aspetta 30 secondi, verifica lo stato via SSH.
3. Se OK, pubblica:
   ssh -i $WP_SSH_KEY -p ${WP_SSH_PORT:-22} $WP_SSH_USER@$WP_SSH_HOST \
     "wp post update $(cat /tmp/wp_post_id.txt) \
      --post_status=publish --path=$WP_REMOTE_PATH"
4. Recupera l'URL del post pubblicato:
   ssh -i $WP_SSH_KEY -p ${WP_SSH_PORT:-22} $WP_SSH_USER@$WP_SSH_HOST \
     "wp post get $(cat /tmp/wp_post_id.txt) --field=url --path=$WP_REMOTE_PATH"
5. Invia conferma su Telegram con titolo, URL, parole, keyword.

#### FASE 7 — Aggiornamento Registro
Aggiorna {baseDir}/config.json segnando il topic come
"ultimo pubblicato" con timestamp per garantire la rotazione.

config.json

{
  "wp_remote_path": "/var/www/html/wordpress",
  "author_id": 1,
  "categories": {
    "tecnologia": 5,
    "economia": 8,
    "startup": 12
  },
  "topics": [
    {
      "name": "Intelligenza Artificiale",
      "keywords": ["AI", "machine learning", "LLM"],
      "category": "tecnologia",
      "last_published": null
    },
    {
      "name": "Cybersecurity",
      "keywords": ["sicurezza informatica", "hacking", "privacy"],
      "category": "tecnologia",
      "last_published": null
    },
    {
      "name": "Startup Tech",
      "keywords": ["startup", "venture capital", "unicorn"],
      "category": "startup",
      "last_published": null
    }
  ]
}

scripts/download_cover.py

Identico alla versione locale: scarica l'immagine da Unsplash sulla macchina locale.

#!/usr/bin/env python3
import sys, requests, os

query   = sys.argv[1]
outfile = sys.argv[2]
api_key = os.environ['UNSPLASH_ACCESS_KEY']

r = requests.get(
    'https://api.unsplash.com/photos/random',
    params={'query': query, 'orientation': 'landscape', 'content_filter': 'high'},
    headers={'Authorization': f'Client-ID {api_key}'}
)
r.raise_for_status()
data = r.json()

img_data = requests.get(data['urls']['regular']).content
with open(outfile, 'wb') as f:
    f.write(img_data)

with open('/tmp/cover_meta.txt', 'w') as f:
    f.write(f"Photo by {data['user']['name']} on Unsplash")

print(f"Immagine scaricata: {outfile}")

scripts/optimize_image.sh

Identico alla versione locale: ottimizza e ritaglia l'immagine sulla macchina locale con ImageMagick.

#!/bin/bash
INPUT=$1
OUTPUT=$2

# Resize a 1200x630 (dimensione Open Graph ottimale) e comprimi
convert "$INPUT" \
  -resize 1200x630^ \
  -gravity Center \
  -extent 1200x630 \
  -quality 85 \
  -strip \
  "$OUTPUT"

echo "Ottimizzazione completata: $(du -h "$OUTPUT" | cut -f1)"

scripts/upload_media_remote.sh

Questo script è la principale differenza rispetto alla versione locale.
Trasferisce l'immagine ottimizzata sul server remoto via scp, poi esegue wp media import tramite ssh.

#!/bin/bash
# ============================================================
# upload_media_remote.sh
# Trasferisce l'immagine sul server remoto e la importa
# in WordPress con WP-CLI remoto via SSH a chiave pubblica.
# ============================================================

IMAGE_PATH=$1

# --- Parametri SSH da variabili d'ambiente ---
SSH_HOST="${WP_SSH_HOST}"
SSH_USER="${WP_SSH_USER}"
SSH_KEY="${WP_SSH_KEY}"
SSH_PORT="${WP_SSH_PORT:-22}"
REMOTE_PATH="${WP_REMOTE_PATH:-/var/www/html/wordpress}"
REMOTE_TMP="${WP_REMOTE_TMP:-/tmp}"

# Opzioni SSH comuni (chiave pubblica, no password, no prompt)
SSH_OPTS="-i $SSH_KEY -p $SSH_PORT \
          -o StrictHostKeyChecking=no \
          -o BatchMode=yes \
          -o ConnectTimeout=15 \
          -o PasswordAuthentication=no"

# --- Validazione variabili ---
if [ -z "$SSH_HOST" ] || [ -z "$SSH_USER" ] || [ -z "$SSH_KEY" ]; then
  echo "ERRORE: WP_SSH_HOST, WP_SSH_USER e WP_SSH_KEY sono obbligatori." >&2
  exit 1
fi

if [ ! -f "$SSH_KEY" ]; then
  echo "ERRORE: chiave SSH non trovata in $SSH_KEY" >&2
  exit 1
fi

if [ ! -f "$IMAGE_PATH" ]; then
  echo "ERRORE: immagine non trovata in $IMAGE_PATH" >&2
  exit 1
fi

REMOTE_FILENAME="wp_cover_$(date +%s).jpg"
REMOTE_FILE_PATH="$REMOTE_TMP/$REMOTE_FILENAME"

# --- Trasferimento immagine via scp ---
echo "Trasferimento immagine su $SSH_USER@$SSH_HOST:$REMOTE_FILE_PATH ..."
scp $SSH_OPTS "$IMAGE_PATH" "$SSH_USER@$SSH_HOST:$REMOTE_FILE_PATH"

if [ $? -ne 0 ]; then
  echo "ERRORE: scp fallito durante il trasferimento dell'immagine." >&2
  exit 1
fi

echo "Immagine trasferita con successo."

# --- Importazione media con WP-CLI remoto ---
echo "Importazione media in WordPress via WP-CLI remoto..."
MEDIA_ID=$(ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" \
  "wp media import '$REMOTE_FILE_PATH' \
   --path='$REMOTE_PATH' \
   --porcelain 2>/dev/null")

if [ -z "$MEDIA_ID" ]; then
  echo "ERRORE: wp media import non ha restituito un ID." >&2
  # Cleanup file remoto anche in caso di errore
  ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" "rm -f '$REMOTE_FILE_PATH'" 2>/dev/null
  exit 1
fi

# --- Cleanup file temporaneo remoto ---
ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" "rm -f '$REMOTE_FILE_PATH'" 2>/dev/null

echo "$MEDIA_ID" > /tmp/wp_media_id.txt
echo "Media importato su WordPress con ID: $MEDIA_ID"

scripts/publish_wp_remote.sh

Esegue tutti i comandi wp sul server remoto tramite SSH. Nessuna chiamata WP-CLI locale.

#!/bin/bash
# ============================================================
# publish_wp_remote.sh
# Crea il post WordPress come draft via WP-CLI remoto (SSH).
# ============================================================

# --- Parametri SSH da variabili d'ambiente ---
SSH_HOST="${WP_SSH_HOST}"
SSH_USER="${WP_SSH_USER}"
SSH_KEY="${WP_SSH_KEY}"
SSH_PORT="${WP_SSH_PORT:-22}"
REMOTE_PATH="${WP_REMOTE_PATH:-/var/www/html/wordpress}"
AUTHOR_ID="${WP_AUTHOR_ID:-1}"

SSH_OPTS="-i $SSH_KEY -p $SSH_PORT \
          -o StrictHostKeyChecking=no \
          -o BatchMode=yes \
          -o ConnectTimeout=15 \
          -o PasswordAuthentication=no"

# --- Leggi dati articolo ---
TITLE=$(python3 -c "import json; d=json.load(open('/tmp/wp_article.json')); print(d['title'])")
CONTENT=$(python3 -c "import json; d=json.load(open('/tmp/wp_article.json')); print(d['content'])")
EXCERPT=$(python3 -c "import json; d=json.load(open('/tmp/wp_article.json')); print(d['excerpt'])")
TAGS=$(python3 -c "import json; d=json.load(open('/tmp/wp_article.json')); print(','.join(d['tags']))")
META_DESC=$(python3 -c "import json; d=json.load(open('/tmp/wp_article.json')); print(d['meta_desc'])")
KEYWORD=$(python3 -c "import json; d=json.load(open('/tmp/wp_article.json')); print(d['keyword'])")
MEDIA_ID=$(cat /tmp/wp_media_id.txt)

# --- Trasferisci il JSON dell'articolo sul server remoto (necessario per content lungo) ---
REMOTE_ARTICLE_JSON="/tmp/wp_article_remote_$(date +%s).json"
scp $SSH_OPTS /tmp/wp_article.json "$SSH_USER@$SSH_HOST:$REMOTE_ARTICLE_JSON"

# --- Crea il post come draft (WP-CLI remoto) ---
echo "Creazione post come draft su WordPress remoto..."
POST_ID=$(ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" bash <<ENDSSH
  TITLE=\$(python3 -c "import json; d=json.load(open('$REMOTE_ARTICLE_JSON')); print(d['title'])")
  CONTENT=\$(python3 -c "import json; d=json.load(open('$REMOTE_ARTICLE_JSON')); print(d['content'])")
  EXCERPT=\$(python3 -c "import json; d=json.load(open('$REMOTE_ARTICLE_JSON')); print(d['excerpt'])")

  wp post create \
    --post_title="\$TITLE" \
    --post_content="\$CONTENT" \
    --post_excerpt="\$EXCERPT" \
    --post_status=draft \
    --post_author=$AUTHOR_ID \
    --post_type=post \
    --path="$REMOTE_PATH" \
    --porcelain 2>/dev/null
ENDSSH
)

if [ -z "$POST_ID" ]; then
  echo "ERRORE: wp post create non ha restituito un ID." >&2
  ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" "rm -f '$REMOTE_ARTICLE_JSON'" 2>/dev/null
  exit 1
fi

echo "Post draft creato con ID: $POST_ID"

# --- Imposta immagine di copertina ---
echo "Impostazione immagine di copertina..."
ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" \
  "wp post meta update $POST_ID _thumbnail_id $MEDIA_ID \
   --path='$REMOTE_PATH'" 2>/dev/null

# --- Aggiungi tag ---
echo "Aggiunta tag..."
ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" \
  "wp post term add $POST_ID post_tag '$TAGS' \
   --path='$REMOTE_PATH'" 2>/dev/null

# --- Meta SEO Yoast ---
echo "Aggiornamento meta SEO Yoast..."
ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" \
  "wp post meta update $POST_ID _yoast_wpseo_metadesc '$META_DESC' \
   --path='$REMOTE_PATH'" 2>/dev/null

ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" \
  "wp post meta update $POST_ID _yoast_wpseo_focuskw '$KEYWORD' \
   --path='$REMOTE_PATH'" 2>/dev/null

# --- Cleanup file temporanei remoti ---
ssh $SSH_OPTS "$SSH_USER@$SSH_HOST" "rm -f '$REMOTE_ARTICLE_JSON'" 2>/dev/null

echo "$POST_ID" > /tmp/wp_post_id.txt
echo "Post WordPress creato come draft con ID: $POST_ID"

Configurazione in ~/.openclaw/openclaw.json

Iniezione chiave pubblica SSH nella skill

"skills": {
  "entries": {
    "wp-remote-publisher": {
      "env": {
        "WP_SSH_HOST":         "203.0.113.10",
        "WP_SSH_USER":         "deploy",
        "WP_SSH_KEY":          "/home/user/.ssh/id_ed25519_wp",
        "WP_SSH_PORT":         "22",
        "WP_REMOTE_PATH":      "/var/www/html/wordpress",
        "WP_REMOTE_TMP":       "/tmp",
        "WP_AUTHOR_ID":        "1",
        "UNSPLASH_ACCESS_KEY": "la-tua-access-key-unsplash"
      }
    }
  }
}

Cron jobs per pubblicazione automatica

"cron": {
  "jobs": [
    {
      "id": "wp-morning-news",
      "schedule": "0 10 * * 1-5",
      "prompt": "Esegui la skill wp-remote-publisher. Scegli il topic dalla rotazione.",
      "channel": "telegram"
    },
    {
      "id": "wp-afternoon-news",
      "schedule": "0 16 * * 1-5",
      "prompt": "Esegui la skill wp-remote-publisher per il pomeriggio.",
      "channel": "telegram"
    }
  ]
}

Setup della chiave SSH (una-tantum)

Prima di usare la skill, configura l'autenticazione a chiave pubblica sul server remoto:

# 1. Genera una coppia di chiavi dedicata (raccomandato: ed25519)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_wp -C "openclaw-wp-publisher" -N ""

# 2. Copia la chiave pubblica sul server remoto
ssh-copy-id -i ~/.ssh/id_ed25519_wp.pub -p 22 [email protected]

# 3. Verifica la connessione automatica (nessuna password richiesta)
ssh -i ~/.ssh/id_ed25519_wp -o BatchMode=yes [email protected] "wp --info"

# 4. (Opzionale) Limita ulteriormente la chiave in ~/.ssh/authorized_keys sul server
# Aggiungi prima della chiave: command="wp --allow-root",no-port-forwarding,no-X11-forwarding

💡 Consiglio sicurezza — Usa un utente SSH dedicato (deploy o wpcli) con permessi minimi sul server. Non usare root. Se WP-CLI richiede permessi su /var/www, aggiungi l'utente al gruppo www-data.


Requisiti sul server remoto

Componente Requisito Verifica
WP-CLI Installato e nel PATH wp --info
PHP ≥ 7.4 (8.x raccomandato) php --version
Python 3 Per leggere JSON nell'articolo python3 --version
Permessi Utente SSH scrive in WP_REMOTE_PATH ls -la /var/www/html/wordpress
Porta SSH Aperta nel firewall ufw status / iptables -L

Requisiti sulla macchina locale (OpenClaw)

Componente Requisito Installazione
ssh, scp Presenti nel PATH Pre-installati su Linux/macOS
ImageMagick Comando convert apt install imagemagick
Python 3 Con libreria requests pip install requests

In sintesi rispetto alla versione locale: WP-CLI non è più richiesto sulla macchina con OpenClaw. Tutti i comandi wp vengono eseguiti via ssh -i chiave ... sul server remoto. Le immagini vengono elaborate localmente e trasferite con scp. La connessione non richiede mai password grazie all'autenticazione a chiave pubblica.

Esempio di articolo generato con stile giornalistico:

Titolo: OpenAI apre i modelli o1 agli sviluppatori: tariffe ridotte del 40% e nuovi limiti di contesto

Lede: OpenAI ha reso disponibili via API i modelli della famiglia o1, finora riservati agli utenti ChatGPT Plus, con una riduzione dei costi del 40% rispetto all'anteprima pubblica. La mossa, annunciata il 20 febbraio, amplia la finestra di contesto a un milione di token per i tier enterprise e segnala un cambio di strategia nella monetizzazione dell'AI per sviluppatori.

Notare: nessun "nell'era digitale", nessun "è importante notare". Il lede risponde subito alle 5W con dati numerici precisi e fonte esplicita. Tono da agenzia stampa, non da blog.


8. Riferimento Comandi CLI {#cli}

Comando Descrizione
openclaw onboard Avvia il wizard di configurazione guidata
openclaw gateway Avvia il Gateway (processo principale)
openclaw gateway --daemon Avvia il Gateway in background
openclaw status Stato del Gateway e degli agenti
openclaw stop Ferma il Gateway
openclaw doctor Diagnosi configurazione e sicurezza
openclaw logs Log del Gateway in tempo reale
clawhub install <slug> Installa una skill da ClawHub
clawhub search <query> Cerca skill nel registry
clawhub update --all Aggiorna tutte le skill installate
openclaw agent list Lista degli agenti configurati
openclaw session list Lista delle sessioni attive

9. Troubleshooting

Il Gateway non si avvia
Verifica che Node.js sia ≥22: node --version. Controlla i log con openclaw logs. Assicurati che la porta 18789 non sia occupata: lsof -i :18789.

Le skill non vengono caricate
Esegui openclaw doctor per rilevare binari mancanti o env non configurate. Controlla che SKILL.md abbia frontmatter YAML valido. Verifica che requires.bins siano nel PATH dell'utente che esegue OpenClaw.

WP-CLI restituisce errore di permessi
Usa l'utente web corretto (es. www-data) o il flag --allow-root solo in ambienti controllati. Verifica il path: wp --path=/var/www/html/wordpress post list.

Consumo eccessivo di token
Imposta spending cap sul dashboard del provider. Usa modelli economici (Gemini Flash) per skill semplici. Disabilita il heartbeat in sviluppo. Controlla che non ci siano loop nei cron job.

L'agente non trova le skill nel prompt
OpenClaw fa uno snapshot delle skill all'avvio della sessione. Dopo aver aggiunto una skill, riavvia la sessione o abilita skills.watcher per il hot-reload automatico.


Risorse Utili


Hai domande o vuoi condividere la tua skill? Lascia un commento qui sotto o apri una issue su GitHub.

Autore articolo: Emilio Petrozzi

🌐 Creazione siti web dinamici e di commercio elettronico 🛍 assistenza WordPress 🌐 Con oltre 20 anni di esperienza nel settore, esperto nella realizzazione di soluzioni digitali personalizzate per il tuo business. 🚀

🔧 Offro assistenza WordPress completa, garantendo che il tuo sito sia sempre aggiornato e funzionante al meglio. 📈 Inoltre mi occupo dell'ottimizzazione per motori di ricerca (SEO), assicurando che il tuo sito sia sempre facilmente rintracciabile dai tuoi clienti. 💻

📢 Le mie campagne pubblicitarie web sono progettate per aumentare la visibilità del tuo brand e generare traffico di qualità verso il tuo sito. 🔒 Inoltre la sicurezza informatica è una priorità in modo tale da garantire i tuoi dati e quelli dei tuoi clienti.

🤝 Affidati a mrtux.it per un servizio professionale e di qualità, e porta il tuo business al successo nel mondo digitale! 🎯

🔑 #CreazioneSitiWeb #Ecommerce #AssistenzaWordPress #OttimizzazioneSEO #SicurezzaInformatica

Tags: openclaw

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *


Aricoli correlati

Emilio Petrozzi  P. I.V.A. IT03080230604 - Professionista ai sensi della Legge 4/2013