diff --git a/scripts/extract-comments.py b/scripts/extract-comments.py
new file mode 100755
index 0000000000000000000000000000000000000000..2b4f854f326fbb2d97a36e1e761597e2edb6cb39
--- /dev/null
+++ b/scripts/extract-comments.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+
+import argparse
+import sys
+import os
+import re
+
+INLINE_CODE_RE = re.compile(r'\[[^]]*?\]')
+
+def comment_ranges(src):
+    "Identify comments in Coq .v files."
+    def cur_is(i, c):
+        return src[i] == c
+
+    def next_is(i, c):
+        if i + 1 < len(src):
+            return src[i + 1] == c
+        else:
+            return False
+
+    in_comment = 0
+    comment_start = None
+
+    # limitation: doesn't do anything smart about nested comments for now
+    for i in range(len(src)):
+        assert in_comment >= 0
+        # comment starting?
+        if cur_is(i, '(') and next_is(i, '*'):
+            in_comment += 1
+            if in_comment == 1:
+                comment_start = i + 2
+        # comment ending?
+        elif cur_is(i, '*') and next_is(i, ')'):
+            in_comment -= 1
+            if in_comment == 0:
+                yield (comment_start, i)
+
+
+def process(opts, fname):
+    src = open(fname, 'r').read()
+    out = sys.stdout
+    for (a, b) in comment_ranges(src):
+        txt = src[a:b]
+        print(INLINE_CODE_RE.sub('', txt))
+#     out.close()
+
+def parse_args():
+    parser = argparse.ArgumentParser(
+        description="extract comments from Gallina files")
+
+    parser.add_argument('input_files', nargs='*',
+        metavar='Gallina-file',
+        help='input Gallina files (*.v)')
+
+    return parser.parse_args()
+
+def main():
+    opts = parse_args()
+
+    had_problem = False
+    for f in opts.input_files:
+        try:
+            process(opts, f)
+        except OSError as e:
+            print(e, file=sys.stderr)
+            had_problem = True
+
+    if had_problem:
+        # signal something went wrong with non-zero exit code
+        sys.exit(1)
+
+if __name__ == '__main__':
+    main()
+
diff --git a/scripts/flag-typos-in-comments.sh b/scripts/flag-typos-in-comments.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7f979ccd9f6c353f70ac5f898247820e9ddc1f41
--- /dev/null
+++ b/scripts/flag-typos-in-comments.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+EXIT=0
+
+KNOWN_EXCEPTIONS=./scripts/wordlist.pws
+
+while ! [ -z "$1" ]
+do
+	SRC="$1"
+	for WORD in $(scripts/extract-comments.py "$SRC" \
+		| aspell --add-extra-dicts=$KNOWN_EXCEPTIONS -l en  list \
+		| sort \
+		| uniq)
+	do
+		echo "$SRC: potentially misspelled word '$WORD'"
+		EXIT=1
+	done
+	shift
+done
+exit $EXIT
diff --git a/scripts/wordlist.pws b/scripts/wordlist.pws
new file mode 100644
index 0000000000000000000000000000000000000000..ce4629446a69af5f2e5033bb03fb369ce8ae3faa
--- /dev/null
+++ b/scripts/wordlist.pws
@@ -0,0 +1,39 @@
+personal_ws-1.1 en 0
+Prosa
+Coq
+typeclass
+iff
+schedulability
+schedulable
+computable
+boolean
+disjunction
+invariant
+invariants
+instantiation
+instantiations
+uniprocessor
+uniprocessors
+jitter
+monotonicity
+antisymmetric
+optimality
+namespace
+nonpreemptive
+preemptive
+preemptable
+EDF
+FP
+JLFP
+JLDP
+TDMA
+aRTA
+RTA
+IBF
+RBF
+RBFs
+Layland
+Liu
+sequentiality
+equalities
+extremum
\ No newline at end of file