diff --git a/src/configuration.ts b/src/configuration.ts
index b9bc9da5b..8acff0503 100644
--- a/src/configuration.ts
+++ b/src/configuration.ts
@@ -10,7 +10,7 @@ import {
 import type { TSInternal } from './ts-compiler-types';
 import { createTsInternals } from './ts-internals';
 import { getDefaultTsconfigJsonForNodeVersion } from './tsconfigs';
-import { assign, createRequire, trace } from './util';
+import { assign, createRequire } from './util';
 
 /**
  * TypeScript compiler option values required by `ts-node` which cannot be overridden.
@@ -94,6 +94,7 @@ export function readConfig(
     readFile = ts.sys.readFile,
     skipProject = DEFAULTS.skipProject,
     project = DEFAULTS.project,
+    tsTrace = DEFAULTS.tsTrace,
   } = rawApiOptions;
 
   // Read project configuration when available.
@@ -137,7 +138,7 @@ export function readConfig(
             readDirectory: ts.sys.readDirectory,
             readFile,
             useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
-            trace,
+            trace: tsTrace,
           },
           bp,
           errors,
diff --git a/src/index.ts b/src/index.ts
index 1fc07cd88..b3506a4cd 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -353,6 +353,12 @@ export interface CreateOptions {
    * the configuration loader, so it is *not* necessary for their source to be set here.
    */
   optionBasePaths?: OptionBasePaths;
+  /**
+   * A function to collect trace messages from the TypeScript compiler, for example when `traceResolution` is enabled.
+   *
+   * @default console.log
+   */
+  tsTrace?: (str: string) => void;
 }
 
 /** @internal */
@@ -389,6 +395,7 @@ export interface TsConfigOptions
     | 'cwd'
     | 'projectSearchDir'
     | 'optionBasePaths'
+    | 'tsTrace'
   > {}
 
 /**
@@ -424,6 +431,7 @@ export const DEFAULTS: RegisterOptions = {
   compilerHost: yn(env.TS_NODE_COMPILER_HOST),
   logError: yn(env.TS_NODE_LOG_ERROR),
   experimentalReplAwait: yn(env.TS_NODE_EXPERIMENTAL_REPL_AWAIT) ?? undefined,
+  tsTrace: console.log.bind(console),
 };
 
 /**
@@ -883,6 +891,7 @@ export function create(rawOptions: CreateOptions = {}): Service {
         getCompilationSettings: () => config.options,
         getDefaultLibFileName: () => ts.getDefaultLibFilePath(config.options),
         getCustomTransformers: getCustomTransformers,
+        trace: options.tsTrace,
       };
       const {
         resolveModuleNames,
@@ -891,7 +900,7 @@ export function create(rawOptions: CreateOptions = {}): Service {
         isFileKnownToBeInternal,
         markBucketOfFilenameInternal,
       } = createResolverFunctions({
-        serviceHost,
+        host: serviceHost,
         getCanonicalFileName,
         ts,
         cwd,
@@ -1036,13 +1045,14 @@ export function create(rawOptions: CreateOptions = {}): Service {
               ),
             useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
           };
+      host.trace = options.tsTrace;
       const {
         resolveModuleNames,
         resolveTypeReferenceDirectives,
         isFileKnownToBeInternal,
         markBucketOfFilenameInternal,
       } = createResolverFunctions({
-        serviceHost: host,
+        host,
         cwd,
         configFilePath,
         config,
@@ -1057,7 +1067,7 @@ export function create(rawOptions: CreateOptions = {}): Service {
         ? ts.createIncrementalProgram({
             rootNames: Array.from(rootFileNames),
             options: config.options,
-            host: host,
+            host,
             configFileParsingDiagnostics: config.errors,
             projectReferences: config.projectReferences,
           })
diff --git a/src/resolver-functions.ts b/src/resolver-functions.ts
index e76528155..df7db9aab 100644
--- a/src/resolver-functions.ts
+++ b/src/resolver-functions.ts
@@ -7,14 +7,14 @@ import type * as _ts from 'typescript';
  */
 export function createResolverFunctions(kwargs: {
   ts: typeof _ts;
-  serviceHost: _ts.ModuleResolutionHost;
+  host: _ts.ModuleResolutionHost;
   cwd: string;
   getCanonicalFileName: (filename: string) => string;
   config: _ts.ParsedCommandLine;
   configFilePath: string | undefined;
 }) {
   const {
-    serviceHost,
+    host,
     ts,
     config,
     cwd,
@@ -93,7 +93,7 @@ export function createResolverFunctions(kwargs: {
         moduleName,
         containingFile,
         config.options,
-        serviceHost,
+        host,
         moduleResolutionCache,
         redirectedReference
       );
@@ -132,7 +132,7 @@ export function createResolverFunctions(kwargs: {
         typeDirectiveName,
         containingFile,
         config.options,
-        serviceHost,
+        host,
         redirectedReference
       );
       if (typeDirectiveName === 'node' && !resolvedTypeReferenceDirective) {
@@ -157,7 +157,7 @@ export function createResolverFunctions(kwargs: {
               ...config.options,
               typeRoots,
             },
-            serviceHost,
+            host,
             redirectedReference
           ));
         }
diff --git a/src/test/index.spec.ts b/src/test/index.spec.ts
index 7b613db66..3b128afdc 100644
--- a/src/test/index.spec.ts
+++ b/src/test/index.spec.ts
@@ -331,6 +331,26 @@ test.suite('ts-node', (test) => {
       });
     }
 
+    test.suite('should support `traceResolution` compiler option', (test) => {
+      test('prints traces before running code when enabled', async () => {
+        const { err, stdout } = await exec(
+          `${BIN_PATH} --compiler-options="{ \\"traceResolution\\": true }" -e "console.log('ok')"`
+        );
+        expect(err).toBeNull();
+        expect(stdout).toContain('======== Resolving module');
+        expect(stdout.endsWith('ok\n')).toBe(true);
+      });
+
+      test('does NOT print traces when not enabled', async () => {
+        const { err, stdout } = await exec(
+          `${BIN_PATH} -e "console.log('ok')"`
+        );
+        expect(err).toBeNull();
+        expect(stdout).not.toContain('======== Resolving module');
+        expect(stdout.endsWith('ok\n')).toBe(true);
+      });
+    });
+
     if (semver.gte(process.version, '12.16.0')) {
       test('swc transpiler supports native ESM emit', async () => {
         const { err, stdout } = await exec(
diff --git a/src/test/repl/helpers.ts b/src/test/repl/helpers.ts
index cc4edfcf7..310b8e221 100644
--- a/src/test/repl/helpers.ts
+++ b/src/test/repl/helpers.ts
@@ -45,6 +45,7 @@ export async function contextReplHelpers(
       ...replService.evalAwarePartialHost,
       project: `${TEST_DIR}/tsconfig.json`,
       ...createServiceOpts,
+      tsTrace: replService.console.log.bind(replService.console),
     });
     replService.setService(service);
     t.teardown(async () => {
diff --git a/src/test/repl/repl.spec.ts b/src/test/repl/repl.spec.ts
index 2ef41d15d..8e1ceab04 100644
--- a/src/test/repl/repl.spec.ts
+++ b/src/test/repl/repl.spec.ts
@@ -4,12 +4,14 @@ import * as expect from 'expect';
 import {
   CMD_TS_NODE_WITH_PROJECT_FLAG,
   contextTsNodeUnderTest,
+  getStream,
   TEST_DIR,
 } from '../helpers';
 import { createExec, createExecTester } from '../exec-helpers';
 import { upstreamTopLevelAwaitTests } from './node-repl-tla';
 import { _test } from '../testlib';
 import { contextReplHelpers } from './helpers';
+import { promisify } from 'util';
 
 const test = _test.context(contextTsNodeUnderTest).context(contextReplHelpers);
 
@@ -412,6 +414,47 @@ test.suite(
   }
 );
 
+test.suite('REPL works with traceResolution', (test) => {
+  test.serial(
+    'startup traces should print before the prompt appears when traceResolution is enabled',
+    async (t) => {
+      const repl = t.context.createReplViaApi({
+        registerHooks: false as true,
+        createServiceOpts: {
+          compilerOptions: {
+            traceResolution: true,
+          },
+        },
+      });
+
+      repl.replService.start();
+
+      repl.stdin.end();
+
+      await promisify(setTimeout)(3e3);
+
+      repl.stdout.end();
+      const stdout = await getStream(repl.stdout);
+
+      expect(stdout).toContain('======== Resolving module');
+      expect(stdout.endsWith('> ')).toBe(true);
+    }
+  );
+
+  test.serial(
+    'traces should NOT appear when traceResolution is not enabled',
+    async (t) => {
+      const { stdout, stderr } = await t.context.executeInRepl('1', {
+        registerHooks: true,
+        startInternalOptions: { useGlobal: false },
+        waitPattern: '1\n>',
+      });
+      expect(stderr).toBe('');
+      expect(stdout).not.toContain('======== Resolving module');
+    }
+  );
+});
+
 test.serial('REPL declares types for node built-ins within REPL', async (t) => {
   const { stdout, stderr } = await t.context.executeInRepl(
     `util.promisify(setTimeout)("should not be a string" as string)
diff --git a/src/util.ts b/src/util.ts
index 23e19bba2..da6cc53be 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -90,9 +90,3 @@ export function cachedLookup<T, R>(fn: (arg: T) => R): (arg: T) => R {
     return cache.get(arg)!;
   };
 }
-
-/**
- * We do not support ts's `trace` option yet.  In the meantime, rather than omit
- * `trace` options in hosts, I am using this placeholder.
- */
-export function trace(s: string): void {}