-
Notifications
You must be signed in to change notification settings - Fork 0
Use Cases
Real-world scenarios for the EFL classroom, each with the input you give the
tools and the output you get back. Vocabulary examples are real runs of
vocab_profile.py; grammar examples follow the profiler's documented JSON/pretty
shape (see GRAMMARPROFILE.md).
Reading the results. Typical is the busiest band (where most of the text sits); Reaches / 90% coverage is the highest band you need to account for. A B1 class can usually handle a text that is typical A2, reaches B1; a text that reaches C1 will need pre-teaching or adaptation first.
Jump to a scenario
- Screening a reading text for a specific class
- Vocabulary pre-teaching — pull the hard words
- Checking grammatical range in a student's writing
- The A2-vocabulary / B2-grammar trap
- Auditing and comparing textbook passages
- Writing or simplifying a graded reader
- Curriculum mapping — did this unit cover the target grammar?
- Profiling a whole document — PDF, Word, Markdown
- Inside Claude Code / Cowork — just ask
- Scripting a classroom pipeline with JSON
- Which of these 20 articles suits my B1 class?
Scenario. You teach a B1 group and found an article you might assign. Before handing it out, you want to know whether the vocabulary is in reach.
Input
python3 vocab_profile.py --type cefr --text \
"The researchers analysed the philosophical implications of photosynthesis and chlorophyll synthesis in aquatic ecosystems."Output (pretty, in a terminal)
Vocabulary Profile
Total words: 14
Typical: A1 90% coverage: C2
Most words are A1; you need C2 to cover ~90%.
■ A1 36% ■ B1 29% ■ B2 14% ■ C1 7% ■ C2 14%
B1 analysed · ecosystems · researchers · synthesis
B2 implications · philosophical
C1 aquatic
C2 chlorophyll · photosynthesis
What you learn. Grammatically simple, but the content words shoot up to C1–C2 (aquatic, chlorophyll, photosynthesis). For a B1 class this text needs the academic terms pre-taught or glossed — it is not a cold read. Compare with a text that stays inside A1/A2 and can be handed straight over:
python3 vocab_profile.py --type cefr --text "Yesterday I walked to the shop to buy bread and milk."
# Typical: A1 90% coverage: A1 → hand it out as-isScenario. You've decided to use the science text anyway. You want the list of words above your class level to put on a pre-teaching slide.
Input — ask for JSON and pull the upper bands (here with jq):
python3 vocab_profile.py --type cefr --format json --text \
"The researchers analysed the philosophical implications of photosynthesis and chlorophyll synthesis in aquatic ecosystems." \
| jq -r '.results.cefr | to_entries[] | select(.key|test("B2|C1|C2")) | .value.words[].word'Output
implications
philosophical
aquatic
chlorophyll
photosynthesis
What you learn. A ready-made pre-teaching list of exactly the words above B1.
The same JSON also drives the academic-vocabulary view — swap --type cefr for
--type awl to get just Coxhead's Academic Word List hits:
Awl 29% (4)
analysed, implications, philosophical, researchers
Nearly a third of the running words are academic vocabulary — a strong signal the text belongs in an EAP / upper-secondary setting, not a general A2 lesson.
Scenario. A student is aiming for B2. You want to see whether their essay actually uses B2-level structures or just strings A2 sentences together.
Input
python3 grammar_profile.py --file student-essay.docxOutput (pretty)
Grammar Profile
Sentences: 24 Tokens: 410
Typical: A2 Reaches: B2
A1 Present simple ×31 · to-infinitive ×12 · Relative: that ×3
A2 Past simple ×18 · Present perfect ×4 · Passive (past) ×2 · First conditional ×2
B1 Modal: could ×2 · Past perfect ×1
B2 Comparison of equality (as … as) ×1 · Passive (perfect) ×1
What you learn. The writing reaches B2, but only just — one as…as comparison and a single perfect passive carry the whole upper band, while the bulk is A1/A2. Concrete, evidence-based feedback: "to push toward B2, bring in more of the passive, add a relative clause with which, try a second conditional." This is the same rule-based grammar evidence RubricMaker surfaces per-criterion during grading (see RubricMaker Alignment).
Scenario. Two texts look equally "easy" on a quick skim. You profile both ways and discover they are not.
Input
python3 vocab_profile.py --type cefr --text "The house was built by workers who had been trained abroad."
python3 grammar_profile.py --text "The house was built by workers who had been trained abroad."Output
# vocabulary
Typical: A1 90% coverage: A2 ← looks easy
# grammar
Typical: A2 Reaches: B2
A1 Relative: who ×1
A2 Passive (past) ×1
B1 Past perfect ×1
B2 Passive (perfect) ×1
What you learn. The words are almost all A1/A2, so a readability formula would call this "easy" — but the sentence stacks a past passive, a past perfect, a perfect passive, and a relative clause. For a real learner it's a B2 sentence. This is the case that justifies running both profilers: difficulty is lexical and grammatical, and the two can diverge sharply.
Scenario. You're choosing between two coursebook units for the same B1 group and want an objective difficulty comparison rather than a gut feeling.
Input — one command over the whole folder (vocabulary + grammar per text, in a spreadsheet-ready summary):
python3 class_profile.py --file units/ --format csvOutput (units.csv on stdout)
file,total_words,vocab_typical,vocab_reached,grammar_typical,grammar_reaches,estimated_level
unit-3.txt,412,A1,A2,A2,B1,A2
unit-7.txt,398,A1,B1,B1,B2,B1
...
(Add --target-level B1 for each text's %-above-target and fits verdict, or
--targets A2,B1,B2 to see how the set splits across several classes at once.)
What you learn. Unit 7 is a step up on both axes — more upper-band vocabulary and B2 grammar. If your group has just reached B1, Unit 3 is the safer opener and Unit 7 the stretch text for later in the term. The old way — a shell loop diffing JSON summaries per file — still works and remains the way to pull a single number, but the built-in CSV replaces the loop for the comparison itself.
Scenario. You're rewriting an authentic article down to A2 for a graded reader. You want a fast feedback loop: edit, re-profile, repeat until the upper bands are gone.
Input — check where you are, then let the rewrite aid name the swaps:
python3 vocab_profile.py --type cefr --file draft.md # where am I?
python3 text_report.py --file draft.md --target-level A2 --suggest # what do I change?Output — the vocabulary view tints every word by its band and lists the
offenders; --suggest shows a simpler alternative next to each one above the
target (and the --export md handout gains a Simpler alternative column):
Typical: A2 90% coverage: B1
■ A1 61% ■ A2 24% ■ B1 11% ■ Off List 4%
B1 acquire · obtain · beneath ← replace these
Above A2 — words: acquire (B1) → get (A1), obtain (B1) → get (A1),
beneath (B1) → under (A1)
→ suggests a simpler alternative (rewrite aid)
What you learn. Three words keep the text at B1 — and --suggest names the
swap straight from the bundled curated list (acquire → get, obtain → get,
beneath → under). Swap them and re-run; when the B1 band empties, you've hit
your A2 target. This is the CLI echo of the original VocabKitchen's "adjust a
text to a target level" workflow, now with the suggestions surfaced automatically
(see Roadmap).
Scenario. Your B1 scheme of work promises the present perfect, the first and second conditionals, and relative clauses. You want to confirm the unit's texts actually contain those structures.
Input
python3 grammar_profile.py --format json --file unit-reading.txt \
| jq -r '.constructions[] | "\(.level)\t\(.name)"' | sort -uOutput
A2 First conditional
A2 Present perfect
B1 Second conditional
A1 Relative: who
A1 Relative: that
B2 Passive (past)
What you learn. Present perfect ✅, first conditional ✅, second conditional ✅, relative clauses ✅ — the unit delivers its promised grammar, plus an unplanned B2 passive worth a note. A missing target would show up as an absent row, flagging a gap to fill before teaching. (Turning this into a one-command checklist against a target curriculum is a Phase 4 item.)
Scenario. The reading you want to assess arrived as a PDF handout or a Word document; you don't want to copy-paste it.
Input
python3 vocab_profile.py --type all --file article.pdf # needs: pip install pypdf
python3 grammar_profile.py --file worksheet.docx
echo "Some pasted prose." | python3 vocab_profile.py --type cefrOutput. Identical reports to the --text examples above — the file's format is
detected from its extension and the prose is extracted first:
| Extension | How it's read |
|---|---|
.txt / other |
UTF-8 text |
.md / .markdown
|
Markdown stripped to prose |
.docx |
paragraph text from the Word XML (stdlib only) |
.pdf |
text layer via pypdf (no OCR for scanned pages) |
What you learn. The same profiling works on the materials you already have, in the formats teachers actually receive them in — no reformatting step.
Scenario. You're in a Claude Code or Cowork session and don't want to remember flags. All four tools ship as plugins, so you can ask in plain language.
Input
/plugin install vocab-profiler@vocabkitchen
/plugin install grammar-profiler@vocabkitchen
/plugin install text-report@vocabkitchen
/plugin install class-profile@vocabkitchen
then simply:
"What CEFR level is this paragraph, and what grammar does it use?" (paste the paragraph)
"Which of the articles in this folder suit my B1 class?" (point at the folder)
Output. Claude runs the plugins and answers conversationally — e.g. "The
vocabulary is typically A2 and reaches B1 (purchase, enormous); grammatically
it reaches B2 on the strength of two passives and a relative clause with
which." — and for the folder: "Three of the eight articles fit B1; two just
miss it with ~15% of words above level — here are the pre-teaching lists." —
with the option to show the full per-band breakdown.
What you learn. The same analysis, with zero CLI syntax — useful for teachers who live in the chat rather than the terminal.
Scenario. You maintain a shared folder of reading texts and want a spreadsheet of every text's level for colleagues.
Input — the built-in batch summary (vocabulary + grammar per text, one row per text, ready for a spreadsheet):
python3 class_profile.py --file readings/ --format csv > levels.csvOutput (levels.csv)
file,total_words,vocab_typical,vocab_reached,grammar_typical,grammar_reaches,estimated_level
climate.txt,312,A1,B1,A2,B2,B1
recipe.txt,208,A1,A2,A2,A2,A2
sports-news.txt,287,A1,B1,A2,B2,B1
For pipelines that need the full JSON, the automatic switch to JSON whenever output is piped still applies to every tool; the loop below is the "manual" version the batch summary replaces:
for f in readings/*.txt; do
level=$(python3 grammar_profile.py --format json --file "$f" | jq -r '.estimatedLevel.reaches')
vocab=$(python3 vocab_profile.py --type cefr --format json --file "$f" \
| jq -r '[.results.cefr | to_entries[] | select(.value.percentage|rtrimstr("%")|tonumber>0) | .key] | last')
printf '%s,%s,%s\n' "$(basename "$f")" "$vocab" "$level"
done > levels.csvWhat you learn. One row per text, vocabulary and grammar side by side — exactly the shape a batch report or a gradebook import expects — now without maintaining the loop. For per-file detail beyond the summary, pipe the single- text tools to JSON as before (see Roadmap).
Scenario. You've collected a folder of candidate readings for next term and need to shortlist the ones a B1 group can handle — and know which are the close calls worth pre-teaching.
Input — rank the set by level and keep only the texts whose estimated level is at or below B1:
python3 class_profile.py --file candidates/ --max-level B1 --target-level B1Output (pretty, in a terminal)
Class Profile — candidates/ (20 texts)
Aggregate vocabulary (20 texts, 6 412 words)
Typical: A1 90% coverage: B2 7% off list
■■■■■■■■□□□□□□□□□□□□□□□□□□□□□□□□□
# file words typical reached grammar est %above fits
1 lakes-and-rivers 214 A1 A1 A2→B1 A2 0% ✓
2 city-birds 187 A1 A2 A2→B1 A2 2% ✓
...
14 synthetic-dyes 302 A1 B2 B1→B2 B2 18% ✗
What you learn. With --max-level B1, only the texts that fit the band are
listed — the "which of these suits B1?" question answered in one command
instead of twenty single-text reports. The close calls are the ones just over the
line: their % above B1 tells you how much pre-teaching they'd need, and
--export md --target-level B1 hands you the per-text word lists to teach them
with (see Roadmap).
- Roadmap — where these workflows are heading, phase by phase.
- RubricMaker Alignment — how the profilers feed the RubricMaker grading platform.
Vocabkitchen CLI — vocabulary & grammar profilers for the EFL classroom. CEFR-anchored, rule-based, no AI. · Companion to RubricMaker.