This is the way I install pwndbg from a local checkout when I want the Python dependencies isolated in a venv.
I am not using setup.sh here. The script is convenient, but it also tries to install system packages with sudo. For a clean user-level install, I prefer doing the Python part explicitly.
The checkout used in this note:
cd /home/ihexon/pwndbgInstall System Packages#
You still need GDB and Python’s venv support from the system package manager.
On Ubuntu/Debian:
sudo apt update
sudo apt install git gdb gdbserver python3-dev python3-venv python3-setuptools libc6-dbglibc6-dbg is not strictly required for loading pwndbg, but it is useful when debugging normal Linux userland binaries.
Check Which Python GDB Uses#
pwndbg runs inside GDB’s embedded Python interpreter. The venv should be created with the same Python version.
Check it:
gdb -batch -q --nx -ex 'pi import sys; print(sys.version)'Also ask GDB for the Python executable path:
gdb -batch -q --nx -ex 'pi import sysconfig; print(sysconfig.get_config_vars().get("EXENAME", sysconfig.get_config_var("BINDIR")+"/python"+sysconfig.get_config_var("VERSION")+sysconfig.get_config_var("EXE")))'On my machine this is:
/usr/bin/python3.13So I use /usr/bin/python3.13 below. If your GDB uses Python 3.12, use that instead.
Create a Fresh venv#
From the pwndbg checkout:
cd /home/ihexon/pwndbg
/usr/bin/python3.13 -m venv .venvThe venv now lives at:
/home/ihexon/pwndbg/.venvCheck it:
.venv/bin/python --versionExpected shape:
Python 3.13.7Install uv#
pwndbg uses uv and ships a uv.lock file. The venv is just the isolated Python environment; uv is the tool that installs the exact dependency set into it.
Install uv inside the venv:
.venv/bin/python -m pip install --upgrade pip uvThen sync the project:
.venv/bin/uv sync --activeThis installs pwndbg itself and its dependencies into .venv.
You should see something like:
+ pwndbg==2026.2.18 (from file:///home/ihexon/pwndbg)That means the local checkout was installed into the venv.
Do not be surprised if uv sync changes the uv version inside the venv. The repo’s lockfile decides the version.
Load pwndbg From GDB#
Add this line to ~/.gdbinit:
source /home/ihexon/pwndbg/gdbinit.pyThat is enough. You do not need to activate the venv before running GDB.
The reason is that GDB starts its own embedded Python interpreter. Activating a shell venv only affects shell-launched Python programs; it does not replace GDB’s embedded interpreter.
Instead, gdbinit.py does the important part:
gdb
-> ~/.gdbinit
-> /home/ihexon/pwndbg/gdbinit.py
-> /home/ihexon/pwndbg/.venv/lib/python3.13/site-packages
-> load pwndbgSo the package is installed in the venv, but GDB reaches into that venv through gdbinit.py.
Test#
Run:
gdb -qIf pwndbg loads, you should see a message like:
pwndbg: loaded ... pwndbg commandsFor a non-interactive check:
PWNDBG_NO_AUTOUPDATE=1 gdb -q -batch -ex 'pi import pwndbg, sys; print(sys.prefix); print(pwndbg.__file__)'Expected shape:
/home/ihexon/pwndbg/.venv
/home/ihexon/pwndbg/pwndbg/__init__.pyAfter that, just use GDB normally:
gdb ./challNo source .venv/bin/activate is required.
Updating Later#
After pulling a newer pwndbg checkout:
cd /home/ihexon/pwndbg
.venv/bin/uv sync --activeIf GDB’s Python version changes after a distro upgrade, recreate .venv with the new Python executable and run uv sync again.

