OSC 3008, formally Hierarchical Context Signalling, is UAPI.15 in the UAPI Group specifications. It defines a set of terminal control sequences that let programs tell a terminal emulator about the current context hierarchy inside a terminal session.
In plain terms, it tries to answer a question that has become common in modern Linux terminals: which layer are you actually in?
For example, you may SSH from your local machine to a server, enter a container, and then use run0 or a similar tool to run a command with elevated privileges. To you, it still looks like one continuous terminal window. To the terminal emulator, without an extra signal, it is hard to know whether the current output comes from the local machine, the remote host, a container, or an elevated command.
OSC 3008 is designed for that kind of situation. The UAPI specification says it allows terminal emulators to track the hierarchical context of the current content on screen. systemd also provides an implementation, usually through a script named 80-systemd-osc-context.sh.
Official references:
- UAPI.15 OSC 3008: Hierarchical Context Signalling: https://uapi-group.org/specifications/specs/osc_context/
- systemd
80-systemd-osc-context.sh: https://github.com/systemd/systemd/blob/main/profile.d/80-systemd-osc-context.sh
Why OSC 3008 Exists
Traditional terminals mainly display program output. At most, they use window titles, colors, and prompts to help distinguish environments. The problem is that modern terminal sessions are often nested:
|
|
If everything depends only on PS1, several problems appear:
- The prompt can only describe the current shell and struggles to express the full nesting hierarchy.
- Different shells, distributions, and user configurations can override one another.
- The terminal emulator cannot reliably know which output belongs to which context.
- Some control sequences become visible garbage in incompatible terminals.
OSC 3008 provides a more structured approach: the program that enters a context sends a start sequence, and the program that leaves the context sends an end sequence. After parsing those sequences, the terminal emulator can know which context node the current output belongs to.
What Information It Sends
OSC 3008 is a set of OSC escape sequences. The specification defines two core commands:
|
|
start means a context starts, is updated, or becomes current again. end means a context ends.
Each context can carry metadata fields. Common fields include:
type=: context type, such asshell,command,remote,container,vm, orelevate.user=: the UNIX user that emits the sequence.hostname=: the hostname.machineid=: the machine ID from/etc/machine-id.bootid=: the boot ID from/proc/sys/kernel/random/boot_id.pid=: the PID of the process that emits the sequence.comm=: the process name.cwd=: the current working directory, mainly forshellorcommand.cmdline=: the command line invoked interactively.container=andvm=: container or virtual machine names.targetuser=andtargethost=: target user or remote target host.
These fields are not meant to be read directly by users. They are meant for terminal emulators to parse. A compatible terminal consumes these control sequences and uses them to improve the interface.
What It Can Improve
If a terminal emulator supports OSC 3008, it can do smarter things.
First, it can mark output from different contexts. For example, container output, elevated-command output, and remote SSH output may use different backgrounds, borders, or hints.
Second, it can display a hierarchy breadcrumb. The terminal may know that the current session is roughly:
|
|
This is more stable than relying only on a window title or PS1.
Third, it can help window titles, tabs, and context menus. The terminal can update tab titles according to the current context, or provide actions such as opening a shell in the same directory for a selected output segment.
Fourth, it can reduce mistakes. If you are inside a production container and running commands as root, the terminal can show a more obvious warning and reduce the chance of running dangerous commands in the wrong environment.
How systemd Hooks Into It
systemd’s implementation mainly lives in 80-systemd-osc-context.sh. This script is loaded through the profile mechanism and sets related functions and prompt hooks in interactive Bash environments.
Common paths may include:
|
|
The exact location depends on the distribution. Comments in the systemd source explain that this file can be activated through systemd-tmpfiles, which links it into /etc/profile.d/.
In Bash, it uses function names such as:
|
|
It also affects PROMPT_COMMAND and PS0. PS0 is expanded after Bash reads a command and before it executes the command. That is why incompatible terminals may show a long 3008;start=... text before each command runs.
Why Some Terminals Show Garbage
Normally, a terminal emulator should parse OSC 3008 as a control sequence and not display it directly.
But if the terminal does not recognize OSC 3008, or an intermediate layer filters, escapes, or breaks the control characters, the raw content may be displayed. Common cases include:
- Older terminal emulators.
- SSH clients that have not adapted to OSC 3008.
- Web bastion hosts or browser terminals, including some Apache Guacamole environments.
- Environments with limited OSC support, such as Emacs
term.el, serial terminals, orminicom. - Multi-hop forwarding where an intermediate layer damages the control sequence.
In that case, you may see something like:
|
|
Or you may see long strings containing machineid=, bootid=, pid=, comm=, and cwd=. These are not normal program output. They are context signals that were supposed to be handled by the terminal.
How to Tell Whether It Is OSC 3008
Check three clues first.
First, does the garbage include 3008;start= or 3008;end=?
Second, does it appear before or after command execution, especially every time you press Enter to run a command?
Third, has the current system loaded systemd’s OSC functions?
|
|
If you can see a function definition, the current shell has loaded the related logic.
You can also check the profile file:
|
|
If this path exists and your terminal does not support OSC 3008, the garbage output likely comes from there.
Temporary Workaround
If only the current session is affected, you can override the related functions and clear PS0:
|
|
If you want this to happen automatically only in SSH sessions, put it in ~/.bashrc:
|
|
This has a small scope. It does not change system-level profile files and is easy to remove later.
System-Level Disable Method
If you are sure this machine’s terminal environment is generally incompatible with OSC 3008, you can consider disabling it system-wide. Be careful: this affects all users and login sessions.
The idea described in the systemd script comments is to remove the /etc/profile.d/80-systemd-osc-context.sh symlink and mask the corresponding tmpfiles fragment so it will not be recreated later.
You can use a command like this:
|
|
This is heavier than changing ~/.bashrc. Try the temporary workaround first to confirm the problem really comes from OSC 3008, then decide whether system-level disablement is justified.
If only your personal SSH client is incompatible, do not change system-level configuration first. Prefer your own ~/.bashrc, or configure a post-login cleanup command in the SSH client.
Upgrade the Terminal or Disable OSC 3008?
If you use a modern terminal that already supports OSC 3008, it is better to keep this capability. It may make remote shells, containers, virtual machines, and elevated commands easier to understand in the future.
If your actual environment is a bastion host, serial console, old terminal, or Web SSH client that cannot be upgraded soon, suppressing it is more practical. For most operations work, clean and readable terminal output is more important than enhanced context display.
Use this order:
- If you can upgrade the terminal emulator, upgrade it first.
- If you cannot upgrade and only your own session is affected, suppress it in
~/.bashrcor the client’s post-login command. - If the whole machine is affected, then consider removing
/etc/profile.d/80-systemd-osc-context.shand masking the tmpfiles fragment.
Short Conclusion
OSC 3008 is not malware and not random program output. It is UAPI.15 terminal context signaling, designed to help terminals understand the hierarchy between shells, SSH sessions, containers, virtual machines, and elevated commands.
The real issue is usually compatibility. A compatible terminal parses it automatically. An incompatible one may show the control sequence as garbage.
If you see content such as 3008;start=, machineid=, bootid=, or cwd=, first check whether systemd’s 80-systemd-osc-context.sh injected it. After confirmation, choose a temporary workaround, a personal .bashrc workaround, or system-level disablement depending on the scope of the impact.