scripts/flesch_kincaid.rb
#!/usr/bin/env ruby
# frozen_string_literal: true
# Flesch-Kincaid Grade Level Calculator
# Reads text from STDIN and outputs the grade level
def count_syllables(word)
word = word.downcase.gsub(/[^a-z]/, "")
return 0 if word.empty?
# Handle special endings
word = word.sub(/e$/, "") unless word.match?(/le$/) && word.length > 2
# Count vowel groups
syllables = word.scan(/[aeiouy]+/).length
# Every word has at least one syllable
[syllables, 1].max
end
def count_sentences(text)
# Count sentence-ending punctuation
count = text.scan(/[.!?]+/).length
[count, 1].max
end
def count_words(text)
text.split(/\s+/).count { |w| !w.gsub(/[^a-zA-Z]/, "").empty? }
end
def extract_words(text)
text.split(/\s+/).map { |w| w.gsub(/[^a-zA-Z]/, "") }.reject(&:empty?)
end
def flesch_kincaid_grade_level(text)
words = extract_words(text)
word_count = words.length
sentence_count = count_sentences(text)
syllable_count = words.sum { |w| count_syllables(w) }
return 0 if word_count.zero?
0.39 * (word_count.to_f / sentence_count) +
11.8 * (syllable_count.to_f / word_count) -
15.59
end
text = $stdin.read
if text.strip.empty?
warn "No input provided. Please pipe text to this script."
exit 1
end
grade_level = flesch_kincaid_grade_level(text)
puts format("Flesch-Kincaid Grade Level: %.1f", grade_level)
scripts/vocabulary_profiler.rb
#!/usr/bin/env ruby
# frozen_string_literal: true
# Vocabulary Profiler
# Reads text from STDIN and reports what percentage uses the top 1000 basic English words
# Word list from: https://simple.wikipedia.org/wiki/Wikipedia:List_of_1000_basic_words
TOP_1000_WORDS = %w[
a about above across act active activity add afraid after again age ago agree air all alone along
already always am amount an and angry another answer any anyone anything anytime appear apple are
area arm army around arrive art as ask at attack aunt autumn away
baby back bad bag ball bank base basket bath be bean bear beautiful bed bedroom beer before begin
behave behind bell below besides best better between big bird birth birthday bit bite black bleed
block blood blow blue board boat body boil bone book border born borrow both bottle bottom bowl
box boy branch brave bread break breakfast breathe bridge bright bring brother brown brush build
burn bus business busy but buy by
cake call can candle cap car card care careful careless carry case cat catch central century
certain chair chance change chase cheap cheese chicken child children chocolate choice choose
circle city class clean clear clever climb clock close cloth clothes cloud cloudy coat coffee
coin cold collect color comb come comfortable common compare complete computer condition contain
continue control cook cool copper corn corner correct cost count country course cover crash cross
cry cup cupboard cut
dance dangerous dark daughter day dead decide decrease deep deer depend desk destroy develop die
different difficult dinner direction dirty discover dish do dog door double down draw dream dress
drink drive drop dry duck dust duty
each ear early earn earth east easy eat education effect egg eight either electric elephant else
empty end enemy enjoy enough enter entrance equal escape even evening event ever every everybody
everyone exact examination example except excited exercise expect expensive explain extremely eye
face fact fail fall false family famous far farm fast fat father fault fear feed feel female fever
few fight fill film find fine finger finish fire first fish fit five fix flag flat float floor
flour flower fly fold food fool foot football for force foreign forest forget forgive fork form
four fox free freedom freeze fresh friend friendly from front fruit full fun funny furniture
further future
game garden gate general gentleman get gift give glad glass go goat god gold good goodbye
grandfather grandmother grass grave gray great green ground group grow gun
hair half hall hammer hand happen happy hard hat hate have he head healthy hear heart heaven heavy
height hello help hen her here hers hide high hill him his hit hobby hold hole holiday home hope
horse hospital hot hotel hour house how hundred hungry hurry hurt husband
i ice idea if important in increase inside into introduce invent invite iron is island it its
jelly job join juice jump just
keep key kill kind king kitchen knee knife knock know
ladder lady lamp land large last late lately laugh lazy lead leaf learn leave left leg lend length
less lesson let letter library lie life light like lion lip list listen little live lock lonely
long look lose lot love low lower luck
machine main make male man many map mark market marry matter may me meal mean measure meat medicine
meet member mention method middle milk million mind minute miss mistake mix model modern moment
money monkey month moon more morning most mother mountain mouth move much music must my
name narrow nation nature near nearly neck need needle neighbor neither net never new news
newspaper next nice night nine no noble noise none nor north nose not nothing notice now number
obey object ocean of off offer office often oil old on once one only open opposite or orange order
other our out outside over own
page pain paint pair pan paper parent park part partner party pass past path pay peace pen pencil
people pepper per perfect period person petrol photograph piano pick picture piece pig pin pink
place plane plant plastic plate play please pleased plenty pocket point poison police polite pool
poor popular position possible potato pour power present press pretty prevent price prince prison
private prize probably problem produce promise proper protect provide public pull punish pupil
push put
queen question quick quiet quite
radio rain rainy raise reach read ready real really receive record red remember remind remove rent
repair repeat reply report rest restaurant result return rice rich ride right ring rise road rob
rock room round rubber rude rule ruler run rush
sad safe sail salt same sand save say school science scissors search seat second see seem sell
send sentence serve seven several sex shade shadow shake shape share sharp she sheep sheet shelf
shine ship shirt shoe shoot shop short should shoulder shout show sick side signal silence silly
silver similar simple since sing single sink sister sit six size skill skin skirt sky sleep slip
slow small smell smile smoke snow so soap sock soft some someone something sometimes son soon
sorry sound soup south space speak special speed spell spend spoon sport spread spring square
stamp stand star start station stay steal steam step still stomach stone stop store storm story
strange street strong structure student study stupid subject substance successful such sudden
sugar suitable summer sun sunny support sure surprise sweet swim sword
table take talk tall taste taxi tea teach team tear telephone television tell ten tennis terrible
test than that the their then there therefore these thick thin thing think third this though
threat three tidy tie title to today toe together tomorrow tonight too tool tooth top total touch
town train tram travel tree trouble true trust try turn twice two type
ugly uncle under understand unit until up use useful usual usually
vegetable very village visit voice
wait wake walk want warm was wash waste watch water way we weak wear weather wedding week weight
welcome well were west wet what wheel when where which while white who why wide wife wild will win
wind window wine winter wire wise wish with without woman wonder word work world worry
yard yell yesterday yet you young your
zero zoo
].to_set.freeze
def extract_words(text)
text.downcase.scan(/[a-z]+/)
end
text = $stdin.read
if text.strip.empty?
warn "No input provided. Please pipe text to this script."
exit 1
end
words = extract_words(text)
total_words = words.length
if total_words.zero?
warn "No words found in input."
exit 1
end
basic_words = words.count { |w| TOP_1000_WORDS.include?(w) }
percentage = (basic_words.to_f / total_words * 100)
puts format("Words in top 1000: %d / %d (%.1f%%)", basic_words, total_words, percentage)
SKILL.md
---
name: readme-writer
license: MIT
description: "Measure and improve the reading level of any prose — docs, READMEs, emails, proposals, specs, plans. Scores Flesch-Kincaid grade level and top-1000 vocabulary coverage with real scripts instead of estimates. Triggers on 'readability', 'reading level', 'grade level', 'Flesch-Kincaid', 'plain language', 'make this easier to read', 'simplify this writing', 'too dense', 'ESL-friendly', and on 'write readme', 'improve readme', 'readme review', 'documentation writing'."
---
# Readability and README Writing
Two jobs. The common one: **measure and improve reading level in any prose** —
a doc, an email, a proposal, a spec, a plan. The narrower one: **structure a
README**.
## Always Measure — Never Estimate
Syllable counts cannot be eyeballed accurately across a document. Reporting a
Flesch-Kincaid score without running the script is guessing. Run it.
```bash
cat FILE | ruby scripts/flesch_kincaid.rb
```
Works on any text, not just markdown — pipe in an email draft, a section of a
doc, a paragraph pasted into a heredoc.
**Target: grade level 11 or below.** Technical terms inflate the score, and
that's fine — the goal is to keep the *surrounding prose* clear so the technical
content stays accessible.
Revise, then re-measure. Focus revision on:
- Shortening sentences (not dumbing down terminology)
- Replacing complex connectors with simple ones
- Breaking multi-clause sentences into two
Report the before and after scores.
## Vocabulary Coverage
Many readers of technical writing are not native English speakers.
```bash
cat FILE | ruby scripts/vocabulary_profiler.rb
```
Aim to raise the percentage of words in the top 1000 most common English words.
Technical terms lower this number — expected. Keep the non-technical words
simple.
**Do:**
- Use active voice
- Keep noun phrases short and direct
- Limit embedded clauses to one level of nesting
- Use simple "if/then" conditionals
- Make logical connections explicit with transition words (however, therefore, because)
- Spread information across multiple sentences when needed
**Don't:**
- Stack multiple modifiers before nouns ("the recently revised standardized testing protocol")
- Rely on mixed or inverted conditionals ("Had she known...")
- Expect readers to infer relationships between ideas
- Pack too many new concepts into a single sentence
- Assume shared knowledge of idioms or cultural references
## Flow and Transitions
- Start with concepts, then details. Give readers the "why" before the "how"
- Add transitions between major sections so the piece reads as a narrative, not a list of disconnected blocks
- Create logical progression from high-level to detailed
## README Structure
When the document is specifically a README, it flows through these sections:
1. **What and why** — what the package does and why it matters (the "what's in it for me")
2. **Install and use** — how to get started quickly
3. **Configuration** — common options and methods
4. **Contributing** — how to contribute, or a pointer to CONTRIBUTING.md. Notes on the build environment and portability
5. **Project layout** — unusual top-level directories or files, hints for navigating the source
## Formatting
Use GitHub-flavored callout blocks to highlight important information:
> [!CAUTION]
> [!IMPORTANT]
> [!NOTE]
> [!TIP]
> [!WARNING]
- Use **bold** for key concepts on first introduction
- Use `code` for commands, filenames, config keys, and values
- Use concrete, descriptive names for examples ("Invoice Approval" not "Example 1")
## Quality Checklist
- [ ] Flesch-Kincaid grade level **measured with the script**, at or below 11
- [ ] Vocabulary coverage measured; non-technical words kept simple
- [ ] Each section flows naturally into the next
- [ ] Key concepts are bolded on first use
- [ ] Examples use real scenario names, not generic placeholders
- [ ] No corporate buzzwords (comprehensive, robust, seamless, leverage, utilize)
- [ ] Terminology is consistent throughout (same word for same concept)
- [ ] Acronyms and specialized terms are defined on first use
- [ ] Active voice is used wherever possible
## Bibliography
- GNU Coding Standards, https://www.gnu.org/prep/standards/html_node/Releases.html
- Software Release Practice HOWTO, https://tldp.org/HOWTO/Software-Release-Practice-HOWTO/distpractice.html