language

An iMessage language-learning buddy

2 min

Texts you like a bilingual friend. It chats mostly in your native language and naturally sprinkles in the language you're learning — picking words and phrases that fit the conversation, glossing what you don't know, gently modeling corrections, and remembering things about you across chats. No app, no lessons. Just a thread.

It reuses the self-hosted iMessage transport (forked from the marco/Bedrock stack): a dylib injected into Messages.app for sending + typing dots + read receipts, and a chat.db poller for inbound. The language-buddy agent loop is built on top.

Your iPhone iMessage chat.db poller inbound agent loop Claude + memory injected dylib send · dots · receipts Messages.app outbound

Layout

PathWhat it does
config.mjslanguages, level, model, whitelist (reads .env)
server.mjswires poller → agent → helper (run this)
core/agent.mjspersona + Claude call + remember tool → reply bubbles
core/memory.mjsper-handle profile + rolling conversation (.memory.json)
imessage/ported transport (poller, helper, injected dylib) — unchanged

Setup

  1. .env (already present, ported from marco). Needs your Anthropic key, plus any product knobs you want to override:
    ANTHROPIC_API_KEY=sk-ant-...
    TARGET_LANGUAGE=Korean       # the language you're learning  (default: Korean)
    NATIVE_LANGUAGE=English      # what the buddy mostly speaks   (default: English)
    LEVEL=beginner               # beginner | intermediate | advanced
    AGENT_NAME=Lingo             # the buddy's name
    MODEL=claude-opus-4-8        # snappier/cheaper: claude-sonnet-4-6
    # ALLOW_FROM=you@icloud.com  # optional: only engage these handles
  2. One-time host setup for the injected dylib (SIP off, library validation off, arm64e preview ABI). See imessage/README.md.
  3. Agent identity — sign Messages.app on the Mac into a separate Apple ID so you can text it from your own phone (see marco's DESIGN.md for the why/how).

Run

npm install
npm run messages   # terminal 1: launches Messages.app with the helper injected
npm start          # terminal 2: listens for the helper, polls chat.db, replies

Text the agent's Apple ID from your iPhone. You'll see read receipts, typing dots, and a few short bubbles back.

Notes