recto
A terminal app, in the spirit of Anki, to learn things by heart with flashcards.
A deck holds only question/answer pairs. When it is imported, a model writes variants of every card: the question asked the other way round when that makes sense, and a few rephrasings. Each review asks one variant at random, so you learn the knowledge, not one wording. You type the answer, the model scores it and says what was missing, and FSRS decides when the card comes back.
Install
uv tool install recto
Each tagged version is published on PyPI and has its wheel attached to a GitHub release.
Use
export OPENAI_API_KEY=...
recto
Press i to import a deck: one of the five examples (Anglais, Géographie, Vins, Maths, Histoire de France, 50 cards each) or your own TOML file. Then pick a deck and press enter to review, or c to browse its cards: pick one to see its variants, where you can add, edit, delete or generate more.
| Variable | Default | |
|---|---|---|
OPENAI_API_KEY |
Required: recto won't start without it | |
RECTO_MODEL |
gpt-5.4-mini |
Any OpenAI model name |
RECTO_DB |
the user data directory | Where reviews and variants are kept |
Write a deck
[deck]
name = "Vins"
description = "Cépages, appellations et régions viticoles françaises"
instructions = "Sois exigeant sur les appellations, tolérant sur l'orthographe des cépages."
[[cards]]
id = "chablis-cepage"
question = "Quel cépage domine les vins blancs de Chablis ?"
answer = "Chardonnay"
The file name is the deck id: importing vins.toml again updates the same deck. instructions is optional and is given to the model when it writes variants and grades answers. Each card needs an id, unique in the deck. Fixing a typo in a question keeps the card's history and regenerates its variants; changing its id starts it over. Cards removed from the file are removed from the deck.
How the code is organized
src/recto/
domain/ cards, variants, grades, FSRS memory, today's cards, what a re-import changes
ports/ what the app needs from outside: a deck repository, a variant generator, an answer judge, a clock
use_cases/ one class per action: import a deck, list decks, next card, submit an answer, manage variants
adapters/ SQLite, PydanticAI, the TOML deck files, the system clock, an in-memory repository
tui/ Textual screens, calling use cases only
decks/ the four example decks
container.py the one place where adapters are plugged into ports
Develop
make install
cp .example.env .env # then put your OpenAI key in .env, which git ignores
make run
make check
make help lists the other targets. Tests use fakes, never mocks: use cases run on an in-memory repository, a fake generator, a fake judge and a fixed clock, and the TUI tests drive the real app headless through Textual's Pilot. The SQLite repository is tested against a real database file.
Release
Every push builds the wheel in CI. Pushing a tag on a commit of main that matches the version in pyproject.toml publishes it on PyPI, through trusted publishing, and as a GitHub release:
uv version --bump minor
git commit -am "chore(release): 0.2.0"
git tag v0.2.0
git push origin main v0.2.0
Metadata
Release files for recto 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| recto-0.3.0.tar.gz | 28.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| recto-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 68.4 kB
Release files / recto-0.3.0.tar.gz
| Download URL | recto-0.3.0.tar.gz |
|---|---|
| Size | 28.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d9cd4805b92fe064e7c26a8ed96ca9d9310967aee58f9489a461496cb05ac71b
|
|
BLAKE2b-256 checksum How to use checksums |
0e8d9dfdab247922ed914bab6f00d6ebfa694ee8ab2831f5250ae90ee053e6bb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / recto-0.3.0-py3-none-any.whl
| Download URL | recto-0.3.0-py3-none-any.whl |
|---|---|
| Size | 39.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b02974b90b0b8c0fa560a15bf68d4503c159c88916920548e4f04f16b94802f7
|
|
BLAKE2b-256 checksum How to use checksums |
66343f9d82b1d38729cb3e7037e2d9085aa4eeb21bcee0fb1f1b1179eac2b688
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|