Quanto ti resta, in parole semplici: i limiti del tuo piano Claude e quanto è piena la conversazione, sopra il prompt. /benzina la mostra o la nasconde.

Cinque mod gratuite per chi usa Claude Code per costruire i propri progetti (un sito, un'app, un'automazione) anche senza saper programmare.
| Mod | In una riga | |
|---|---|---|
| 💾 | save-point | Claude ha rotto qualcosa? Torni a quando funzionava con un clic. |
| 💡 | cosa-hai-fatto | Dopo ogni modifica ti spiega in parole semplici cosa ha fatto Claude e come provarlo. |
| ⛽ | benzina | Vedi quanto ti resta del piano Claude prima che si fermi, e quando si ricarica. |
| ⚡ | quick-replies | Pulsanti per le risposte che scrivi sempre: "Continua", "Procedi", "Non funziona, controlla tu". |
| 🌐 | localhost | Vedi le app che hai acceso sul computer, aprile nel browser o spegnile. |
Puoi installarne una sola, alcune o tutte e cinque: sono indipendenti.
Una mod è un piccolo plugin che cambia come Claude Code si comporta e cosa ti mostra: una riga sopra il punto dove scrivi, un pannello laterale, un pulsante, un avviso. Non cambia il modello e non legge niente fuori dal tuo computer: gira dentro Claude Code, sul tuo Mac o PC.
Dove le vedi:
/salvataggi (save-point) e /localhost. claude --version ` Se è più vecchio, aggiornalo con: ` claude update ``xcode-select --install. Su Linux: installa il pacchetto git. cd percorso/del/tuo/progetto claude `` /plugin install save-point --marketplace cavallinilorenzo/claude-code-mods ` ` /plugin install cosa-hai-fatto --marketplace cavallinilorenzo/claude-code-mods ` ` /plugin install benzina --marketplace cavallinilorenzo/claude-code-mods ` ` /plugin install quick-replies --marketplace cavallinilorenzo/claude-code-mods ` ` /plugin install localhost --marketplace cavallinilorenzo/claude-code-mods ``Add marketplace?: rispondi y.Installed <nome>. Plugin is now active. La mod è già attiva, non serve riavviare.In alternativa, dal terminale normale (fuori da Claude Code):
claude plugin marketplace add cavallinilorenzo/claude-code-mods
claude plugin install save-point@lorenzo-mods
claude plugin install cosa-hai-fatto@lorenzo-mods
claude plugin install benzina@lorenzo-mods
claude plugin install quick-replies@lorenzo-mods
claude plugin install localhost@lorenzo-mods
Il problema: chiedi una modifica, Claude cambia dieci file e l'app non parte più. Non sai cosa ha toccato e non sai come tornare indietro.
Cosa fa: ogni volta che Claude sta per modificare i file, save-point salva com'era il progetto un attimo prima. Lo fa da solo, una volta per ogni tua richiesta, e il salvataggio prende il nome della richiesta.
Come si usa:
| Comando | Cosa succede |
|---|---|
/salvataggi | Apre l'elenco dei salvataggi. Accanto a ognuno c'è Torna qui: lo premi, confermi con Sì, torna qui e tutti i file tornano com'erano in quel momento. |
/salva | Salva adesso, a mano. |
/salva funziona il login | Salva adesso con un nome tuo: comparirà come ⭐ funziona il login. |
Cosa vedi in /salvataggi:
oggi 15:42 Prima di: «aggiungi il carrello» [ Torna qui ]
oggi 15:10 ⭐ funziona il login [ Torna qui ]
oggi 14:31 Prima di: «cambia i colori del sito» [ Torna qui ]
Da sapere:
~/.claude/save-points/.node_modules, .venv, venv, __pycache__, .next, dist, build, target, .cache), i file .log e i file che il tuo progetto ignora già con .gitignore.~/.claude/save-points/.Il problema: Claude risponde con nomi di file, funzioni e comandi. Tu vuoi solo sapere cosa è cambiato e se funziona.
Cosa fa: quando una risposta di Claude ha modificato dei file, sopra il prompt compare un riassunto in parole semplici, senza gergo tecnico, con un passo concreto per provarlo.
💡 In breve: Ora i clienti possono pagare con la carta e il carrello mostra le spese di spedizione.
👉 Prova: aggiungi un prodotto al carrello e premi «Paga».
[ Spiegamelo meglio ] [ Nascondi ]
Da sapere:
english, español).Il problema: stai lavorando e all'improvviso Claude si ferma perché hai finito il limite del tuo piano. Oppure la chat è così lunga che Claude inizia a dimenticare le cose.
Cosa fa: mostra sopra il prompt quanto ti resta, come l'indicatore della benzina:
⛽ 5 ore ▰▰▰▱▱▱▱▱ 38% · ricarica alle 16:40 Settimana ▰▰▰▰▰▰▱▱ 80% Chat ▰▰▰▰▰▱▱▱ 64%
Quando serve ti dà un consiglio in chiaro:
Ti avvisa anche con una notifica quando superi l'80% e il 95% di un limite.
| Comando | Cosa succede |
|---|---|
/benzina | Nasconde l'indicatore, o lo fa ricomparire. La scelta resta salvata. |
Da sapere: i limiti delle 5 ore e della settimana compaiono solo con un abbonamento Claude (Pro o Max) e dopo la prima risposta di Claude. Se usi una chiave API vedi solo la Chat.
Il problema: scrivi cento volte al giorno "continua", "procedi", "ok va bene".
Cosa fa: dopo ogni risposta di Claude, sopra il prompt compaiono dei pulsanti con le risposte che usi sempre. Un clic e la risposta parte.
[ Continua ] [ Procedi ] [ Ok a tutte le tue raccomandazioni ] [ Non funziona, controlla tu e sistemalo ]
Le risposte si cambiano dalle impostazioni: scrivile separate da |, fino a 9. Ad esempio:
Continua|Procedi|Spiegamelo in parole semplici|Avviamelo così lo provo
Il problema: Claude ti dice "l'app è su localhost:5173". Ma quale? Quante ne hai accese? Come le spegni?
Cosa fa: /localhost apre un pannello con tutte le app che hai acceso sul computer (vite, next, django, flask, uvicorn…), la porta, la cartella da cui sono partite e due pulsanti:
:5173 node ~/progetti/negozio apri [ ferma ]
:8000 Python ~/progetti/negozio/backend apri [ ferma ]
:3000 node ~/progetti/vecchio-test apri [ ferma ]
[ Ferma quelli di questo progetto (2) ] [ Ferma tutti ] [ Aggiorna ]
Da sapere: funziona su Mac e Linux.
Due mod hanno impostazioni:
| Mod | Impostazione | Default | ||||
|---|---|---|---|---|---|---|
| quick-replies | Risposte rapide (separate da `\ | `) | `Continua\ | Procedi\ | Ok a tutte le tue raccomandazioni\ | Non funziona, controlla tu e sistemalo` |
| cosa-hai-fatto | Lingua delle spiegazioni | italiano |
Le scegli la prima volta, nella schermata che compare durante l'installazione. Per cambiarle dopo, dal terminale:
echo '{"replies": "Continua|Procedi|Spiegamelo in parole semplici"}' | claude plugin configure quick-replies@lorenzo-mods --values-stdin
echo '{"language": "english"}' | claude plugin configure cosa-hai-fatto@lorenzo-mods --values-stdin
Per vedere i valori attuali: claude plugin configure quick-replies@lorenzo-mods.
Dal terminale:
claude plugin update save-point@lorenzo-mods # prende l'ultima versione
claude plugin disable benzina@lorenzo-mods # la spegne senza toglierla
claude plugin enable benzina@lorenzo-mods # la riaccende
claude plugin uninstall localhost@lorenzo-mods # la toglie
Dentro Claude Code, /plugin apre lo stesso menu con i pulsanti.
Devo saper programmare? No. Si installano incollando una riga e si usano con pulsanti e comandi in italiano.
Costano qualcosa? Le mod sono gratis. Solo cosa-hai-fatto fa una piccola chiamata a Claude Haiku dopo le risposte che modificano file, che conta sul tuo piano Claude come qualsiasi altro messaggio.
Mandano i miei dati da qualche parte? No. Lavorano sul tuo computer. save-point salva i file in ~/.claude/save-points/. cosa-hai-fatto manda a Claude (come fa già Claude Code) la tua richiesta, i nomi dei file modificati e la risposta di Claude, per scrivere il riassunto. Il codice è tutto in questa pagina: puoi leggerlo.
save-point sostituisce git o GitHub? No. È una rete di sicurezza per tornare indietro mentre lavori con Claude. Se vuoi pubblicare il progetto o lavorarci con altre persone, git e GitHub restano lo strumento giusto.
E il tasto Esc due volte di Claude Code ("rewind")? Il rewind di Claude Code annulla le modifiche fatte con i suoi strumenti di modifica dei file. save-point salva tutta la cartella, quindi copre anche quello che cambia per altre vie (comandi, installazioni, script), e i salvataggi non dipendono dalla conversazione: li ritrovi anche in una chat nuova.
Funzionano nell'app desktop? Sì, nella scheda Code. Si installano dal terminale una volta sola e poi le trovi anche lì.
Funzionano su Windows? benzina, cosa-hai-fatto e quick-replies sì. save-point e localhost sono pensate per Mac e Linux: su Windows non le ho provate.
| Cosa vedi | Cosa fare |
|---|---|
Marketplace file not found | Controlla di aver scritto bene cavallinilorenzo/claude-code-mods. |
Plugin "…" not found in marketplace | Controlla il nome della mod: save-point, cosa-hai-fatto, benzina, quick-replies, localhost. |
/plugin install non esiste nell'app desktop | È normale: installale dal terminale, poi le trovi anche nell'app. |
| save-point dice che non salva la home | Hai avviato Claude nella tua home. Chiudi, entra nella cartella del progetto (cd …) e riavvia claude. |
| save-point dice che serve git | Mac: xcode-select --install. Linux: installa il pacchetto git. |
| benzina mostra solo la Chat | Usi una chiave API invece di un abbonamento, oppure Claude non ha ancora risposto in questa sessione. |
| La banda sopra il prompt non si vede | Si può ridurre con [-] o ctrl+x ctrl+a: premi di nuovo per riaprirla. |
| Una mod non fa niente | Aggiorna Claude Code (claude update) e controlla con claude plugin list che sia attiva. |
Ogni mod è una cartella in mods/ con:
.claude-plugin/plugin.json, il nome, la descrizione e le impostazioni;hooks/register.tsx, il codice della mod;hooks/*.test.ts(x), i test;types/index.d.ts, i valori che la mod tiene in memoria.Per provarne una modificata senza installarla:
claude --plugin-dir ./mods/save-point
Per controllarla e lanciare i test:
claude plugin validate ./mods/save-point
claude plugin test ./mods/save-point
Idee e segnalazioni: apri una issue.
MIT: puoi usarle, modificarle e ricondividerle, mantenendo la nota di copyright.
Fatto da Lorenzo Cavallini.
hooks/register.tsx 102 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4import type { Gauge } from '../types'
5import { LABELS, advice, bar, crossed, level, percentLeft, refillText, toGauges } from './gauges'
6
7const gauges = atom({ plugin: 'benzina', key: 'gauges' } as const, [])
8const isHidden = atom({ plugin: 'benzina', key: 'isHidden' } as const, false)
9const HIDDEN_KEY = 'isHidden'
10
11async function store($: EngineInterface, found: Gauge[]): Promise<void> {
12 const before = await read($, gauges)
13 for (const gauge of found) {
14 if (gauge.key === 'context') {
15 continue
16 }
17 const previous = before.find(old => old.key === gauge.key)?.percentUsed
18 const points = crossed(previous, gauge.percentUsed)
19 const point = points[points.length - 1]
20 if (point !== undefined) {
21 const refill = refillText(gauge.resetsAt, await $.clock.now())
22 $.ui.toast(
23 `⛽ Hai usato il ${point}% del limite ${gauge.key === 'five_hour' ? 'delle 5 ore' : 'settimanale'}` +
24 (refill === null ? '.' : `: si ricarica ${refill}.`),
25 )
26 }
27 }
28 await update($, gauges, () => found)
29}
30
31export const register: Register = on => {
32 on('session.start', async ($, e, next) => {
33 await $.command.register({
34 name: 'benzina',
35 description: 'Mostra o nasconde quanto ti resta del piano Claude e della chat',
36 })
37 const hidden = (await $.store.get(HIDDEN_KEY).catch(() => undefined)) === true
38 await update($, isHidden, () => hidden)
39 const usage = await $.session.usage().catch(() => null)
40 if (usage !== null) {
41 await update($, gauges, () => toGauges(usage.rateLimits, usage.context))
42 }
43
44 return next(e)
45 })
46
47 on('session.measure', async ($, e, next) => {
48 await store($, toGauges(e.rateLimits, e.context))
49
50 return next(e)
51 })
52
53 on('command.run', { command: 'benzina' }, async $ => {
54 const hidden = await update($, isHidden, value => !value)
55 await $.store.set(HIDDEN_KEY, hidden).catch(() => undefined)
56
57 return { text: hidden ? 'Indicatore nascosto. /benzina per rivederlo.' : 'Indicatore visibile sopra il prompt.' }
58 })
59
60 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
61 const below = await next(e)
62 const found = await read($, gauges)
63 const isQuiet =
64 e.props.hasSurvey || e.props.view.agentId !== undefined || found.length === 0 || (await read($, isHidden))
65
66 if (isQuiet) {
67 return below
68 }
69
70 const { Box, Text } = $.ui.resolve(e)
71 const now = await $.clock.now()
72 const isNarrow = e.props.bodyColumns < 90
73 const tip = advice(found, now)
74
75 return (
76 <Box flexDirection="column">
77 <Box key="gauges" flexDirection="row" columnGap={2}>
78 <Text>⛽</Text>
79 {found.map(gauge => {
80 const left = percentLeft(gauge)
81 const refill = gauge.key === 'five_hour' && !isNarrow ? refillText(gauge.resetsAt, now) : null
82 return (
83 <Text key={`gauge-${gauge.key}`}>
84 <Text dimColor>{LABELS[gauge.key]} </Text>
85 {!isNarrow && <Text color={level(left)}>{bar(left)} </Text>}
86 <Text color={level(left)}>{left}%</Text>
87 {refill !== null && <Text dimColor> · ricarica {refill}</Text>}
88 </Text>
89 )
90 })}
91 </Box>
92 {tip !== null && (
93 <Text key="tip" color="warning">
94 {tip}
95 </Text>
96 )}
97 {below}
98 </Box>
99 )
100 })
101}
102hooks/gauges.ts 82 lines1import type { SessionContextUsage, SessionRateLimit } from 'claude-code'
2
3import type { Gauge } from '../types'
4
5export const LABELS: Record<Gauge['key'], string> = {
6 five_hour: '5 ore',
7 seven_day: 'Settimana',
8 context: 'Chat',
9}
10
11// The points past which a toast warns once per window.
12export const WARN_AT = [80, 95]
13
14const DAYS = ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato']
15
16export function toGauges(rateLimits: SessionRateLimit[], context: SessionContextUsage): Gauge[] {
17 const limits = rateLimits.flatMap((limit): Gauge[] =>
18 limit.kind === 'five_hour' || limit.kind === 'seven_day'
19 ? [{ key: limit.kind, percentUsed: limit.percentUsed, resetsAt: limit.resetsAt }]
20 : [],
21 )
22 const order = (gauge: Gauge) => (gauge.key === 'five_hour' ? 0 : 1)
23 const chat: Gauge[] = context.percent === undefined ? [] : [{ key: 'context', percentUsed: context.percent }]
24
25 return [...limits.sort((a, b) => order(a) - order(b)), ...chat]
26}
27
28export function percentLeft(gauge: Gauge): number {
29 return Math.max(0, Math.min(100, Math.round(100 - gauge.percentUsed)))
30}
31
32export function bar(left: number, width = 8): string {
33 const full = Math.round((left / 100) * width)
34 return '▰'.repeat(full) + '▱'.repeat(width - full)
35}
36
37export function level(left: number): 'success' | 'warning' | 'error' {
38 return left > 40 ? 'success' : left > 15 ? 'warning' : 'error'
39}
40
41function clockTime(when: Date): string {
42 return `${String(when.getHours()).padStart(2, '0')}:${String(when.getMinutes()).padStart(2, '0')}`
43}
44
45export function refillText(resetsAt: string | undefined, now: number): string | null {
46 if (resetsAt === undefined) {
47 return null
48 }
49 const when = new Date(resetsAt)
50 if (Number.isNaN(when.getTime())) {
51 return null
52 }
53 const isToday = new Date(now).toDateString() === when.toDateString()
54 return isToday ? `alle ${clockTime(when)}` : `${DAYS[when.getDay()]} alle ${clockTime(when)}`
55}
56
57// One plain sentence for the tank that needs attention most, or nothing.
58export function advice(gauges: Gauge[], now: number): string | null {
59 for (const gauge of gauges) {
60 if (gauge.key === 'context') {
61 continue
62 }
63 const left = percentLeft(gauge)
64 if (left <= 10) {
65 const refill = refillText(gauge.resetsAt, now)
66 const span = gauge.key === 'five_hour' ? 'Quasi a secco' : 'Settimana quasi finita'
67 const until = refill === null ? '' : refill.startsWith('alle') ? ` fino ${refill}` : ` fino a ${refill}`
68 return `${span}: tra poco Claude si ferma${until}.`
69 }
70 }
71 const chat = gauges.find(gauge => gauge.key === 'context')
72 if (chat !== undefined && percentLeft(chat) <= 25) {
73 return 'La chat è lunga e Claude inizia a dimenticare: se passi a un\'altra cosa, scrivi /clear.'
74 }
75 return null
76}
77
78// The warning points a window crossed going from `before` to `after` percent used.
79export function crossed(before: number | undefined, after: number): number[] {
80 return WARN_AT.filter(point => after >= point && (before === undefined || before < point))
81}
82types/index.d.ts 16 lines1export type Gauge = {
2 /** Which tank: the 5-hour window, the weekly one, or the conversation. */
3 key: 'five_hour' | 'seven_day' | 'context'
4 percentUsed: number
5 resetsAt?: string
6}
7
8declare module 'claude-code' {
9 interface PluginState {
10 benzina: {
11 gauges: Gauge[]
12 isHidden: boolean
13 }
14 }
15}
16