A spaced-repetition CLI for LeetCode practice problems
Project description
Jobbernaut Sensei
My Python solutions for LeetCode problems, with a built-in spaced-repetition review system.
Repository Structure
jobbernaut-sensei/
├── src/
│ ├── mark.py # mark a problem as reviewed
│ ├── new.py # scaffold a new problem file
│ ├── lopen.py # open a problem in editor + browser
│ ├── revisit.py # daily review runner
│ ├── hooks/
│ │ └── pre-commit # git hook: validate problem metadata
│ ├── completions/
│ │ └── _jobbernaut # zsh tab-completion for all commands
│ └── copy_templates/
│ ├── problem.py # copy this when starting a new problem
│ └── problem.md # copy this for your notes (optional)
├── problems/
│ ├── 1-arrays-and-hashing/
│ │ └── 217-Contains-Duplicate/
│ │ ├── 217-Contains-Duplicate.py
│ │ └── 217-Contains-Duplicate.md
│ ├── 2-two-pointers/
│ │ └── ...
│ └── ...
├── pyproject.toml
└── README.md
Setup
pip install -e .
This installs the sensei command globally so you can run it without python src/.
Daily Loop
1. Morning — see what's due
sensei revisit
# or: python src/revisit.py
2. Start a problem — scaffold it
sensei new 217 contains-duplicate 1-arrays-and-hashing -d easy -t arrays hash-set
# or: python src/new.py ...
3. Open a problem — jump back in
sensei open 217
# or: python src/lopen.py 217
4. After solving — mark it
sensei mark 217
sensei mark "valid anagram"
sensei mark contains-duplicate
# or: python src/mark.py ...
You'll be prompted with one question:
How did it go?
[e] easy → 90 days
[g] good → 30 days
[h] hard → 7 days
[s] struggled → 3 days
Press one key. last_solved and revisit_in_days are updated automatically.
Commands
sensei revisit — daily review runner
sensei revisit
Example output:
📅 LeetCode Revisit — Thursday, May 14 2026
🔴 OVERDUE
──────────────────────────────────────────────────────────────────────────
7d ago [easy ] 217. Contains Duplicate (arrays, hash-set)
🟡 DUE TODAY
──────────────────────────────────────────────────────────────────────────
today [medium ] 1. Two Sum (arrays, hash-map)
🟢 UPCOMING (7 days)
──────────────────────────────────────────────────────────────────────────
in 2d [medium ] 49. Group Anagrams (arrays, hash-map)
──────────────────────────────────────────────────────────────────────────
2 problem(s) need attention today. Total tracked: 3
| Flag | What it does |
|---|---|
| (none) | Overdue + due today + upcoming 7 days |
--all |
Everything, including far-future problems |
--topic arrays |
Filter by topic tag (partial match) |
--export |
Export all problems to export.csv |
--export-md |
Export all problems to export.md |
sensei new — scaffold a new problem
Creates the folder and pre-fills all metadata:
sensei new 217 contains-duplicate 1-arrays-and-hashing
sensei new 217 contains-duplicate 1-arrays-and-hashing -d easy -t arrays hash-set
sensei new 217 contains-duplicate 1-arrays-and-hashing -d easy -t arrays hash-set --open
| Argument | Description |
|---|---|
number |
LeetCode problem number |
slug |
LeetCode URL slug, e.g. contains-duplicate |
category |
Topic folder, e.g. 1-arrays-and-hashing |
-d / --difficulty |
easy / medium / hard (default: medium) |
-t / --tags |
One or more topic tags |
--open |
Open the file in $EDITOR / code immediately |
The URL is derived automatically from the slug:
contains-duplicate → https://leetcode.com/problems/contains-duplicate/
sensei open — open a problem
Opens the solution file in your editor and the LeetCode page in your browser:
sensei open 217
sensei open contains-duplicate
sensei open "valid anagram"
sensei open 217 --no-browser # editor only
Accepts problem number, slug, or title words — same fuzzy matching as mark.
sensei mark — mark a problem as reviewed
sensei mark 217
sensei mark "valid anagram"
sensei mark contains-duplicate
Updates last_solved to today and sets revisit_in_days based on your rating.
Adding a New Problem
The new command handles everything in one step:
sensei new 217 contains-duplicate 1-arrays-and-hashing -d easy -t arrays hash-set --open
Manual alternative
-
Create the folder following the naming convention:
problems/{category}/{number}-{Title-In-Kebab-Case}/ -
Copy the Python template:
cp src/copy_templates/problem.py problems/1-arrays-and-hashing/217-Contains-Duplicate/217-Contains-Duplicate.py
-
Optionally copy the Markdown template for notes:
cp src/copy_templates/problem.md problems/1-arrays-and-hashing/217-Contains-Duplicate/217-Contains-Duplicate.md
The 4 Metadata Fields
Every .py solution file must have these 4 lines for revisit to track it:
| Field | Type | Example | Notes |
|---|---|---|---|
last_solved |
str |
"2026-05-14" |
ISO 8601 date — update every time you re-solve |
revisit_in_days |
int |
3 |
How many days until next review |
difficulty |
str |
"medium" |
easy / medium / hard |
topic_tags |
list |
["arrays", "hash-map"] |
Used for --topic filtering |
Suggested revisit_in_days schedule (spaced repetition):
- First time solving:
3 - Solved it clean on review: double it →
7, then14, then30 - Struggled on review: reset to
1or3
Pre-commit Hook
Validates that every staged .py file under problems/ has all 4 metadata fields filled in with non-placeholder values before allowing a commit.
Install once:
cp src/hooks/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Zsh Shell Completions
Tab-complete sensei subcommands, problem numbers/names for mark and open, and category names for new.
Add to ~/.zshrc:
fpath=(/path/to/jobbernaut-sensei/src/completions $fpath)
autoload -Uz compinit && compinit
Then reload: source ~/.zshrc
Topic Folder Names
All topic folders live under problems/. Full paths look like problems/1-arrays-and-hashing/.
| # | Folder |
|---|---|
| 1 | 1-arrays-and-hashing |
| 2 | 2-two-pointers |
| 3 | 3-sliding-window |
| 4 | 4-stack |
| 5 | 5-binary-search |
| 6 | 6-linked-list |
| 7 | 7-trees |
| 8 | 8-tries |
| 9 | 9-heap-priority-queue |
| 10 | 10-backtracking |
| 11 | 11-graphs |
| 12 | 12-advanced-graphs |
| 13 | 13-1d-dynamic-programming |
| 14 | 14-2d-dynamic-programming |
| 15 | 15-greedy |
| 16 | 16-intervals |
| 17 | 17-math-and-geometry |
| 18 | 18-bit-manipulation |
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 jobbernaut_sensei-0.1.0.tar.gz.
File metadata
- Download URL: jobbernaut_sensei-0.1.0.tar.gz
- Upload date:
- Size: 14.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c267e10cad72d343bdb82a8691c95be1597491cb5e095a809715c67aa09cf972
|
|
| MD5 |
83150457c7e48404ce161b1a1a1ac024
|
|
| BLAKE2b-256 |
34270bb58de27a1e1d2021c32f3e14866d28f63dd979cf0e28cb0fe7b30f2e0b
|
File details
Details for the file jobbernaut_sensei-0.1.0-py3-none-any.whl.
File metadata
- Download URL: jobbernaut_sensei-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4526c9e0208df326ccae68eea86946ebbf4a6f28a070be90b3a070f88d0d18e6
|
|
| MD5 |
b61cb12c1fb15ca8cea2cf8668ac1e13
|
|
| BLAKE2b-256 |
b53d33c3dccb7b97937f80ee3deef41a2c7c7a3edb6784c139ba58628482c128
|