Clipboard assistant for Windows with hotkeys and a popup answer window, plus its installer, built as one Cargo workspace.
.
├── Cargo.toml # workspace + shared dependency versions
├── assets/ # icon.ico (embedded in both exes), joker.png
├── config/config.ini # sample configuration (copied next to joker.exe)
├── scripts/ # build.ps1 (dev build), publish.ps1/.bat (release zip)
├── .vscode/ # tasks.json + build.ps1 (Ctrl+Shift+B menu)
├── crates/
│ ├── shared/ # config model + INI load/validate/write, paths, errors
│ ├── core/ # pure logic: hotkey state machine, popup sizing, prompt building
│ ├── services/ # chat API client, clipboard, processes, Task Scheduler (schtasks XML),
│ │ # UAC elevation
│ ├── app/ # joker.exe: global input hook, Win32 popup, event loop
│ └── installer/ # joker_installer.exe: menu, validation, install/uninstall
└── tests/ # cross-crate integration tests
Dependency direction: app and installer depend on services, core
and shared; services depends on core and shared; core depends on
shared; shared depends on nothing internal.
- Windows 10/11
- Rust stable (1.80 or newer). Both the MSVC and the GNU toolchain work.
- Optional: a resource compiler (
rc.exefrom the Windows SDK, orwindresfrom MinGW) to embed the icon. Without one the build still succeeds and prints a warning.
cargo build --workspace --release
# or: builds and copies joker.exe, joker_installer.exe and config.ini to .\app\
powershell -ExecutionPolicy Bypass -File scripts\build.ps1Executables: target\release\joker.exe (no console window) and
target\release\joker_installer.exe (console). Debug builds of joker.exe
keep a console so log output is visible while developing.
scripts\publish.ps1 (or double-click scripts\publish.bat) builds the
release binaries and assembles a ready-to-ship folder plus archive under
dist\:
dist\joker-v<version>\ joker.exe, joker_installer.exe, config.ini, README.txt
dist\joker-v<version>-windows-x64.zip
dist\joker-v<version>-windows-x64.sha256.txt
Options: -NoZip (folder only), -SkipBuild (reuse target\release),
-Clean (wipe dist\ first), -OutputDir <path>, -AppName <name> and
-Description <text>. The version comes from Cargo.toml. The installer
installs the joker.exe sitting next to it, so the zip is self-contained.
-AppName / -Description rename the product. With -AppName "SchoolEasy"
the output is dist\schooleasy-v<version>\ containing schooleasy.exe and
schooleasy_installer.exe, the installer looks for schooleasy.exe next to
itself, defaults the installation / task name to schooleasy, shows
"SCHOOLEASY SETUP" in its banner, the app logs to schooleasy.log, and both
executables carry the name and description in their Windows version info
(ProductName / FileDescription, the values Explorer's Details tab and
Task Manager show). The values travel through environment variables set
while building: JOKER_APP_ID (lower-case file name stem) and
JOKER_APP_NAME are read by crates\shared\src\constants.rs,
JOKER_APP_NAME / JOKER_APP_DESCRIPTION by the two build.rs files. A
plain cargo build without them produces the usual joker / Joker.
In VS Code, Ctrl+Shift+B lists the same actions; Joker: Publish...
prompts for the app name and the description before it runs.
Put config.ini next to joker.exe (or in the working directory), fill in
api_key, then start joker.exe.
key_exit(defaultKey.esc): toggle Joker on/offkey_pop(default1): send the clipboard text to the model and show the answerkey_repop(default2): show the last answer again- Right click: sends Ctrl+C so the selection is copied (only while enabled)
The popup is placed by two [window] settings: anchor picks the screen
corner the offset starts from (top-left, top-right, bottom-left,
bottom-right or center; default bottom-left) and position = +X+Y is the
distance from that corner, e.g. anchor = bottom-right with
position = +20+20 puts it 20 px from the right and bottom edges. A -
sign measures from the opposite edge instead. The popup is sized to its
text and only wraps when it would leave the screen.
Only one instance runs at a time. Set enabled = true in the [log]
section of config.ini to write joker.log next to the executable (debug
builds also print to the console). The section is optional and defaults to
false; a config file that cannot be loaded is always reported in
joker.log so the error is visible.
joker_installer.exe with no arguments shows the interactive menu and asks
for elevation through UAC. Use the arrow keys and Enter to navigate, Esc to
cancel; inputs are validated as you type and a summary of the plan is shown
before anything is changed. When stdin is not a terminal (scripts, pipes)
the same prompts fall back to plain numbered/line input.
- Install Joker takes the
joker.exenext to the installer (suggested; any otherjoker.execan be typed in) and either copies it into<folder>\<name>with a freshconfig.iniand the autostart task (default), or uses it where it is:config.ininext to it only if missing (an existing one is kept untouched) plus the autostart task, nothing copied. The task starts Joker at logon and on session unlock. - Uninstall Joker removes the task, stops the app and deletes the folder.
Unattended use:
joker_installer.exe install --dir C:\Users\me\Documents --name joker -y # copies the joker.exe next to the installer
joker_installer.exe install --exe D:\tools\joker.exe --dir C:\apps -y # copies another joker.exe
joker_installer.exe install --exe D:\tools\joker.exe -y # uses it where it is ("setup" is an alias)
joker_installer.exe uninstall --dir C:\Users\me\Documents --name joker -y
joker_installer.exe --help--skip-task skips the Task Scheduler step, --no-elevate skips the UAC
prompt (registration then fails unless the console is already elevated).
cargo fmt --all --check
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test --workspace
cargo test --workspace -- --ignored # from an elevated console: imports the task XMLThe tests need no network, no admin rights and no GUI: the API call hits a local one-shot server, the popup is exercised only through pure sizing logic, and installer flows run against temporary folders.