diff --git a/dataframe-csv.cabal b/dataframe-csv.cabal
--- a/dataframe-csv.cabal
+++ b/dataframe-csv.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.4
 name:               dataframe-csv
-version:            2.3.1.1
+version:            2.3.2.0
 synopsis:           CSV reader and writer for the dataframe ecosystem.
 description:
     @DataFrame.IO.CSV@ — strict single-pass CSV read/write (pure
@@ -39,8 +39,8 @@
     build-depends:      base >= 4 && < 5,
                         bytestring >= 0.11 && < 0.14,
                         containers >= 0.6.7 && < 0.10,
-                        dataframe-core >= 2.6 && < 2.7,
-                        dataframe-operations >= 2.6 && < 2.7,
+                        dataframe-core >= 2.7 && < 2.8,
+                        dataframe-operations >= 2.7 && < 2.8,
                         dataframe-parsing >= 2.2 && < 2.3,
                         text >= 2.1 && < 3,
                         time >= 1.12 && < 2,
diff --git a/src/DataFrame/Typed/IO/CSV.hs b/src/DataFrame/Typed/IO/CSV.hs
--- a/src/DataFrame/Typed/IO/CSV.hs
+++ b/src/DataFrame/Typed/IO/CSV.hs
@@ -8,8 +8,10 @@
     readCsvWithError,
     readTsv,
     readCsvWithOpts,
+    readSeparated,
     writeCsv,
     writeTsv,
+    writeSeparated,
 ) where
 
 import Control.Applicative ((<|>))
@@ -76,3 +78,14 @@
 -- | Write a typed DataFrame to a tab-separated file.
 writeTsv :: FilePath -> TypedDataFrame cols -> IO ()
 writeTsv path = CSV.writeTsv path . thaw
+
+-- | Read a character-separated file with custom options; throws on mismatch.
+readSeparated ::
+    forall cols.
+    (KnownSchema cols, RuntimeSchema cols) =>
+    ReadOptions -> FilePath -> IO (TypedDataFrame cols)
+readSeparated = readCsvWithOpts @cols
+
+-- | Write a typed DataFrame with the given separator.
+writeSeparated :: Char -> FilePath -> TypedDataFrame cols -> IO ()
+writeSeparated sep path = CSV.writeSeparated sep path . thaw
