diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
new file mode 100644
index 00000000..22650fda
--- /dev/null
+++ b/.github/workflows/codespell.yml
@@ -0,0 +1,23 @@
+# Codespell configuration is within pyproject.toml
+---
+name: Codespell
+
+on:
+  push:
+    branches: [master]
+  pull_request:
+    branches: [master]
+
+permissions:
+  contents: read
+
+jobs:
+  codespell:
+    name: Check for spelling errors
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+      - name: Codespell
+        uses: codespell-project/actions-codespell@v2
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
new file mode 100644
index 00000000..3da32f4a
--- /dev/null
+++ b/.github/workflows/pre-commit.yml
@@ -0,0 +1,10 @@
+name: Pre-commit
+on: [push, pull_request]
+jobs:
+  pre-commit:
+    name: Format
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v3
+    - uses: actions/setup-python@v3
+    - uses: pre-commit/action@v3.0.1
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 799985da..4630a73f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -4,3 +4,11 @@ repos:
     hooks:
     - id: black
       language_version: python3.6
+
+-   repo: https://github.com/codespell-project/codespell
+    # Configuration for codespell is in pyproject.toml
+    rev: v2.2.6
+    hooks:
+    - id: codespell
+      additional_dependencies:
+      - tomli
diff --git a/CHANGES b/CHANGES
index 9d999e29..1b3183a9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2321,7 +2321,7 @@ Version 2.1.0 - February, 2016
   aristotle2600 on reddit.
 
 - Removed keepOriginalText helper method, which was deprecated ages ago.
-  Superceded by originalTextFor.
+  Superseded by originalTextFor.
 
 - Same for the Upcase class, which was long ago deprecated and replaced
   with the upcaseTokens method.
@@ -2605,7 +2605,7 @@ Version 1.5.6 - June, 2011
   and robust in the face of future Python versions - much thanks to
   Raymond Hettinger for this rewrite!
 
-- Removal of exception cacheing, addressing a memory leak condition
+- Removal of exception caching, addressing a memory leak condition
   in Python 3. Thanks to Michael Droettboom and the Cape Town PUG for
   their analysis and work on this problem!
 
@@ -3583,7 +3583,7 @@ Version 1.4.2 - April 1, 2006 (No foolin'!)
   2004, so I'm guessing people really shouldn't have been using this
   feature - I'll drop it altogether in the next release, which will
   allow users to return a tuple from a parse action (which is really
-  handy when trying to reconstuct tuples from a tuple string
+  handy when trying to reconstruct tuples from a tuple string
   representation!).
 
 
@@ -4029,7 +4029,7 @@ Version 1.2beta2 - 19 May 2004
   sample Delphi forms as tests.  (Well done, Dang!)
 
 - Another performance speedup, 5-10%, inspired by Dang!  Plus about a 20%
-  speedup, by pre-constructing and cacheing exception objects instead of
+  speedup, by pre-constructing and caching exception objects instead of
   constructing them on the fly.
 
 - Fixed minor bug when specifying oneOf() with 'caseless=True'.
diff --git a/README.rst b/README.rst
index 24d603c7..4aa37a18 100644
--- a/README.rst
+++ b/README.rst
@@ -91,3 +91,4 @@ See `CHANGES <https://github.com/pyparsing/pyparsing/blob/master/CHANGES>`__ fil
 .. |Snyk Score| image:: https://snyk.io//advisor/python/pyparsing/badge.svg
    :target: https://snyk.io//advisor/python/pyparsing
    :alt: pyparsing
+Installing
diff --git a/examples/bf.py b/examples/bf.py
index 76144295..dbb0e8ef 100644
--- a/examples/bf.py
+++ b/examples/bf.py
@@ -15,7 +15,7 @@
 
 # define the basic parser
 
-# define Literals for each symbol in the BF langauge
+# define Literals for each symbol in the BF language
 PLUS, MINUS, GT, LT, INP, OUT, LBRACK, RBRACK = pp.Literal.using_each("+-<>,.[]")
 
 # use a pyparsing Forward for the recursive definition of an instruction that can
diff --git a/pyproject.toml b/pyproject.toml
index 77145f48..56a561db 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -61,3 +61,11 @@ exclude = [
     "tests/.mypy_cache",
     "update_pyparsing_timestamp.py",
 ]
+
+[tool.codespell]
+# Ref: https://github.com/codespell-project/codespell#using-a-config-file
+skip = '.git,hola_mundo.py'
+check-hidden = true
+# case sensitive names, lines likely with regexpressions
+ignore-regex = '\b(OnlyOnce|fontEnd|Nd|Ned|Bu|Donn|[a-zA-Z]*\*[a-zA-Z]*)\b|.*\(.*\|.*\).*|itemsvisibles visibles'
+ignore-words-list = 'inout,halp,strng,te,ans,strin,datas,helpe,fourty'
diff --git a/tests/json_parser_tests.py b/tests/json_parser_tests.py
index 1b8c058d..b2603732 100644
--- a/tests/json_parser_tests.py
+++ b/tests/json_parser_tests.py
@@ -156,7 +156,7 @@
         /*
             Defines the implementation of org.cofax.Redirection that
             Cofax will use.  If this Redirection class does not suit
-            your needs simply implenet a new Redirection class
+            your needs simply implement a new Redirection class
             and set here.
         */
         "redirectionClass": "org.cofax.SqlRedirection",
diff --git a/tests/test_unit.py b/tests/test_unit.py
index 8b2ae5ad..80ded51b 100644
--- a/tests/test_unit.py
+++ b/tests/test_unit.py
@@ -3505,16 +3505,16 @@ def keywords(name):
         modifier_key = charString1
 
         # relations
-        comparitor_symbol = oneOf(RELATION_SYMBOLS)
-        named_comparitors = keywords("comparitors")
-        comparitor = Group(comparitor_symbol | named_comparitors)("comparitor")
-        comparitor.addParseAction(_set_info)
+        comparator_symbol = oneOf(RELATION_SYMBOLS)
+        named_comparators = keywords("comparators")
+        comparator = Group(comparator_symbol | named_comparators)("comparator")
+        comparator.addParseAction(_set_info)
 
         def modifier_list1(key):
             modifier = Dict(
                 Literal("/")
                 + Group(modifier_key(key))("name")
-                + Optional(comparitor_symbol("symbol") + term("value"))
+                + Optional(comparator_symbol("symbol") + term("value"))
             )("modifier")
             modifier.addParseAction(_set_info)
             return ZeroOrMore(modifier)("modifier_list")
@@ -3523,7 +3523,7 @@ def modifier_list2(key):
             modifier = Dict(
                 Literal("/")
                 + Group(modifier_key(key))("name")
-                + Optional(comparitor_symbol("symbol") + term("value")),
+                + Optional(comparator_symbol("symbol") + term("value")),
                 asdict=True,
             )("modifier")
             modifier.addParseAction(_set_info)
@@ -3534,7 +3534,7 @@ def modifier_list3(key):
                 Dict(
                     Literal("/")
                     + Group(modifier_key(key))("name")
-                    + Optional(comparitor_symbol("symbol") + term("value"))
+                    + Optional(comparator_symbol("symbol") + term("value"))
                 )
             )
             modifier.addParseAction(_set_info)
@@ -3544,7 +3544,7 @@ def modifier_list4(key):
             modifier = Dict(
                 Literal("/")
                 + Group(modifier_key(key))("name")
-                + Optional(comparitor_symbol("symbol") + term("value")),
+                + Optional(comparator_symbol("symbol") + term("value")),
                 asdict=True,
             )
             modifier.addParseAction(_set_info)