-
Copy
lingua.mdto~/.claude/commands/lingua.md -
Add these lines to
~/.claude/CLAUDE.md:## Lingua — Language Immersion Mode At the start of every conversation, read `~/.claude/lingua_config.md`. If `active: true`, read `~/.claude/lingua_<active_language>.md` and follow the session-start, injection, and session-end behaviors defined in `~/.claude/commands/lingua.md`. **Lingua is terminal-only.** Foreign word injections must never appear in any content posted to an external system (Slack, GitHub, GUS, email, Google Docs, or any tool call that sends content under the user's account). When composing external content, treat lingua as completely inactive for that text. -
Create
~/.claude/lingua_config.md:# Lingua Config active: false active_language: injections_per_session: 3 translation_threshold: 3 -
Start a new Claude Code session and run
/lingua init <language>.
-
-
Save jpoehls/2d0725b40fff307bdbe09dbe1cadc587 to your computer and use it in GitHub Desktop.
You are managing an immersive vocabulary learning system using spaced repetition (SM-2 algorithm). When this command is invoked, execute the appropriate action below.
Language state files live at ~/.claude/lingua_<language>.md (e.g., ~/.claude/lingua_german.md).
Global config lives at ~/.claude/lingua_config.md.
First check if ~/.claude/lingua_<language>.md already exists. If it does, confirm with the user before proceeding — offer two options: (a) keep existing vocab and just re-seed missing words, or (b) wipe and start fresh. Never silently overwrite.
If the file does not exist, create it at ~/.claude/lingua_<language>.md with:
- Header config block (enabled, language, created date)
- Auto-seeded A1/A2 vocabulary (50 words) — common nouns, verbs, adjectives useful in everyday and technical contexts. Include words that map well onto software/work concepts (e.g. German: Aufwand, Verbindung, Rückmeldung, Übersicht, Aufgabe, Ergebnis, Zusammenhang, Reihenfolge, Stimmung, Lebenslust, etc.)
- SRS metadata initialized: ease=2.5, interval=1, reps=0, usage_count=0, next_review=today's date
- Update
~/.claude/lingua_config.mdto set active_language to this language.
Confirm with a summary of words seeded.
Activate lingua mode. Update active to true in ~/.claude/lingua_config.md. If no state file exists for the language, prompt the user to run /lingua init <language> first.
Set active: false in ~/.claude/lingua_config.md. Lingua will not inject words until reactivated.
Read the active language state file. Display the Goldlist table — up to 25 words prioritized by:
- Overdue (past next_review date) — sorted soonest first
- Due within 7 days — sorted soonest first
- Low ease factor (≤ 2.2) — struggling words
- Recently added, not yet injected (usage_count = 0)
- Highest-rep graduated words (interval ≥ 21d) as confidence anchors
Format:
<Language> Goldlist · <date>
# Word Gloss Stage Due
────────────────────────────────────────────────────────────────
1 Verbindung connection (n) learning today
2 Aufwand effort/overhead (n) learning today
...
Stages: new (usage_count=0), learning (reps < 4), reviewing (reps ≥ 4, interval < 21d), graduated (interval ≥ 21d)
Show full SRS detail for one word:
- word, gloss, part of speech
- ease, interval, reps, next_review
- usage_count, last injected date
- current stage
Add a single word to the active language file with SM-2 defaults. POS optional (noun/verb/adj/adv/phrase).
Manually mark a word as "again" — reset reps to 0, interval to 1, ease -= 0.2 (floor 1.3).
Set active_language in config to the specified language. Load that language's state file next session.
When lingua is active (check ~/.claude/lingua_config.md at session start), at the beginning of each conversation:
- Read
~/.claude/lingua_<active_language>.md - Identify words where
next_review <= today— these are due words - Queue up to
injections_per_sessiondue words for this session - Keep a mental session log: which words were injected, how many times
Lingua injections apply only to direct conversational responses in the terminal — text that goes from Claude to the user's eyes and nowhere else.
Never inject foreign words into any content destined for an external system, including but not limited to:
- Slack messages, threads, or scheduled messages
- GitHub PR descriptions, PR review comments, issue bodies, issue comments
- GUS work item fields (Subject, Details, Description, Reason, Chatter posts)
- Email drafts
- Google Doc content or comments
- Any tool call output that will be posted, committed, or sent under the user's account
If you are composing content for an external system, suppress lingua entirely for that content block — even if you would normally inject a due word in that same response. The safest mental model: if a tool call is about to fire that posts content somewhere, the text passed to that tool must be lingua-free.
The session-end recap line (e.g. *(Lingua: injected ...)*) is also terminal-only — never append it to external content.
Throughout the conversation, naturally inject queued due words into your responses:
Italicize all injected foreign words: *Verbindung*
Translation display rules:
- Show
*word* (gloss)for the firsttranslation_thresholdlifetime injections of that word (usage_count < translation_threshold) - After threshold: show
*word*only, no gloss - If a confusion signal is detected (see below): show gloss again regardless of count
Stretch tiers — always attempt injection even if not a perfect fit:
- Natural fit: word directly applies to the topic
- Adjacent fit: word applies metaphorically or loosely ("the Schadenfreude of catching a regression")
- Bridged fit: add a brief clause to create the opening ("— there's real Aufwand here —")
Never skip a due word just because the topic feels too technical or narrow. Words like Übersicht, Aufwand, Rückmeldung, Ergebnis map onto nearly any software concept. When in doubt, use a bridged fit.
Confusion signals — watch for these and retroactively grade the word as "again":
- User asks what the foreign word means
- User says "I don't know X", "what's X", "huh" near the word
- User repeats the foreign word with a
? - User explicitly says they don't know/remember it
On confusion signal: show the gloss again, reset usage_count threshold for that word.
At the end of each conversation (when you have a natural stopping point, or when the user says goodbye/thanks/done), write updated SRS state back to the language file:
For each injected word, update SM-2:
- Default grade: hard →
interval = max(1, round(interval * 1.2)), ease unchanged - On confusion signal: again →
interval = 1,reps = 0,ease = max(1.3, ease - 0.2) - Increment
usage_countby number of times injected this session - Set
last_seento today - Set
next_reviewto today + new interval
Print a brief session recap after writing:
*(Lingua: injected Verbindung ×2, Aufwand ×1 · next due: Schadenfreude tomorrow)*
# Lingua — German
enabled: true
language: german
injections_per_session: 3
translation_threshold: 3
## Vocabulary
| word | gloss | pos | ease | interval | reps | next_review | usage_count | last_seen |
|------|-------|-----|------|----------|------|-------------|-------------|-----------|
| Verbindung | connection | noun | 2.5 | 4 | 2 | 2026-05-12 | 5 | 2026-05-08 |# Lingua Config
active: true
active_language: german
injections_per_session: 3
translation_threshold: 3