Lightweight Windows 10/11 tray app: global hotkeys grab text from your editor and send it to an AI chat with a prepared prompt.
Pure Win32 + C++17. No third-party libraries. Built to debug, trace, and extend.
Windows tray app: hotkeys grab editor text and send it to an AI chat with a prepared prompt.
- System tray icon, single instance
- Ergonomic hotkeys (left hand
Ctrl+Alt, right hand letter) - Fire on key release so modifiers are up before automation runs
- Send-to-AI workflow:
- Select-all + copy from the focused editor
- Prefer Chrome MV3 companion (DOM paste into the composer)
- Fallback: activate Chrome (Dev/Beta/stable) / Edge → new tab → AI URL
- Adaptive wait (window title + UI Automation chat input)
- Paste
prompt + editor text - Restore clipboard
- Insert-only mode (paste template into the current field)
- File + debugger logging; optional
titles.logfor mining real window titles - Bindings live in
%LOCALAPPDATA%\QiuckPrompts\qiuckprompts.ini(seed:config/qiuckprompts.ini) - Binding / update URLs must be
https://
User config (edit this): %LOCALAPPDATA%\QiuckPrompts\qiuckprompts.ini
Seeded on first run from the install template (<exe>\config\qiuckprompts.ini).
Updates never overwrite the user file. Backups live in %LOCALAPPDATA%\QiuckPrompts\backups\.
Logs: %LOCALAPPDATA%\QiuckPrompts\logs\ (qiuckprompts.log, titles.log; rotated ~5 MiB × 4 files).
Default log_level=info (length only). Payload / clipboard / editor previews are debug/trace — they can contain secrets.
Tray → Open config / Open data folder. Override path: --config=D:\path\qiuckprompts.ini
Each [section] binds hotkey + service URL + full prompt text:
[grammar_meta]
label=Grammar quick (Meta)
service=meta
hotkey=Ctrl+Alt+J
url=https://www.meta.ai/
title_hint=Meta
capture_editor=1
prompt<<<
Light edit only. Fix grammar...
Message:
>>>Multi-line prompts use prompt<<< … >>> (so you can use ; and markdown ``` inside).
Single-line prompt=... still works. External prompt=file.txt is optional if you really want a separate file.
| Hotkey | Service | Purpose |
|---|---|---|
Ctrl+Alt+J |
Meta | Quick grammar / light sanity, keep your voice |
Ctrl+Alt+O |
Gemini | Grammar in-thread; optional clipboard {{CONTEXT}} |
Ctrl+Alt+K |
Gemini | Improve message: fact-check + grammar + recommended text |
Ctrl+Alt+L |
Grok | Collaborate on an idea |
Ctrl+Alt+I |
Gemini | Screenshot on clipboard + dialog structure / polish |
Ctrl+Alt+M |
ChatGPT | Clipboard → Suno-ready style + lyrics (<<<STYLE: >>> editable) |
Restart the app after edits. Override path: --config=D:\path\qiuckprompts.ini
Screenshot flow: Win+Shift+S, then Ctrl+Alt+I.
Song flow: copy inspiration → Ctrl+Alt+M → optionally edit <<<STYLE: >>> in ChatGPT → send.
| Hotkey | Action |
|---|---|
Ctrl+Alt+J |
Grammar quick → Meta |
Ctrl+Alt+K |
Improve message (facts + grammar) → Gemini |
Ctrl+Alt+L |
Idea collab → Grok |
Ctrl+Alt+I |
Screenshot review → Gemini |
Ctrl+Alt+O |
Grammar in context → Gemini |
Ctrl+Alt+M |
Song from clipboard → ChatGPT (Suno) |
Edit bindings and prompts in %LOCALAPPDATA%\QiuckPrompts\qiuckprompts.ini (seed: config/qiuckprompts.ini).
- Windows 10 or 11 (x64)
- CMake 3.20+
- Visual Studio 2022 with C++ desktop workload (MSVC)
scripts\build.batOr manually:
cmake -S . -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Debug| Output | Path |
|---|---|
| Exe | build\Debug\qiuckprompts.exe |
| PDB | build\Debug\qiuckprompts.pdb |
Release-style local build:
cmake --build build --config RelWithDebInfobuild\Debug\qiuckprompts.exe
build\Debug\qiuckprompts.exe --console --log-level=debug
build\Debug\qiuckprompts.exe --self-test| Flag | Meaning |
|---|---|
--console |
Live logs on a console |
--log-level=LEVEL |
trace | debug | info | warn | error (default info) |
--log-file=PATH |
Override log path |
--ai-url=URL |
Default AI chat URL (https:// only) |
--update-url=URL |
Velopack feed directory (https:// only) |
--browser-hint=TEXT |
Prefer matching window/path (default Chrome Dev) |
--page-title-hint=TEXT |
Title must contain this (auto from URL if empty) |
--page-ready-timeout=MS |
Max wait for page/input (default 10000) |
--page-ready-min=MS |
Min wait after navigate (default 500) |
--no-uia |
Title-only wait (disable UI Automation) |
--no-extension |
Skip Chrome companion; UIA-only path |
--hotkey-on-press |
Fire on key-down (default is on-release) |
--hotkey-release-timeout=MS |
Max wait for key-up (default 3000) |
--insert-only |
Paste template only (no browser flow) |
--config=PATH |
Override user ini path |
--self-test |
Headless checks, exit 0/1 |
--help |
Help text |
Optional MV3 extension gives reliable DOM paste (preferred over UIA when connected).
- Run the tray app once (registers native messaging host under
%LOCALAPPDATA%\QiuckPrompts\nm\). - Chrome/Edge → Developer mode → Load unpacked →
extension/(orbuild\Debug\extension). - Keep extension enabled; id should be
aodehlngahndannepofbddnacfaldmih.
Details: extension/README.md. Disable with prefer_extension=0 or --no-extension.
This project ships installable binaries via GitHub Releases using Velopack (Setup + in-app updates) and a plain zip.
CI builds on every push/PR as 0.0.0-dev. Pushing a version tag injects that
version into the binary (CMake -DQP_RELEASE_VERSION=), builds RelWithDebInfo, runs
vpk pack, and publishes a Release:
git checkout master
git pull
git tag v0.3.2
git push origin v0.3.2| Item | Detail |
|---|---|
| Trigger | Git tag matching v* |
| Version | Tag without v → PE + About + Velopack pack version + Chrome companion manifest.json (X.Y.Z only) |
| Local/PR | Always 0.0.0-dev (not a release); companion stamped 0.0.0 beside Debug exe |
| Beta tags | e.g. v1.0.0-b1 (SemVer pre-release; GitHub prerelease; companion stamped 1.0.0) |
| Build | RelWithDebInfo (MSVC x64) |
| Installer | QiuckPrompts-win-Setup.exe (Velopack one-click → %LocalAppData%\QiuckPrompts) |
| Portable | QiuckPrompts-win-Portable.zip (Velopack portable layout) |
| Feed | releases.win.json + *-full.nupkg (in-app update) |
| Zip | qiuckprompts-<tag>-win-x64.zip (raw exe + config + extension) |
| Notes | Auto-generated from commits since previous tag |
- Download QiuckPrompts-win-Setup.exe and run (no admin).
- Config/logs stay in
%LOCALAPPDATA%\QiuckPrompts\(not wiped by updates). - Tray → Check for updates… fetches the latest feed and applies via
Update.exe. - Tray → Start with Windows (checked) registers HKCU Run for the Velopack stub when installed.
Chrome companion after Setup:
| Step | What |
|---|---|
| Install/update hook | Registers native messaging host; copies packaged extension/ → %LOCALAPPDATA%\QiuckPrompts\extension (stable path). Companion version = app PE X.Y.Z. |
| You once | Chrome → Load unpacked → that stable folder (not current\extension) |
| After app update | Extension files are re-copied to the same path — click Reload on chrome://extensions if Chrome still shows the old companion version |
| Uninstall | NM registry keys removed; your config/logs/extension folder are left |
Local pack (needs vpk):
dotnet tool install -g vpk
scripts\build.bat
cmake --build build --config RelWithDebInfo
scripts\pack-velopack.bat 0.3.2Default feed URL: https://github.com/summeroff/qiuckprompts/releases/latest/download
Override: update_url= in ini or --update-url=.
See CONTRIBUTING.md for branch/PR workflow and release checklist.
See CODING_STYLE.md. Braces are Allman-style ({ on its own line); } else { stays joined. CI runs clang-format.
scripts\format.bat :: apply
scripts\format.bat --check :: CI-style checkExtension paste helpers:
node --test tests\paste_logic.test.cjsUse feature branches and squash-merge PRs into master — details in CONTRIBUTING.md.
| Path | Role |
|---|---|
config/qiuckprompts.ini |
Shipped template (hotkeys + prompts). Live copy is AppData. |
%LOCALAPPDATA%\QiuckPrompts\ |
User config, logs, backups, NM host, stable extension |
include/config.hpp |
Built-in fallback bindings + workflow knobs |
src/workflow.cpp |
Send-to-AI pipeline (extension → UIA fallback) |
src/ext_bridge.cpp |
Named pipe + native-messaging host relay |
extension/ |
MV3 companion (DOM composer paste) |
extension/paste_logic.js |
Shared paste/URL helpers (Node + content + background) |
tests/paste_logic.test.cjs |
Node unit tests for those helpers |
src/browser.cpp |
Find / activate browser window |
src/page_ready.cpp |
Title + UI Automation wait |
src/title_sample.cpp |
TITLE_SAMPLE → titles.log |
src/hotkeys.cpp |
Global hotkeys, fire-on-release |
src/injector.cpp |
Insert-only paste path |
src/input_sim.cpp |
Keys, clipboard, focus helpers |
src/tray.cpp |
Notify icon + menu |
.github/workflows/ci.yml |
Build, test, tagged releases |
For tuning pageTitleHint / browser matching:
- Run the app
- Open AI tabs in Chrome
- Tray → Sample window titles now
- Tray → Open titles.log →
%LOCALAPPDATA%\QiuckPrompts\logs\titles.log
Lines are tagged TITLE_SAMPLE with stable where= fields.
- User data lives under
%LOCALAPPDATA%\QiuckPromptsso installers/updates cannot clobber config or logs. - Chrome does not expose the chat box as a Win32
HWND. Prefer the MV3 companion (DOM); readiness otherwise uses the UI Automation tree plus the tab title. - Hotkeys arm on press and run on release so Ctrl/Alt are up before Select-all/Copy/Paste.
- Send-to-AI / insert-only run on a worker thread; the tray message loop stays responsive. COM/UIA is initialized per-thread.
- After app update, Reload the unpacked companion if the tray warns that versions differ.
- Hidden top-level HWND (not
HWND_MESSAGE) so a second launch can FindWindow + take over. - Binding
url=andupdate_url=must behttps://. The updater refuses HTTPS→HTTP redirects.
MIT — see LICENSE.