giampaolo/psutil
Cross-platform lib for process and system monitoring in Python
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit today
- ✓2 active contributors
- ✓BSD-3-Clause licensed
Show all 7 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Small team — 2 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 98% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/giampaolo/psutil)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/giampaolo/psutil on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: giampaolo/psutil
Generated by RepoPilot · 2026-05-07 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/giampaolo/psutil shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit today
- 2 active contributors
- BSD-3-Clause licensed
- CI configured
- Tests present
- ⚠ Small team — 2 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 98% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live giampaolo/psutil
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/giampaolo/psutil.
What it runs against: a local clone of giampaolo/psutil — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in giampaolo/psutil | Confirms the artifact applies here, not a fork |
| 2 | License is still BSD-3-Clause | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of giampaolo/psutil. If you don't
# have one yet, run these first:
#
# git clone https://github.com/giampaolo/psutil.git
# cd psutil
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of giampaolo/psutil and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "giampaolo/psutil(\\.git)?\\b" \\
&& ok "origin remote is giampaolo/psutil" \\
|| miss "origin remote is not giampaolo/psutil (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(BSD-3-Clause)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"BSD-3-Clause\"" package.json 2>/dev/null) \\
&& ok "license is BSD-3-Clause" \\
|| miss "license drift — was BSD-3-Clause at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "psutil/__init__.py" \\
&& ok "psutil/__init__.py" \\
|| miss "missing critical file: psutil/__init__.py"
test -f "psutil/_common.py" \\
&& ok "psutil/_common.py" \\
|| miss "missing critical file: psutil/_common.py"
test -f "psutil/_psutil_posix.c" \\
&& ok "psutil/_psutil_posix.c" \\
|| miss "missing critical file: psutil/_psutil_posix.c"
test -f "psutil/_process_common.py" \\
&& ok "psutil/_process_common.py" \\
|| miss "missing critical file: psutil/_process_common.py"
test -f "Makefile" \\
&& ok "Makefile" \\
|| miss "missing critical file: Makefile"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/giampaolo/psutil"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
psutil is a cross-platform Python library that exposes process and system-level metrics (CPU, memory, disk, network, sensors) via a unified API, implementing functionality equivalent to UNIX tools like ps, top, free, iotop, and netstat. It wraps platform-specific system calls (via C extensions for Linux/Windows/BSD/Solaris) and provides high-level Python interfaces to query running processes and real-time system utilization. Hybrid Python/C monorepo: psutil/ contains the main Python package with platform-specific C extensions in subdirectories (psutil/_pslinux.c, psutil/_pswindows.c, etc.); tests/ holds comprehensive unit and integration tests; docs/ contains Sphinx documentation with custom extensions for API docs; Makefile orchestrates build, test, and release workflows; _bootstrap.py handles initial environment setup.
👥Who it's for
System administrators, DevOps engineers, and Python application developers who need to monitor process behavior, enforce resource limits, profile applications, or build system monitoring dashboards without writing OS-specific code. Users include major projects and 760,000+ GitHub dependents relying on it for telemetry and process management.
🌱Maturity & risk
Production-ready and heavily adopted: psutil ranks in the top 100 most-downloaded PyPI packages with 330+ million monthly downloads and is used by 15,000+ dependent packages. The project has mature CI/CD (GitHub Actions for Linux, macOS, Windows, BSD, Solaris), comprehensive test coverage, and active maintenance visible through the Makefile and documented development notes in docs/DEVNOTES.md.
Low risk for stable use but platform fragmentation is inherent: the C extension layer adds maintenance burden across 6+ operating systems (Linux, Windows, macOS, FreeBSD, NetBSD, OpenBSD, Solaris, AIX), and changes to one platform's syscall interface can ripple across the codebase. The maintainer (giampaolo) appears primarily responsible, creating potential single-point-of-failure risk; however, the mature test suite and CI/CD mitigate breaking changes.
Active areas of work
Active maintenance with automated CI/CD workflows (.github/workflows/build.yml for multi-platform testing, changelog_bot.yml for release notes). The repository includes GitHub Actions for Linux/macOS/Windows builds and dedicated BSD/SunOS test workflows. Recent tooling additions visible in .clang-format and .dprint.jsonc suggest code formatting standardization efforts.
🚀Get running
Clone the repo and install for development: git clone https://github.com/giampaolo/psutil.git && cd psutil && pip install -e . (or make install using the Makefile). Run tests with make test. Full details in INSTALL.rst and CONTRIBUTING.md.
Daily commands:
Development: make install to install in editable mode, then make test to run unit tests. Building C extensions requires a C compiler (gcc/clang on Unix, MSVC on Windows). Check Makefile for specific targets: make build compiles extensions, make clean removes build artifacts. Documentation builds via sphinx-build (see docs/Makefile).
🗺️Map of the codebase
psutil/__init__.py— Main package entry point exposing all public APIs (Process, cpu_, memory_, disk_, net_, etc.)—every contributor must understand the public interface.psutil/_common.py— Defines named tuples and common data structures (ProcessStatus, CPUTimes, MemoryInfo) shared across all platform implementations.psutil/_psutil_posix.c— Core C extension for POSIX systems (Linux, macOS, BSD)—handles low-level process and system information retrieval.psutil/_process_common.py— Platform-agnostic Process class implementation—defines the common interface all platform-specific subclasses must follow.Makefile— Build automation for compiling C extensions and running tests—essential for contributors setting up development environment.CONTRIBUTING.md— Contributor guidelines including platform-specific testing, coding standards, and pull request process._bootstrap.py— Initialization script handling platform detection and C extension loading—critical for understanding how the library adapts to different OSes.
🛠️How to make changes
Add a New System-Wide Function (e.g., cpu_freq())
- Define the return namedtuple in psutil/_common.py with all fields (
psutil/_common.py) - Implement the function in each platform module (psutil/_pslinux.py, _psosx.py, _pswindows.py) following the pattern: def cpu_freq(): ... (
psutil/_pslinux.py) - Add a wrapper in psutil/init.py that imports and exposes the platform function, with docstring (
psutil/__init__.py) - Write unit tests in tests/test_system.py covering normal operation, edge cases, and platform-specific behavior (
tests/test_system.py) - Document the function in docs/api.rst under the appropriate section (System APIs) with availability markers (
docs/api.rst)
Add a New Process Method (e.g., process.get_nice())
- Add the method stub to psutil._process_common.Process class with docstring and @availability decorator (
psutil/_process_common.py) - Implement platform-specific logic in psutil._pslinux.Process, _psosx.Process, _pswindows.Process subclasses (
psutil/_pslinux.py) - If performance-critical, add C helper in psutil/_psutil_posix.c and call via ctypes from Python (
psutil/_psutil_posix.c) - Add unit tests to tests/test_process.py with parametrized tests across platforms (
tests/test_process.py) - Update docs/api.rst under Process section with availability markers (@availability decorator) (
docs/api.rst)
Support a New Operating System (e.g., RISC-V Linux)
- Create new platform module psutil/_psrisc.py subclassing _psposix.py (if POSIX-compatible) (
psutil/_psrisc.py) - Update _bootstrap.py to detect the new OS and import the new module (
_bootstrap.py) - Implement or override system_specific methods (e.g., cpu_count, virtual_memory) for the new platform (
psutil/_psrisc.py) - Add CI/CD workflow in .github/workflows/ to test the new platform on every commit (
.github/workflows/build.yml) - Document platform support and any OS-specific quirks in docs/api.rst with @availability markers (
docs/api.rst)
Add Performance Optimization via C Extension
- Write new C function in psutil/_psutil_posix.c (or platform-specific .c) and expose via PyMethodDef array (
psutil/_psutil_posix.c) - Create Python wrapper in appropriate platform module (e.g., _pslinux.py) calling the C function via ctypes (
psutil/_pslinux.py) - Update setup.py Extension[] configuration if adding new .c file or dependencies (
setup.py) - Add benchmark tests in tests/test_bench.py to measure before/after performance impact (
tests/test_bench.py)
🪤Traps & gotchas
C extension compilation is mandatory on non-pure-Python builds; missing compiler (gcc/MSVC) or Python dev headers will cause install failures. Platform-specific behavior: Process.open_files() and net_connections() may return incomplete data on some systems if ptrace or netstat permissions are insufficient. Memory calculations differ subtly across platforms (swapped vs. resident); always check platform-specific docstrings. Tests require appropriate OS-level permissions (e.g., reading /proc on Linux, Windows admin rights). No external service dependencies, but beware: the library's behavior mirrors kernel state and may fail gracefully (returning empty lists) when querying terminated processes or restricted resources.
🏗️Architecture
💡Concepts to learn
- procfs (/proc filesystem on Linux) — Understanding how psutil._pslinux.c parses /proc/{pid}/stat, /proc/meminfo, /proc/net/* is essential for Linux-specific debugging and understanding per-process metric accuracy
- ctypes and Python C Extensions — psutil uses both ctypes (for FFI to libc) and compiled C extensions (for direct syscalls); understanding both is crucial for adding cross-platform features or debugging permission errors
- WinAPI (Windows API) process enumeration — psutil._pswindows.c relies heavily on WinAPI calls like CreateToolhelp32Snapshot, GetProcessMemoryInfo, and registry queries; essential for contributing Windows-specific fixes
- namedtuple and dataclass-like structures — psutil returns custom namedtuples (e.g., psutil.Process.memory_info(), psutil.cpu_times()) with platform-varying fields; understanding when fields are available vs. stubbed is critical for cross-platform code
- Platform-specific syscall differences and fallbacks — psutil gracefully handles missing syscalls, permission denials, and API differences across Linux versions, BSD variants, and Windows editions; writing robust code requires understanding these fallback chains
- Cache invalidation and real-time metrics — psutil caches certain metrics (e.g., boot_time(), cpu_count()) but exposes fresh data for others (memory_info()); misunderstanding cache behavior leads to stale or incorrect metrics in monitoring use cases
- Resource limits and prlimit (Process Resource Limits) — psutil.Process.rlimit() exposes POSIX resource limits (RLIMIT_NOFILE, RLIMIT_NPROC, etc.) for process sandbox enforcement; crucial for developers building container orchestrators or resource-constrained environments
🔗Related repos
nicolargo/glances— High-level system monitoring TUI built on top of psutil; shows how to compose psutil APIs into a user-facing toolelastic/beats— Metricbeat (Go-based) collects system metrics for Elasticsearch; competes with psutil for cross-platform telemetry but in different ecosystemprometheus-community/node_exporter— Go alternative for exposing system and process metrics as Prometheus metrics; shares same problem domain but different approach (agent vs. library)giampaolo/pyftpdlib— Sibling project by same author; demonstrates how to build cross-platform Python/C libraries with similar build and CI patternstornadoweb/tornado— Web framework that uses psutil for process monitoring and resource profiling in production; typical consumer of psutil APIs
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add macOS/Darwin CI workflow for ARM64 (Apple Silicon) testing
The repo has bsd.yml, build.yml, and sunos.yml workflows, but no dedicated macOS ARM64 testing. Given psutil's cross-platform nature and increasing Apple Silicon adoption, testing on arm64-darwin would catch architecture-specific bugs early. This is critical since psutil interfaces with low-level system APIs that differ between x86_64 and ARM64.
- [ ] Create
.github/workflows/macos-arm64.ymlbased on existingbsd.ymlandbuild.ymlpatterns - [ ] Configure GitHub Actions to use
macos-latest-largeormacos-14-arm64runners - [ ] Run psutil test suite against ARM64 macOS targets (test CPU affinity, process info, system stats)
- [ ] Ensure C extensions compile correctly on ARM64 (psutil uses ctypes and native extensions)
- [ ] Document in
CONTRIBUTING.mdwhy ARM64 testing matters for this project
Add comprehensive doctests to core API functions in psutil/init.py
The repo has Sphinx documentation infrastructure (docs/_ext/, sphinx plugins) but the main psutil module likely lacks inline doctests. Given psutil is a library with public API functions (process monitoring, system stats), adding doctests would improve code coverage, serve as executable documentation examples, and catch regressions. The .github/workflows/ already has changelog and issue automation, so adding a doctest CI step is low-hanging fruit.
- [ ] Identify top-level public API functions in
psutil/__init__.pyandpsutil/*.pylacking docstrings with examples - [ ] Add docstring examples following Python doctest format for core functions (e.g.,
psutil.cpu_count(),psutil.Process(),psutil.virtual_memory()) - [ ] Add a CI step in
.github/workflows/build.ymlto runpython -m doctest psutil/*.pyor use pytest's--doctest-modules - [ ] Verify examples work across platforms (Linux, Windows, macOS) by checking for platform-specific assertions
- [ ] Reference the new doctests in
docs/DEVNOTES.mdfor contributor guidance
Add Windows-specific GitHub Actions workflow for testing psutil on Windows Server/native APIs
The build.yml workflow likely runs on Ubuntu. psutil has significant Windows-specific code (Windows API calls, registry access, WMI queries) but may lack dedicated Windows CI. Adding a Windows-specific workflow would catch Windows-only bugs (e.g., registry permissions, Windows privilege escalation, WMI timeouts). This is especially valuable since Windows system APIs are distinct from POSIX.
- [ ] Create
.github/workflows/windows.yml(or extendbuild.yml) withruns-on: windows-latest - [ ] Add steps to test Windows-specific psutil features:
psutil.net_connections(kind='inet'),psutil.Process().create_time(), registry-based system info - [ ] Include tests for Windows privilege scenarios (test elevated vs. non-elevated process contexts)
- [ ] Run against both Python 3.x stable and dev versions on Windows
- [ ] Document any Windows-specific test skip conditions in the workflow (e.g., skipping if not running as admin)
🌿Good first issues
- Add missing docstring examples to psutil/_psosx.py and psutil/_psbsd.c for BSD-specific APIs like Process.memory_maps(), which are documented but lack runnable examples in docs/source/. This helps BSD users debug memory issues.
- Write integration tests in tests/ for the sensors_* functions (battery, fans, temperatures) on systems where they are available; current coverage is sparse and platform-dependent, causing blind spots when changes regress sensor detection.
- Enhance the .github/workflows/build.yml to include linting checks (flake8, mypy) and add type hints to psutil/init.py core functions, improving IDE support and catching regressions early without requiring local setup.
📝Recent commits
Click to expand
Recent commits
cff7690— Doc: dynamical refresh of adoption stats + fix site for mobile (giampaolo)e165f87— Doc: cross-reference roles + assorted polish (giampaolo)2bfa3b4— Doc: custom 404 page + easter egg (#2829) (giampaolo)cff1b1c— Blog & site cleanups (giampaolo)d53c708— Merge branch 'github-stars' (giampaolo)571ee28— Add github stars + versions in the topbar (giampaolo)36c677a— CSS / style refact + change font + align JS TOC aligned with pydata-theme (giampaolo)368cc61— Doc: TOC navigation bar (#2828) (giampaolo)3d9dbbc— Fix some broken URLs (giampaolo)c987b0c— CSS: split sections into code.css and home.css (giampaolo)
🔒Security observations
The psutil codebase demonstrates a reasonable security posture with a defined security policy and responsible disclosure process through Tidelift. No critical vulnerabilities were identified in the provided file structure and dependency list. The main security concerns are: (1) the need for regular audits of Sphinx documentation dependencies which are used in the build pipeline, (2) enhanced documentation of security fixes in changelog/release notes, and (3) potentially providing additional direct security contact channels beyond the Tidelift coordination service. As a cross-platform system monitoring library, the actual C/Python implementation code (not visible in this analysis) should receive additional security review for memory safety and privilege escalation risks.
- Medium · Outdated Sphinx Documentation Dependencies —
Dependencies/Package file (docs build requirements). Several Sphinx-related dependencies in the documentation build chain may have known vulnerabilities. sphinx==9.1.0, sphinx_rtd_theme==3.1.0, and other sphinx extensions should be regularly audited for security patches. While these are development/documentation dependencies, they could be exploited if the documentation build process is compromised. Fix: Regularly update Sphinx and all Sphinx extension dependencies to the latest stable versions. Implement dependency scanning with tools like pip-audit or Dependabot to detect and alert on known vulnerabilities in documentation build tools. - Low · Missing CHANGELOG or HISTORY Security Information —
Repository root - HISTORY.rst, CHANGELOG. While HISTORY.rst exists, there is no dedicated CHANGELOG file documenting security fixes. This makes it harder for users to identify when security patches are released. Fix: Maintain a clear CHANGELOG with a dedicated 'Security' section. Clearly mark all security-related fixes in release notes so users can easily identify critical updates. - Low · Broad Security Policy Reliance on Third-party Coordinator —
SECURITY.md. The SECURITY.md policy relies exclusively on Tidelift as the security contact mechanism. While this is a reasonable approach for commercial support, there is no mention of alternative contact methods or a direct security contact email/PGP key for the maintainer(s). Fix: Consider providing a direct security contact email (security@psutil.org or similar) in addition to the Tidelift contact. Consider publishing a PGP key for encrypted vulnerability reports. Ensure multiple channels exist for security researchers to report issues.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.