- .claude/agents/planer.md - .claude/settings.json - .claude/workflows/executer-welle.js - .claude/workflows/plankritik.js - .claude/workflows/planung.js - .claude/workflows/quorum.js - .claude/workflows/verbrauch.js - .claude/workflows/welle-mit-pruefung.js - .vault-tools/shell-wache/ENTWURF.md - .vault-tools/shell-wache/docs/code/shell_wache.md - .vault-tools/shell-wache/docs/plans/2026-10-30-shell-wache/00-uebersicht.md - .vault-tools/shell-wache/docs/plans/2026-10-30-shell-wache/task-01-shell-wache.md - … und 34 weitere Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
96 lines
3.9 KiB
Python
96 lines
3.9 KiB
Python
"""Listet die Sitzungs-Scratchpads eines Projekts mit Größe, Titel und letzter Aktivität des Transkripts.
|
|
|
|
Ersteller: Pascal Michel
|
|
Erstellt: 2026-10-30
|
|
Doku: LIESMICH.md in diesem Ordner
|
|
|
|
Nur lesend. Gibt Sitzungskennung (acht Zeichen), Titel, Größe und Alter aus, keine Dateiinhalte.
|
|
Was es nicht sieht: welche Sitzungen gerade laufen. Die nennst du mit --laufend (Kennungsanfänge der
|
|
Claude-Code-Sitzung, nicht die local_-Kennung der App; Zuordnung nur über den Titel). Das Alter kommt
|
|
aus der mtime des Transkripts, die nach einem App-Neustart für viele Sitzungen frisch ist
|
|
(Harness-Erinnerung transkript-usage-groesster-wert-je-nachricht).
|
|
Aufruf: python -I -X utf8 scratchpads.py [--scratch <Ordner>] [--projekt <Ordner>] [--laufend id8,id8] [--ab-mb 50]
|
|
"""
|
|
import argparse
|
|
import collections
|
|
import json
|
|
import os
|
|
import sys
|
|
import time
|
|
|
|
|
|
def groesse_kb(p):
|
|
total = 0
|
|
for root, dirs, files in os.walk(p):
|
|
# Junctions nicht betreten, sonst zählt ein verlinkter Ordner doppelt (os.path.isjunction ab Python 3.12).
|
|
dirs[:] = [d for d in dirs if not getattr(os.path, "isjunction", lambda _: False)(os.path.join(root, d))]
|
|
for f in files:
|
|
try:
|
|
total += os.lstat(os.path.join(root, f)).st_size
|
|
except OSError:
|
|
pass
|
|
return total // 1024
|
|
|
|
|
|
def titel_aus(ct):
|
|
try:
|
|
with open(ct, encoding="utf-8") as f:
|
|
d = json.load(f)
|
|
except (OSError, ValueError):
|
|
return None
|
|
return (d.get("customTitle") or d.get("title")) if isinstance(d, dict) else None
|
|
|
|
|
|
def main(argv=None):
|
|
ap = argparse.ArgumentParser(description="Sitzungs-Scratchpads mit Größe und letzter Aktivität")
|
|
ap.add_argument("--scratch", default=r"D:\ClaudeData\claude\D--Claude")
|
|
ap.add_argument("--projekt", default=r"D:\ClaudeData\config\projects\D--Claude")
|
|
ap.add_argument("--laufend", default="", help="kommagetrennte Kennungsanfänge laufender Sitzungen")
|
|
ap.add_argument("--ab-mb", type=float, default=50, help="nur Scratchpads ab dieser Größe einzeln auflisten")
|
|
a = ap.parse_args(argv)
|
|
if not os.path.isdir(a.scratch) or not os.path.isdir(a.projekt):
|
|
print(f"Ordner fehlt: {a.scratch if not os.path.isdir(a.scratch) else a.projekt}")
|
|
return 2
|
|
laufend = {x.strip()[:8] for x in a.laufend.split(",") if x.strip()}
|
|
jetzt = time.time()
|
|
zeilen = []
|
|
for name in os.listdir(a.scratch):
|
|
d = os.path.join(a.scratch, name)
|
|
if not os.path.isdir(d):
|
|
continue
|
|
tr = os.path.join(a.projekt, name + ".jsonl")
|
|
letzte = os.path.getmtime(tr) if os.path.exists(tr) else None
|
|
titel = titel_aus(os.path.join(a.projekt, name, "custom-title.json"))
|
|
tage = (jetzt - letzte) / 86400 if letzte else None
|
|
zeilen.append((groesse_kb(d), name, titel, tage, letzte is not None))
|
|
|
|
zeilen.sort(reverse=True)
|
|
print("| Sitzung | Titel | Scratchpad MB | letzte Transkript-Aktivität | Klasse |")
|
|
print("|---|---|---|---|---|")
|
|
summen = collections.Counter(); anzahl = collections.Counter()
|
|
for kb, name, titel, tage, hat_tr in zeilen:
|
|
if name[:8] in laufend:
|
|
klasse = "läuft"
|
|
elif not hat_tr:
|
|
klasse = "kein Transkript"
|
|
elif tage <= 7:
|
|
klasse = "aktiv ≤ 7 Tage"
|
|
elif tage <= 14:
|
|
klasse = "ruhend 7-14 Tage"
|
|
else:
|
|
klasse = "ruhend > 14 Tage"
|
|
summen[klasse] += kb; anzahl[klasse] += 1
|
|
if kb > a.ab_mb * 1024:
|
|
print(f"| {name[:8]} | {(titel or '-')[:45]} | {kb/1024:.0f} | {('vor %.1f Tagen' % tage) if tage is not None else '-'} | {klasse} |")
|
|
print()
|
|
print("| Klasse | Sitzungen | GB |")
|
|
print("|---|---|---|")
|
|
for k in summen:
|
|
print(f"| {k} | {anzahl[k]} | {summen[k]/1024/1024:.1f} |")
|
|
print(f"| Summe | {sum(anzahl.values())} | {sum(summen.values())/1024/1024:.1f} |")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|