diff --git a/CHANGES.markdown b/CHANGES.markdown
--- a/CHANGES.markdown
+++ b/CHANGES.markdown
@@ -1,3 +1,8 @@
+## Changes in 0.14.0 [2024.04.30]
+ - This coincides with the `base-compat-batteries-0.14.0` release. Refer to the
+   [`base-compat-batteries` changelog](https://github.com/haskell-compat/base-compat/blob/master/base-compat-batteries/CHANGES.markdown#changes-in-0140-20240430)
+   for more details.
+
 ## Changes in 0.13.1 [2023.10.11]
  - This coincides with the `base-compat-batteries-0.13.1` release. Refer to the
    [`base-compat-batteries` changelog](https://github.com/haskell-compat/base-compat/blob/master/base-compat-batteries/CHANGES.markdown#changes-in-0131-20231011)
diff --git a/base-compat-batteries.cabal b/base-compat-batteries.cabal
--- a/base-compat-batteries.cabal
+++ b/base-compat-batteries.cabal
@@ -1,5 +1,5 @@
 name:             base-compat-batteries
-version:          0.13.1
+version:          0.14.0
 license:          MIT
 license-file:     LICENSE
 copyright:        (c) 2012-2018 Simon Hengel,
@@ -48,10 +48,11 @@
                   , GHC == 8.8.4
                   , GHC == 8.10.7
                   , GHC == 9.0.2
-                  , GHC == 9.2.7
-                  , GHC == 9.4.5
-                  , GHC == 9.6.2
-                  , GHC == 9.8.1
+                  , GHC == 9.2.8
+                  , GHC == 9.4.8
+                  , GHC == 9.6.5
+                  , GHC == 9.8.2
+                  , GHC == 9.10.1
 
 source-repository head
   type: git
@@ -65,7 +66,7 @@
       Haskell2010
   build-depends:
       base        >= 4.3 && < 5,
-      base-compat == 0.13.1,
+      base-compat == 0.14.0,
       ghc-prim
   if !impl(ghc >= 7.8)
     build-depends:
diff --git a/src/Data/List/NonEmpty/Compat.hs b/src/Data/List/NonEmpty/Compat.hs
--- a/src/Data/List/NonEmpty/Compat.hs
+++ b/src/Data/List/NonEmpty/Compat.hs
@@ -24,11 +24,15 @@
   , uncons
   , unfoldr
   , sort
+  , sortOn
   , reverse
   , inits
   , inits1
   , tails
   , tails1
+  , append
+  , appendList
+  , prependList
   -- * Building streams
   , iterate
   , repeat
@@ -54,6 +58,8 @@
   , groupBy1
   , groupWith1
   , groupAllWith1
+  , permutations
+  , permutations1
   -- * Sublist predicates
   , isPrefixOf
   -- * \"Set\" operations
@@ -85,6 +91,40 @@
 #endif
 
 #if !(MIN_VERSION_base(4,9,0))
+-- | A monomorphic version of 'Prelude.<>' for 'NonEmpty'.
+--
+-- >>> append (1 :| []) (2 :| [3])
+-- 1 :| [2,3]
+--
+-- /Since: 4.16/
+append :: NonEmpty a -> NonEmpty a -> NonEmpty a
+append = (Prelude.<>)
+
+-- | Attach a list at the end of a 'NonEmpty'.
+--
+-- >>> appendList (1 :| [2,3]) []
+-- 1 :| [2,3]
+--
+-- >>> appendList (1 :| [2,3]) [4,5]
+-- 1 :| [2,3,4,5]
+--
+-- /Since: 4.16/
+appendList :: NonEmpty a -> [a] -> NonEmpty a
+appendList (x :| xs) ys = x :| xs Prelude.<> ys
+
+-- | Attach a list at the beginning of a 'NonEmpty'.
+--
+-- >>> prependList [] (1 :| [2,3])
+-- 1 :| [2,3]
+--
+-- >>> prependList [negate 1, 0] (1 :| [2, 3])
+-- -1 :| [0,1,2,3]
+--
+-- /Since: 4.16/
+prependList :: [a] -> NonEmpty a -> NonEmpty a
+prependList ls ne = case ls of
+  [] -> ne
+  (x : xs) -> x :| xs Prelude.<> toList ne
 -- | Construct a 'NonEmpty' list from a single element.
 --
 -- /Since: 4.15/
@@ -126,4 +166,68 @@
   -- - Therefore, if we take all but the last element of `tails xs` i.e.
   --   `init (tails xs)`, we have a nonempty list of nonempty lists
   fromList . Prelude.map fromList . List.init . List.tails . Foldable.toList
+
+-- | The 'permutations' function returns the list of all permutations of the argument.
+--
+-- /Since: 4.20.0.0/
+permutations            :: [a] -> NonEmpty [a]
+permutations xs0        =  xs0 :| perms xs0 []
+  where
+    perms []     _  = []
+    perms (t:ts) is = List.foldr interleave (perms ts (t:is)) (permutations is)
+      where interleave    xs     r = let (_,zs) = interleave' Prelude.id xs r in zs
+            interleave' _ []     r = (ts, r)
+            interleave' f (y:ys) r = let (us,zs) = interleave' (f . (y:)) ys r
+                                     in  (y:us, f (t:y:us) : zs)
+-- The implementation of 'permutations' is adopted from 'GHC.Internal.Data.List.permutations',
+-- see there for discussion and explanations.
+
+-- | 'permutations1' operates like 'permutations', but uses the knowledge that its input is
+-- non-empty to produce output where every element is non-empty.
+--
+-- > permutations1 = fmap fromList . permutations . toList
+--
+-- /Since: 4.20.0.0/
+permutations1 :: NonEmpty a -> NonEmpty (NonEmpty a)
+permutations1 xs = fromList Prelude.<$> permutations (toList xs)
+
+-- | Sort a 'NonEmpty' on a user-supplied projection of its elements.
+-- See 'List.sortOn' for more detailed information.
+--
+-- ==== __Examples__
+--
+-- >>> sortOn fst $ (2, "world") :| [(4, "!"), (1, "Hello")]
+-- (1,"Hello") :| [(2,"world"),(4,"!")]
+--
+-- >>> sortOn length $ "jim" :| ["creed", "pam", "michael", "dwight", "kevin"]
+-- "jim" :| ["pam","creed","kevin","dwight","michael"]
+--
+-- ==== __Performance notes__
+--
+-- This function minimises the projections performed, by materialising
+-- the projections in an intermediate list.
+--
+-- For trivial projections, you should prefer using 'sortBy' with
+-- 'comparing', for example:
+--
+-- >>> sortBy (comparing fst) $ (3, 1) :| [(2, 2), (1, 3)]
+-- (1,3) :| [(2,2),(3,1)]
+--
+-- Or, for the exact same API as 'sortOn', you can use `sortBy . comparing`:
+--
+-- >>> (sortBy . comparing) fst $ (3, 1) :| [(2, 2), (1, 3)]
+-- (1,3) :| [(2,2),(3,1)]
+--
+-- 'sortWith' is an alias for `sortBy . comparing`.
+--
+-- /Since: 4.20.0.0/
+sortOn :: Prelude.Ord b => (a -> b) -> NonEmpty a -> NonEmpty a
+sortOn f = lift (List.sortOn f)
+
+-- | Lift list operations to work on a 'NonEmpty' stream.
+--
+-- /Beware/: If the provided function returns an empty list,
+-- this will raise an error.
+lift :: Foldable.Foldable f => ([a] -> [b]) -> f a -> NonEmpty b
+lift f = fromList . f . Foldable.toList
 #endif
