Toolbox: a button at the bottom right of the prompt footer (or /eszkozok) opens switches above the prompt for Szabolcs's mods (focus mode, usage bar, project…

Saját Claude Code mod-ok (function hook pluginek) egy pluginpiacon.
claude plugin marketplace add Szotasz/claude-mods
claude plugin install usage-band@claude-mods
claude plugin install usage-header@claude-mods
claude plugin install project-pane@claude-mods
claude plugin install focus-mode@claude-mods
claude plugin install tool-hub@claude-mods
claude plugin install snake-pane@claude-mods
claude plugin install supabase-guard@claude-mods
claude plugin install public-repo-guard@claude-mods
claude plugin install decision-popup@claude-mods
Frissítés: claude plugin update usage-band@claude-mods, majd /reload-plugins (vagy új session).
A státuszsorba (a prompt alá) írja:
🤖 Opus 5.5 │ Ctx ███░░░░░ 42% 420k/1M │ 5h ███░░░░░ 34% → 16:20 │ Hét ███████░ 93% ⚠ → Cs 10:00
/model váltáskor és turn végén frissül)Nyelv / Language: /config → usage-band.language, vagy a settings.json-ban:
"pluginConfigs": { "usage-band": { "language": "en" } }
auto (alapértelmezett): magyar, ha a rendszer nyelve (LANG) magyar, különben angolhu: magyar (Hét, Cs 10:00)en: English (Week, Thu 10:00)Követelmény: Claude Code 2.1.289 körüli verzió. A mod-API early access, kiadásról kiadásra változhat.
Sáv a prompt fölött: a kontextusablak kategóriánként színezve, alatta az 5 órás és a heti limit.
Kontextus ██▓▓▓▓▓▓████████████▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░ 42% 84k/200k
■ Rendszerprompt 3k ■ Eszközök 12k ■ Memória 400 ■ Üzenetek 69k ▒ Tömörítési tartalék 33k ░ Szabad 83k
Limitek 5 óra ███████░░░░░░░░░░░░░ 34% → 16:20 Hét ███████████████████░ 93% ⚠ → Cs 10:00
/context saját színével látszik (rendszerprompt, eszközök, MCP, memóriafájlok, skillek, ágensek, üzenetek), utána a tömörítési tartalék és a szabad hely halványan; alatta jelmagyarázat tokenszámmal. Az igény szerint betöltött (halasztott) eszközsémák kimaradnak, mert nincsenek az ablakban.$.session.usage({ breakdown: 'summary' })), API-hívás nélkül; minden turn végén és limitmozduláskor frissül./hasznalat kapcsolja, /hasznalat be|ki beállítja; az állapotot sessionök között megőrzi. Az eszköztárban (/eszkozok) is kapcsolható.Beállítás (/config): usage-header.language (auto/hu/en).
Oldalpanel az aktuális git repóhoz. Magától megnyílik, ha a session git repóban indul és a terminál legalább 144 oszlop széles (miután egyszer /project-tel megnyitottad, 110 is elég); keskenyebb ablaknál egy toast szól, hogy vár. Bármikor: /project.
acme/shop ↻ most [ Frissítés ]
GIT
🌿 develop ↑0 ↓0 · 7 módosított fájl
utolsó commit: 57704fe · 7 hónapja — Fix checkout flow
⚠ a main 13 committal előrébb jár, te a develop branch-en vagy
Előbb commitold a módosításokat, vagy tedd félre őket:
[ Stash + szinkron ]
DEPLOY (Netlify)
✔ ready main 3 perce
PULL REQUESTEK
✔ #142 Stripe webhook retry · approved
CI (GitHub Actions)
✘ netlify-deploy-verify main · 5 napja [ Kérdezd Claude-ot ]
SUPABASE
abcdefghijklmnopqrst · Acme Shop · eu-west-3
18 migráció · utolsó: 018_add_orders_rls.sql
GitHub Netlify Supabase
s): csak fast-forward, soha nem merge-öl, rebase-el vagy töröl.git pull --ff-onlygit switch main + git merge --ff-only origin/maingit stash push -u, vissza: git stash popr): 60 mp-enként és minden turn végén; git fetch 5 percenként.a): a legutóbbi elbukott CI-futásról kérdést tesz a promptba.Adatforrások (a CLI-k saját bejelentkezésével, a plugin tokent nem olvas):
| Szekció | Forrás | Ha hiányzik |
|---|---|---|
| Git | git | — |
| PR, CI | gh (gh auth login) | tipp a panelen |
| Deploy | netlify CLI + .netlify/state.json | npm i -g netlify-cli && netlify login |
| Supabase | supabase/.temp/project-ref, supabase/migrations, supabase projects list | supabase login az állapothoz |
Beállítás (/config): project-pane.language (auto/hu/en), project-pane.autoOpen (alapból be).
Fókusz mód: a transcriptből eltűnnek az eszközhívások és eredményeik, a köztes szövegek, a saját promptjaid és a parancsok kimenete. Csak két dolog marad: a prompt fölötti sávban a részfeladatok listája állapotsávval és pipával, alatta a turn végső válasza.
✔ Meglévő mod-repo áttekintése
◐ Játék-mod megírása ██████░░░░ 60%
○ Felvétel az eszközök közé
/fokusz kapcsolja, /fokusz be / /fokusz ki beállítja; az állapotot sessionök között megőrzi.mcp__focus-mode__plan eszközzel; a rendszerprompt bekapcsolt állapotban erre utasítja (minden több lépéses kérésnél előbb a részfeladatok, aztán frissítés indításkor, haladáskor és befejezéskor).Beállítás (/config): focus-mode.language (auto/hu/en).
Eszköztár: egy helyről kapcsolhatók a fenti modok. A prompt alatti lábléc jobb oldalán lévő ⚙ Eszközök gomb (vagy /eszkozok) a prompt fölötti sávban nyitja meg:
⚙ Szabolcs eszközei kattintás, vagy ctrl+x tab után szám [ Bezár ]
1. Fókusz mód ● BE [ Kikapcsol ] · Csak a részfeladatok listája és a végső válasz látszik
2. Limitsáv ○ KI [ Bekapcsol ] · Alsó sáv: 5 órás és heti limit, kontextusablak
3. Használati sáv ● BE [ Kikapcsol ] · Prompt fölött: kontextus kategóriánként színezve, 5 órás és heti limit
4. Projektpanel ● BE [ Kikapcsol ] · GitHub, CI, Netlify és Supabase állapot oldalt
5. Kígyó játék ● BE [ Kikapcsol ] · Oldalt nyílik promptküldéskor, amíg Claude dolgozik
ctrl+x tab után az 1–5 számbillentyűvel is./fokusz, /limitsav, /hasznalat, /project, /jatek (mind be|ki argumentummal).Új mod felvétele az eszköztárba: a mod írja a saját isOn állapotát, adjon /<parancs> be|ki-t, és hookolja a state.set-et { plugin: 'tool-hub', key: 'request' }-re; a hubban egy sor a TOOLS listába, egy ág a stateOf-ba és a kulcs a types/index.d.ts-be.
Beállítás (/config): tool-hub.language (auto/hu/en).
Kígyó játék az oldalpanelben, amíg Claude dolgozik.
⏳ Claude dolgozik…
Pont: 4 Rekord: 17
╭──────────────────────────────────────╮
│ │
│ ████████ │
│ ██ ● │
╰──────────────────────────────────────╯
p: szünet · r: újra
w: ↑ a: ← s: ↓ d: → p: szünet r: új
/jatek mindig nyitja). /jatek ki kikapcsolja, az eszköztárban (/eszkozok) is kapcsolható.wasd / hjkl, szóköz vagy p szünet, r új játék. Vagy ctrl+x tab a panelre, és a w a s d p r gombok.Client surface modul), nem terheli a sessiont.Supabase-őr: megállítja a Supabase-hívást, ha nem az aktuális mappa projektjére menne, és egygombos felugróban rákérdez.
supabase/.temp/project-ref, a .env* fájlok https://<ref>.supabase.co címei és a CLAUDE.md (ha egyetlen projekt-ID-t említ) adják, plusz amit a felugróban „Ez a mappa projektje” gombbal megerősítettél.execute_sql, apply_migration, deploy_edge_function, branch-műveletek, illetve supabase db push --project-ref …): kérdez — Megtiltom / Engedélyezem / Ez a mappa projektje.DROP, TRUNCATE, DELETE FROM, WHERE nélküli UPDATE, REVOKE, RLS kikapcsolása, reset_branch, delete_branch, pause_project, supabase db reset --linked./supaor be|ki, vagy az eszköztárban.Push-őr: nyilvános GitHub-repóba push előtt (és gh repo edit --visibility public / gh repo create --public előtt) átnézi, mi menne ki.
git push origin forrás:cél alakot is.project_id, táblázatsor), JWT / Supabase-kulcs, Stripe/Anthropic/OpenAI/GitHub/AWS/Google/Slack/Resend/Telegram/ElevenLabs kulcsok, privát kulcs, e-mail-cím (a saját git e-mail és a noreply/példa címek kivételével), helyi /Users/<te>/ útvonal, privát repóid nevei (gh repo list --visibility private), .env fájlok, és amit /pushor figyel <szöveg>-gel felvettél.gh CLI (bejelentkezve). /pushor be|ki.Döntési felugró: a döntések egygombos kérdésként jönnek.
/dontes be|ki, vagy az eszköztárban.project-pane bővítése:
vercel ls)Státuszsor bővítése (usage-band):
/compact$.session.usage().cost)userConfig)Új mod-ok:
.env, kulcsfájlok, supabase/.temp szerkesztésének tiltása (tool.call → deny)turn.complete, $.audio.play)/quote — a kijelölt szöveget idézetként a promptba teszi ($.ui.selection)prompt.compose)Egy plugin mappája közvetlenül is betölthető:
claude --plugin-dir ./plugins/usage-band
Ellenőrzés:
claude plugin validate plugins/usage-band
claude plugin test plugins/usage-bandhooks/register.tsx 236 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4// Az eszköztár a prompt fölötti sávban nyílik (nem oldalpanelként).
5const isOpen = atom({ plugin: 'tool-hub', key: 'isOpen' } as const, false)
6// Kapcsolási kérés a modoknak: parancsfuttatás helyett, mert az minden gombnyomásnál sort hagyna a transcriptben.
7const request = atom({ plugin: 'tool-hub', key: 'request' } as const, null)
8
9type Lang = 'hu' | 'en'
10
11// A kapcsolható modok. Új mod felvétele: egy sor ide, egy ág a stateOf-ba, és az `isOn` kulcsa a types/index.d.ts-be.
12// A mod maga írja az állapotát; a gomb a hub `request` értékét írja, amit a mod state.set hookja átvesz.
13// A `command` csak tájékoztató: kézzel így kapcsolható.
14const TOOLS = [
15 {
16 id: 'focus',
17 command: 'fokusz',
18 label: { hu: 'Fókusz mód', en: 'Focus mode' },
19 detail: {
20 hu: 'Csak a részfeladatok listája és a végső válasz látszik',
21 en: 'Only the subtask list and the final answer are shown',
22 },
23 },
24 {
25 id: 'limits',
26 command: 'limitsav',
27 label: { hu: 'Limitsáv', en: 'Usage bar' },
28 detail: {
29 hu: 'Alsó sáv: 5 órás és heti limit, kontextusablak',
30 en: 'Bottom bar: 5-hour and weekly limits, context window',
31 },
32 },
33 {
34 id: 'header',
35 command: 'hasznalat',
36 label: { hu: 'Használati sáv', en: 'Usage band' },
37 detail: {
38 hu: 'Prompt fölött: kontextus kategóriánként színezve, 5 órás és heti limit',
39 en: 'Above the prompt: context by category in colours, 5-hour and weekly limits',
40 },
41 },
42 {
43 id: 'project',
44 command: 'project',
45 label: { hu: 'Projektpanel', en: 'Project pane' },
46 detail: {
47 hu: 'GitHub, CI, Netlify és Supabase állapot oldalt',
48 en: 'GitHub, CI, Netlify and Supabase status at the side',
49 },
50 },
51 {
52 id: 'game',
53 command: 'jatek',
54 label: { hu: 'Kígyó játék', en: 'Snake game' },
55 detail: {
56 hu: 'Oldalt nyílik promptküldéskor, amíg Claude dolgozik',
57 en: 'Opens at the side when you send a prompt, while Claude works',
58 },
59 },
60 {
61 id: 'supabase',
62 command: 'supaor',
63 label: { hu: 'Supabase-őr', en: 'Supabase guard' },
64 detail: {
65 hu: 'Rossz projektre menő és romboló Supabase-hívás előtt rákérdez',
66 en: 'Asks before Supabase calls to the wrong project or destructive ones',
67 },
68 },
69 {
70 id: 'pushguard',
71 command: 'pushor',
72 label: { hu: 'Push-őr', en: 'Push guard' },
73 detail: {
74 hu: 'Nyilvános repóba push előtt titkokat, ID-ket, e-maileket keres',
75 en: 'Looks for secrets, IDs and emails before pushing to a public repo',
76 },
77 },
78 {
79 id: 'decision',
80 command: 'dontes',
81 label: { hu: 'Döntési felugró', en: 'Decision popup' },
82 detail: {
83 hu: 'A döntések egygombos kérdésként jönnek, keretben',
84 en: 'Decisions come as one-key questions in a frame',
85 },
86 },
87] as const
88
89type Tool = (typeof TOOLS)[number]
90
91const STRINGS = {
92 hu: {
93 button: '⚙ Eszközök',
94 title: 'Szabolcs eszközei',
95 command: 'Megnyitja az eszköztárat (modok be/ki)',
96 opened: 'Eszköztár megnyitva a prompt fölött.',
97 closed: 'Eszköztár bezárva.',
98 on: 'BE',
99 off: 'KI',
100 missing: 'nincs betöltve',
101 turnOn: 'Bekapcsol',
102 turnOff: 'Kikapcsol',
103 hint: 'kattintás, vagy ctrl+x tab után szám',
104 close: 'Bezár',
105 },
106 en: {
107 button: '⚙ Tools',
108 title: "Szabolcs's tools",
109 command: 'Open the toolbox (mods on/off)',
110 opened: 'Toolbox opened above the prompt.',
111 closed: 'Toolbox closed.',
112 on: 'ON',
113 off: 'OFF',
114 missing: 'not loaded',
115 turnOn: 'Turn on',
116 turnOff: 'Turn off',
117 hint: 'click, or ctrl+x tab then a digit',
118 close: 'Close',
119 },
120}
121
122let lang: Lang = 'en'
123const t = () => STRINGS[lang]
124
125async function pickLanguage($: EngineInterface, setting: unknown): Promise<Lang> {
126 if (setting === 'hu' || setting === 'en') return setting
127 const locale = (await $.env.get('LC_ALL')) || (await $.env.get('LANG')) || ''
128 return locale.toLowerCase().startsWith('hu') ? 'hu' : 'en'
129}
130
131// A hivatkozásoknak szó szerint kell a forrásban állniuk (így listázható, mit olvas a mod).
132const FOCUS = { plugin: 'focus-mode', key: 'isOn' } as const
133const LIMITS = { plugin: 'usage-band', key: 'isOn' } as const
134const HEADER = { plugin: 'usage-header', key: 'isOn' } as const
135const PROJECT = { plugin: 'project-pane', key: 'isOn' } as const
136const GAME = { plugin: 'snake-pane', key: 'isOn' } as const
137const SUPABASE = { plugin: 'supabase-guard', key: 'isOn' } as const
138const PUSHGUARD = { plugin: 'public-repo-guard', key: 'isOn' } as const
139const DECISION = { plugin: 'decision-popup', key: 'isOn' } as const
140
141// undefined: a mod nincs betöltve (még sosem írta az állapotát).
142async function stateOf($: EngineInterface, tool: Tool): Promise<boolean | undefined> {
143 switch (tool.id) {
144 case 'focus':
145 return (await $.state.get(FOCUS)).value
146 case 'limits':
147 return (await $.state.get(LIMITS)).value
148 case 'header':
149 return (await $.state.get(HEADER)).value
150 case 'project':
151 return (await $.state.get(PROJECT)).value
152 case 'game':
153 return (await $.state.get(GAME)).value
154 case 'supabase':
155 return (await $.state.get(SUPABASE)).value
156 case 'pushguard':
157 return (await $.state.get(PUSHGUARD)).value
158 case 'decision':
159 return (await $.state.get(DECISION)).value
160 }
161}
162
163const toggleOpen = ($: EngineInterface) => update($, isOpen, open => !open)
164
165export const register: Register = (on, options) => {
166 if (options.language === 'hu' || options.language === 'en') lang = options.language
167
168 on('session.start', async ($, e, next) => {
169 const started = await next(e)
170 lang = await pickLanguage($, options.language)
171 await $.command.register({ name: 'eszkozok', description: t().command, immediate: true })
172 // Ékezettel is: ha a motor nem fogad el ékezetes nevet, marad az ékezet nélküli.
173 await $.command.register({ name: 'eszközök', description: t().command, immediate: true }).catch(() => undefined)
174 return started
175 })
176
177 on('command.run', { command: ['eszkozok', 'eszközök'] }, async $ => {
178 await toggleOpen($)
179 return { text: (await read($, isOpen)) ? t().opened : t().closed }
180 })
181
182 // A prompt alatti lábléc jobb oldala: a motor módfeliratai, mellettük az eszköztár gombja.
183 on('ui.render', { component: 'SessionMode' }, async ($, e) => {
184 const { Box, Text, Button } = $.ui.resolve(e)
185 const focus = TOOLS[0]
186 const modes = (await stateOf($, focus)) === true ? [...e.props.modes, focus.label[lang]] : e.props.modes
187 return (
188 <Box flexDirection="row" gap={1}>
189 {modes.length > 0 ? <Text dimColor>{modes.join(' & ')}</Text> : null}
190 <Button key="open-hub" label={t().button} onPress={() => toggleOpen($).then(() => undefined)} />
191 </Box>
192 )
193 })
194
195 // A sávot más mod is rajzolhatja (fókusz mód): az övé alá tesszük a kapcsolókat.
196 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
197 if (e.props.hasSurvey || !(await read($, isOpen))) return next(e)
198 const below = await next(e)
199 const { Box, Text, Button } = $.ui.resolve(e)
200 const rows = []
201 for (const [i, tool] of TOOLS.entries()) {
202 const state = await stateOf($, tool)
203 rows.push(
204 <Box key={`row-${tool.id}`} flexDirection="row" gap={1}>
205 <Text bold>{`${i + 1}. ${tool.label[lang]}`}</Text>
206 {state === undefined ? (
207 <Text dimColor>{t().missing}</Text>
208 ) : (
209 <Box flexDirection="row" gap={1}>
210 <Text color={state ? 'green' : 'gray'} bold>{state ? `● ${t().on}` : `○ ${t().off}`}</Text>
211 <Button
212 key={`toggle-${tool.id}`}
213 label={state ? t().turnOff : t().turnOn}
214 hotkey={String(i + 1)}
215 onPress={() => update($, request, prev => ({ tool: tool.id, on: !state, n: (prev?.n ?? 0) + 1 })).then(() => undefined)}
216 />
217 </Box>
218 )}
219 <Text dimColor wrap="truncate-end">{`· ${tool.detail[lang]}`}</Text>
220 </Box>,
221 )
222 }
223 return (
224 <Box flexDirection="column">
225 {below}
226 <Box flexDirection="row" gap={1}>
227 <Text color="cyan" bold>{`⚙ ${t().title}`}</Text>
228 <Text dimColor>{t().hint}</Text>
229 <Button key="close-hub" label={t().close} onPress={() => update($, isOpen, () => false).then(() => undefined)} />
230 </Box>
231 {rows}
232 </Box>
233 )
234 })
235}
236types/index.d.ts 18 lines1// Az eszköztár a kapcsolt modok saját `isOn` értékét olvassa (írni csak a tulajdonos írhatja:
2// a gomb a saját `request` értékét írja, a mod a state.set hookjában veszi át). Új mod: ide is fel kell venni.
3export type HubRequest = { tool: string; on: boolean; n: number }
4
5declare module 'claude-code' {
6 interface PluginState {
7 'tool-hub': { isOpen: boolean; request: HubRequest | null }
8 'focus-mode': { isOn: boolean }
9 'usage-band': { isOn: boolean }
10 'usage-header': { isOn: boolean }
11 'project-pane': { isOn: boolean }
12 'snake-pane': { isOn: boolean }
13 'supabase-guard': { isOn: boolean }
14 'public-repo-guard': { isOn: boolean }
15 'decision-popup': { isOn: boolean }
16 }
17}
18