Realtime-Attack-Map
SURICATA / LIVE FEED

Pi Agent - Agentic AI ohne Cloud-Zwang

Agentic AI ohne Cloud: Pi Agent kombiniert vier Kernwerkzeuge mit lokaler KI.

Pi Agent - Agentic AI ohne Cloud-Zwang

Der Pi Coding Agent ist ein vollständig quelloffener, minimalistischer KI-Agent, der direkt im Terminal lebt - ohne Cloud-Zwang, ohne Datenschutz-Bauchschmerzen, und erstaunlicherweise ohne die nervtötenden "Bist du wirklich sicher?"-Popups, die man von anderen Tools kennt. Mit einem Ollama-Modell entsteht ein vollständig selbst gehosteter Agentenstack, der auf nichts Externes angewiesen ist.

Was ist Pi Agent

Pi wurde von Mario Zechner mit einer klaren Design-Philosophie entwickelt: weniger ist mehr. Read, Write, Edit und Bash.

Pi ist dabei vollständig erweiterbar: Extensions, Skills, Prompt-Templates und Themes lassen sich über TypeScript-Module nachrüsten oder als Pi-Packages über npm installieren - aber das alles ist optional.

Die Unterstützung für über 20 Provider - darunter Anthropic, OpenAI, Google Gemini, Groq, OpenRouter und Ollama - macht Pi zur universellen Schaltzentrale.

Installation

Die Installation läuft in Sekunden:

curl -fsSL https://pi.dev/install.sh | sh

Alternativ geht es auch via npm:

npm install -g @earendil-works/pi-coding-agent

Nach der Installation startet Pi mit dem Kommando pi.

Ollama als lokalen Provider einrichten

Wer Ollama bereits betreibt und etwa auf einer RTX 3090 Modelle lokal ausführt, hat alles, was Pi braucht. ~/.pi/agent/models.json angelegt oder erweitert:

{
  "providers": [
    {
      "name": "local-ollama",
      "api": "openai",
      "baseUrl": "http://ai:11434/v1",
      "apiKey": "ollama"
    }
  ],
  "models": [
    {
      "id": "gemma4:26b",
      "provider": "local-ollama",
      "contextWindow": 131072
    }
  ]
}

Nach dem nächsten Start von Pi steht das Modell per /model zur Auswahl:

> /model
? Select a model:
  claude-sonnet-4-5
  gpt-4o
❯ gemma4:26b          [local-ollama]

Für Coding-Aufgaben empfiehlt sich ein Modell mit ausreichend Kontextfenster. Ich habe hier bereits eine passende Anleitung erstellt.

Ollama-Optimierung: Umgebungs-Variablen, die wirklich zählen
Ollama schweigt über seine Standard-Defaults – und das kostet Kontext. Hier die vollständige Konfiguration für maximale Agenten-Leistung.

Das aktive Modell und die Kontextfenster-Auslastung werden immer in der Statuszeile am unteren Bildschirmrand angezeigt:

[gemma4:26b]  context: 4.2k / 128k  thinking: medium

Der Thinking-Mode lässt sich jederzeit über /settings anpassen - für einfache Aufgaben reicht low, für komplexe Codegenerierung ist medium oder high sinnvoll.

AGENTS.md - das Gedächtnis des Agenten

Das Konzept der AGENTS.md ist einer der wichtigsten Bausteine für effektives Arbeiten mit Pi. Während README.md für menschliche Leser gedacht ist, ist die AGENTS.md für den Agenten.

Pi lädt AGENTS.md-Dateien beim Start aus ~/.pi/agent/, aus übergeordneten Verzeichnissen und aus dem aktuellen Projektverzeichnis.

Eine gut strukturierte AGENTS.md spart Token und verhindert Missverständnisse.

# Project Context

## Infrastructure
- Docker Compose deployments: /var/docker/<service>/docker-compose.yml
- web server: webdocker (SSH via ssh-config alias "web")
- monitoring server: srvdocker (SSH via ssh-config alias "srv")
- Monitoring stack: Grafana + Prometheus on srv:3000

## Conventions
- Always validate compose files with `docker compose config` before applying
- Never apply changes directly; commit to git and let the CI pipeline deploy
- Prefer rootless containers (UID 1000)

## Services
- Watchtower auto-updates all containers tagged :latest
- npm handles reverse proxy on web, config in /var/docker/npm/

Wenn Pi nun die Anfrage check if grafana is running erhält, weiß der Agent ohne weitere Erläuterung, dass Grafana auf srv über Port 3000 erreichbar ist und ein SSH-Alias existiert.

$ ssh srv "docker ps --filter name=grafana --format '{{.Names}}\t{{.Status}}'"
grafana   Up 3 days (healthy)

Erste Schritte und Kernbefehle

Ein erster Test lässt sich direkt in einem beliebigen Projektverzeichnis starten. @-Syntax erlaubt es, Dateien explizit in den Kontext zu laden:

> Beschreibe das Setup in `@docker-compose.yml`

Pi: Die Compose-Datei startet einen Nginx-Reverse-Proxy sowie drei Backend-Services.
Die Services teilen sich ein internes Netzwerk `web`. Nginx lauscht auf Port 443 und übernimmt die TLS-Terminierung über Let's Encrypt. Die Backend-Services sind nicht direkt nach außen exponiert.

Verwendete Tools: `read(docker-compose.yml)`

Für Shell-Befehle ohne Kontext-Verlust steht das Ausrufezeichen als Präfix bereit:

> !docker ps
CONTAINER ID   IMAGE           COMMAND                  STATUS
a1f3c2e4b5d6   nginx:alpine    "/docker-entrypoint.…"   Up 2 hours

Der Befehl wird direkt an die Shell weitergereicht, ohne als Prompt an das LLM gesendet zu werden - praktisch für schnelle Inspektion nebenbei.

Prompt-Templates für wiederkehrende Aufgaben

Wer regelmäßig die gleichen Analyseaufgaben ausführt, kann diese als Prompt-Template in ~/.pi/agent/prompts/ ablegen. security-review.md könnte so aussehen:

---
description: Security review of the current project
---

Review all files in the current directory for:
- Hardcoded credentials or API keys
- Insecure file permissions
- Exposed ports without authentication
- Missing input validation in scripts

Report findings grouped by severity (critical, high, medium, low).

Nach dem nächsten Pi-Start ist /security-review als Slash-Command verfügbar:

> /security-review

Pi: Starte Security-Review...

    [HIGH] docker-compose.yml:14 - Port 8080 ohne Auth-Middleware exponiert
    [MEDIUM] deploy.sh:7 - MQTT_PASS als Klartext in Variable gesetzt
    [LOW] .env.example - Beispielwerte ohne Warnhinweis vorhanden

    Tools used: read(docker-compose.yml), read(deploy.sh), read(.env.example)

Auf der Pi-Website finden sich außerdem Community-Packages mit fertigen Skills und Extensions, die sich per pi install npm:@paketname/pi-extension einbinden lassen.

Session-Management

Pi speichert alle Sessions als Baumstruktur.

Mit /tree lässt sich der vollständige Session-Verlauf einsehen:

> /tree

  Session: btc-analysis-2025-05-19
  ├─ [0] Initiale Projektbeschreibung
  ├─ [1] API-Struktur besprochen
  │  ├─ [2] Ersten Entwurf erstellt
  │  └─ [3] Alternative Struktur (current)
  └─ [4] Tests hinzugefügt

Mit /fork lässt sich ab jedem Knoten eine neue Entwicklungslinie starten - nützlich, um alternative Lösungsansätze parallel zu verfolgen, ohne den Hauptpfad zu beeinflussen.

Wenn das Kontextfenster des lokalen Modells langsam voll wird, hilft /compact:

> /compact Keep all API endpoints, data structures and the MQTT publishing logic

Pi: Komprimiere Session-Kontext...
    Reduziert von 18.400 auf 3.200 Token.
    Wichtige Strukturen und MQTT-Logik beibehalten.

Gerade bei lokalen Modellen mit begrenztem Kontextfenster ist das eine wichtige Funktion - ohne Komprimierung beginnt das Modell irgendwann, frühere Entscheidungen zu "vergessen".

Beim nächsten Terminalstart lässt sich die letzte Session mit pi -r fortsetzen oder eine ältere Session interaktiv auswählen.

Praxisbeispiel - Bitcoin-Marktanalyse per Bash-Script

Ein konkretes Beispiel zeigt, wie Pi bei der Entwicklung eines komplexeren Shell-Scripts als Sparringspartner dient. Das fertige Script soll die ermittelten Metriken zusätzlich an ioBroker weitermelden.

Der Prompt an Pi war bewusst knapp gehalten:

> Erstelle ein Bash-Script, das Bitcoin-Marktdaten von der Binance-API und
  dem Fear & Greed Index abruft. Berechne RSI (14 Tage), SMA200 und OBV aus
  den Kline-Daten. Verdichte alles zu einem Score und veröffentliche die
  Werte per MQTT an meinen ioBroker (Konfiguration steht in der AGENTS.md).
  Das Script soll auch vor extremen Marktlagen warnen (Long-Squeeze,
  Short-Squeeze).

Das Ergebnis nach wenigen Iterationen - Pi hat dabei selbst Korrekturen an der awk-Berechnung vorgenommen, als ein Edge-Case bei Division durch null auftrat:

#!/bin/bash
# Bitcoin-Marktanalyse & ioBroker-MQTT-Publisher - M. Meister

for tool in curl jq bc awk mosquitto_pub; do
    if ! command -v "$tool" &> /dev/null; then
        echo "Fehler: '$tool' ist nicht installiert." && exit 1
    fi
done

echo "======================================================"
echo "   BITCOIN MARKT-ANALYSE & WARNSYSTEM"
echo "======================================================"
echo "Lade Daten von Binance und CoinBubble..."

SCORE=0

# --- Fear & Greed Index ---
FNG_VALUE=$(curl -s https://api.coinybubble.com/v1/latest \
    | jq -r .actual_value | sed 's/\..*//')

if   [ "$FNG_VALUE" -lt 30 ]; then SCORE=$((SCORE+2)); FNG_TEXT="Extreme Angst"
elif [ "$FNG_VALUE" -gt 70 ]; then SCORE=$((SCORE-2)); FNG_TEXT="Extreme Gier"
else FNG_TEXT="Neutral"
fi

# --- Funding Rate (Binance Futures) ---
FUNDING_RATE=$(curl -s "https://fapi.binance.com/fapi/v1/premiumIndex?symbol=BTCUSDT" \
    | jq -r '.lastFundingRate')
FUNDING_PERCENT=$(echo "$FUNDING_RATE * 100" | bc -l)
FUNDING_FORMATTED=$(LC_NUMERIC=C printf "%.4f" "$FUNDING_PERCENT")

# --- Kline-Daten: SMA200, RSI, OBV ---
KLINES=$(curl -s "https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d&limit=200")

CALCS=$(echo "$KLINES" | jq -r '.[] | "\(.[4]) \(.[5])"' | awk '
BEGIN { sum=0; gain=0; loss=0; obv=0 }
{
    c=$1; vol=$2; sum+=c
    if (NR==186) { prev_c=c; price_start=c }
    if (NR>186) {
        diff = c - prev_c
        if (diff > 0) { gain+=diff; obv+=vol }
        else if (diff < 0) { loss+=(-diff); obv-=vol }
        prev_c=c
    }
}
END {
    sma200 = sum/200
    avg_gain = gain/14; avg_loss = loss/14
    rsi = (avg_loss == 0) ? 100 : 100 - (100 / (1 + (avg_gain/avg_loss)))
    price_trend = (c > price_start) ? 1 : -1
    obv_trend   = (obv > 0) ? 1 : -1
    printf "%.2f %.2f %d %d %.2f\n", sma200, rsi, obv_trend, price_trend, c
}')

read -r SMA200 RSI OBV_TREND PRICE_TREND BTC_PRICE <<< "$CALCS"
BTC_PRICE_FORMATTED=$(LC_NUMERIC=C printf "%.2f" "$BTC_PRICE")

# --- Makro-Trend und OBV-Divergenz ---
IS_BULL=$(echo "$BTC_PRICE > $SMA200" | bc -l)
if [ "$IS_BULL" -eq 1 ]; then
    SCORE=$((SCORE+2)); MACRO_TEXT="BULLENMARKT (Preis über SMA200)"
else
    SCORE=$((SCORE-2)); MACRO_TEXT="BÄRENMARKT (Preis unter SMA200)"
fi

VOL_WARNING="Keine Auffälligkeiten"
if   [ "$PRICE_TREND" -eq 1 ] && [ "$OBV_TREND" -eq -1 ]; then
    SCORE=$((SCORE-2)); VOL_WARNING="FAKE-PUMP: Preis steigt, Volumen fällt"
elif [ "$PRICE_TREND" -eq -1 ] && [ "$OBV_TREND" -eq 1 ]; then
    SCORE=$((SCORE+2)); VOL_WARNING="AKKUMULATION: Preis fällt, Wale kaufen"
fi

# --- Master-Alert ---
IS_OVERBOUGHT=$(echo "$RSI > 75" | bc -l)
IS_OVERSOLD=$(echo "$RSI < 25"  | bc -l)
HIGH_FUNDING=$(echo "$FUNDING_PERCENT > 0.05"  | bc -l)
LOW_FUNDING=$(echo  "$FUNDING_PERCENT < -0.05" | bc -l)

MASTER_ALERT="Marktstruktur unauffällig."
if [ "$IS_OVERBOUGHT" -eq 1 ] && [ "$HIGH_FUNDING" -eq 1 ] && [ "$FNG_VALUE" -gt 75 ]; then
    MASTER_ALERT="CRASH-GEFAHR: Gier, Hebel und RSI auf Maximum. Long-Squeeze droht!"
    SCORE=$((SCORE-5))
fi
if [ "$IS_OVERSOLD" -eq 1 ] && [ "$LOW_FUNDING" -eq 1 ] && [ "$FNG_VALUE" -lt 25 ]; then
    MASTER_ALERT="AUSBRUCH-SIGNAL: Extreme Angst + Short-Squeeze-Druck. Möglicher Pump!"
    SCORE=$((SCORE+5))
fi

# --- Ausgabe ---
echo ""
echo "[ CHART & TREND ]"
echo "Aktueller Preis:  $BTC_PRICE_FORMATTED USDT"
echo "SMA 200 (Makro):  $SMA200 USDT -> $MACRO_TEXT"
echo "Volumen (OBV):    $VOL_WARNING"
echo ""
echo "[ MOMENTUM & LEVERAGE ]"
echo "Fear & Greed:     $FNG_VALUE / 100 ($FNG_TEXT)"
echo "RSI (14 Tage):    $RSI  (Neutral: 30-70)"
echo "Funding Rate:     $FUNDING_FORMATTED %  (Gefahr ab > 0.05%)"
echo ""
echo "[ MASTER-WARNSYSTEM ]"
echo "$MASTER_ALERT"
echo "------------------------------------------------------"
echo -n ">>> EMPFEHLUNG: "
if   [ "$SCORE" -ge 4  ]; then echo "STARKER KAUF  (hohe Confluence)"
elif [ "$SCORE" -ge 1  ]; then echo "KAUFEN"
elif [ "$SCORE" -le -4 ]; then echo "STARKER VERKAUF (hohes Risiko)"
elif [ "$SCORE" -le -1 ]; then echo "VERKAUFEN"
else                            echo "NEUTRAL / ABWARTEN"
fi
echo "======================================================"

# --- MQTT an ioBroker ---
MQTT_HOST="iobroker"
MQTT_PORT="1884"
MQTT_USER="mqtt_user"
MQTT_PASS="<mqtt-passwort>"
MQTT_ID="btc_analyzer"

_mqtt() {
    mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" \
                  -u "$MQTT_USER" -P "$MQTT_PASS" \
                  -i "$MQTT_ID" -t "$1" -m "$2"
}

echo ""
echo "[ MQTT PUBLISH ]"

# Wallet-Guthaben in EUR ermitteln
WALLET_ADDR="<bitcoin-wallet-adresse>"
BTC_EUR=$(echo "scale=2;
    $(curl -s "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=eur" | jq .bitcoin.eur) *
    $(curl -s "https://blockchain.info/balance?active=${WALLET_ADDR}" | jq .[].final_balance) *
    0.00000001 / 1" | bc)

_mqtt "Banking/Bitcoins"    "$BTC_EUR"           && echo "  Banking/Bitcoins    -> $BTC_EUR EUR"
_mqtt "Banking/FearnGreed"  "$FNG_VALUE"         && echo "  Banking/FearnGreed  -> $FNG_VALUE"
_mqtt "Banking/RSI"         "$RSI"               && echo "  Banking/RSI         -> $RSI"
_mqtt "Banking/FundingRate" "$FUNDING_FORMATTED" && echo "  Banking/FundingRate -> $FUNDING_FORMATTED %"
_mqtt "Banking/Score"       "$SCORE"             && echo "  Banking/Score       -> $SCORE"

echo "======================================================"

Eine typische Ausgabe des Scripts sieht so aus:

======================================================
   BITCOIN MARKT-ANALYSE & WARNSYSTEM
======================================================
Lade Daten von Binance und CoinBubble...

[ CHART & TREND ]
Aktueller Preis:  103241.87 USDT
SMA 200 (Makro):  87442.18 USDT -> BULLENMARKT (Preis über SMA200)
Volumen (OBV):    Keine Auffälligkeiten

[ MOMENTUM & LEVERAGE ]
Fear & Greed:     71 / 100 (Extreme Gier)
RSI (14 Tage):    68.34  (Neutral: 30-70)
Funding Rate:     0.0312 %  (Gefahr ab > 0.05%)

[ MASTER-WARNSYSTEM ]
Marktstruktur unauffällig.
------------------------------------------------------
>>> EMPFEHLUNG: KAUFEN
======================================================

[ MQTT PUBLISH ]
  Banking/Bitcoins    -> 4821.33 EUR
  Banking/FearnGreed  -> 71
  Banking/RSI         -> 68.34
  Banking/FundingRate -> 0.0312 %
  Banking/Score       -> 2
======================================================

Die MQTT-Werte landen direkt in ioBroker und lassen sich dort mit Alarmen verknüpfen - etwa eine NTFY-Benachrichtigung, wenn der Score auf -4 fällt oder der Master-Alert aktiv wird. cron soll das Script alle fünf Minuten ausführen:

# crontab -e
*/5 * * * * /opt/scripts/btc-analysis.sh >> /var/log/btc-analysis.log 2>&1

Was an diesem Beispiel bemerkenswert ist: Die awk-Logik für RSI und OBV wurde komplett von Pi generiert - inklusive des Edge-Case-Handling für avg_loss == 0.

Der Score-Wert zuckt, bevor der Bitcoin sich bewegt.

Sicherheitshinweis - volle Kontrolle bedeutet volle Verantwortung

Pi ist bewusst ohne Sicherheitsschranken gebaut.

Features wie Sub-Agents, Plan-Mode und Permission-Gates existieren nicht im Pi-Kern - sie lassen sich jedoch als Extensions nachrüsten.

Empfehlenswerte Gegenmaßnahmen für den produktiven Einsatz:

  • AGENTS.md-Guardrails: Klare Verbote direkt in die AGENTS.md schreiben, z.B. Never run rm -rf.
  • Git-Workflow: Alle Arbeitsverzeichnisse als Git-Repos führen. git diff und git restore der Sicherheitsgurt.
  • Read-Only-Benutzer für kritische Systeme: SSH-Keys für Produktionssysteme nur mit eingeschränkten Rechten hinterlegen. Zum Beispiel bei der Problemsuche auf einer entfernten Firewall.
  • Permission-Gate-Extension installieren, wenn vollständige Kontrolle über jeden Tool-Call gewünscht ist.

Der Vergleich mit Warp, das einen dreistufigen Allow-List-Mechanismus mitbringt, ist hier aufschlussreich: Warp schützt stärker von Haus aus, Pi delegiert diese Entscheidung konsequent an den Nutzer.

Apropos Warp: Der damals genannte Kritikpunkt der fehlenden Quelloffenheit hat sich erledigt. Der gesamte Quellcode ist inzwischen auf GitHub verfügbar.

Fazit

Pi Agent ist die konsequente Umsetzung des Prinzips "weniger ist mehr" für KI-gestützte Terminal-Arbeit - vollständig quelloffen, vollständig lokal betreibbar und vollständig anpassbar.