How witr Detects and Interprets tmux and screen Sessions as Valid Process Sources

witr detects tmux and screen sessions by walking the process ancestry tree, identifying multiplexers by executable name, and extracting session identifiers from environment variables TMUX and STY.

The open-source tool witr (Who Is This Running) enriches process metadata by tracing lineage through the process tree. When analyzing how a process started, witr treats terminal multiplexers as first-class sources, allowing it to display contextual information like "bash in tmux session 'dev'" rather than generic shell identification.

Process Ancestry Traversal and Shell Detection

witr begins source detection by resolving the complete ancestry chain of a target process. In internal/source/shell.go, the detectShell function (lines 55‑73) traverses this tree to locate the first interactive shell or known user tool. Upon identifying a shell, it constructs a model.Source struct and immediately invokes enrichMultiplexer to check for multiplexer contexts.

src := &model.Source{Type: model.SourceShell, Name: base}
enrichMultiplexer(src, ancestry)   // ← adds tmux/screen info

This enrichment step occurs before returning the source, ensuring that any tmux or screen session wrapping the shell is captured and recorded in the source description.

Multiplexer Detection Logic

The enrichMultiplexer function (lines 108‑138 in internal/source/shell.go) iterates through the process ancestry—excluding the target process itself—to identify known multiplexer executables. It extracts the basename of each ancestor's executable and performs case-insensitive prefix matching to recognize tmux and screen processes.

Identifying tmux Sessions

For tmux detection, witr checks if the executable basename equals "tmux" or starts with the prefix "tmux:". When matched, the function calls findEnvVar to locate the TMUX environment variable, which contains the session socket path and name. The session identifier is parsed and formatted into the source's Description field.

if base == "tmux" || strings.HasPrefix(base, "tmux:") {
    session := findEnvVar(ancestry, "TMUX")
    desc := "tmux session"
    if session != "" { 
        // Extract session name from TMUX value
        desc = fmt.Sprintf("tmux session '%s'", sessionName)
    }
    src.Description = desc
}

Identifying screen Sessions

For GNU screen detection, witr looks for executables named "screen" or starting with "SCREEN". Upon finding a match, it searches the ancestry for the STY environment variable, which holds the session name. The function constructs a human-readable description incorporating this identifier.

if base == "screen" || strings.HasPrefix(base, "SCREEN") {
    session := findEnvVar(ancestry, "STY")
    desc := "screen session"
    if session != "" { 
        desc = fmt.Sprintf("screen session '%s'", session) 
    }
    src.Description = desc
}

Environment Variable Extraction

The findEnvVar helper function (lines 141‑150 in internal/source/shell.go) performs a backward walk through the process ancestry—from the target process to the init process—searching for specific environment variables. It examines the Env slice of each Process struct, parsing key=value pairs until finding the first match.

for i := len(ancestry) - 1; i >= 0; i-- {
    for _, entry := range ancestry[i].Env {
        k, v, ok := strings.Cut(entry, "=")
        if ok && k == key { return v }
    }
}

This traversal ensures witr captures the session environment as it existed when the multiplexer initialized, even if intermediate processes have modified their own environments.

Practical Implementation Examples

When resolving a process tree using witr's public API, the detection happens automatically through the DetectSource entry point. The following example demonstrates resolving a PID and accessing the enriched source description:

// Resolve a process tree and print its source description
procTree, _ := witr.ResolvePID(12345)               // Resolve PID → ancestry
src := source.DetectSource(procTree)                // Internally calls detectShell

fmt.Println(src.Type)        // → "shell"
fmt.Println(src.Name)        // → "bash"
fmt.Println(src.Description) // → "tmux session 'dev'"  (if launched from tmux)

For advanced use cases requiring direct manipulation, you can invoke the enrichment helper explicitly:

// Direct enrichment of a source object
src := &model.Source{Type: model.SourceShell, Name: "zsh"}
source.EnrichMultiplexer(src, procTree) // Mutates src.Description if tmux/screen present

Summary

  • Ancestry walking: witr traces the complete process tree via detectShell to find the originating shell.
  • Executable matching: enrichMultiplexer identifies tmux by "tmux" or "tmux:" prefixes, and screen by "screen" or "SCREEN" prefixes.
  • Session extraction: The findEnvVar function retrieves TMUX or STY environment variables to obtain session identifiers.
  • Source enrichment: Session information is stored in the model.Source.Description field, providing contextual process attribution.
  • Implementation location: All detection logic resides in internal/source/shell.go within the pranshuparmar/witr repository.

Frequently Asked Questions

How does witr distinguish between tmux and screen?

witr distinguishes between tmux and screen by checking the executable basename of each ancestor process. It looks for "tmux" or strings starting with "tmux:" to identify tmux, and "screen" or strings starting with "SCREEN" to identify screen. Each detection path then queries its respective environment variable—TMUX for tmux and STY for screen—to confirm the session context.

What environment variables does witr use for session detection?

witr uses the TMUX environment variable for tmux sessions and the STY environment variable for screen sessions. These variables are searched across the process ancestry using the findEnvVar function, which performs a reverse traversal of the process tree to find the first occurrence of the specified key.

Where is the multiplexer detection logic implemented in witr?

The multiplexer detection logic is implemented in internal/source/shell.go, specifically within the enrichMultiplexer function (lines 108‑138). This function is called by detectShell (lines 55‑73) after identifying a shell process, and it utilizes the findEnvVar helper (lines 141‑150) to extract session identifiers from environment variables.

Can witr detect nested tmux or screen sessions?

Yes, witr can detect nested sessions because it traverses the entire process ancestry rather than stopping at the first match. The enrichMultiplexer function iterates through all ancestors, meaning if a process runs inside a tmux session that itself runs inside a screen session, witr will encounter both multiplexers in the ancestry chain and can enrich the source description with information about the outermost or most relevant session depending on the implementation details of the enrichment logic.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →