SLOPSHOPPER

prompt-boost

Knopf ueber dem Eingabefeld: schreibt den Prompt-Entwurf besser um (passende Skills, offene Entscheidungen, Zielbild), ersetzt nur den Entwurf, sendet nicht…

newbandcommandtoastpromptmodel
v0.1.0MITupdated 2026-10-12broening/claude-mods/prompt-boost
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · prompt-boost
› fix the failing auth test and add an audit log call ⏺ Read(src/auth.ts) ⎿ Read 6 lines ⏺ Update(src/auth.ts) ⎿ Added 2 lines, removed 1 line ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ● Done. refresh now rejects expired claims and logs an audit event. ✻ Worked for 42s · done 4:20 PM › /verbessern ⎿ prompt-boost: Prompt-Verbesserer ist aus. ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts
README

claude-mods

Mods für Claude Code. Jeder Mod ist ein kleines Plugin aus TypeScript-Hooks. Er ändert Claude Code von innen: ein Band über dem Eingabefeld, ein Seitenfenster, eigene Slash-Befehle oder eine Rückfrage vor Tool-Aufrufen.

Mods prüfen

Die Mods

ModWas er machtBefehl
cache-countdownZeigt über dem Prompt, wie lange der Prompt-Cache (1 Stunde) noch warm ist: grün, orange ab 15 Min, rot wenn kalt. Knopf Compact und Schalter Auto: verdichtet 2 Minuten vor kalt von selbst./compact-cache
blast-radiusHält gefährliche Shell-Befehle (Bash und PowerShell) an, zum Beispiel rm -rf, Remove-Item -Recurse, git reset --hard, git push --force, DROP TABLE. Fragt vor dem Ausführen nach. Standard aus./ward an/aus
next-stepsSchlägt nach jeder Antwort drei nächste Schritte vor. Ein Klick schickt den Schritt als Prompt./vorschlaege
todo-listArbeitsliste im Seitenfenster. Aufgaben einreihen, ohne Claude zu unterbrechen. Mit Auto arbeitet Claude sie nacheinander ab./todo
annahmenZeigt nach jeder Antwort die Annahmen, die Claude still getroffen hat. Du markierst sie als richtig oder falsch. Korrektur senden schickt die falschen als neuen Auftrag./annahmen an/aus
prompt-boostKnopf Prompt verbessern über dem Eingabefeld. Schreibt deinen Entwurf besser um (passende Skills, offene Fragen, Zielbild). Ersetzt nur den Entwurf, sendet nichts. rueckgaengig holt den alten Text zurück./verbessern an/aus
sitzungs-waechterWarnt über dem Prompt, wenn eine zweite Claude-Code-Sitzung im selben Ordner läuft. Dann können sich Dateien überschreiben. ok blendet die Warnung aus.–
grillStellt bis zu 5 Rückfragen zu deinem Plan, eine nach der anderen, mit Antwortknöpfen und KI-Vorschlag./grill [thema]

Hinweis: next-steps, annahmen, prompt-boost und grill rufen das Modell zusätzlich auf ($.model.fork). Das kostet etwas Kontingent. next-steps und annahmen teilen sich eine Anfrage pro Antwort; annahmen braucht dafür next-steps.

Voraussetzungen

  • Claude Code mit Mod-Unterstützung (getestet mit 2.1.287)
  • Git
  • Windows: PowerShell 5.1 oder neuer. macOS und Linux: siehe unten.

Installieren (neuer Rechner)

Unter Windows in PowerShell:

git clone https://github.com/broening/claude-mods.git "$env:USERPROFILE\.claude\mods"
& "$env:USERPROFILE\.claude\mods\install.ps1"

Danach Claude Code neu starten. Das Skript trägt alle Mod-Ordner in ~/.claude/settings.json unter env.CLAUDE_CODE_PLUGIN_DIRS ein. Andere Einstellungen bleiben. Eine Sicherung liegt danach in settings.json.bak.

Nur einzelne Mods:

& "$env:USERPROFILE\.claude\mods\install.ps1" -Only cache-countdown,blast-radius

macOS und Linux: Repo nach ~/.claude/mods klonen und in ~/.claude/settings.json eintragen (Trennzeichen :):

{
  "env": {
    "CLAUDE_CODE_PLUGIN_DIRS": "/home/<du>/.claude/mods/cache-countdown:/home/<du>/.claude/mods/blast-radius"
  }
}

Alternative: als Plugin-Marktplatz

Das Repo ist auch ein Claude-Code-Marktplatz (.claude-plugin/marketplace.json). In Claude Code:

/plugin marketplace add broening/claude-mods
/plugin install cache-countdown@claude-mods

Nicht beides gleichzeitig nutzen, sonst lädt ein Mod doppelt.

Aktualisieren

git -C "$env:USERPROFILE\.claude\mods" pull

Danach Claude Code neu starten. Kommt ein neuer Mod dazu, install.ps1 noch einmal ausführen.

Aufbau eines Mods

<mod>/
  .claude-plugin/plugin.json   Name, Version, Beschreibung
  hooks/hooks.json             { "modules": ["./register.tsx"] }
  hooks/register.tsx           die Hooks: export const register: Register = on => { ... }
  types/index.d.ts             Vertrag für den gespeicherten Zustand ($.state)
  tsconfig.json

.claude-plugin/types/ erzeugt Claude Code bei jedem Build selbst. Der Ordner ist nicht im Repo.

Entwickeln

  1. Mod in seinem Ordner ändern. In einer laufenden Sitzung lädt Claude Code ihn nach dem nächsten Turn neu.
  2. Prüfen:
   claude plugin validate .\cache-countdown
  1. version in plugin.json erhöhen und einen Eintrag in CHANGELOG.md schreiben.
  2. Committen und pushen. GitHub Actions prüft alle Mods bei jedem Push.

Neue Mods am einfachsten mit dem Claude-Code-Skill plugin-authoring bauen.

Lizenz

MIT

Source 2 files
hooks/register.tsx 187 lines
1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4// Prompt-Verbesserer als Band UEBER dem Eingabefeld. Steht ein Entwurf im
5// Eingabefeld, zeigt das Band den Knopf "Prompt verbessern". Der Knopf fragt
6// Claude (ueber $.model.fork, kennt also Gespraech, Projekt und Skill-Liste),
7// den Entwurf besser zu schreiben: passende Skills/Agents nennen, Entscheidungen
8// vorher klaeren, Zielbild beschreiben. Das Ergebnis ERSETZT nur den Entwurf im
9// Eingabefeld; gesendet wird nichts. "rueckgaengig" holt den alten Entwurf
10// zurueck. Mit "/verbessern" an/aus.
11
12const FORK_PROMPT_HEAD = [
13  'Der Nutzer hat im Eingabefeld diesen Prompt-Entwurf getippt, aber NOCH NICHT',
14  'gesendet. Fuehre ihn NICHT aus. Schreibe ihn nur als besseren Prompt an dich',
15  'selbst um, in der Sprache des Entwurfs:',
16  '- Behalte Absicht und alle Fakten des Entwurfs. Erfinde nichts dazu.',
17  '- Nutze, was du aus dem bisherigen Gespraech und dem Projekt weisst.',
18  '- Nenne die Skills (als /name) und Agent-Typen aus deiner Liste, die wirklich',
19  '  passen. Keine, wenn keine passt.',
20  '- Liste die wichtigen Entscheidungen, die du vor dem Start fragen sollst.',
21  '- Beschreibe kurz, woran man erkennt, dass die Aufgabe fertig ist.',
22  '- Hoechstens etwa 15 kurze Zeilen.',
23  'Antworte NUR mit dem neuen Prompt-Text: ohne Einleitung, ohne Codeblock,',
24  'ohne Erklaerung. Nutze keine Werkzeuge.',
25  '',
26  'Entwurf:',
27].join('\n')
28
29const hasDraft = atom({ plugin: 'prompt-boost', key: 'hasDraft' } as const, false)
30const busy = atom({ plugin: 'prompt-boost', key: 'busy' } as const, false)
31// Der Entwurf vor dem Umschreiben; '' = nichts rueckgaengig zu machen.
32const original = atom({ plugin: 'prompt-boost', key: 'original' } as const, '')
33const enabled = atom({ plugin: 'prompt-boost', key: 'enabled' } as const, true)
34// Meldet das Eingabefeld Tippen (prompt.edit)? Manche Oberflaechen tun das
35// nicht; dann steht der Knopf immer da und prueft beim Druecken selbst.
36const editSeen = atom({ plugin: 'prompt-boost', key: 'editSeen' } as const, false)
37
38// Zaehler, damit eine alte Antwort nach "abbrechen" nichts mehr ersetzt.
39let generation = 0
40
41// Antwort des Forks saeubern: Codeblock-Zaeune und Rahmen-Leerzeilen weg.
42export function cleanRewrite(text: string): string {
43  let t = text.trim()
44  const fence = /^```[a-zA-Z]*\r?\n([\s\S]*?)\r?\n```$/.exec(t)
45  if (fence?.[1] !== undefined) t = fence[1].trim()
46  t = t.replace(/^(?:verbesserter prompt|neuer prompt|prompt)\s*:\s*\n/i, '')
47
48  return t.trim()
49}
50
51export function buildForkPrompt(draft: string): string {
52  return FORK_PROMPT_HEAD + '\n<<<\n' + draft + '\n>>>'
53}
54
55async function boost($: EngineInterface) {
56  const { text: draft } = await $.prompt.read()
57  if (!draft.trim()) {
58    $.ui.toast('Prompt verbessern: Erst einen Entwurf ins Eingabefeld tippen.')
59    return
60  }
61  const mine = ++generation
62  await update($, busy, () => true)
63
64  let rewrite = ''
65  try {
66    const r = await $.model.fork({ prompt: buildForkPrompt(draft) })
67    if (r.isAnswered) {
68      rewrite = cleanRewrite(r.text)
69    } else if (r.reason === 'api-error') {
70      $.ui.toast('Prompt verbessern: Fehler bei der Anfrage.')
71    }
72  } catch {
73    $.ui.toast('Prompt verbessern: Anfrage fehlgeschlagen.')
74  }
75
76  if (mine !== generation) return
77  await update($, busy, () => false)
78  if (!rewrite) return
79
80  // Hat der Nutzer inzwischen weitergetippt, nichts ueberschreiben.
81  const { text: now } = await $.prompt.read()
82  if (now !== draft) {
83    $.ui.toast('Prompt verbessern: Entwurf hat sich geaendert, nichts ersetzt.')
84    return
85  }
86  const filled = await $.prompt.fill({ text: rewrite, mode: 'replace' })
87  if (filled.isFilled) {
88    await update($, original, () => draft)
89  } else {
90    $.ui.toast('Prompt verbessern: Eingabefeld nimmt gerade keinen Text an.')
91  }
92}
93
94async function cancel($: EngineInterface) {
95  generation++
96  await update($, busy, () => false)
97}
98
99async function undo($: EngineInterface) {
100  const old = await read($, original)
101  if (!old) return
102  await update($, original, () => '')
103  await $.prompt.fill({ text: old, mode: 'replace' })
104}
105
106async function toggleEnabled($: EngineInterface) {
107  const next = !(await read($, enabled))
108  await update($, enabled, () => next)
109  await $.store.set('enabled', next)
110  if (!next) {
111    await cancel($)
112    await update($, original, () => '')
113  }
114}
115
116export const register: Register = on => {
117  on('session.start', async ($, e, next) => {
118    const saved = await $.store.get('enabled')
119    await update($, enabled, () => saved !== false)
120    await $.command.register({
121      name: 'verbessern',
122      description: 'Prompt-Verbesserer ueber dem Eingabefeld an- oder ausschalten',
123    })
124
125    return next(e)
126  })
127
128  on('command.run', { command: 'verbessern' }, async $ => {
129    await toggleEnabled($)
130    const isOn = await read($, enabled)
131
132    return { text: isOn ? 'Prompt-Verbesserer ist an.' : 'Prompt-Verbesserer ist aus.' }
133  })
134
135  // Merken, ob ein Entwurf im Eingabefeld steht (nur bei Wechsel schreiben).
136  on('prompt.edit', async ($, e, next) => {
137    const r = await next(e)
138    if (!(await read($, editSeen))) await update($, editSeen, () => true)
139    const has = r.text.trim().length > 0
140    if ((await read($, hasDraft)) !== has) await update($, hasDraft, () => has)
141
142    return r
143  })
144
145  // Gesendet: Rueckgaengig gilt nicht mehr, Entwurf ist weg.
146  on('prompt.submit', async ($, e, next) => {
147    await update($, original, () => '')
148    await update($, hasDraft, () => false)
149
150    return next(e)
151  })
152
153  // Nur EIN Band ueber dem Prompt: darunterliegendes Band durchreichen, unseres
154  // anhaengen.
155  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
156    const below = await next(e)
157    if (e.props?.hasSurvey) return below
158    if (!(await read($, enabled))) return below
159
160    const isBusy = await read($, busy)
161    const draft = (await read($, hasDraft)) || !(await read($, editSeen))
162    const old = await read($, original)
163    if (!isBusy && !draft && !old) return below
164
165    const { Box, Text, Button } = $.ui.resolve(e)
166
167    return (
168      <Box flexDirection="column">
169        {below}
170        <Box gap={1}>
171          <Text color="magenta">{'✨'}</Text>
172          {isBusy ? <Text dimColor>verbessert den Prompt ...</Text> : null}
173          {isBusy ? (
174            <Button key="cancel" label="abbrechen" onPress={() => void cancel($)} />
175          ) : null}
176          {!isBusy && draft ? (
177            <Button key="boost" label="Prompt verbessern" onPress={() => void boost($)} />
178          ) : null}
179          {!isBusy && old ? (
180            <Button key="undo" label="rueckgaengig" onPress={() => void undo($)} />
181          ) : null}
182        </Box>
183      </Box>
184    )
185  })
186}
187
types/index.d.ts 12 lines
1declare module 'claude-code' {
2  interface PluginState {
3    'prompt-boost': {
4      hasDraft: boolean
5      busy: boolean
6      original: string
7      enabled: boolean
8      editSeen: boolean
9    }
10  }
11}
12