|
|
||
|---|---|---|
| cmd/nub | ||
| docs | ||
| internal | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
| test.py | ||
nub
Schlanker, terminal-nativer Coding-Agent als einzelnes Go-Binary. Keine Laufzeit-Abhängigkeiten, interaktive TUI, skriptbarer Print-Modus.
- Features: docs/FEATURES.md
- Architektur/Design: docs/KONZEPT.md
- Entwicklung/Tests: docs/TESTING.md
Voraussetzungen
- Go 1.24+
- OpenAI-kompatibler Endpoint (OpenAI-API-Key oder lokaler Server: Ollama, LM Studio, vLLM, …)
- Linux/macOS (Windows nur über WSL)
Installation
git clone <repo-url> nub && cd nub
go build -o nub ./cmd/nub
mv nub /usr/local/bin/ # optional
Schnellstart
export OPENAI_API_KEY=sk-...
cd /pfad/zu/deinem/projekt
nub
Startet eine interaktive Session im aktuellen Verzeichnis — das wird zur
Wurzel für alle Datei-Tools und bash-Aufrufe. Ohne Config-Datei laufen
sinnvolle Defaults (Modell gpt-4o gegen die echte OpenAI-API).
Konfiguration
Geschichtet, spätere Schicht gewinnt: Defaults → ~/.config/nub/config.toml
(global) → <projekt>/.nub/config.toml (projektlokal) → NUB_*-Env-Vars.
Nur Umgebungsvariablen
| Variable | Pflicht | Default | Bedeutung |
|---|---|---|---|
NUB_API_KEY |
nein* | — | API-Key, Vorrang vor OPENAI_API_KEY |
OPENAI_API_KEY |
nein* | — | Fallback |
NUB_BASE_URL |
nein | https://api.openai.com/v1 |
Endpoint-URL |
NUB_MODEL |
nein | gpt-4o |
Modellname |
* Pflicht, außer der Endpoint beginnt mit http:// (lokal, kein Key nötig).
export OPENAI_API_KEY=sk-...
export NUB_MODEL=gpt-4o-mini
export NUB_BASE_URL=http://localhost:11434/v1
export NUB_MODEL=qwen2.5-coder:7b
Mit Config-Datei
nub init (oder /init in der TUI) legt .nub/config.toml (kommentierte
Beispiel-Config inkl. Permissions) und ein minimales AGENTS.md an — nur
falls noch nicht vorhanden.
Von Hand, .nub/config.toml (version = 1 ist Pflicht):
version = 1
[model]
default = "gpt-4o-mini"
endpoint = "openai"
[[endpoint]]
name = "openai"
base_url = "https://api.openai.com/v1"
api_key = "env:OPENAI_API_KEY" # oder direkt der Key, oder "none" für lokal
[context]
files = ["AGENTS.md", "REPOMAP.md"]
walk_up = true
max_tokens = 20000
- Mehrere
[[endpoint]]-Blöcke möglich;model.endpointwählt aus. [endpoint.caps]überschreibt einzelne Fähigkeiten (z.B.parallel_tool_calls = falsefür Server, die das nicht unterstützen).- Fehlt bei einem Nicht-lokalen Endpoint der Key, bricht
nubsofort ab.
Bedienung
TUI standardmäßig im Terminal (stdin+stdout), sonst Print-Modus. -p
erzwingt Print-Modus.
TUI
| Taste/Kommando | Wirkung |
|---|---|
Enter |
Nachricht senden (läuft ein Turn: als Steering zwischen zwei Tool-Aufrufen eingeschleust) |
Alt+Enter |
als Follow-up queuen (erst nach Ende des laufenden Turns) |
↑/↓ |
Eingabe-Historie (bei leerer Eingabezeile) |
PgUp/PgDn, Ctrl+U/Ctrl+D, Mausrad |
Nachrichtenliste scrollen |
Ctrl+C, /exit, /quit |
beenden |
Diffs (write/edit) farbig im Transkript, fertige Antworten als Markdown.
Farben passen sich automatisch an helles/dunkles Terminal-Theme an.
Slash-Kommandos:
| Kommando | Wirkung |
|---|---|
/model [name] |
Modell anzeigen oder für den Rest der Session wechseln |
/tree, /branch |
Session-Baum anzeigen, Rewind mit ↑/↓ + Enter |
/sessions |
Sessions auflisten, wechseln (Enter), löschen (Entf, Rückfrage) |
/compact |
Session sofort zusammenfassen |
/context |
geladenen Kontext mit Herkunft/Tokenkosten anzeigen |
/mcp |
verbundene MCP-Server und ihre Tools |
/skills |
gefundene Skills |
/export [pfad] |
Transkript als Markdown exportieren |
/init |
.nub/config.toml + AGENTS.md anlegen, falls nicht vorhanden |
/clear |
Anzeige leeren (Session bleibt erhalten) |
/exit, /quit |
beenden |
/help |
Kommando-Übersicht |
Jeder gefundene Skill ist zusätzlich direkt als /<name> [Zusatzinfo]
aufrufbar (siehe Skills).
Print-Modus (-p)
Zeilenweise stdin = eine Nachricht. Antworten auf stdout, Tool-Aktivität
(→ tool_name {...}, ← tool_name [ok|error], bash-Output) auf stderr.
Ctrl+D (EOF) beendet sauber nach dem aktuellen Turn.
./nub -p
Lies die Datei go.mod und fasse in einem Satz zusammen, was das Modul ist.
Beim Start gibt nub (beide Modi) auf stderr die Session-ID aus
(session: 01J...).
Sessions
Jeder Lauf ohne Subcommand startet eine neue Session, persistiert unter
.nub/sessions/<id>.jsonl (automatisch von Git ausgeschlossen via
.git/info/exclude).
nub sessions # Sessions im aktuellen Verzeichnis auflisten
nub resume <session-id> # Session fortsetzen
In der TUI: /sessions (Liste, wechseln, löschen).
Rewind/Branch: in der TUI über /tree//branch. Über CLI/Print-Modus
per Node-ID:
cat .nub/sessions/<session-id>.jsonl | jq -r 'select(.node) | .node.id + " " + (.node.message.content[0].text // "" | .[0:60])'
nub resume <session-id> --branch <node-id>
Setzt den Head auf den gewählten Knoten zurück; eine neue Nachricht bildet dort einen zweiten Ast. Der ursprüngliche Ast bleibt erhalten.
Kontext (AGENTS.md, REPOMAP.md, nub map)
System-Prompt = Basis-Prompt (überschreibbar durch SYSTEM.md im
Projekt-Root) + statische Umgebungsinfo (OS/Shell/Repo-Root/Branch) + Dateien
aus context.files (Default: AGENTS.md, REPOMAP.md). Mit
walk_up = true (Default) werden Treffer zwischen aktuellem Verzeichnis und
Projekt-Root eingesammelt.
nub context # geladene Kontext-Dateien mit Herkunft und Tokenkosten
nub map # REPOMAP.md generieren/aktualisieren
context.max_tokens (Default 20000) begrenzt Kontext-Dateien, kürzt sichtbar
statt still. nub map erzeugt Verzeichnisbaum + exportierte Symbole
(.go über go/ast, sonst erste Zeile als Fallback); warnt, wenn die
Repomap vom Git-Stand abweicht.
Compaction & todo-Tool
Vor jedem Turn geschätzte Tokenkosten; über Schwelle (Default 75 % des Modell-Fensters) wird automatisch komprimiert: ältere Hälfte der Session wird per separatem Prompt zusammengefasst, letzte Turns bleiben im Original. Original-Nodes bleiben erhalten — Rewind vor die Compaction funktioniert weiterhin.
nub compact <session-id> # Compaction sofort erzwingen
todo-Tool: In-Memory-Todo-Liste für lange Aufgaben (nicht persistiert),
das Modell entscheidet selbst über die Nutzung.
Skills
.nub/skills/<name>/SKILL.md (projektlokal) oder
~/.nub/skills/<name>/SKILL.md (global, konfigurierbar über
[skills] paths = [...]). Projektlokal überschreibt global.
---
name: refactoring
description: Vorgehen für größere Refactorings in diesem Repo.
---
# Refactoring
...Body...
Beim Start landet nur name+description im System-Prompt (~30 Token pro
Skill); den Body lädt das Modell selbst nach (read_skill), weitere
Dateien im Skill-Verzeichnis über read/glob.
nub skills # Index-Vorschau
Als Slash-Command: /<name> [Zusatzinfo], z.B. /refactoring fokus auf error handling — schickt eine kurze Direktive statt Rohdaten, Progressive
Disclosure bleibt erhalten. Eingebaute Kommandos haben bei Namenskollision
Vorrang.
MCP
[[mcp]]
name = "github"
command = "gh-mcp-server"
args = []
tools = ["create_issue", "get_pull_request"] # Allowlist; leer = alle
[[mcp]]
name = "linear"
url = "https://mcp.linear.app/mcp"
Alle Server parallel verbunden (Timeout 5s/Server), Tools mit
<server>__-Präfix (z.B. github__create_issue). Nicht erreichbare Server
verhindern den Start nicht (Warnung, nub läuft weiter).
nub mcp # verbindet und listet Tools
Profile grenzen ein, welche Server pro Aufruf verbunden werden:
[profiles]
review = ["github"]
default = []
nub --profile review
nub resume <session-id> --profile review
Ohne [profiles]-Sektion: immer alle konfigurierten Server.
Permissions
[permissions]
read = "auto"
glob = "auto"
grep = "auto"
write = "ask"
edit = "ask"
bash = "ask"
deny_paths = [".git/**", "**/.env", "**/id_rsa*"]
deny_bash = ["rm -rf /", "git push --force*"]
| Modus | Verhalten |
|---|---|
auto (Default) |
läuft ohne Rückfrage |
ask |
TUI: Rückfrage-Block im Transkript, y/Y erlaubt, jede andere Taste lehnt ab. Print-Modus: harter Fehler |
deny |
läuft nie |
deny_paths/deny_bashüberstimmenauto/askimmer.deny_pathsgilt fürread/write/edit/grep(path-Feld),deny_bashmatcht den Befehlstext (Glob/Teilstring).- Tools ohne eigenes Config-Feld (MCP,
todo,read_skill) laufen immerauto. - Mehrere gleichzeitige Tool-Aufrufe: Rückfragen laufen nacheinander vor dem parallelen Start der erlaubten Calls — nie zwei Dialoge gleichzeitig.
question-Tool
Gleiche Rückfrage-Mechanik als eigenständiges Tool: Modell oder Skill-Anweisung stellt eine freie Frage (optional mit Vorschlägen), Antwort kommt als Tool-Ergebnis zurück. TUI: Block im Transkript, nächste Eingabe zählt als Antwort statt neuer Nachricht/Kommando. Print-Modus: sofortiger Fehler (kein Blockieren, Print läuft headless).
Alle CLI-Kommandos
nub init .nub/config.toml + AGENTS.md anlegen, falls nicht vorhanden
nub neue Session starten (TUI im Terminal)
nub -p Print-Modus erzwingen
nub resume <session-id> Session fortsetzen
nub resume <session-id> --branch <node-id>
von einem früheren Knoten fortsetzen (Rewind)
nub sessions Sessions auflisten
nub map REPOMAP.md erzeugen/aktualisieren
nub context geladenen Kontext anzeigen
nub compact <session-id> Compaction erzwingen
nub skills gefundene Skills auflisten
nub mcp MCP-Server verbinden, Tools auflisten
nub [resume ...] --profile <p> nur MCP-Server aus profiles.<p> verbinden
Bekannte Grenzen
- Bilder werden nicht verarbeitet, auch wenn der Endpoint sie unterstützt.
- Permissions/
deny_pathsgelten nur für die sechs eingebauten Datei-/ Bash-Tools — MCP-Tools laufen immerauto. - Compaction nutzt immer dasselbe Modell wie die Session.
- MCP-Server reconnecten nicht zur Laufzeit (Neustart nötig); nur Tools angebunden, keine Prompts/Resources.
- Skills müssen von Hand angelegt werden.
Ausführlichere Liste: docs/TESTING.md.
Mitentwickeln
Build, Tests, manuelle Testrezepte: docs/TESTING.md. Architektur/Design-Entscheidungen: docs/KONZEPT.md.