Terminal spaced repetition for coding problems and reference solutions
Project description
Recode
A terminal-based spaced repetition tool for practicing any code from memory. Write implementations, compare against reference solutions with a side-by-side diff, get AI hints when stuck, and let the SM-2 algorithm schedule your reviews.
Features
- Spaced repetition — SM-2 algorithm schedules reviews so you spend time on what you actually need to practice
- Side-by-side diff — your attempt vs. the reference solution, line by line
- AI hints — Socratic nudges that guide you without just giving away the answer
- AI suggest fix — targeted bullet-point suggestions when you want more direct feedback
- OpenCode chat modal — conversational help in-context while you study a problem
- Agent-like chat tools — presets (
/nudge,/test-me), TODO capture, diff split view, and/health - 158 themes — full terminal.sexy palette, switchable live from the command palette
- Extensible — add any problem by dropping a
.py,.jl, or.Rfile into your writableproblems_dir
Screenshots
| Problem list with SM-2 schedule | Side-by-side diff |
| SM-2 rating (Again / Hard / Good / Easy) | AI Socratic hint |
AI suggest fix — targeted bullet-point suggestions
Requirements
- Python 3.10+
uv(recommended),pipx, orpip- A Gemini or OpenRouter API key
- OpenCode CLI on your PATH for in-app chat (auto-started by Recode)
Install
Homebrew
brew tap ever-oli/homebrew-tap
brew install ever-oli/homebrew-tap/recode
PyPI
uv tool install recode-cli
# or
pipx install recode-cli
Local dev
git clone https://github.com/ever-oli/recode.git
cd recode
uv sync
uv run python -m recode
Configuration
Recode reads environment variables from your shell, a local .env, or ~/.config/recode/.env.
Use recode --paths to print the exact runtime directories for your machine.
On first run, Recode seeds its bundled problem set into your writable problems_dir so generated and imported problems live beside the defaults instead of inside the installed package.
Example .env:
# Option A — Google Gemini
GEMINI_API_KEY=your_gemini_api_key_here
AI_PROVIDER=gemini
# Option B — OpenRouter
OPENROUTER_API_KEY=your_openrouter_api_key_here
AI_PROVIDER=openrouter
# Optional: override the editor (default: hx)
EDITOR=nvim
# Optional: override runtime locations
# PROBLEMS_DIR=/path/to/your/problems
# DB_PATH=/path/to/recode.db
# Optional: OpenCode server URL for in-app chat modal
# OPENCODE_SERVER_URL=http://127.0.0.1:4096
# Optional: disable automatic `opencode serve` on first chat request
# OPENCODE_AUTOSTART=0
Run
Once installed:
recode
Useful non-interactive commands:
recode --version
recode --paths
recode --doctor
Chat modal behavior (OpenCode)
By default, pressing c in a problem will auto-start a local OpenCode server if it is not already running.
The chat modal shows a live status line (connected, auto-started OpenCode, or offline).
In chat, type /health to print OpenCode connection diagnostics.
Use /help for chat commands and /clear to clear chat history in the modal.
Chat also supports /hint, /fix, /todo ..., preset prompts, and /split (or Ctrl+D) to show diff + chat side by side.
If you prefer running it yourself (or disabled auto-start), start it manually:
opencode serve --port 4096
Usage
| Key | Action |
|---|---|
Enter |
Open the selected problem |
/ |
Focus search |
c |
Change collection on the main menu |
g |
Generate problems from an arXiv paper |
i |
Import from Exercism or LeetCode |
r |
Refresh the problem list |
q / Ctrl+C |
Quit |
Inside a problem:
| Key | Action |
|---|---|
e |
Open the editor |
s |
Submit and review |
h |
Ask for a hint |
f |
Ask for a suggested fix |
c |
Open the in-problem chat modal |
x |
Explain the solution or gap |
q |
Return to the menu |
Workflow
- Select a problem from the list and press
Enter - Press
eto open your editor and write the implementation from memory - Save and close the editor
- Recode shows a side-by-side diff of your attempt vs. the reference
- Use Hint or Suggest Fix if you need AI assistance
- Rate your recall (Again / Hard / Good / Easy)
- SM-2 schedules the next review automatically
Adding Problems
Problems are plain .py, .jl, or .R files. Drop them into the writable problems_dir from recode --paths and they will appear in the list on the next refresh (r).
TensorPoly ships as a bundled collection and is copied into your writable problems directory on first run. The built-in importer currently supports Exercism Python and free LeetCode problems.
A problem file contains two things:
# The reference solution Recode compares against
SOLUTION = """
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
""".strip()
# The prompt shown in the problem list
DESCRIPTION = "Implement the sigmoid function using NumPy."
36 curated ML problems are included covering ResNet, Transformers, GANs, U-Net, ViT, and more.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file recode_cli-0.1.0.tar.gz.
File metadata
- Download URL: recode_cli-0.1.0.tar.gz
- Upload date:
- Size: 188.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca8c16f23bfc0cd7a29b0cb19d860988d2786fc1d2815f09ab962024e68004c9
|
|
| MD5 |
8e9920d65b0dc801ff0ded1b02634aa4
|
|
| BLAKE2b-256 |
d5ce3f76d940693caeed92c121128ad761507d2d3ead1f534750c0a9930b838b
|
Provenance
The following attestation bundles were made for recode_cli-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on ever-oli/recode
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recode_cli-0.1.0.tar.gz -
Subject digest:
ca8c16f23bfc0cd7a29b0cb19d860988d2786fc1d2815f09ab962024e68004c9 - Sigstore transparency entry: 1209127363
- Sigstore integration time:
-
Permalink:
ever-oli/recode@8bcc6cdeb7ff33b47338d3fb94c6372e548c95f4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ever-oli
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@8bcc6cdeb7ff33b47338d3fb94c6372e548c95f4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file recode_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: recode_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 381.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03a4b08f16f3f138bfea79d9042411d1bbcd0c12e17a1c332b0245d9d6e9d5be
|
|
| MD5 |
0fc208770aed0e3aabca9160f374640c
|
|
| BLAKE2b-256 |
1e3f0a636b8fa7f934d07d86d672b8092b74cc2ed1514d33528e41672aa70139
|
Provenance
The following attestation bundles were made for recode_cli-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on ever-oli/recode
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recode_cli-0.1.0-py3-none-any.whl -
Subject digest:
03a4b08f16f3f138bfea79d9042411d1bbcd0c12e17a1c332b0245d9d6e9d5be - Sigstore transparency entry: 1209127478
- Sigstore integration time:
-
Permalink:
ever-oli/recode@8bcc6cdeb7ff33b47338d3fb94c6372e548c95f4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ever-oli
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@8bcc6cdeb7ff33b47338d3fb94c6372e548c95f4 -
Trigger Event:
push
-
Statement type: