diff --git a/muppet/puppet/strings/__init__.py b/muppet/puppet/strings/__init__.py
index 25c0650c18860d1ac0802055b3a8fd9148a89600..fabaf14c048874d76b4c28040fb0f05f1c1cdba0 100644
--- a/muppet/puppet/strings/__init__.py
+++ b/muppet/puppet/strings/__init__.py
@@ -34,6 +34,7 @@ from typing import (
 from dataclasses import dataclass, field
 import logging
 from .internal import Deserializable
+import re
 
 
 logger = logging.getLogger(__name__)
@@ -370,14 +371,42 @@ def puppet_strings(path: str) -> bytes:
 
         >>> PuppetStrings.from_json(puppet_strings("/etc/puppetlabs/code/modules/stdlib"))
     """
-    # TODO adding an --out flag (to not stdout) causes warnings to be
-    # printed to stdout. Warnings
-
-    cmd = subprocess.run('puppet strings generate --format json'.split(' '),
-                         cwd=path,
-                         check=True,
-                         stdout=subprocess.PIPE)
-    return cmd.stdout
+    # All this extra weird stuff with tempfiles and pipes since puppet
+    # strings output errors on stdout, and only if the --out flag
+    # isn't used.
+    import tempfile
+
+    tmpfile = tempfile.NamedTemporaryFile()
+
+    cmd = subprocess.Popen(
+            ['puppet', 'strings', 'generate',
+             '--format', 'json',
+             '--out', tmpfile.name],
+            cwd=path,
+            stdout=subprocess.PIPE,
+            text=True,
+            )
+
+    if not cmd.stdout:
+        # TODO better error?
+        raise Exception(cmd.returncode)
+
+    for line in cmd.stdout:
+        line = line.strip()
+        # These debug levels are by best effort, and based on the
+        # enum found here:
+        # https://github.com/puppetlabs/puppet-strings/blob/afe75151f8b47ce33433c488e22ca508aa48ac7c/spec/unit/puppet-strings/yard/handlers/ruby/rsapi_handler_spec.rb#L105
+        # Expected formatting from observing the output.
+        if m := re.match(r'^\[(\w+)]: (.*)', line):
+            match m[1]:
+                case "debug":  logger.debug(m[2])
+                case "warn":   logger.warning(m[2])
+                case "error":  logger.error(m[2])
+                case _:        logger.warning(line)
+        else:
+            logger.info(line)
+
+    return tmpfile.read()
 
 
 class HasDocstring(Protocol):