// ZSH-LEARN — MYSQL-BACKED LEARNING COLLECTION // SAVE / QUERY / QUIZ

zsh plugin · persistent flashcard / snippet store backed by MySQL/MariaDB · fzf fuzzy search · randomized recall · in-place $EDITOR

GitHub Issues
// Color scheme

>_ZSH-LEARN

Turn your terminal into a persistent knowledge base. Save snippets, one-liners, notes. Search with filters, fzf fuzzy matching, or random sampling. Drill yourself with randomized quizzes for spaced recall. Edit in-place with $EDITOR. Backed by MySQL/MariaDB.

Install

# Zinit
zinit ice lucid nocompile
zinit load MenkeTechnologies/zsh-learn

# Oh My Zsh
git clone https://github.com/MenkeTechnologies/zsh-learn \
    "$HOME/.oh-my-zsh/custom/plugins/zsh-learn"
# then: plugins+=(zsh-learn)

# Manual
git clone https://github.com/MenkeTechnologies/zsh-learn
source zsh-learn/zsh-learn.plugin.zsh

After install: zsh-learn-CreateLearningCollection generates the DDL and creates the table.

Configuration

Every knob is a ZPWR_* environment variable. The plugin sets defaults with test -z … && export, so anything you export before sourcing the plugin wins.

ZPWR_LEARN_COMMANDdefault mysql — database command every verb pipes SQL into (e.g. 'sudo mysql' for MariaDB unix-socket auth)
ZPWR_SCHEMA_NAMEdefault root — schema name for the learning table
ZPWR_TABLE_NAMEdefault LearningCollection — table name for stored entries
ZPWR_LEARN_MAX_SIZEdefault 3000 — character cap on le / editl inserts; also the learning column width in the generated DDL
ZPWR_LEARNset to false to skip all ZLE / bindkey / zstyle / fpath / autoload registration (opt-out)
ZPWR_COLORSset to true for ANSI-colorized se output
ZPWR_USE_NEOVIMset to true to make rsql open nvim instead of vim

Migration note: the default table name was LearningCollectiion (typo) before the rename. Existing installs: RENAME TABLE root.LearningCollectiion TO root.LearningCollection; — or keep the old name with export ZPWR_TABLE_NAME=LearningCollectiion.

Command matrix

Write — create, edit, delete entries.

le [-e] [-c CAT] LEARNINGinsert a new entry. -c sets the category (default programming); -e opens $EDITOR on a temp file instead of taking an inline argument
editl IDload entry ID into $EDITOR, then write the edit back as an UPDATE
del [N]delete the most-recent N entries (default 1)
delid IDdelete a specific entry by ID

Search — three tiers by projected columns, plus fzf browse.

se [FILTER...]search the learning column; each filter applied via ag -i (if installed) or grep -i; no filter dumps all rows numbered
see [FILTER]same, also projecting the category column
seee [FILTER]same, projecting id + date + learning + category
sefbrowse all entries in fzf (recency-first); the selection is pushed back as a re ID redo line

Randomized recall — spaced-repetition drilling.

ser [N]N random entries (default 100)
seraall entries in random order
qu [N]N random entries piped into fzf -m for an interactive quiz (default 100)
quaall entries randomized into fzf -m

SQL passthrough & admin.

re [ID|REGEX]...print a ready-to-run UPDATE onto the command line (print -rz); no arg = last entry; args resolve by numeric ID or regex
rsql [ID|REGEX]...same selection, but write the UPDATEs to a temp file, open in vim (or nvim), then apply on save
zsh-learn-CreateLearningCollection [PW]create the schema + table (category, learning, dateAdded, auto-increment id PK); optional first arg is the mysql password, else uses ~/.my.cnf
zsh-learn-DropLearningCollectiondrop the learning table

Each verb is reachable through typo-proof aliases (es/ees/ses/ese/sse/sseese; er/rerre) and is aliased with noglob so filter wildcards (*, ?, []) reach the function instead of expanding against the filesystem.

Key bindings

^k (viins + vicmd)zsh-learn-Learn — insert the current buffer as a learning entry

Workflow

# 1. one-time: create the schema + table
zsh-learn-CreateLearningCollection

# 2. save a learning (inline, default category 'programming')
le "git rebase -i HEAD~3  # interactive rebase last 3 commits"

# 3. save with a custom category, or compose in your editor
le -c git "git reflog  # recover lost commits"
le -e            # opens $EDITOR; whatever you write is the entry

# 4. search
se rebase        # learning column, filtered
see git          # also show category
seee             # id + date + learning + category, all rows

# 5. drill yourself: 50 random entries into fzf
qu 50
qua              # every entry, randomized, into fzf

# 6. fix an entry
editl 42         # edit entry 42 in $EDITOR
re 42            # push an UPDATE for entry 42 onto the command line
rsql rebase      # edit every 'rebase' match's UPDATE in vim, apply on save

# 7. delete
del              # delete the most recent entry
del 3            # delete the last 3
delid 42         # delete entry 42

The Ctrl-K widget saves whatever is currently on the command line as a learning without leaving the prompt — type a command, press Ctrl-K, and it is stored.

Troubleshooting

Nothing is stored / silent errorsThe database command's stderr is appended to $ZPWR_LOGFILE (default /tmp/.zpwr-log) to keep search output clean — check it. Confirm $ZPWR_LEARN_COMMAND connects: echo 'select 1' | mysql.
MariaDB needs sudo / unix-socket authexport ZPWR_LEARN_COMMAND='sudo mysql' before sourcing the plugin.
Table not found after upgradeThe default table was renamed from LearningCollectiion. Rename the old table or set ZPWR_TABLE_NAME=LearningCollectiion (see Configuration).
Entry rejected on saveLearnings over ZPWR_LEARN_MAX_SIZE characters (default 3000) are refused. Raise the cap or shorten the entry.
qu / qua / sef do nothingThese require fzf on PATH. The inline se / ser verbs work without it.
Bindings / completion not loadingIf ZPWR_LEARN=false is set, all ZLE / bindkey / zstyle / autoload registration is skipped by design. Unset it.

Engineering report

For the full source breakdown — per-file line counts, the exact SQL each verb emits, the environment-variable reference, and the 457-test zunit coverage map — see the engineering report.

Sibling plugins

Part of the MenkeTechnologies zsh plugin family — the MenkeTechnologiesMeta umbrella: