Jev copilot for macOS Messages (iMessage/SMS): reads the open chat, ranks reply candidates, never sends
Python
0
3 commits
updated Oct 1, 2026
A copilot that sits next to Messages.app on macOS (iMessage and SMS). When a new message comes in, a floating panel shows what the sender really means, a risk level, and reply candidates ranked by a judgment model. One click puts a candidate into the Messages input field. You always press Return yourself — the app never sends.
Read-only and non-invasive. It reads the Messages window through the macOS
accessibility (AX) API. No injection, no hooks, no reading of ~/Library/Messages/chat.db,
no screenshots, no AppleScript send.
Derived from jev-chat-jarvis-mac (WeChat / QQ). This repo keeps only the Messages.app adapter.
Probed on macOS 27.2 with the English UI (details: _reports/imessage-probe_report.md):
<sender>, <body>, <time>. Your own messages start with Your iMessage, ….Your … prefix confirms it.ConversationTitle button; the input is the messageBodyField text
field, which accepts an AX value write and reads it back.Check it on your machine (a chat must be open in Messages):
uv run python probe/imessage_probe.py # tree, frames, parsed messages (text masked)
uv run python probe/imessage_probe.py --fill hi # also write "hi" to an empty input, read back, clear
uv run python src/apps/imessage_app.py # the adapter's own read
jev-imessage-macos-latest.zip
(all releases). Unzip, drag
jev-imessage.app into Applications, then right-click → Open the first time (the app is
not notarized). If macOS says the app is damaged:
sudo xattr -r -d com.apple.quarantine /Applications/jev-imessage.app.
First launch installs its Python dependencies (network needed once).
.app. Screen Recording is not needed../start.command # Ctrl+C to quit
uv run python -B -m unittest discover -s tests # offline tests (fake AX tree, no screen, no API)
uv run python src/generate.py --check # generation credentials
One env file: ~/.config/jev-imessage/env (mode 600). The settings window (gear icon on the
panel) edits the same file. Restart after changing model settings.
mkdir -p ~/.config/jev-imessage
cat > ~/.config/jev-imessage/env <<'ENV'
# Judgment (intent, risk, ranking): TypeSafe Jev via OpenRouter
export TYPESAFE_API_KEY="" # your OpenRouter key
export TYPESAFE_BASE_URL="https://openrouter.ai/api/alpha/decisions"
export TYPESAFE_MODEL="typesafe/jev-1.13"
# Reply generation: any OpenAI-compatible endpoint (or ANTHROPIC_* for Anthropic format)
export OPENAI_API_KEY=""
export OPENAI_BASE_URL="https://api.openai.com/v1"
export OPENAI_MODEL=""
ENV
chmod 600 ~/.config/jev-imessage/env
max_tokens and no
candidates come back.export JEV_REPLY_LANGUAGE="Same as message". Restart after changing.See PRIVACY.md. In short: message text stays in memory on your Mac, except the text you send to the judgment and generation services you configure. Logs contain no message text.
Your iMessage prefix and time format are English), SMS vs RCS
sender prefixes. Direction falls back to bubble geometry, which is language-neutral.src/apps/imessage_app.py (run the probe first).MIT, see LICENSE and NOTICE. Keep both when you redistribute. This project is not affiliated with Apple.
Jev copilot for macOS Messages (iMessage/SMS): reads the open chat, ranks reply candidates, never sends
Python
0
3 commits
updated Oct 1, 2026
A copilot that sits next to Messages.app on macOS (iMessage and SMS). When a new message comes in, a floating panel shows what the sender really means, a risk level, and reply candidates ranked by a judgment model. One click puts a candidate into the Messages input field. You always press Return yourself — the app never sends.
Read-only and non-invasive. It reads the Messages window through the macOS
accessibility (AX) API. No injection, no hooks, no reading of ~/Library/Messages/chat.db,
no screenshots, no AppleScript send.
Derived from jev-chat-jarvis-mac (WeChat / QQ). This repo keeps only the Messages.app adapter.
Probed on macOS 27.2 with the English UI (details: _reports/imessage-probe_report.md):
<sender>, <body>, <time>. Your own messages start with Your iMessage, ….Your … prefix confirms it.ConversationTitle button; the input is the messageBodyField text
field, which accepts an AX value write and reads it back.Check it on your machine (a chat must be open in Messages):
uv run python probe/imessage_probe.py # tree, frames, parsed messages (text masked)
uv run python probe/imessage_probe.py --fill hi # also write "hi" to an empty input, read back, clear
uv run python src/apps/imessage_app.py # the adapter's own read
jev-imessage-macos-latest.zip
(all releases). Unzip, drag
jev-imessage.app into Applications, then right-click → Open the first time (the app is
not notarized). If macOS says the app is damaged:
sudo xattr -r -d com.apple.quarantine /Applications/jev-imessage.app.
First launch installs its Python dependencies (network needed once).
.app. Screen Recording is not needed../start.command # Ctrl+C to quit
uv run python -B -m unittest discover -s tests # offline tests (fake AX tree, no screen, no API)
uv run python src/generate.py --check # generation credentials
One env file: ~/.config/jev-imessage/env (mode 600). The settings window (gear icon on the
panel) edits the same file. Restart after changing model settings.
mkdir -p ~/.config/jev-imessage
cat > ~/.config/jev-imessage/env <<'ENV'
# Judgment (intent, risk, ranking): TypeSafe Jev via OpenRouter
export TYPESAFE_API_KEY="" # your OpenRouter key
export TYPESAFE_BASE_URL="https://openrouter.ai/api/alpha/decisions"
export TYPESAFE_MODEL="typesafe/jev-1.13"
# Reply generation: any OpenAI-compatible endpoint (or ANTHROPIC_* for Anthropic format)
export OPENAI_API_KEY=""
export OPENAI_BASE_URL="https://api.openai.com/v1"
export OPENAI_MODEL=""
ENV
chmod 600 ~/.config/jev-imessage/env
max_tokens and no
candidates come back.export JEV_REPLY_LANGUAGE="Same as message". Restart after changing.See PRIVACY.md. In short: message text stays in memory on your Mac, except the text you send to the judgment and generation services you configure. Logs contain no message text.
Your iMessage prefix and time format are English), SMS vs RCS
sender prefixes. Direction falls back to bubble geometry, which is language-neutral.src/apps/imessage_app.py (run the probe first).MIT, see LICENSE and NOTICE. Keep both when you redistribute. This project is not affiliated with Apple.