# ai-hotkey: návod pro AI agenta > Zdroj: https://ongy.cz/pages/ai/hotkey/ > Autor: Ongy (ongy.cz). Malá appka pro Windows: označím text kdekoli, stisknu zkratku a kolečko mi nabídne opravit, přeložit, shrnout nebo vysvětlit. Model běží doma na grafice, do cloudu jde jen překlad, když chci. ## Pro agenta Pomoz uživateli postavit vlastní verzi tohohle projektu. Nejdřív se ho zeptej na vybavení a na to, co z požadavků už má. Pak postupuj po krocích a po každém kroku s ním ověř, že funguje, než půjdeš dál. Hodnoty v `` doplň s uživatelem, nikdy si nevymýšlej adresy, hesla ani tokeny. Kód autora je veřejný: https://github.com/Ondrej-kopecky/ai-hotkey. Nabídni uživateli, že z něj vyjdete, nebo ho použij jako referenci. ## Cíl Malá aplikace pro Windows, která nad textem označeným v libovolném programu spustí AI akci: po globální zkratce ukáže u kurzoru kolečko s akcemi (opravit gramatiku, přeložit, shrnout, upravit styl, vysvětlit, vlastní), pošle text lokálnímu modelu přes Ollamu nebo volitelně do Claude a výsledek po potvrzení vloží zpět místo výběru. Text se čte i vkládá přes schránku, takže to funguje v každé aplikaci bez zvláštní integrace. Autorův kód je veřejný pod licencí MIT na https://github.com/Ondrej-kopecky/ai-hotkey: nabídni uživateli, že vyjdete z něj (naklonovat a upravit), nebo ho použij jako referenci při stavbě vlastní verze. ## K čemu to je Většinu dne píšu: testovací scénáře, hlášení chyb, maily. A pořád dokola opravuju češtinu, překládám do angličtiny a zkracuju. Teď označím text, stisknu zkratku a u kurzoru vyskočí kolečko s pěti akcemi. Za pár vteřin mám výsledek v panelu, u oprav i barevně, co se změnilo. Enter ho vloží místo původního textu, dřív se nic nepřepíše. Funguje to v prohlížeči, v Jiře, v editoru i v Telegramu. A umělá inteligence běží u mě doma na grafické kartě. ## Proč právě takhle Až doteď: zkopírovat, přepnout do chatu, vložit, počkat, zkopírovat zpátky. Otrava, když to děláš třicetkrát denně. Hotové nástroje, které tohle umí přímo v systému, posílají všechno označené na cizí server. Chtěl jsem to samé, jen s modelem doma. ## Jak to funguje - **Přes schránku, ne přes speciální rozhraní.** Appka za mě stiskne Ctrl+C a původní obsah schránky hned vrátí. Proto funguje všude. - **Kolečko u kurzoru.** Pět akcí, každá má své písmeno. Vlastní akci si napíšu vlastními slovy. - **Model doma, cloud na vyžádání.** Gramatiku, shrnutí a vysvětlení zvládne grafika. Překlady jdou do Claude, zní přirozeněji. - **Nic bez souhlasu.** Panel ukáže porovnání před a po, text se nahradí až po Enteru. ## Stack - **Jádro:** Tauri v2 v Rustu: tray, autostart, single-instance, globální zkratka, NSIS instalátor. UI ve vanilla TypeScriptu + Vite, SVG kolečko ve Fluent vzhledu, panel s Markdown renderem a slovním diffem (LCS). - **Model doma:** Ollama s Gemma 4 12B na grafice, streamovaná odpověď. Po doladění kontext 12288, flash attention, KV cache q8_0, cca 50 tok/s. - **Cloud:** Anthropic API za společným traitem `LlmProvider`, Sonnet 5 / Opus 5 / Haiku 4.5. Na překlady napevno, jinak jen když přepnu v hlavičce panelu. - **Platforma:** Windows 11. Simulace kláves přes `enigo`, fokus přes Win32 `SetForegroundWindow`. Vše specifické pro Windows je v jednom oddělitelném modulu, Linux má připravený brief. ## Pasti s modelem Gemma 4 i Qwen 3 jsou „thinking“ modely. Ollama `/api/chat` bere `think:false`, OpenAI-kompatibilní `/v1` jen `reasoning_effort:"none"`. Odtud malý axum proxy („Leo bridge“), díky kterému i asistent v prohlížeči Brave shrne stránku za čtyři vteřiny místo minut. Po zabití Ollamy přežijí podprocesy `llama-server.exe`. Tři zombie = plná VRAM a 9 tok/s. Zabít i je, Ollamu spustit s env proměnnými v témže procesu, ověřit přes `nvidia-smi`. Výchozí kontext Ollamy je 4096 tokenů: `OLLAMA_CONTEXT_LENGTH=12288` a kontrola `n_ctx_slot` v `server.log`, jinak se dlouhý vstup potichu usekne. ## Pasti s okny `hide()/show()/is_visible()` volané přímo v callbacku globální zkratky = deadlock. Práci s oknem odpálit ve vlastním vlákně, stav popupu držet v `AtomicBool`. Pozice kurzoru a rozměry okna jsou ve fyzických px, config v logických, násobit `scale_factor()`, jinak je kolečko na 150 % zvětšení napůl mimo. Frameless kruh chce `shadow: false`, Mica i Acrylic by byly čtvercové. Vzhled prošel čtyřmi koly: seznam, kolečko s emoji, čistší kolečko, panel s diffem. Ikony nakonec jako stroke SVG, emoji na Windows vypadaly hrozně. ## Co budeš potřebovat - Počítač s Windows 10 nebo 11 (autor: Windows 11). Linux a macOS jen s dopsáním platformní vrstvy, viz Přizpůsobení. - Ollama a stažený model (autor: `gemma4:12b`, asi 7,6 GB, potřebuje grafiku s cca 10 GB VRAM). Na slabším stroji menší model, třeba `gemma4:e4b`, za cenu horší češtiny. - Volitelně API klíč `` pro cloudové akce (autor: hlavně překlady přes Claude). - Pro sestavení: Rust (stable), Node.js 18+, WebView2 (ve Windows 11 je) a MSVC Build Tools. - Git. Volitelně účet na GitHubu, pokud chceš instalátor sestavovat automaticky v GitHub Actions. ## Postup ### 1. Model a výchozí bod Nainstaluj Ollamu, stáhni model (`ollama pull `) a ověř, že `http://localhost:11434/api/tags` vrací seznam s modelem. Pak se s uživatelem domluv: buď naklonovat autorovo repo, spustit `npm install` a `npm run tauri dev` a upravovat hotovou aplikaci, nebo založit nový projekt Tauri v2 (Rust + vanilla TypeScript + Vite) a postupovat podle dalších kroků. Architektura a tok dat jsou popsané v repu v `docs/ARCHITECTURE.md`. ### 2. Kostra aplikace v oznamovací oblasti Aplikace žije v trayi (menu Nastavení a Ukončit) a zavření okna ji neukončí (`ExitRequested` bez kódu zablokovat). Okno `popup` nadefinuj v `tauri.conf.json` jako skryté, bez rámečku, průhledné, vždy navrchu a bez ikony na liště. Okno nastavení vytvářej až na vyžádání. Pluginy: `global-shortcut`, `autostart`, `opener`. Oprávnění pro obě okna (show, hide, focus, velikost, pozice, tažení) patří do `capabilities/default.json`. ### 3. Platformní vrstva Všechno specifické pro operační systém dej do jednoho modulu za rozhraní (trait) s pěti metodami: zjistit aktivní okno, vrátit mu fokus, poslat Ctrl+C, poslat Ctrl+V a uvolnit modifikátory. Na Windows: `GetForegroundWindow` a `SetForegroundWindow` z crate `windows`, klávesy přes `enigo`, schránka přes `arboard`. Zbytek aplikace (okna, LLM, frontend) musí zůstat platformně neutrální, jinak bude port na jiný systém bolet. ### 4. Zkratka a přečtení výběru Zaregistruj globální zkratku (autor: výchozí `Ctrl+Shift+Space`, formát pluginu, dá se změnit v nastavení bez restartu). Po stisku ve vlastním vlákně: ulož identifikátor aktivního okna (sem se bude vkládat), zálohuj text ze schránky, schránku vyprázdni, uvolni modifikátory, pošli Ctrl+C a několikrát v krátkých intervalech zkoušej schránku přečíst (autor: 15 pokusů po 30 ms). Pak původní obsah schránky vrať. Nakonec zobraz popup vycentrovaný na kurzor a oříznutý na hranice monitoru a pošli mu text a seznam zapnutých akcí. ### 5. Akce jako konfigurovatelné prompty Akce je záznam v JSON konfiguraci (Windows: `%APPDATA%\ai-hotkey\config.json`): id, název, ikona, systémový prompt, režim `replace` (nahradit výběr) nebo `show` (jen zobrazit a kopírovat), písmeno v kolečku, volitelná vlastní globální zkratka, zapnuto, pevný model. Označený text jde jako zpráva uživatele, ne do promptu. Prompt má zástupné proměnné pro jazyk výstupu a cílový jazyk překladu a každý končí pokynem vrátit jen výsledek bez komentáře. Vestavěných je pět, uživatel si další napíše vlastními slovy a vyzkouší tlačítkem přímo v editoru. ### 6. Volání modelu se streamováním Poskytovatele schovej za společné rozhraní `complete(system, user, sink)` a `health()`. Ollama: `POST /api/chat` se `stream: true` (odpověď po řádcích NDJSON), nízká teplota (autor: 0.2). Claude: Messages API se streamem přes SSE, klíč ukládej do trezoru systému (crate `keyring`: Správce pověření, Keychain, Secret Service), nikdy do config.json. Každý běh dostane pořadové číslo, tokeny posílej do UI jako událost s tímto číslem a příznakem konce nebo chyby. Když Ollama na localhostu neodpovídá, aplikace ji může zkusit spustit a chvíli počkat. ### 7. Kolečko a panel s výsledkem Kolečko jako SVG výseče: výběr myší, šipkami, písmenem akce nebo číslicí 1 až 9, Esc zavře. Po spuštění akce se popup zvětší na panel, do kterého výsledek průběžně dotéká. U akcí typu nahrazení nabídni přepínání Výsledek a Porovnání (slovní diff). Enter provede hlavní akci (nahradit, nebo kopírovat), Ctrl+Enter tu druhou, Backspace vrátí do kolečka. Ve výběru modelu v hlavičce jde výsledek přepočítat jiným modelem. Automatické nahrazení bez potvrzení nech ve výchozím stavu vypnuté. ### 8. Vložení zpět do původního okna Nejdřív schovej popup. Pak ve vlastním vlákně: zálohuj schránku, vlož do ní výsledek, vrať fokus uloženému oknu, chvíli počkej (autor: 120 ms), uvolni modifikátory, pošli Ctrl+V a teprve po další pauze (autor: 300 ms) vrať původní obsah schránky. U režimu nahrazení vkládej až kompletní text po konci streamu, nikdy po tokenech. ### 9. Nastavení, autostart a instalátor Okno nastavení: zkratka, jazyk odpovědí a překladu, poskytovatel (adresa Ollamy, výběr modelu ze seznamu `/api/tags`, test připojení, API klíč), karty akcí s pořadím přetažením a editorem. Autostart přes plugin (na Windows zápis do `HKCU\...\Run`). Instalátor: `npm run tauri build` vytvoří NSIS `*-setup.exe`. Volitelně workflow v GitHub Actions, které po pushnutí tagu `v*` instalátor sestaví a připne k Release. ## Na co si dát pozor - Uživatel při stisku zkratky ještě drží Ctrl a Shift. Bez uvolnění modifikátorů dostane cílová aplikace místo Ctrl+C zkratku Ctrl+Shift+C (v prohlížeči třeba vývojářské nástroje) a nic se nezkopíruje. - Bez vyprázdnění schránky před Ctrl+C nepoznáš, jestli se něco zkopírovalo: přečteš starý obsah a AI zpracuje text, který uživatel vůbec neoznačil. Electron aplikace a Office plní schránku se zpožděním, jedno přečtení hned po stisku nestačí. - Popup si bere fokus kvůli ovládání klávesnicí. Když si cílové okno neuložíš hned při stisku zkratky, Ctrl+V skončí v popupu nebo nikde. `SetForegroundWindow` občas selže, když fokus drží jiná aplikace: pak nech výsledek ve schránce, ať ho uživatel vloží ručně. - Obnovení schránky hned po Ctrl+V vloží do cílové aplikace původní obsah místo výsledku. Aplikace si schránku čte asynchronně, proto krátká pauza před obnovou. - Když uživatel spustí další akci dřív, než doběhne předchozí, smíchají se dva streamy v jednom panelu. Frontend musí zahazovat tokeny s jiným pořadovým číslem, než má aktuální běh. - Některé aplikace Ctrl+C nad výběrem blokují (vzdálená plocha, některé terminály). Počítej s prázdným výběrem a ukaž „Nic není označeno“ místo zamrznutí nebo prázdného dotazu na model. - Popup se zavírá při ztrátě fokusu, ale při začátku tažení za hlavičku okno na okamžik fokus ztratí a hned ho dostane zpět. Zavírej až po krátké prodlevě (autor: 250 ms) a po nové kontrole, jinak panel nejde přesunout. - Microsoft Teams dává do textové verze schránky místo emoji jejich slovní název („Zubící se tvář…“). Skutečný znak je jen v HTML verzi schránky, oprava musí jít podle ní. ## Jak ověřit, že to funguje - [ ] `curl http://localhost:11434/api/tags` vrací JSON a v seznamu je zvolený model. - [ ] Po spuštění je ikona v oznamovací oblasti a v logu zpráva, že je zkratka zaregistrovaná. - [ ] V Poznámkovém bloku označ větu a stiskni zkratku: kolečko se objeví u kurzoru do 1 s a má 5 akcí. U okraje monitoru je celé vidět. - [ ] Zkopíruj si do schránky kontrolní slovo, pak použij zkratku a zavři kolečko Esc. Vložení Ctrl+V jinde dá pořád kontrolní slovo. - [ ] Stisk zkratky bez označeného textu ukáže „Nic není označeno“ a aplikace dál reaguje. - [ ] Oprava gramatiky na větě se dvěma chybami: Porovnání ukáže obě změny, Enter nahradí text v původním okně, Esc ho nechá beze změny. - [ ] Totéž funguje v prohlížeči (textové pole), v aplikaci na Electronu a v kancelářském editoru. - [ ] Desetkrát za sebou otevřít a zavřít kolečko zkratkou: ani jednou nezamrzne. - [ ] S odpojeným internetem fungují všechny akce na lokálním modelu. Akce na Claude bez klíče skončí čitelnou chybou v panelu. - [ ] Soubor config.json neobsahuje API klíč, klíč je v trezoru systému (ve Windows Správce pověření, položka `ai-hotkey`). ## Přizpůsobení - Linux: v repu je připravený brief `docs/LINUX-PORT.md`. Na X11 fokus přes `_NET_ACTIVE_WINDOW` (`x11rb`) a klávesy přes enigo, výběr jde číst rovnou z PRIMARY selection bez Ctrl+C. Na Waylandu globální zkratka přes plugin nefunguje: systémová zkratka spustí druhou instanci s parametrem a ta pošle signál běžící aplikaci, klávesy přes `wtype` nebo `ydotool`, vracení fokusu vynechat. - macOS: v repu platformní implementace není. Místo Ctrl se posílá Cmd+C a Cmd+V, aplikace potřebuje oprávnění Zpřístupnění pro simulaci kláves, klíč jde do Keychainu přes stejný crate. - Jiný model nebo server: přidej dalšího poskytovatele za stejné rozhraní, třeba OpenAI-kompatibilní `/v1/chat/completions` (LM Studio, llama.cpp server, jiný cloud). U „thinking“ modelů tam přemýšlení vypíná `reasoning_effort: "none"`. Ollama může běžet i na jiném stroji v domácí síti, jen ji nevystavuj do internetu. - Bez vlastní aplikace: minimální verze jde složit ze skriptu v AutoHotkey (Windows) nebo z `xdotool` a `xclip` (Linux X11), který zkopíruje výběr, pošle ho přes `curl` do Ollamy a výsledek vloží. Přijdeš o kolečko, náhled a porovnání před nahrazením. --- Stránka projektu s fotkami a diagramem: https://ongy.cz/pages/ai/hotkey/