diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index 5198e93d8d..b7388f2948 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -119,6 +119,58 @@ class InteractConsoleLogFilter(logging.Filter):
         self.tf.clearFooter()
         return True
 
+class Osc94FilterNotifier(logging.Filter):
+    def __init__(self, tf):
+        self.tf = tf
+
+    def filter(self, record):
+        if record.levelno == bb.msg.BBLogFormatter.ERROR:
+            self.tf.osc94.error()
+        elif record.levelno == bb.msg.BBLogFormatter.WARNING:
+            self.tf.osc94.warning()
+
+        return True
+
+class Osc94(object):
+    REMOVE = 0
+    SET = 1
+    ERROR = 2
+    INDETERMINATE = 3
+    WARNING = 4
+
+    def __init__(self, fd = None):
+        self.fd = fd
+        self._warning = False
+        self._error = False
+
+    def _write(self, what, argument = None):
+        if self.fd is not None:
+            argument = "" if argument is None else argument
+            self.fd.write(f"\x1b]9;4;{what};{argument}\x07")
+            self.fd.flush()
+
+    def clear(self):
+        self._write(self.REMOVE)
+
+    def indeterminate(self):
+        self._write(self.INDETERMINATE)
+
+    def error(self):
+        self._error = True
+
+    def warning(self):
+        self._warning = True
+
+    def progress(self, value):
+        value = int(min(max(value, 0), 100))
+        if self._error:
+            self._write(self.ERROR, value)
+        elif self._warning:
+            self._write(self.WARNING, value)
+        else:
+            self._write(self.SET, value)
+
+
 class TerminalFilter(object):
     rows = 25
     columns = 80
@@ -160,6 +212,7 @@ class TerminalFilter(object):
         self.lastpids = []
         self.lasttime = None
         self.quiet = quiet
+        self.osc94 = Osc94(sys.stdout)
 
         if not self.interactive:
             return
@@ -203,8 +256,10 @@ class TerminalFilter(object):
 
         for h in handlers:
             h.addFilter(InteractConsoleLogFilter(self))
+            h.addFilter(Osc94FilterNotifier(self))
 
         self.main_progress = None
+        self.osc94.indeterminate()
 
     def clearFooter(self):
         if self.footer_present:
@@ -274,6 +329,7 @@ class TerminalFilter(object):
                 tasks.append(msg)
 
         if self.main.shutdown:
+            self.osc94.indeterminate()
             content = pluralise("Waiting for %s running task to finish",
                                 "Waiting for %s running tasks to finish", len(activetasks))
             if not self.quiet:
@@ -303,6 +359,7 @@ class TerminalFilter(object):
             self.main_progress.setmessage(msg)
             progress = max(0, self.helper.tasknumber_current - 1)
             content += self.main_progress.update(progress)
+            self.osc94.progress(self.main_progress.percent)
             print('')
         lines = self.getlines(content)
         if not self.quiet:
@@ -335,6 +392,7 @@ class TerminalFilter(object):
         return lines
 
     def finish(self):
+        self.osc94.clear()
         if self.stdinbackup:
             fd = sys.stdin.fileno()
             self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
