Terminal-based spaced repetition app, with these additions:
- The original card question stays unchanged.
- Your typed answer is graded on a 1-10 scale with feedback grounded in the card's ground truth.
- After grading, you can continue chatting per card and request a transfer question before moving on.
The app keeps normal SRS control via again/hard/good/easy.
- Multi-user web accounts (register, email verification, login, logout, password reset)
- Per-user private data isolation (decks, cards, sessions, reviews)
- Per-user encrypted OpenAI API key in profile settings
- SM-2 style scheduling for
again/hard/good/easy - Deck import from CSV or JSON
- SQLite persistence for decks, cards, states, sessions, and review events
- Free fallback tutor (no personal API key required)
- Optional personal OpenAI key upgrade for stronger grading/chat/transfer quality
- Web interface with dashboard, import page, and guided study session
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"export OPENAI_MODEL="gpt-4o-mini" # or e.g. gpt-5.2 for personal-key users
export MEMRY_SECRET_KEY="change-this-to-a-strong-secret"
export APP_BASE_URL="http://127.0.0.1:8000" # production: your HTTPS domain
export MEMRY_FREE_LLM_ENABLED=true # optional, default true
# optional for real verification/reset emails
export RESEND_API_KEY="re_..."
export MEMRY_FROM_EMAIL="noreply@yourdomain.com"Alternatively, put these values in a local .env file in the project root.
Notes:
- Users can study without a key via the built-in free fallback tutor.
- Each user can optionally configure a personal OpenAI key in
/profile. OPENAI_MODELcontrols which OpenAI model is used for personal-key requests.MEMRY_SECRET_KEYis required for secure session cookies and encrypted key storage.MEMRY_FREE_LLM_ENABLED=falsedisables the free fallback tutor.- In production, set
MEMRY_ENV=production. - In production,
APP_BASE_URLmust be a publichttps://...URL. - In production with auth enabled, startup requires:
- strong
MEMRY_SECRET_KEY(minimum 24 chars) APP_BASE_URLwithhttps://and non-localhost hostRESEND_API_KEYandMEMRY_FROM_EMAIL
- strong
- Auth debug links are disabled by default in production. Override only if needed with
MEMRY_AUTH_DEBUG_LINKS=true.
CSV (front,back,tags):
front,back,tags
What is ATP?,Adenosine triphosphate,bio;metabolismJSON:
[
{"front": "What is ATP?", "back": "Adenosine triphosphate", "tags": ["bio", "metabolism"]}
]Initialize DB:
anki2 --db anki2.db init-dbImport cards:
anki2 --db anki2.db import --deck biology --file ./cards.csv --format csvStudy:
anki2 --db anki2.db study --deck biology --limit 20Deck stats:
anki2 --db anki2.db stats --deck biologyStart web UI:
anki2 --db anki2.db serve --host 127.0.0.1 --port 8000You can pass auth/mail/runtime options explicitly:
anki2 --db anki2.db serve \
--require-auth \
--model gpt-4o-mini \
--secret-key "change-this" \
--app-base-url "https://your-domain.example" \
--resend-api-key "re_..." \
--from-email "noreply@yourdomain.com"Then open http://127.0.0.1:8000 in your browser.
Routes:
/public landing page/dashboardauthenticated app dashboard/auth/loginand/auth/registeraccount entry points
- Register at
/auth/register. - Verify email via the verification link.
- Login at
/auth/login. - (Optional) Set personal OpenAI key at
/profileto upgrade model quality. - Use dashboard/import/study normally as a private flashcard app.
GET /healthzreturns{"status":"ok"}.
- Connect this repo in Render and use
render.yaml. - Ensure a persistent disk is attached at
/var/data. - Set environment variables in Render:
MEMRY_ENV=production
MEMRY_AUTH_DEBUG_LINKS=false
MEMRY_SECRET_KEY=<strong-random-secret>
APP_BASE_URL=https://<your-service>.onrender.com
RESEND_API_KEY=re_...
MEMRY_FROM_EMAIL=noreply@yourdomain.com
OPENAI_MODEL=gpt-4o-mini
MEMRY_FREE_LLM_ENABLED=true- Deploy and verify:
GET https://<your-service>.onrender.com/healthzreturns{"status":"ok"}- registration email arrives
- verification link works
- login + profile API key save works