pax_global_header 0000666 0000000 0000000 00000000064 15210311512 0014501 g ustar 00root root 0000000 0000000 52 comment=16729768c2d841139fd936f507299725d719f3a8
AGuyMarc-lsgpu-ce4c7bd/ 0000775 0000000 0000000 00000000000 15210311512 0015056 5 ustar 00root root 0000000 0000000 AGuyMarc-lsgpu-ce4c7bd/.gitignore 0000664 0000000 0000000 00000000131 15210311512 0017041 0 ustar 00root root 0000000 0000000 __pycache__/
*.pyc
*.egg-info/
dist/
build/
*.deb
*.info
debian_backup/
*.bak
notes_*.md
AGuyMarc-lsgpu-ce4c7bd/CHANGELOG.md 0000664 0000000 0000000 00000007345 15210311512 0016700 0 ustar 00root root 0000000 0000000 # Changelog
All notable changes to **lsgpus**. This is the canonical upstream changelog;
`debian/changelog` tracks Debian packaging only.
> The installed binary, man page and Debian package are named `lsgpus` (with a
> trailing `s`) since 0.2.0. The GitHub repository and the Python module stay
> `lsgpu`.
## 0.2.4 — 2026-06-04
* watch: the `--watch` header now carries the same identity as the default
listing — the canonical PCI bus id + nvidia-smi GPU index
(`[PCI 02:00.0 | nvidia-smi GPU0]`) and the `Driver:` line. These were only
in the non-watch output before; nothing is lost in watch mode anymore.
* docs: refresh the README demo GIF and the man OUTPUT sample to the new header.
## 0.2.3 — 2026-06-04
* watch: show the **full card name** in `--watch` headers. The previous code
kept only the bracketed model and left a dangling `]`
(e.g. `GeForce RTX 3050 6GB] (rev a1)`); it now shows the complete name.
* docs(README): add an animated demo of `lsgpus --watch` during an Ollama run
(VRAM climbing, GPU pegged, process list) in the real-time monitoring section.
* docs(man): add a static sample of a `--watch` frame to the OUTPUT section.
## 0.2.2 — 2026-06-04
* docs(man): document the two options that were missing from the man page —
`--all`/`-a` (show disconnected outputs) and `--watch`/`-w [SEC]` (live
in-place refresh; stop with **Ctrl+C** — there is no quit key). Add matching
EXAMPLES. The man had drifted behind the binary.
## 0.2.1 — 2026-05-29
* Show the canonical **PCI bus id** and the **nvidia-smi GPU index** next to
each card — e.g. `card1: … [PCI 02:00.0 | nvidia-smi GPU0]`. This resolves
the long-standing confusion between the kernel DRM `cardN` numbering (probe
order, what `lsgpus` lists) and the bus-sorted `GPU N` index reported by
`nvidia-smi` on multi-GPU machines — the PCI bus id is the only stable,
unambiguous identifier. Also surfaced in `--short` and as `nvidia_index` in
`--json`.
* Declare the license as the SPDX expression `GPL-2.0-or-later` and drop the
deprecated `License :: OSI Approved ::` classifier in `setup.py`.
* tests: add a version-consistency guard that fails if the version sources
(`setup.py`, `__version__`, man `.TH`, `debian/changelog`, this file) diverge.
## 0.2.0 — 2026-05-19
* Rename the installed binary `lsgpu` → `lsgpus` and the man page `lsgpu(1)` →
`lsgpus(1)` to avoid the clash with the `lsgpu(1)` tool shipped by
`igt-gpu-tools`. The Debian source/binary package is renamed to `lsgpus`
with `Replaces`/`Breaks` for a clean migration. The GitHub repository keeps
the name `AGuyMarc/lsgpu`. (Reported by seraf1 while packaging the AUR build.)
## 0.1.5 — 2026-05-18
* Clarify the dependency model in the README: Python 3.7+ and `/sys/class/drm`
only; reads `nvidia-smi` / `rocm-smi` when present, but no CUDA / ROCm /
pycuda required.
## 0.1.4 — 2026-05-15
* Packaging fixes: ship the man page and README, add a `debian/copyright`,
move the `/usr/bin/lsgpu` symlink to `debian/lsgpu.links`, drop the postinst
hack. Fix maintainer name `Aprin` → `APRIN`.
## 0.1.3 — 2026-05-15
* Lower `debhelper-compat` from 13 to 11 so the source package builds out of
the box on Ubuntu 22.04 LTS. (Reported by bigbob.)
## 0.1.2 — 2026-05-14
* Add the SPDX license header (`GPL-2.0-or-later`).
* EDID DTD sanity check: prefer the coarse size when the DTD diagonal exceeds
2× the coarse diagonal — fixes ~8" panels reported as 59" (e.g. SGN L01N8A,
BOE panels). (Reported by Blaise on LinuxFr.org.)
## 0.1.1 — 2026-05-03
* Initial release: NVIDIA stats (`nvidia-smi`), AMD stats (sysfs), GPU process
listing, real-time `--watch` sparklines, EDID monitor identification,
override-file support, connected-only default (`-a` for all).
AGuyMarc-lsgpu-ce4c7bd/LICENSE 0000664 0000000 0000000 00000043100 15210311512 0016061 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, see .
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Moe Ghoul, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
AGuyMarc-lsgpu-ce4c7bd/README.md 0000664 0000000 0000000 00000026476 15210311512 0016354 0 ustar 00root root 0000000 0000000 # lsgpus
List GPUs with details, outputs, and connected monitors.
Like `lscpu`, `lsusb`, `lspci`, `lsblk`, `lsmem` — but for graphics cards.
A useful CLI tool for Linux users and admins. Zero-dependency — just Python 3.7+ and /sys/class/drm. Reads info from standard tools (nvidia-smi/rocm-smi) when present — no CUDA, no ROCm, no pycuda needed.
> **Binary renamed in v0.2.0.** The installed command is now `lsgpus` (with a trailing `s`) instead of `lsgpu`, to avoid a name clash with the `lsgpu(1)` utility shipped by [`igt-gpu-tools`](https://gitlab.freedesktop.org/drm/igt-gpu-tools) on both Debian/Ubuntu and Arch. The GitHub repository keeps its original name (`AGuyMarc/lsgpu`).
**Companion tool:** [`lsdisplay`](https://github.com/AGuyMarc/lsdisplay) — list the connected displays/monitors that those GPUs drive.
## Why this exists
I built `lsgpus` and its companion [`lsdisplay`](https://github.com/AGuyMarc/lsdisplay) 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 card was driving which physical screen, 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?
`lsgpus` answers the silicon side. It lists each card, its driver, current load, and the processes pinning its VRAM:
```
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.
`lsdisplay` answers the screen-and-cable side. It identifies each physical panel and shows where it sits on my desk:
```
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 |
| |
| |
| |
| |
| |
| |
| |
+---------------------------------------------------+
```
→ that `HDMI-A-1` is the 32" Samsung in the bottom-right corner of my desk. The three Iiyama 27" on the top row are all on `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 silicon, the cable, the panel, and what each card is currently doing. That's the workflow `lsgpus` exists for — and zero-dependency Python is what makes it work on the locked-down sysadmin boxes where I actually need it.
## Daily use: tracking VRAM for local AI
If you run local LLMs (Ollama, vLLM, llama.cpp, text-generation-webui) or image/video models (ComfyUI, Forge, Stable Diffusion WebUI, Fooocus), you spend half your day asking the same four questions:
- *Which card has enough free VRAM to load this model right now?*
- *What is currently pinning 12 GB on `card1` — Ollama still loaded, ComfyUI that didn't release, an orphaned `python` process?*
- *Did Ollama actually land on the 4060 Ti, or did it fall back to the iGPU / a smaller card?*
- *Why is inference suddenly slow — is something else competing for the GPU?*
`lsgpus` answers all of those in a single shot. The `Processes:` block under each card (NVIDIA cards today) shows the PIDs that own VRAM and how much, **broken out by card** — no need to grep `nvidia-smi` and cross-reference `/proc//cmdline` to figure out which Python process is which.
Looking at `card1` from the workstation above:
```
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
```
Reading this: the card is idle (`GPU:0%`), but 12.7 GB of its 16.4 GB are pinned by `ollama` — typical of a model loaded and waiting for the next request. From those four lines I now know:
- I have ~3.6 GB of headroom left on this card before the next load OOMs,
- the heavy tenant is Ollama (not a forgotten ComfyUI worker I should kill),
- if I want to load a bigger model, my options are: close Ollama, drop to a smaller quant, or move to a card with more free VRAM — and `lsgpus` shows the headroom on all cards in the same call.
For real-time monitoring — watching a model load, diagnosing a sudden inference slowdown, seeing tokens-per-second pressure on the GPU — `lsgpus --watch` redraws in place with a rolling 20-sample utilization sparkline (▁▂▃▄▅▆▇█) and a progress bar next to each card, while keeping the process list visible so VRAM creep is observable as it happens:
```bash
lsgpus --watch # default 2 s interval
lsgpus --watch 5 # 5 s interval (gentler on the system)
# press Ctrl+C to stop (there is no quit key; Esc / q / Ctrl+D do nothing)
```

In a typical local-AI workflow that looks like: launch `lsgpus --watch` in a side terminal, start `ollama run ` in another, see the VRAM of the chosen card climb to its plateau, then watch the utilization sparkline pulse as each generation runs.
## Features
- **GPU details**: name, driver, PCI address, VRAM
- **NVIDIA stats**: utilization, memory, temperature, power draw (via nvidia-smi)
- **Output mapping**: each port mapped to its connected monitor via EDID
- **Monitor identification**: manufacturer, model, serial, diagonal size
- **JSON output** for scripting
- No external Python dependencies, works with Python 3.7+
## Installation
### Debian / Ubuntu (.deb)
Download the `.deb` from the [Releases page](https://github.com/AGuyMarc/lsgpu/releases/latest), then:
```bash
sudo dpkg -i lsgpus_0.2.0-1_all.deb
```
The package installs `/usr/bin/lsgpus`, the man page `lsgpus(1)`, and documentation.
**Upgrading from v0.1.x** (when the package was named `lsgpu`): the new package declares `Replaces: lsgpu (<< 0.2.0)` and `Breaks: lsgpu (<< 0.2.0)`, so `dpkg -i lsgpus_0.2.0-1_all.deb` cleanly removes the old `lsgpu` package on install. If you prefer an explicit cleanup first:
```bash
sudo apt remove lsgpu
sudo dpkg -i lsgpus_0.2.0-1_all.deb
```
### Arch Linux / Manjaro (AUR)
Available in the AUR thanks to [@seraf1](https://aur.archlinux.org/account/seraf1):
```bash
yay -S lsgpu-git
```
Package page: https://aur.archlinux.org/packages/lsgpu-git
(The AUR package name may follow the binary rename to `lsgpus-git` after seraf1's next update — check the AUR page for the current name.)
### From source
```bash
git clone https://github.com/AGuyMarc/lsgpu
cd lsgpu
sudo cp lsgpu.py /usr/local/bin/lsgpus
sudo chmod +x /usr/local/bin/lsgpus
```
## Usage
```bash
lsgpus # Full output
lsgpus --short # Compact one-line-per-GPU
lsgpus --all # Include disconnected outputs
lsgpus --watch # Real-time monitoring (Ctrl+C to stop)
lsgpus --json # JSON output
```
## Example output
```
GRAPHICS CARDS
==============
card0: NVIDIA Corporation GA107 [GeForce RTX 3050 6GB] (rev a1)
Driver: nvidia | VRAM: 6 GB | GPU:0% MEM:2077/6144MB 37°C 16.7W
├─ 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 | VRAM: 16 GB | GPU:0% MEM:277/16380MB 41°C 14.9W
├─ DP-1: -
├─ DP-2: -
├─ DP-3: -
├─ HDMI-A-1: connected ← Samsung SAMSUNG 32"
card2: Intel Corporation Arrow Lake-S [Intel Graphics] (rev 06)
Driver: i915
├─ HDMI-A-4: connected ← Iiyama PL2793Q 27"
├─ HDMI-A-5: connected ← Samsung SAMSUNG 65"
Total: 3 GPU(s), 6 output(s) connected
```
## Requirements
- Python 3.7+
- Linux with `/sys/class/drm`
- `lspci` (from pciutils)
- `nvidia-smi` (optional, for NVIDIA stats)
## See also
Hardware enumeration `ls*` family on Linux:
- [`lsdisplay`](https://github.com/AGuyMarc/lsdisplay) — connected displays/monitors (companion to this tool)
- `lsgpu(1)` from `igt-gpu-tools` — low-level Intel Graphics Tests utility (different audience)
- `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](LICENSE) for the full text.
AGuyMarc-lsgpu-ce4c7bd/debian/ 0000775 0000000 0000000 00000000000 15210311512 0016300 5 ustar 00root root 0000000 0000000 AGuyMarc-lsgpu-ce4c7bd/debian/changelog 0000664 0000000 0000000 00000010475 15210311512 0020161 0 ustar 00root root 0000000 0000000 lsgpus (0.2.4-1) unstable; urgency=medium
* New upstream release 0.2.4; see CHANGELOG.md for the upstream changes.
No Debian packaging changes.
-- Guy-Marc APRIN <2026@gm.casa> Thu, 04 Jun 2026 17:01:28 +0200
lsgpus (0.2.3-1) unstable; urgency=medium
* New upstream release 0.2.3; see CHANGELOG.md for the upstream changes.
No Debian packaging changes.
-- Guy-Marc APRIN <2026@gm.casa> Thu, 04 Jun 2026 14:56:41 +0200
lsgpus (0.2.2-1) unstable; urgency=medium
* New upstream release 0.2.2; see CHANGELOG.md for the upstream changes.
No Debian packaging changes.
-- Guy-Marc APRIN <2026@gm.casa> Thu, 04 Jun 2026 13:18:31 +0200
lsgpus (0.2.1-1) unstable; urgency=medium
* New upstream release 0.2.1 — see CHANGELOG.md for the full list of software
changes (each card now shows its PCI bus id + nvidia-smi GPU index).
* Packaging: declare the license as the SPDX expression GPL-2.0-or-later and
drop the deprecated "License :: OSI Approved ::" classifier in setup.py
(aligns with the SPDX headers already in the sources).
* Packaging: the project's canonical changelog now lives in CHANGELOG.md at
the repo root; this debian/changelog tracks packaging changes only.
-- Guy-Marc APRIN <2026@gm.casa> Fri, 29 May 2026 22:19:09 +0200
lsgpus (0.2.0-1) unstable; urgency=medium
* Rename installed binary from /usr/bin/lsgpu to /usr/bin/lsgpus and
man page from lsgpu(1) to lsgpus(1), to avoid a name clash with the
lsgpu(1) tool shipped by the igt-gpu-tools package (low-level Intel
Graphics Tests utility, present in /usr/bin/lsgpu on both Arch and
Debian/Ubuntu). Reported by Philippe Séraphin (seraf1) while
packaging the AUR build.
* Debian source/binary package renamed from lsgpu to lsgpus to match.
Replaces/Breaks lsgpu (<< 0.2.0) so dpkg can clean-migrate users
of the v0.1.x .deb. Upgrade procedure documented in README.
* GitHub repository keeps its original name (AGuyMarc/lsgpu) so
existing links from the LinuxFr.org journal and elsewhere stay
valid; only the installed binary and the Debian package were
renamed.
-- Guy-Marc APRIN <2026@gm.casa> Tue, 19 May 2026 01:00:00 +0200
lsgpu (0.1.5-1) unstable; urgency=medium
* Update README description to clarify dependency model: Python 3.7+ and
/sys/class/drm only, reads info from standard tools (nvidia-smi/rocm-smi)
when present, but no CUDA / no ROCm / no pycuda required.
* Match GitHub repo description with the new README phrasing.
-- Guy-Marc APRIN <2026@gm.casa> Mon, 18 May 2026 22:18:00 +0200
lsgpu (0.1.4-1) unstable; urgency=medium
* Fix Debian packaging regression introduced in 0.1.3:
- Install man page via debian/lsgpu.manpages (was missing from .deb).
- Install README.md via debian/lsgpu.docs.
- Add Debian-format debian/copyright file.
- Move /usr/bin/lsgpu symlink from postinst hack to debian/lsgpu.links
(the symlink now appears in dpkg-deb -c output, no runtime hack).
- Remove now-unused debian/postinst (debhelper auto-handles man-db).
* Fix Maintainer in debian/control: 'Aprin' -> 'APRIN' to match the
upstream convention applied across all source headers.
-- Guy-Marc APRIN <2026@gm.casa> Fri, 15 May 2026 19:30:00 +0200
lsgpu (0.1.3-1) unstable; urgency=medium
* Lower debhelper-compat level from 13 to 11 in Build-Depends so the
source package builds out of the box on Ubuntu 22.04 LTS. Reported
by Creteil (bigbob) in lsdisplay#2 (same root cause).
-- Guy-Marc APRIN <2026@gm.casa> Fri, 15 May 2026 00:21:00 +0200
lsgpu (0.1.2-1) unstable; urgency=medium
* Add SPDX license header (GPL-2.0-or-later)
* Sanity check on EDID detailed timing (DTD): prefer coarse size from
bytes 21-22 when DTD diagonal exceeds 2× coarse diagonal — fixes ~8"
displays appearing as 59" when the DTD field contains pixels instead
of millimetres (e.g. SGN L01N8A, BOE panels). Reported by Blaise on
LinuxFr.org.
-- Guy-Marc APRIN <2026@gm.casa> Thu, 14 May 2026 21:51:04 +0200
lsgpu (0.1.1-1) unstable; urgency=medium
* Initial release
* NVIDIA stats via nvidia-smi
* AMD stats via sysfs
* GPU process listing
* Real-time monitoring with sparklines (--watch)
* EDID monitor identification
* Override file support
* Connected-only default (-a for all)
-- Guy-Marc Aprin <2026@gm.casa> Sat, 03 May 2026 12:00:00 +0200
AGuyMarc-lsgpu-ce4c7bd/debian/control 0000664 0000000 0000000 00000001547 15210311512 0017712 0 ustar 00root root 0000000 0000000 Source: lsgpus
Section: utils
Priority: optional
Maintainer: Guy-Marc APRIN <2026@gm.casa>
Build-Depends: debhelper-compat (= 11), python3
Standards-Version: 4.6.2
Homepage: https://github.com/AGuyMarc/lsgpu
Package: lsgpus
Architecture: all
Depends: python3 (>= 3.7), ${misc:Depends}
Recommends: pciutils, nvidia-utils
Replaces: lsgpu (<< 0.2.0)
Breaks: lsgpu (<< 0.2.0)
Description: List GPUs with details, outputs, and connected monitors
lsgpus lists all graphics cards with driver, VRAM, PCI address,
and for NVIDIA: utilization, memory, temperature, power draw.
Each output port is mapped to its connected monitor via EDID.
Supports real-time monitoring (--watch), GPU process listing,
AMD and NVIDIA stats, and sparkline history.
.
Binary renamed from lsgpu to lsgpus in v0.2.0 to avoid a clash with
the lsgpu(1) tool shipped by the igt-gpu-tools package.
AGuyMarc-lsgpu-ce4c7bd/debian/copyright 0000664 0000000 0000000 00000002016 15210311512 0020232 0 ustar 00root root 0000000 0000000 Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: lsgpus
Upstream-Contact: Guy-Marc APRIN <2026@gm.casa>
Source: https://github.com/AGuyMarc/lsgpu
Files: *
Copyright: 2026 Guy-Marc APRIN <2026@gm.casa>
License: GPL-2+
License: GPL-2+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
.
On Debian systems, the complete text of the GNU General Public
License version 2 can be found in "/usr/share/common-licenses/GPL-2".
AGuyMarc-lsgpu-ce4c7bd/debian/install 0000664 0000000 0000000 00000000021 15210311512 0017662 0 ustar 00root root 0000000 0000000 lsgpu.py usr/bin
AGuyMarc-lsgpu-ce4c7bd/debian/lsgpus.docs 0000664 0000000 0000000 00000000012 15210311512 0020460 0 ustar 00root root 0000000 0000000 README.md
AGuyMarc-lsgpu-ce4c7bd/debian/lsgpus.links 0000664 0000000 0000000 00000000040 15210311512 0020651 0 ustar 00root root 0000000 0000000 usr/bin/lsgpu.py usr/bin/lsgpus
AGuyMarc-lsgpu-ce4c7bd/debian/lsgpus.manpages 0000664 0000000 0000000 00000000011 15210311512 0021322 0 ustar 00root root 0000000 0000000 lsgpus.1
AGuyMarc-lsgpu-ce4c7bd/debian/rules 0000775 0000000 0000000 00000000177 15210311512 0017365 0 ustar 00root root 0000000 0000000 #!/usr/bin/make -f
%:
dh $@
override_dh_auto_clean:
override_dh_auto_build:
override_dh_auto_install:
override_dh_auto_test:
AGuyMarc-lsgpu-ce4c7bd/docs/ 0000775 0000000 0000000 00000000000 15210311512 0016006 5 ustar 00root root 0000000 0000000 AGuyMarc-lsgpu-ce4c7bd/docs/lsgpus-watch.gif 0000664 0000000 0000000 00000255305 15210311512 0021130 0 ustar 00root root 0000000 0000000 GIF89am (*6)+7*,8')5(*6*,8+-8+-9,.9,.:.01<02=13>13?24@35@46A57B68C78C79C8:D9;E:H=?I>@J?AJ@BKABLACMBDNCENDFOEGPEFQFGQFHRGIRHJSIKTJKTKLUKMVLNWMOXNPXOPYPQZQR[QS[RT\SU]TU^UV_VW_VX`WY`XZaYZbZ[b[\c[]d\^e]_f^_f_`g`ahabiacibckbdjcdkcdldemefmegnfhoghohipijpjlrkmslntmntnouopvpqwprwqsxrsystztu{uv{uw|vx}wx~xy~yz~xzz{{|{}|}}~~!NETSCAPE2.0 ! !gif.ski , m
H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@
JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿LÇ +^̸㞈#?L##̹Ϗ5'MpEnyckc˞P?i۳mܽ-vq?μɕ.;}dسv1NHHgW_-?>_7Z? z_Qh64`6T>(af!Ln ~a$hC#,0(4h8<@)DiH&L6PF)TViXf\v`)dihlp)tix襟|%!JW1Q*iXU]r(
ڔ0jJvrfkgʢ+k&6F+Vkfv+K覫+Nfn ,l'7G,Wlg ,$l(,0,4l8<@-DmŦz|L7PG-TWmXg\w`-y*Mfojv{-pKwލ7zn~xn'7G.Wngw砇.褗n騧ꬷ.nqNث(Nޠ>ߧeԾ/o DS:Z|'H
Z̠7z GH(L
W0gH8̡w@H"d &:PH*ZX̢--:^dh1RB1y5e#9¦v<
> IBL"=2r0q#'i-IR2Sۊ%/N
m(GIRL*WVi|,gX!-wˍ鲗0IbL2f:M|4h3̦6ofmz8IrL:vɁ~
@LDF>ZY"eЗG&4HGJҒ(MJWҖ0LgJSI8nӞ@
PJԢHMRԦ:PTJժZ ! ,
G;
8*\ȰÇ#JHŋ3j"CIɓ(SnHP˗0cʜI!˂5sp1ó&a:1f[ P W͎g?PwvP:{V poAm~ J Vt~ `ګBױJ1^V[!Ý`p1-Ŭ!IbVuqD#>!k$osf)[/$@] p V\7.&mdi#)o
@-\M,b6`%VB" M`BN7 '"P`ZlIH:[nndRh KK-eeV]i
CHv:?TrgPzwP H|PH)ERWFԠ]JT% LB%eIPnB^S&