Barra sopra il prompt che si svuota col tempo: quanto resta dell'ora di prompt cache dall'ultima richiesta

claude-code-mods è un marketplace di mod per Claude Code che ti permette di aggiungere all'interfaccia una barra della prompt cache, i prossimi passi a fine turno, un pannello di bottoni rapidi e il replay delle modifiche. Ogni mod è un plugin indipendente, installabile singolarmente con un comando.
⏳ cache-meter — una riga sopra il prompt con una barra che si svuota nel tempo: indica quanto resta dell'ora di prompt cache dall'ultima richiesta della conversazione principale. Verde oltre i 20 minuti, gialla oltre i 5, rossa sotto; allo scadere segnala che la richiesta successiva riscriverà la cache. Le richieste dei subagent non rinnovano la barra, perché usano una cache separata.
➡️ next-steps — a fine turno propone sopra il prompt due bottoni con i prossimi passi più naturali della conversazione, più un terzo bottone Replay. Premendo un passo, il prompt corrispondente viene inviato come se lo avessi scritto tu. I passi sono generati con una richiesta al modello a ogni fine turno, che consuma token.
🎛️ quick-buttons — un pannello laterale con un bottone per ogni comando ricorrente. Alla prima sessione dopo l'installazione la mod ti chiede quali skill e comandi vuoi come bottoni, elencando quelli presenti nella tua sessione; la scelta resta salvata tra le sessioni e puoi modificarla in qualsiasi momento.
⏪ replay-theater — registra le modifiche ai file dell'ultimo turno e le mostra in un pannello, un diff alla volta. È una variante della mod di esempio pubblicata da Anthropic in claude-code-playground, distribuita con licenza Apache-2.0; le differenze sono descritte in replay-theater/README.md.
claude --version.Una mod è codice eseguito con i tuoi permessi: può leggere e scrivere file, avviare processi e vedere prompt e tool call della sessione. Il sorgente di ogni mod è in hooks/, poche decine di righe: leggilo prima dell'installazione.
claude plugin marketplace add DarioFontanel/claude-code-mods
claude plugin install cache-meter@dario-mods
claude plugin install next-steps@dario-mods
claude plugin install quick-buttons@dario-mods
claude plugin install replay-theater@dario-mods
next-steps dichiara replay-theater come dipendenza: installandola, replay-theater viene installata automaticamente.
claude.Verifica: apri /plugin — sotto i tab compare la riga con le mod attive, ad esempio 4 mods active.
Gli stessi comandi sono disponibili dall'interno di una sessione come /plugin marketplace add e /plugin install. Per provare una mod in una sola sessione senza installarla, clona la repo e avvia claude --plugin-dir ./claude-code-mods/cache-meter.
Per disattivare una mod, disabilitala o disinstallala dal tab Installed di /plugin.
/replay — apre il pannello di replay sull'ultimo turno che ha modificato file. Nel pannello: n passo successivo, p passo precedente, c o Esc chiusura./azioni — apre il pannello di quick-buttons. Su un terminale di almeno 144 colonne il pannello si apre da solo all'avvio della sessione. Ogni bottone ha come tasto rapido la prima lettera libera del nome del comando./azioni config — riapre la scelta dei bottoni. Nel pannello di scelta: scrivi nel campo Cerca per filtrare l'elenco, spostati con le frecce, Invio aggiunge o toglie un comando, s salva, n e p cambiano pagina. Puoi scegliere fino a 9 comandi.ctrl+x poi Tab — sposta il focus sulla banda sopra il prompt. Da lì 1 e 2 inviano i passi proposti da next-steps, 3 apre il replay.Bottoni di quick-buttons — si scelgono dal pannello, con /azioni config, senza modificare il codice. L'elenco propone skill, comandi personalizzati e comandi di altri plugin; i comandi integrati di Claude Code sono esclusi. Un comando scelto che una sessione non ha non viene mostrato in quella sessione.
Durata della cache in cache-meter — la costante TTL_MS in cache-meter/hooks/register.js vale un'ora, la durata della prompt cache negli abbonamenti Claude. Se la tua cache dura 5 minuti, imposta 5 * 60 * 1000.
Lingua di next-steps — la richiesta al modello è la costante ASK in next-steps/hooks/register.tsx. I prompt proposti seguono la lingua della conversazione.
Per modificare una mod, clona la repo e caricala con claude --plugin-dir: ogni salvataggio ricarica il modulo nella sessione aperta.
claude-code-mods/
├── .claude-plugin/marketplace.json # elenco delle mod installabili
├── cache-meter/
├── next-steps/
├── quick-buttons/
└── replay-theater/ # Apache-2.0, con LICENSE propria
Ogni cartella è un plugin completo:
.claude-plugin/plugin.json — nome, versione e descrizione.hooks/hooks.json — il modulo da caricare.hooks/register.* — gli hook della mod.tests/ — i test, eseguibili con claude plugin test ./<mod>.claude plugin validate ./<mod> elenca gli eventi intercettati e le chiamate al motore di ciascuna mod.
Designed by Dario Fontanel, PhD
Aiuto PMI italiane ad integrare l'intelligenza artificiale per automatizzare i lavori ripetitivi, abbattere i costi e guadagnare tempo per crescere.
Licenza: MIT — replay-theater è distribuita con licenza Apache-2.0.
hooks/register.js 79 lines1// Quanto dura la prompt cache dall'ultima richiesta che l'ha letta o scritta
2const TTL_MS = 60 * 60 * 1000
3// Ogni quanto la barra si ridisegna da sola
4const TICK_MS = 30 * 1000
5
6// L'istante dell'ultima richiesta della conversazione principale: da lì riparte l'ora
7let lastAt = null
8// L'ora letta all'ultimo tick o all'ultima richiesta
9let now = 0
10// Il timer che fa scorrere la barra, avviato alla prima richiesta
11let ticking = null
12
13// Verde finché c'è margine, rosso quando la cache sta per scadere
14function leftColor(minutes) {
15 if (minutes > 20) return 'green'
16 if (minutes > 5) return 'yellow'
17 return 'red'
18}
19
20export function register(on) {
21 // Una richiesta al modello rinnova la cache: l'ora riparte dal suo risultato
22 on('turn.step', async function* ($, e, next) {
23 const result = yield* next(e)
24 // Solo la conversazione principale: i subagent hanno una cache loro
25 if (!e.agentId && result.usage) {
26 lastAt = now = await $.clock.now()
27 ticking ??= $.clock.every(TICK_MS, async () => {
28 now = await $.clock.now()
29 $.ui.invalidate('ui.render')
30 })
31 $.ui.invalidate('ui.render')
32 }
33 return result
34 })
35
36 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
37 // Quello che disegnano le altre mod nella banda resta sotto la nostra riga
38 const theirs = await next(e)
39 const { Box, Text } = $.ui.resolve(e)
40 const dim = (text) => Text({ dimColor: true, children: [text] })
41 const withTheirs = (line) => (theirs ? Box({ flexDirection: 'column', children: [line, theirs] }) : line)
42
43 if (lastAt === null) return withTheirs(dim('cache · in attesa della prima richiesta'))
44
45 const width = e.props.bodyColumns >= 110 ? 24 : 12
46 const leftMs = Math.max(0, TTL_MS - (now - lastAt))
47
48 if (leftMs === 0) {
49 return withTheirs(
50 Box({
51 flexDirection: 'row',
52 children: [
53 dim('cache ' + '░'.repeat(width) + ' '),
54 Text({ color: 'red', children: ['scaduta'] }),
55 dim(' · la prossima richiesta la riscrive'),
56 ],
57 }),
58 )
59 }
60
61 // La parte piena è il tempo che resta: la barra si svuota da destra
62 const minutes = Math.ceil(leftMs / 60000)
63 const full = Math.ceil((leftMs / TTL_MS) * width)
64 const color = leftColor(minutes)
65 return withTheirs(
66 Box({
67 flexDirection: 'row',
68 children: [
69 dim('cache '),
70 Text({ color, children: ['█'.repeat(full)] }),
71 dim('░'.repeat(width - full) + ' '),
72 Text({ color, children: [minutes + ' min rimasti'] }),
73 dim(' · ' + (60 - minutes) + ' min dall\'ultima richiesta'),
74 ],
75 }),
76 )
77 })
78}
79