Skip to main content

lsdisplay

List connected displays with details and ASCII layout diagram.

Like lsusb, lspci, lscpu, lsblk, lsmem — but for displays.

A useful CLI tool for Linux users and admins. Zero-dependency — just Python 3.7+ and /sys/class/drm. (Config-path handling follows the XDG spec more closely when the optional pyxdg module — Debian python3-xdg — is installed.)

Companion tool: lsgpu — list the GPUs that drive those displays (with NVIDIA/AMD stats).

Why this exists

I built lsdisplay and its companion lsgpu in parallel, both for the same reason: setting up my sysadmin workstation — six monitors driven by three GPUs (two NVIDIA cards plus the Arrow Lake iGPU), one of them a 65" overview TV — and finding that no single Linux command could tell me which physical screen was driven by which output, on which card, doing what.

Try answering this concretely: which GPU is driving the 32" Samsung sitting in the bottom-right corner of my desk right now, and what is that card actually doing?

lsdisplay answers the screen-and-cable side. It identifies each physical panel and shows where it sits:

CONNECTED DISPLAYS
==================

  HDMI-A-2     1440x2560+1441+0        27"  75Hz  Iiyama PL2792Q       HDMI         S/N:1152032422031   rot=left [PRIMARY]
  HDMI-A-3     1440x2560+2881+0        27"  75Hz  Iiyama PL2792Q       HDMI         S/N:1152032422030   rot=left
  HDMI-A-5     5376x3024+0+2561        65"  60Hz  Samsung TQ65QN800DTXXC HDMI       S/N:94:e6:ba:dd:9a:7a
  DP-4         1440x2560+0+0           27"  75Hz  Iiyama PL2792Q       DisplayPort  S/N:1152031921274   rot=left
  HDMI-A-4     1440x2560+4322+0        27"  75Hz  Iiyama PL2793Q       HDMI         S/N:12464540C1808   rot=left
  HDMI-A-1     1920x1080+5376+2561     32"  60Hz  Samsung QE32Q50A     HDMI         S/N:bc:45:5b:e4:e8:13

Total: 6 displays connected

LAYOUT
======

  +-------------+-------------+------------+-------------+
  |             |             |            |             |
  |             |             |            |             |
  |             |             |            |             |
  |             |             |            |             |
  |             |             |            |             |
  |    DP-4     |  HDMI-A-2*  |  HDMI-A-3  |  HDMI-A-4   |
  |             |             |            |             |
  |             |             |            |             |
  |             |             |            |             |
  |             |             |            |             |
  |             |             |            |             |
  +-------------+-------------+------------+----------+-----------------+
  |                                                   |                 |
  |                                                   |    HDMI-A-1     |
  |                                                   |                 |
  |                                                   |                 |
  |                                                   +-----------------+
  |                                                   |
  |                     HDMI-A-5                      |
  |                                                   |
  |                                                   |
  |                                                   |
  |                                                   |
  |                                                   |
  |                                                   |
  |                                                   |
  +---------------------------------------------------+

→ the 32" Samsung in the bottom-right corner is HDMI-A-1.

lsgpu answers the silicon side. It identifies each card and shows what it is currently running:

GRAPHICS CARDS
==============

  card0: NVIDIA Corporation GA107 [GeForce RTX 3050 6GB] (rev a1)
         Driver: nvidia | GPU:26% MEM:4422/6144MB 48°C 27.3W
    ├─ DP-4: connected ← Iiyama PL2792Q 27"
    ├─ HDMI-A-2: connected ← Iiyama PL2792Q 27"
    ├─ HDMI-A-3: connected ← Iiyama PL2792Q 27"

  card1: NVIDIA Corporation AD106 [GeForce RTX 4060 Ti] (rev a1)
         Driver: nvidia | GPU:0% MEM:12794/16380MB 48°C 15.1W
    ├─ HDMI-A-1: connected ← Samsung QE32Q50A 32"
    Processes:
      PID 9728  ollama  12744MB

  card2: Intel Corporation Arrow Lake-S [Intel Graphics] (rev 06)
         Driver: i915
    ├─ HDMI-A-4: connected ← Iiyama PL2793Q 27"
    ├─ HDMI-A-5: connected ← Samsung TQ65QN800DTXXC 65"

Total: 3 GPUs, 6 outputs connected

HDMI-A-1 lives on card1, the RTX 4060 Ti, currently pinned by Ollama with 12.7 GB of VRAM. The three Iiyama 27" on the top row are all driven by card0 (RTX 3050 6 GB); the fourth 27" and the 65" overview TV come straight out of the Intel Arrow Lake iGPU (card2).

Together they tell the whole story: the screen in front of me, the cable behind it, the card driving it, and what that card is doing right now. That's the workflow lsdisplay exists for — and zero-dependency Python is what makes it work on the locked-down sysadmin boxes where I actually need it.

Features

  • EDID parsing from /sys/class/drm/*/edid: manufacturer, model, serial number
  • Resolution, position, rotation via xrandr (fallback: kscreen-doctor, wlr-randr)
  • ASCII art layout diagram with correct proportions
  • JSON output for scripting
  • Works on X11 and Wayland (KDE, Sway, etc.)
  • No external dependencies, Python 3.7+

Installation

Debian / Ubuntu (.deb)

Download the .deb from the Releases page, then:

sudo dpkg -i lsdisplay_0.2.1-1_all.deb

The package installs /usr/bin/lsdisplay, the man page lsdisplay(1), and documentation.

Arch Linux / Manjaro (AUR)

Available in the AUR thanks to @seraf1:

yay -S lsdisplay-git

Package page: https://aur.archlinux.org/packages/lsdisplay-git

Fedora (COPR)

Available from the ls-tools COPR repository:

sudo dnf copr enable guy-marc-aprin/ls-tools
sudo dnf install lsdisplay

Builds are provided for Fedora 43, 44 and rawhide (x86_64). Enabling the COPR also gives you lsgpus (the companion GPU-listing tool).

Updates come with the system: sudo dnf upgrade picks up new releases automatically once the COPR is enabled. To remove the repository later:

sudo dnf copr remove guy-marc-aprin/ls-tools

RHEL / Rocky / AlmaLinux / CentOS Stream — the same COPR works; just enable the COPR plugin first:

sudo dnf install dnf-plugins-core
sudo dnf copr enable guy-marc-aprin/ls-tools
sudo dnf install lsdisplay

From source

git clone https://github.com/AGuyMarc/lsdisplay
cd lsdisplay

# System-wide
sudo cp lsdisplay.py /usr/local/bin/lsdisplay
sudo chmod +x /usr/local/bin/lsdisplay

# Or user-local
cp lsdisplay.py ~/.local/bin/lsdisplay
chmod +x ~/.local/bin/lsdisplay

Usage

lsdisplay                  # Full output with layout diagram
lsdisplay --short          # Compact one-line-per-display
lsdisplay --json           # JSON output for scripting
lsdisplay --no-layout      # Skip the ASCII art diagram
lsdisplay --connected-only # Hide disconnected outputs
lsdisplay --list-priority  # Display priority order with GPU mapping
lsdisplay --no-color       # Disable coloured output
lsdisplay --version        # Show version

Smart TV network scan

lsdisplay --scan                 # Auto-detect the local subnet
lsdisplay --scan 192.168.1.0/24  # Scan a specific subnet

Display overrides (for wrong or missing EDID)

lsdisplay --override-list        # List current overrides
lsdisplay --override-add         # Interactive wizard for a detected display
lsdisplay --override-set SAM7513 --override-model QN65QN900B --override-diagonal 65 --override-note Salon
lsdisplay --override-remove SAM7513

Save or restore the config

lsdisplay --write-config           # Save overrides to your user config
lsdisplay --write-config=system    # Install overrides machine-wide (needs sudo)
lsdisplay --restore-config=system  # Copy machine config into your user config

Scripting

lsdisplay --json | jq '.[].manufacturer'

Configuration

Display overrides live in overrides.json, searched in XDG order (first match wins per key):

Scope Path
User $XDG_CONFIG_HOME/lsdisplay/ (default ~/.config/lsdisplay/)
System $XDG_CONFIG_DIRS entries, then /etc/xdg/lsdisplay/ — canonical system path
Legacy /etc/lsdisplay/deprecated, still read as a last-resort fallback

Full XDG semantics need the optional pyxdg module; without it the fallback paths above are used. If /etc/lsdisplay/overrides.json is found, a one-line deprecation note is printed to stderr (stdout and --json stay clean). lsdisplay never moves or writes it for you.

Saving & restoring overrides

lsdisplay --write-config            # save current overrides to your user config
lsdisplay --write-config=system     # install them machine-wide (needs sudo)
sudo lsdisplay --write-config=system

lsdisplay --restore-config=system          # pull the machine config into your user config
lsdisplay --restore-config=~/backup.json   # import an overrides.json (e.g. a *.bak)

--write-config pushes your active overrides to a scope; --restore-config pulls a config into your user scope. Both back up any existing target to *.bak first. --write-config=system replaces the old silent /etc auto-copy with an explicit, visible action.

Example output

Compact one-line-per-display view (lsdisplay --short) of a six-screen workstation — * marks the primary. The full table with serials plus the ASCII layout diagram is shown in Why this exists above.

  HDMI-A-1     1920x1080@60Hz  32" Samsung QE32Q50A [HDMI]
* HDMI-A-2     1440x2560@75Hz  27" Iiyama PL2792Q [HDMI]
  HDMI-A-3     1440x2560@75Hz  27" Iiyama PL2792Q [HDMI]
  HDMI-A-5     5376x3024@60Hz  65" Samsung TQ65QN800DTXXC [HDMI]
  DP-4         1440x2560@75Hz  27" Iiyama PL2792Q [DisplayPort]
  HDMI-A-4     1440x2560@75Hz  27" Iiyama PL2793Q [HDMI]

Requirements

Required:

  • Python 3.7+
  • Linux with /sys/class/drm (any modern kernel)

Optional (lsdisplay still lists every display with EDID details without them):

  • xrandr (X11), kscreen-doctor (KDE Wayland) or wlr-randr (wlroots Wayland) — for live resolution, position and rotation
  • pyxdg (Debian python3-xdg) — full $XDG_CONFIG_HOME/$XDG_CONFIG_DIRS config-path semantics

How it works

  1. Scans /sys/class/drm/card*/edid for raw EDID data
  2. Parses EDID to extract PNP manufacturer ID, monitor name, serial number
  3. Maps PNP IDs to human-readable names (Samsung, Dell, Iiyama, etc.)
  4. Uses xrandr output for resolution, position, rotation
  5. Draws ASCII art layout proportional to actual pixel dimensions

See also

Hardware enumeration ls* family on Linux:

  • lsgpu — GPUs (NVIDIA/AMD/Intel) with stats and output mapping (companion to this tool)
  • lscpu — CPU architecture info
  • lspci — PCI devices
  • lsusb — USB devices
  • lsblk — block devices (disks, partitions)
  • lsmem — memory ranges
  • lsmod — kernel modules
  • lsipc — IPC facilities
  • lsns — namespaces

License

GPL-2.0. See LICENSE for the full text.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lsdisplay-0.2.5.tar.gz (33.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lsdisplay-0.2.5-py3-none-any.whl (29.9 kB view details)

Uploaded Python 3

File details

Details for the file lsdisplay-0.2.5.tar.gz.

File metadata

  • Download URL: lsdisplay-0.2.5.tar.gz
  • Upload date:
  • Size: 33.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.4

File hashes

Hashes for lsdisplay-0.2.5.tar.gz
Algorithm Hash digest
SHA256 52160992b2f982bfbc9c21a657d3df2730829bb02a2e128a768ff61d5736a357
MD5 97a00d14ad9add0eccacf22b01b6a6a2
BLAKE2b-256 4bf83d04348854817322dcd97887c31c6609fc52223ef5343c746aad75286f9b

See more details on using hashes here.

File details

Details for the file lsdisplay-0.2.5-py3-none-any.whl.

File metadata

  • Download URL: lsdisplay-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 29.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.4

File hashes

Hashes for lsdisplay-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 62b5856eac97e1940c5fbc3be70c1715f26111ba1f842af39e3f205b7bd9b730
MD5 9f2235cb6191ef47c5b60e543b100bb4
BLAKE2b-256 6c9016e58f43888cc376061ada3d77afc1f5f74537742500e71f4c0f1e5ff81f

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.5 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page