JevChat-Windows: OCR read of your own chat window to draft reply candidates
JevChat-Windows:聊天窗口旁挂的回复辅助。窗口截图 + 本地离线 OCR 读对方消息 → Jev 判断意图 → 3 条候选一键填入,发送永远手动
At a glance
- What is it?
- A Windows desktop tool that screenshots your own chat window, reads it with offline OCR, asks two models to judge intent and draft three replies, and pastes them into the input box without ever pressing send.
- Who is it for?
- Adopt JevChat-Windows if you reply to a lot of chat messages in English or Chinese and want help judging tone before you write, and you are comfortable with the reading window contents being sent to the model provider you configure. Do not adopt it if you need it to send messages, if your provider cannot receive the context payload it requires, or if you need a chat client that is not WeChat or KakaoTalk, since the project maintains only those two recognisers.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 28 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The pipeline is screen capture, OCR, then two model calls
The mechanism is fully described in the project documentation, and it reads as a pipeline. Windows Graphics Capture grabs the chat window, which works for GPU-composited windows and for windows that are covered by other windows. Pixel anchors then locate the message area by recognising background colour and separator lines rather than hardcoded coordinates, so the same code works in light and dark themes. The OCR of the panel header reads the conversation name and uses it as a key, and the header is only re-read when its pixels change. RapidOCR then runs on the message area only, and the frame is split into me and her by bubble colour, with grey text filtered out, covering quoted blocks, timestamps, speaker names in group chats and link cards. Speaker names are extracted and attached to the message below them.
Frames are compared with the previous one so that older messages scrolled into view are not reported again. Only when a new message from the other side appears does the code call `core.engine.analyze()`, which runs in three stages: Jev judges with seven questions, that judgement is fed to the drafting model as a brief for writing three candidates, and Jev then only ranks the results.
The architectural decision that matters is process separation. Screenshots and OCR run in a separate child process, because a frame takes 250 to 800 milliseconds of OCR time and doing that on the Qt main thread would freeze the interface. The parent process handles only the interface and the network calls.
Only WeChat and KakaoTalk are recognised, by design
The project is explicit that it maintains one recognition setup only, and that people who want to adapt a different chat window should fork it themselves, with the author declining to provide that adaptation and declining responsibility for forked changes. There is no plug-in interface for adding a new application.
The supported table lists two entries. WeChat uses RapidOCR with its Chinese and English models, its own bubbles are green, and the target is the main window titled 微信. KakaoTalk uses Windows.Media.Ocr from the system language packs, offline, its own bubbles are `#FEE500`, and the target is one window per conversation, excluding the main list window.
The Korean case is the interesting part, because it shows what went wrong and how it was fixed. RapidOCR ships only Chinese and English models, so Korean text came out as garbled output. The documentation reports a measurement of eight bubbles in one KakaoTalk window with zero correctly recognised, a frame time of 2.0 seconds, and every bubble judged as coming from the other side, because the bubble colour rule only knew WeChat green. Switching the Korean interface to the built-in Windows OCR produced nine bubbles all recognised correctly, with the speaker sides distinguished, at 0.20 seconds per frame. The approach and the measurements are written up in docs/KOREAN.md, and adding another application is described as a single line in `app/chatapps.py`.
That single-line claim applies to the framework, not to the model problem. A language that the OCR backend cannot read is a separate piece of work.
Two keys, two jobs, and a hard rule about sending
The settings page splits the model configuration into two cards. The judgement card, labelled Jev, judges intent and tension and ranks three candidates, and it can use OpenRouter, which is the default, or a direct TypeSafe connection. The drafting card writes the candidates themselves, and it defaults to the DeepSeek official API, with OpenAI, Anthropic and Gemini protocols all supported plus a custom base URL.
Only two environment variables hold secrets: `JEV_API_KEY` for judgement and `LLM_API_KEY` for drafting, regardless of which provider you picked. They are written to the Windows user environment in the registry under `HKCU\Environment`, the same place `setx` writes, and they never appear in a file or in a log, where error text is masked. Older versions stored `OPENROUTER_API_KEY` and `DEEPSEEK_API_KEY` per source; those are still read and migrated to the new names on save. Everything else lives in a `config.json` next to the executable, so copying the folder carries the settings with it.
The rule that defines the project is stated more than once: sending is always manual. The program pastes text into the input box and stops, never pressing enter and never clicking the send button. The debug window, the settings page and the pause switch all reinforce it, and the pause control stops the Windows Graphics Capture session entirely, including the yellow capture border on Windows 10, while leaving existing candidates usable and copyable.
What actually leaves the machine
The privacy section is specific enough to be checked, which is unusual and worth taking at face value only after reading it carefully.
The project runs no server of its own. When a trigger fires, the payload sent is fixed: the last N conversation texts, where N is the reference context setting defaulting to 10, with speaker names in group chats, plus the relationship setting, plus your own last 12 messages of 60 characters or fewer as a tone sample where links and long passages are not sent, plus your own style description, plus a reply target name if you set one in a group chat. OCR runs offline throughout. The only other outbound request is an optional update check at startup, a single GET to the GitHub Releases API carrying only a user agent and the current version number, which can be switched off in the settings, and which does not happen when running from source since there is no version number.
The capturing side has matching guarantees. Frames are numpy arrays held in memory; they are never written to disk, never logged and never uploaded, and the main program directories `app/` and `core/` contain no `.save()` call. The development scripts under `probe/` and `tools/` do save images as files, but they are not part of the release package, so the exe a normal user receives does not contain them. The debug view draws the same in-memory frame in a child process, receives it over a process queue, and discards it after drawing.
The boundary the project draws around money is equally explicit: transfer, red packet and payment receiving interface elements are never touched, and the drafting system prompt forbids those topics.
Download and run, or build it yourself
The recommended path is to download the latest release and run it. The release artefact is a zip named `jev-chat-windows-vX.Y.Z.zip`, roughly 146 MB, which you unpack to a fixed directory, keeping the whole folder together because the executable needs the files next to it, and then double-click `jev-chat-windows.exe`.
Requirements are Windows 10 1903 or later, or Windows 11, with the chat window open, and two API keys. On first launch a settings page asks for them. The executable is not signed, so SmartScreen will warn and you have to go through more information and run it anyway. The documentation's own suggestion for anyone uncomfortable with that is to package it yourself.
For developers, the repository has `main.py`, an `app/` directory for the interface, `core/` for the engine, `probe/` and `tools/` for diagnostics, `docs/`, a `jev.spec` file for the packager, a `build.bat` script, `requirements.txt` and a LICENSE and NOTICE pair.
The requirements file carries one warning that matters if you run from source, and these two lines are the whole story of the dependency pinning:
rapidocr-onnxruntime>=1.4,<2 # offline Chinese OCR; 1.2.x rejects det_limit_* ctor args and 1.4.x has no text_detector attr, so pin 1.4; all 1.4.x require Python <3.13 - on 3.13+ pip silently falls back to 1.2.3 (KeyError at startup)
numpy # frames are numpy arrays; chat-area detection is all numpyThe comment on the OCR line explains it. `rapidocr-onnxruntime` is pinned to the 1.4 series because 1.2.x rejects the det_limit constructor arguments while 1.4.x has no text_detector attribute, and every 1.4.x build requires Python below 3.13, so on Python 3.13 or newer pip silently falls back to 1.2.3 and the application fails at startup with a KeyError. The file is deliberately ASCII only, since pip on Chinese Windows decodes it as GBK and chokes on UTF-8 comments. The model SDKs are installed as official clients, one per protocol, with no hand written HTTP calls, and `windows-capture` provides the Windows Graphics Capture support that reaches GPU-composited windows.
Two API calls per new message, and what each one buys
Cost is described in terms that are unusually concrete. A model call happens only when the other side sends a new message: one drafting call and one judgement call. Ten minutes of silence means ten minutes of zero calls. The thinking mode is off by default, and the documentation advises leaving it off, since drafting three sentences does not need it and it makes things several times slower and more expensive.
The reason drafting defaults to the DeepSeek official API rather than OpenRouter is explained in terms of latency rather than quality. Drafting is the heavier of the two calls, OpenRouter sits abroad and takes several seconds from China with intermittent failures, while the DeepSeek official API at `api.deepseek.com` is reachable directly and makes drafting roughly one HTTP request. Judgement is much lighter, so the default of OpenRouter is acceptable there, and the documentation suggests switching it to the TypeSafe direct connection if the latency is bothersome.
For judgement, the OpenRouter route uses the alpha decisions endpoint at `openrouter.ai/api/alpha/decisions` with the model `typesafe/jev-1.13`, and the TypeSafe direct route uses the official `typesafe-sdk` against `api.typesafe.ai` with `jev-latest`.
The judging and ranking core comes from an Android project, `Finderchangchang/jev-chat-JARVIS`. The judgement itself runs seven questions and produces a summary of suggested action, probable intent, what the other person may need, and a tension score from 0 to 9. The three candidates are then ranked by Jev with a win probability percentage, the recommended one pinned to the top and marked, and each candidate has both a fill-in button and a copy button.
Where this is the wrong tool
There are three honest limits.
The first is language coverage. The OCR layer works for Chinese and English through RapidOCR and for Korean through the Windows system packs. A conversation in any other language is not covered by either recogniser, and the Korean write-up shows what a language mismatch looks like in practice: every bubble misclassified and a frame time four times worse. The project maintains only the WeChat and KakaoTalk recognition setups, and does not provide adaptation for others.
The second is that the tool reads only what a screen capture can see. It captures one window at a time. A desktop client with several conversations in one window, or a web chat inside a browser tab, is not the shape it was built for. The group chat handling works because it parses speaker names out of the message area and attaches them to the following message, which depends on the rendering convention of the supported clients.
The third is a licensing question that has to be read rather than assumed. The licence classification on the repository is one GitHub cannot categorise, with the terms in the LICENSE file and a NOTICE file beside it. For a personal tool that is easy to accept; for anything shipped inside a company, the file should be read before use.
On the maintenance side, the repository is not archived, the last push was on 2026-09-28, and the tags v0.1.10, v0.1.11 and v0.1.12 all landed in the last week of September 2026, with v0.1.10 named for its change, judging before drafting. The project is pre-1.0 and moving quickly.
Editorial conclusion
Adopt JevChat-Windows if you reply to a lot of chat messages in English or Chinese and want help judging tone before you write, and you are comfortable with the reading window contents being sent to the model provider you configure. Do not adopt it if you need it to send messages, if your provider cannot receive the context payload it requires, or if you need a chat client that is not WeChat or KakaoTalk, since the project maintains only those two recognisers. Verify first that the exe you download is unsigned, that JEV_API_KEY and LLM_API_KEY are the only two secrets stored, and that the configured provider is one you accept receiving the last N messages.
Frequently asked questions
Does JevChat-Windows send chat messages automatically?
No. The program pastes the text into the input box and stops. It never presses enter and never clicks the send button, and the documentation states as a hard constraint that sending is always manual.
Which chat applications does JevChat-Windows support?
Only WeChat and KakaoTalk. The project maintains just this one recognition setup and asks anyone who wants another chat window to fork it and adapt it themselves, adding a line in app/chatapps.py for a new application.
How does JevChat-Windows read the chat, and is the screenshot stored?
It uses Windows Graphics Capture to screenshot the chat window and runs offline OCR on the message area, so the capture works even for GPU-composited or covered windows. Captured frames are numpy arrays kept in memory, never written to disk, logged or uploaded, and the main program directories contain no save call.
What data does JevChat-Windows send to the model provider?
The last N conversation texts with N defaulting to 10, the relationship setting, your own last 12 messages of 60 characters or fewer as a tone sample, your style description, and a reply target name if set in a group chat. The project runs no server of its own, and OCR stays offline.
Which API keys does JevChat-Windows need and where are they stored?
Two keys are needed, JEV_API_KEY for judgement and LLM_API_KEY for drafting, whichever providers you choose. They are written to the Windows user environment in the registry under HKCU\Environment and never appear in a file or a log, while the rest of the settings live in a config.json next to the executable.
Can I run JevChat-Windows from source on Python 3.13?
The requirements file warns against it. Every 1.4.x build of rapidocr-onnxruntime requires Python below 3.13, so on 3.13 or newer pip silently falls back to 1.2.3 and the application fails at startup with a KeyError.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jev-chat-jev-chat-windows)Was this useful?