diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
 # Changelog
 
+## [0.1.0.2] - 2026-07-14
+
+### Changed
+
+* Lower bound on `autodocodec >=0.6`
+
+## [0.1.0.1] - 2026-04-25
+
+### Changed
+
+* Attribute keys that are not valid Nix identifiers are now quoted in rendered expressions.
+
 ## [0.1.0.0] - 2025-02-13
 
 ### Added
diff --git a/autodocodec-nix.cabal b/autodocodec-nix.cabal
--- a/autodocodec-nix.cabal
+++ b/autodocodec-nix.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.36.0.
+-- This file has been generated from package.yaml by hpack version 0.38.3.
 --
 -- see: https://github.com/sol/hpack
 
 name:           autodocodec-nix
-version:        0.1.0.0
+version:        0.1.0.2
 synopsis:       Autodocodec interpreters for nix
 homepage:       https://github.com/NorfairKing/autodocodec#readme
 bug-reports:    https://github.com/NorfairKing/autodocodec/issues
@@ -35,7 +35,7 @@
       src
   build-depends:
       aeson
-    , autodocodec >=0.4.0.0
+    , autodocodec >=0.6.0.0
     , base >=4.7 && <5
     , containers
     , scientific
diff --git a/src/Autodocodec/Nix/Expression.hs b/src/Autodocodec/Nix/Expression.hs
--- a/src/Autodocodec/Nix/Expression.hs
+++ b/src/Autodocodec/Nix/Expression.hs
@@ -18,6 +18,7 @@
 import Data.Aeson as JSON
 import qualified Data.Aeson.Key as Key
 import qualified Data.Aeson.KeyMap as KeyMap
+import Data.Char (isAsciiLower, isAsciiUpper, isDigit)
 import Data.Map.Strict (Map)
 import qualified Data.Map.Strict as M
 import Data.Scientific
@@ -82,9 +83,24 @@
         parensWhen (d > 10) $
           ("with " <> t <> ";") : go 0 e
     goBind key e =
-      prependWith " " (key <> " =") $
+      prependWith " " (nixAttrKey key <> " =") $
         (`append` ";") $
           go 0 e
+
+-- | Quote an attribute key if it is not a valid Nix identifier.
+-- Valid identifiers match @[a-zA-Z_][a-zA-Z0-9_'-]*@.
+nixAttrKey :: Text -> Text
+nixAttrKey key
+  | isNixIdentifier key = key
+  | otherwise = T.pack $ show $ T.unpack key
+
+isNixIdentifier :: Text -> Bool
+isNixIdentifier t = case T.uncons t of
+  Nothing -> False
+  Just (c, rest) -> isNixIdentStart c && T.all isNixIdentChar rest
+  where
+    isNixIdentStart c = c == '_' || isAsciiLower c || isAsciiUpper c
+    isNixIdentChar c = isNixIdentStart c || isDigit c || c == '-' || c == '\''
 
 indent :: [Text] -> [Text]
 indent = map ("  " <>)
diff --git a/src/Autodocodec/Nix/Options.hs b/src/Autodocodec/Nix/Options.hs
--- a/src/Autodocodec/Nix/Options.hs
+++ b/src/Autodocodec/Nix/Options.hs
@@ -71,7 +71,7 @@
     go = \case
       NullCodec -> Just OptionTypeNull
       BoolCodec _ -> Just $ OptionTypeSimple "lib.types.bool"
-      StringCodec _ -> Just $ OptionTypeSimple "lib.types.str"
+      StringCodec _ _ -> Just $ OptionTypeSimple "lib.types.str"
       IntegerCodec _ bounds -> Just $
         OptionTypeSimple $
           case guessIntegerBoundsSymbolic bounds of
