nub/docs/FEATURES.md
Tom a97013d876 initial commit
- v 0.1.0 siehe CHANGELOG.md
2026-07-25 11:08:01 +02:00

206 lines
10 KiB
Markdown

# nub — Feature-Übersicht
Diese Seite beschreibt, was `nub` kann, aus Anwendersicht. Für die
Architektur dahinter siehe [KONZEPT.md](KONZEPT.md), für
Bau-/Test-Anleitungen siehe die [README](../README.md) und
[TESTING.md](TESTING.md).
## Grundprinzip
`nub` ist ein terminal-nativer Coding-Agent: ein einzelnes Go-Binary ohne
Laufzeit-Abhängigkeiten, das mit einem LLM über Tool-Calling zusammenarbeitet,
um Aufgaben in einem Code-Repository zu erledigen — Dateien lesen und
ändern, Befehle ausführen, Tests laufen lassen, und das Ganze über mehrere
Schritte hinweg, bis die Aufgabe erledigt ist.
Zwei Bedienmodi:
- **TUI** (Standard, wenn stdin/stdout ein Terminal sind) — interaktive
Oberfläche mit Streaming-Anzeige, Farb-Hervorhebung, Diff-Overlay und
Slash-Kommandos.
- **Print-Modus** (`-p`) — zeilenbasiert über stdin/stdout, für Skripte,
Pipes und Automatisierung.
Beide Modi sind dünne Consumer desselben Event-Streams; der Kern-Loop kennt
keinen von beiden und verhält sich in beiden identisch.
## Agent-Loop
- **Streaming-Antworten** — Text erscheint, während das Modell es erzeugt,
nicht erst am Ende.
- **Paralleles Tool-Calling** — fordert das Modell mehrere Tool-Aufrufe in
einem Schritt an, laufen sie gleichzeitig statt nacheinander.
- **Steering** — während der Agent noch arbeitet, eine neue Nachricht
schicken (TUI: Enter); sie wird eingeschleust, sobald der aktuelle
Tool-Aufruf fertig ist, ohne auf das Ende des ganzen Turns zu warten.
- **Follow-up-Queue** — alternativ eine Nachricht für *nach* dem aktuellen
Turn vormerken (TUI: Alt+Enter), statt den laufenden Gedankengang zu
unterbrechen.
- **Sicherheitsgrenzen** — Obergrenze für Turns pro Anfrage, Timeout pro
Tool-Aufruf, automatische Erkennung, wenn das Modell denselben Tool-Aufruf
wiederholt in eine Schleife läuft.
- **Sauberer Abbruch** — Ctrl+C (TUI) bzw. Ctrl+C im Print-Modus bricht
einen laufenden `bash`-Aufruf inklusive aller Kindprozesse ab, statt sie
als Zombies zurückzulassen.
## Eingebaute Tools
| Tool | Was es tut |
|---|---|
| `read` | Datei mit Zeilennummern lesen, mit Offset/Limit für große Dateien |
| `write` | Datei vollständig (neu) schreiben |
| `edit` | Gezielter String-Ersatz; bei mehrdeutigem Treffer Fehler statt Raten |
| `bash` | Shell-Befehl ausführen, mit Timeout und sauberem Abbruch |
| `glob` | Dateien per Muster finden, `.gitignore` wird respektiert |
| `grep` | Volltextsuche mit Kontextzeilen |
| `todo` | Fortschritts-Liste für lange Aufgaben (nur In-Memory) |
| `read_skill` | Vollständigen Inhalt eines Skills nachladen (siehe unten) |
| `question` | Freitext-Rückfrage an den Nutzer stellen (in der TUI als Block im Transkript, Antwort kommt als normales Tool-Ergebnis zurück; im Print-Modus ein harter Fehler, siehe unten) |
Dazu kommen automatisch alle Tools, die über angebundene MCP-Server
verfügbar sind (siehe „MCP" unten).
## Sessions
- Jede Konversation ist ein **Baum**, kein linearer Verlauf — jederzeit
lässt sich zu einem früheren Punkt zurückspringen und von dort aus neu
weiterarbeiten, ohne den ursprünglichen Verlauf zu verlieren.
- **Persistenz**: Jede Session wird fortlaufend auf die Platte geschrieben
(`.nub/sessions/`), nicht erst beim Beenden — ein Absturz verliert keine
Historie.
- **Fortsetzen**: `nub resume <session-id>` nimmt eine frühere Session genau
dort wieder auf, wo sie aufgehört hat.
- **Rewind/Branch**: Auf einen früheren Punkt zurückspringen und neu
weiterarbeiten erzeugt einen zweiten Ast — beide bleiben erhalten und
einzeln aufrufbar (TUI: `/tree` oder `/branch`; CLI: `nub resume --branch`).
- **Sessions auflisten**: `nub sessions` zeigt alle Sessions im aktuellen
Verzeichnis mit Kurzbeschreibung.
- **Session-Wechsel ohne Neustart**: In der TUI listet `/sessions` alle
Sessions des Projekts; Enter wechselt live zur gewählten Session (der
bisherige Verlauf wird aus der Historie neu aufgebaut), Entf löscht eine
Session unwiderruflich (mit Rückfrage). Die gerade aktive Session lässt
sich nicht löschen.
## Kontext
- **Automatischer System-Prompt** aus Basis-Prompt, Umgebungsinfo
(OS/Shell/Repo-Root/Branch) und konfigurierten Kontext-Dateien
(Default: `AGENTS.md`, `REPOMAP.md`).
- **`walk_up`**: Kontext-Dateien werden nicht nur im Repo-Root gesucht,
sondern auf dem Weg vom aktuellen Verzeichnis dorthin eingesammelt —
näher am Arbeitsverzeichnis gewinnt inhaltlich.
- **Budget-Kontrolle**: Kontext-Dateien werden auf ein Token-Budget
begrenzt; bei Überschreitung wird sichtbar gekürzt statt still
abgeschnitten.
- **`nub map`**: generiert eine `REPOMAP.md` mit Verzeichnisbaum und
exportierten Symbolen (Go: über `go/ast`, andere Sprachen: Dateikopf als
Fallback). Warnt, wenn die Repomap gegenüber dem aktuellen Git-Stand
veraltet ist.
- **`SYSTEM.md`**: eine Datei im Repo-Root überschreibt den eingebauten
Basis-System-Prompt vollständig, für projektspezifisches Verhalten.
## Auto-Compaction & Tokens
- Sobald der geschätzte Kontextverbrauch eine Schwelle (Default 75 % des
Modell-Fensters) überschreitet, fasst `nub` die ältere Hälfte der Session
automatisch zusammen (bearbeitete Dateien, Entscheidungen, offene
Aufgaben) und ersetzt sie durch eine kompakte Zusammenfassung — die
letzten Turns bleiben immer im Original erhalten.
- Die Zusammenfassung ist **nicht destruktiv**: der Originalverlauf bleibt
im Session-Baum erhalten, ein Rewind auf einen Punkt davor funktioniert
weiterhin.
- **Manuell erzwingen**: `/compact` (TUI) oder `nub compact <session-id>`.
- Die Token-Schätzung kalibriert sich während des Laufs gegen die
tatsächlich vom Provider gemeldete Token-Nutzung.
## Skills
- Wiederverwendbare Anleitungen für wiederkehrende Aufgaben (z.B.
„Vorgehen bei Refactorings"), als Markdown-Datei mit kurzem
Frontmatter (Name + Beschreibung) unter `.nub/skills/<name>/SKILL.md`
oder global unter `~/.nub/skills/`.
- **Progressive Disclosure**: Nur Name und Beschreibung stehen im
System-Prompt (~30 Token pro Skill). Der volle Inhalt wird erst geladen,
wenn das Modell ihn über `read_skill` tatsächlich braucht — spart Kontext
bei Skills, die in der aktuellen Aufgabe gar nicht relevant sind.
- `nub skills` (CLI) bzw. `/skills` (TUI) zeigen, was gefunden wurde.
- **Als Slash-Command**: Jeder Skill ist in der TUI direkt per `/<name>
[Zusatzinfo]` aufrufbar — schickt eine kurze Direktive statt den Body
einzufügen, das Modell lädt ihn weiterhin selbst nach. Eingebaute
Kommandos gewinnen bei Namenskollision.
## MCP (Model Context Protocol)
- Externe Tool-Server lassen sich per Config anbinden (`[[mcp]]`-Einträge:
lokaler Prozess über stdio oder ein HTTP-Endpoint).
- Alle konfigurierten Server werden **parallel** verbunden, mit Timeout —
ein nicht erreichbarer oder kaputter Server verhindert den Start nicht,
sondern fällt mit einer Warnung raus.
- Tools erscheinen mit `<server>__`-Präfix, um Namenskollisionen zwischen
Servern zu vermeiden.
- **Allowlist**: pro Server lässt sich einschränken, welche Tools geladen
werden (`tools = [...]`); ohne Allowlist wird ab 15 Tools gewarnt, weil
das spürbar Kontext kostet.
- **Profile**: `[profiles]` in der Config gruppiert Server, sodass sich
z.B. nur die für eine Code-Review relevanten Server verbinden lassen
(`--profile review`), statt immer alle.
- `nub mcp` (CLI) bzw. `/mcp` (TUI) zeigen verbundene Server und ihre Tools.
## TUI-Details
- **Streaming mit Markdown-Rendering**: laufender Text erscheint sofort,
fertige Antworten werden nachträglich als Markdown formatiert.
- **Diff-Overlay**: Datei-Änderungen (`write`/`edit`) erscheinen farbig
(+/-) direkt im Transkript.
- **Farbliche Unterscheidung** zwischen eigenen Nachrichten, Assistant-Text,
Tool-Aufrufen/-Ergebnissen, Slash-Kommando-Ausgaben, Hintergrund-
Ereignissen (z.B. Auto-Compaction) und echten Fehlern — alle Farben
passen sich automatisch an helle oder dunkle Terminals an.
- **Eingabe-Historie** (↑/↓), Scrollen der Nachrichtenliste (PgUp/PgDn,
Ctrl+U/D, Mausrad).
- **Interaktives Baum-Modal** (`/tree`, `/branch`) zum Durchsuchen und
Auswählen früherer Punkte der Session.
- **Export**: `/export [pfad]` schreibt das komplette Transkript als
Markdown-Datei.
## Konfiguration
- **Geschichtet**: eingebaute Defaults → `~/.config/nub/config.toml`
(global) → `.nub/config.toml` (projektlokal) → `NUB_*`-Umgebungs-
variablen — spätere Schicht gewinnt.
- **Mehrere Endpoints**: beliebig viele `[[endpoint]]`-Einträge (OpenAI,
lokale Server wie Ollama/LM Studio/vLLM, …), einzeln in ihren
Fähigkeiten konfigurierbar (z.B. `parallel_tool_calls = false` für
Server, die das nicht unterstützen).
- Ohne jede Config-Datei funktioniert `nub` bereits mit sinnvollen
Defaults gegen die echte OpenAI-API.
- **`nub init`** (CLI) bzw. **`/init`** (TUI) legen `.nub/config.toml` mit
einer vollständig kommentierten Beispiel-Config (inkl. Permissions-
Beispiel) sowie ein minimalistisches `AGENTS.md` an — beides nur, falls
noch nicht vorhanden, nichts wird überschrieben.
## Sicherheit & Robustheit
- **Permissions pro Tool**: `read`/`glob`/`grep`/`write`/`edit`/`bash`
lassen sich einzeln auf `auto`, `ask` (Rückfrage in der TUI, im
Print-Modus ein harter Fehler) oder `deny` setzen. `deny_paths`/
`deny_bash` sperren zusätzlich bestimmte Pfade bzw. Befehlsmuster,
unabhängig vom sonst konfigurierten Modus.
- **`question`-Tool**: generische Rückfrage-Fähigkeit, die sowohl das
Modell selbst als auch Skills (per Anweisung) nutzen können, um eine
Freitext-Frage (optional mit Vorschlägen) an den Nutzer zu stellen und
die Antwort direkt als Tool-Ergebnis zurückzubekommen — dieselbe
Mechanik wie bei einer `ask`-Permission-Rückfrage, nur nicht an ein
bestimmtes Tool gebunden. In der TUI erscheint sie als Block im
Transkript (kein Overlay); die nächste Eingabe wird als Antwort
gewertet statt als neue Nachricht oder Slash-Kommando. Im Print-Modus
liefert sie einen klaren Fehler statt zu blockieren, da Print bewusst
headless laufen soll.
- Datei-Tools sind auf das Repository beschränkt (inkl. Auflösen von
Symlinks, um ein Verlassen des Repo-Roots zu verhindern).
- Sessiondateien haben restriktive Dateirechte (`0600`) und werden
automatisch von Git ausgeschlossen (`.git/info/exclude`, nicht
`.gitignore` — das bleibt Sache des Projekts).
- Kein Tool-Aufruf endet ohne Ergebnis — auch bei Abbruch oder Fehler
bekommt das Modell eine verwertbare Antwort statt eines hängenden
Zustands.