How witr Visualizes Process Trees Including Child Processes
witr renders process hierarchies by recursively collecting ancestry and child process data into structured slices, then printing them with ASCII tree connectors and dynamic indentation in internal/output/tree.go.
The witr command-line tool provides a clear, hierarchical view of running processes on Linux systems. According to the pranshuparmar/witr source code, it achieves this visualization by combining recursive process discovery with a specialized tree-rendering algorithm that displays both parent lineage and direct children in a single structured view.
Process Discovery and Data Structure
The visualization pipeline begins in the proc package, where witr gathers process information for the target PID. It constructs a model.Process struct (defined in pkg/model/process.go) and recursively discovers two critical relationships: the ancestry (the chain of parent processes leading to the target) and the children (direct descendants of the target).
The discovery layer returns two slices: []model.Process for ancestry (ordered from system root to target) and another []model.Process for immediate children. These data structures serve as the foundation for the visual tree.
Rendering the Tree with PrintTree
In internal/app/app.go at line 654, the application orchestrates the display by calling:
output.PrintTree(outw, res.Ancestry, res.Children, colorEnabled)
This invocation passes four parameters to the output layer:
outw– theio.Writerinterface that streams to the terminalres.Ancestry– the parent chain sliceres.Children– the direct descendants slicecolorEnabled– a boolean flag toggling ANSI color codes
The PrintTree function in internal/output/tree.go implements the core rendering logic using nested iteration over these slices.
Indentation and Visual Connectors
For each entry in the ancestry and children slices, the renderer calculates indentation using strings.Repeat(" ", i), where i represents the depth level. This creates the visual hierarchy that distinguishes parent, target, and child processes.
The function employs Unicode box-drawing characters to create branching lines:
└─indicates the final child in a branch├─indicates intermediate children with siblings
Process Labeling
Each node displays its command name and PID using ChainName(proc), a helper that extracts readable command identifiers from the process struct, paired with proc.PID. This combination appears at every indentation level to identify processes clearly.
Child Process Limiting and Truncation
To maintain readable output, witr imposes a hard limit of 10 child processes (limit := 10 in the source code). When the target process has more than 10 children, the renderer truncates the list and appends a summary line formatted as … and X more.
This truncation logic resides in internal/output/children.go, which provides helper utilities for managing overflow scenarios while preserving the visual integrity of the tree structure.
Colorized Output Support
When colorEnabled is true, the tree applies semantic coloring using constants defined in the output package:
- ColorMagenta highlights the branch connectors (
└─,├─) - ColorGreen emphasizes the target process name
- ColorDim grays out PID numbers for visual hierarchy
- ColorReset returns the terminal to default styling
These ANSI codes are applied conditionally throughout internal/output/tree.go (lines 16-28 and 59-64) to enhance readability without breaking the ASCII tree alignment.
Practical Usage Examples
Display the process tree for a specific PID:
witr tree 1234
Enable colorized output for better visual distinction:
witr tree 1234 --color
Typical plain-text output resembles:
systemd (pid 1)
└─ service-manager (pid 500)
└─ my-app (pid 1234)
├─ worker-1 (pid 5678)
├─ worker-2 (pid 5679)
└─ ... and 3 more
Summary
- Data Collection: The proc package gathers
model.Processstructs for ancestry and children, storing them as ordered slices. - Rendering Engine:
output.PrintTreeininternal/output/tree.gohandles indentation viastrings.Repeatand draws connectors using Unicode characters. - Display Limits: Child processes are capped at 10 entries, with truncation handled by
internal/output/children.go. - Color Support: Optional ANSI coloring highlights branches in magenta, target names in green, and PIDs in dim gray.
- Integration:
internal/app/app.go:654orchestrates the flow from data collection to terminal output.
Frequently Asked Questions
How does witr handle processes with hundreds of children?
witr limits the display to 10 child processes to prevent terminal flooding. If more children exist, it renders the first 10 and appends a … and X more line to indicate the total count. This logic is implemented in the children rendering utilities within the output package.
What determines the indentation depth in the tree output?
The indentation depth corresponds to the process's position in the hierarchy. The renderer uses strings.Repeat(" ", i) where i increments for each level of ancestry or child depth, creating the visual nested structure in internal/output/tree.go.
Can I disable the colors in witr's tree view?
Yes. The colorEnabled parameter passed to output.PrintTree controls ANSI color codes. You can disable colors by running the command without the color flag or by ensuring your terminal environment doesn't support or request color output, resulting in plain ASCII characters.
Where is the process name extracted from in the source code?
The readable command name is extracted using the ChainName(proc) helper function during the tree rendering phase. This function operates on the model.Process struct defined in pkg/model/process.go, which contains the command-line information collected during the initial process discovery phase.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →