DominicBreuker/pspy
Monitor linux processes without root permissions
Single-maintainer risk — review before adopting
weakest axiscopyleft license (GPL-3.0) — review compatibility; no CI workflows detected
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 2mo ago
- ✓6 active contributors
- ✓GPL-3.0 licensed
Show all 7 evidence items →Show less
- ✓Tests present
- ⚠Single-maintainer risk — top contributor 80% of recent commits
- ⚠GPL-3.0 is copyleft — check downstream compatibility
- ⚠No CI workflows detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
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 "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/dominicbreuker/pspy)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/dominicbreuker/pspy on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: DominicBreuker/pspy
Generated by RepoPilot · 2026-05-09 · 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/DominicBreuker/pspy 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
WAIT — Single-maintainer risk — review before adopting
- Last commit 2mo ago
- 6 active contributors
- GPL-3.0 licensed
- Tests present
- ⚠ Single-maintainer risk — top contributor 80% of recent commits
- ⚠ GPL-3.0 is copyleft — check downstream compatibility
- ⚠ No CI workflows detected
<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 DominicBreuker/pspy
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/DominicBreuker/pspy.
What it runs against: a local clone of DominicBreuker/pspy — 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 DominicBreuker/pspy | Confirms the artifact applies here, not a fork |
| 2 | License is still GPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | Last commit ≤ 97 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of DominicBreuker/pspy. If you don't
# have one yet, run these first:
#
# git clone https://github.com/DominicBreuker/pspy.git
# cd pspy
#
# 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 DominicBreuker/pspy and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "DominicBreuker/pspy(\\.git)?\\b" \\
&& ok "origin remote is DominicBreuker/pspy" \\
|| miss "origin remote is not DominicBreuker/pspy (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(GPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"GPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is GPL-3.0" \\
|| miss "license drift — was GPL-3.0 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"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 97 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~67d)"
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/DominicBreuker/pspy"
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
pspy is a Go-based command-line tool that monitors Linux process execution in real-time without requiring root permissions by parsing /proc filesystem and using inotify watchers. It catches short-lived processes and cron jobs by combining procfs scans triggered by inotify events on key directories like /usr, /tmp, /etc, /home, /var, and /opt, making it invaluable for system enumeration in CTFs and security audits. Single-binary CLI application with modular internal packages: cmd/root.go is the CLI entry point using spf13/cobra, internal/fswatcher/ handles inotify watching (with walker.go for recursive directory traversal and inotify/ for event handling), internal/config/ manages CLI flags, internal/logging/ handles output, and internal/pspy/ contains the core process monitoring logic. Docker setup supports reproducible builds across architectures.
👥Who it's for
Penetration testers, CTF competitors, and security researchers who need to enumerate running processes on Linux systems they don't have root access to; also system administrators demonstrating why passing secrets as command-line arguments is dangerous.
🌱Maturity & risk
Actively maintained and production-ready. The project has CircleCI CI/CD, comprehensive test coverage tracked by CodeClimate, static multi-architecture binaries (pspy32, pspy64, pspy32s, pspy64s), and a v1.2.1 release tag. The Go module is well-defined (go 1.26+) with minimal dependencies (spf13/cobra, golang.org/x/sys).
Low risk: only 3 direct dependencies (cobra, spf13/pflag, mousetrap) and relies entirely on stable Linux syscalls (inotify, procfs). Single-maintainer repository (DominicBreuker) with no visible recent commit history in provided data, so responsiveness to bugs is uncertain. The tool's security-focused nature means vulnerabilities in inotify or procfs parsing could have wider impact.
Active areas of work
No visible active development indicated in the file list provided (no recent PRs or open issues shown). The project appears stable at v1.2.1 with Docker build infrastructure in place for consistent multi-architecture releases (32-bit, 64-bit, stripped versions). CircleCI is configured for continuous integration.
🚀Get running
git clone https://github.com/DominicBreuker/pspy.git
cd pspy
go build -o pspy ./cmd
./pspy --help
Or use the Makefile: make build-build-image && make build for Docker-based multi-arch builds, or download prebuilt binaries from releases.
Daily commands:
./pspy # Start monitoring with defaults (/usr, /tmp, /etc, /home, /var, /opt)
./pspy -p -f # Enable process AND filesystem event printing
./pspy -r /custom/dir # Watch custom directory recursively
./pspy -i 100 # Scan procfs every 100ms instead of default
./pspy -c # Suppress colors in output
Docker: docker build -f docker/Dockerfile.example . && docker run <image> for demo environment.
🗺️Map of the codebase
- cmd/root.go: CLI entry point using spf13/cobra; defines all command flags (-p, -f, -r, -d, -i, -c) and main execution flow
- internal/fswatcher/fswatcher.go: Core inotify watcher management; sets up recursive directory monitoring and event handling loop
- internal/fswatcher/inotify/inotify.go: Low-level inotify syscall wrapper (golang.org/x/sys); handles kernel event subscription and parsing
- internal/fswatcher/walker/walker.go: Recursive directory tree walker; builds initial inotify watch list for all subdirectories
- internal/config/config.go: Configuration struct and parsing; bridges CLI flags to runtime behavior
- internal/pspy/: Core process monitoring package (location inferred from package structure); implements procfs scanning and process diff logic
- Makefile: Build orchestration; targets for Docker image creation and multi-architecture binary compilation
- docker/Dockerfile.build: Reproducible build environment; ensures consistent binaries across all platforms and architectures
🛠️How to make changes
Start with internal/pspy/ for process monitoring logic. For inotify changes, edit internal/fswatcher/inotify/inotify.go and internal/fswatcher/inotify/event.go. CLI behavior lives in cmd/root.go. New flags go into internal/config/config.go. Add tests alongside files: see _test.go pattern (e.g., internal/fswatcher/fswatcher_test.go, internal/logging/logging_test.go). Docker entry points in docker/entrypoint-.sh control test/demo execution.
🪤Traps & gotchas
The tool requires inotify support in the kernel (most modern Linux, but missing in some containers/VMs). Procfs parsing is Linux-specific; no cross-platform support. When watching large directory trees recursively (-r), inotify watch limit (/proc/sys/fs/inotify/max_user_watches, often ~8192) can be exceeded, silently stopping monitoring of deeper directories. Short-lived processes (<1 polling interval) may be missed regardless of inotify tuning. The Docker test environments (docker/entrypoint-testing.sh) expect cron and password reset scripts to run; test assumptions are fragile if cron is disabled.
💡Concepts to learn
- inotify (Linux file system event notification) — Core mechanism pspy uses to detect file system changes that trigger procfs rescans; essential to understanding why certain directories are watched and how the tool avoids constant polling.
- procfs (/proc file system) — pspy parses /proc/[pid]/cmdline, /proc/[pid]/status, and process listings to extract running commands; procfs is the bridge between kernel process state and user-space monitoring.
- Process enumeration without privilege escalation — pspy's key innovation is reading /proc entries available to unprivileged users; understanding Linux DAC (Discretionary Access Control) permissions on /proc is critical to knowing what the tool can and cannot see.
- Inotify watch depth limits and recursive directory walking — The walker package implements depth-first recursion to set up watches, but /proc/sys/fs/inotify/max_user_watches limits total watches; understanding this constraint is essential for troubleshooting missed processes.
- Static binary compilation and UPX compression — pspy is distributed as 32/64-bit static and compressed variants; understanding Go's CGO flags and UPX trade-offs (portability vs. size) is important for building and deploying variants.
- Cobra CLI framework and flag parsing — cmd/root.go uses spf13/cobra for command definition and flag management; learning this framework is necessary to add or modify CLI arguments.
- Cron job detection via procfs during execution — pspy's main use case is catching cron jobs in flight; understanding how crond spawns children and the window of visibility in /proc is key to why inotify on /var/spool/cron is triggered.
🔗Related repos
DominicBreuker/strace-like-shim— Same author's alternative approach to process monitoring using ptrace instead of procfs/inotify for more detailed syscall visibilityDominicBreuker/ps-wrapper— Related low-privilege process introspection tool exploring alternative Linux APIs for process discoverynetdata/netdata— Broader system monitoring stack also using procfs and inotify; complementary tool for system-wide metrics and process telemetrynicolaka/netshoot— Container troubleshooting image and tools; pspy is often bundled into netshoot containers for process debugging in Kubernetes environmentsfalcosecurity/falco— Enterprise runtime security tool using eBPF for syscall tracing; successor technology to pspy's inotify approach for detecting privilege escalation and suspicious processes
🪄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 comprehensive integration tests for pspy end-to-end process monitoring
The repo has unit tests for individual components (fswatcher_test.go, psscanner_test.go, inotify_test.go) but lacks integration tests that verify the complete pspy pipeline works correctly. The internal/pspy/pspy_test.go exists but is likely minimal. Adding integration tests would validate that process detection, filesystem watching, and output generation work together correctly across different scenarios (cron execution, background processes, permission boundaries).
- [ ] Review internal/pspy/pspy_test.go and identify coverage gaps in the main pspy.go logic
- [ ] Create internal/pspy/integration_test.go with test cases for: spawning child processes and verifying detection, simulating cron job execution, testing output filtering/formatting
- [ ] Add Docker-based test scenarios in docker/entrypoint-testing.sh to run integration tests in isolated environments
- [ ] Ensure tests verify the interaction between internal/psscanner/psscanner.go, internal/fswatcher/fswatcher.go, and cmd/root.go
Migrate from CircleCI to GitHub Actions for native repository CI/CD
The project uses CircleCI (.circleci/config.yml) for CI/CD, but hosting on GitHub (DominicBreuker/pspy) makes GitHub Actions more convenient for contributors and maintainers. GitHub Actions reduces external dependencies, provides better visibility within the repo, and is free for public repos. This would modernize the workflow while maintaining the same test/build/coverage checks.
- [ ] Analyze .circleci/config.yml to extract all jobs, steps, and environment configurations
- [ ] Create .github/workflows/build-and-test.yml that runs: Go linting, unit tests for all packages in internal/, code coverage reporting to CodeClimate
- [ ] Create .github/workflows/docker-build.yml to build and push Docker images for docker/Dockerfile.build, docker/Dockerfile.testing on new releases
- [ ] Update README.md to replace the CircleCI badge with GitHub Actions badge, and document how to run tests locally using the Makefile
Add platform-specific tests and documentation for process monitoring edge cases
The repo uses golang.org/x/sys (Linux syscalls) and has platform-specific code for process scanning, but there's minimal documentation of how pspy behaves under different Linux kernel versions, container environments (Docker, Kubernetes), or with different proc filesystem configurations. Adding tests for edge cases and documenting limitations would improve reliability.
- [ ] Create internal/psscanner/psscanner_edge_cases_test.go with tests for: missing /proc entries, permission-denied scenarios, zombie processes, PID wraparound
- [ ] Add a TESTING.md document explaining how to test pspy across different Linux versions (using the Docker containers already present: docker/Dockerfile.testing, docker/Dockerfile.example)
- [ ] Update README.md with a 'Known Limitations' section documenting: which process events may be missed, behavior in containers/namespaces, kernel version requirements
- [ ] Review internal/fswatcher/inotify/inotify.go and add tests for inotify limitations (e.g., queue overflow, event coalescing)
🌿Good first issues
- Add unit tests for internal/pspy/ package (no test file visible in listing): create internal/pspy/pspy_test.go with benchmarks for procfs parsing performance and process diff accuracy.
- Expand inotify event type coverage: internal/fswatcher/inotify/event.go currently handles basic events; add tests and documentation for IN_Q_OVERFLOW handling when watch limits are exceeded, and add graceful degradation.
- Create a --output-format flag allowing JSON output: modify cmd/root.go to support structured logging (currently only stdout text); add internal/output/json.go module for marshaling process events and filesystem changes.
⭐Top contributors
Click to expand
Top contributors
- @DominicBreuker — 80 commits
- [@Dominic Breuker](https://github.com/Dominic Breuker) — 7 commits
- @kazkansouh — 6 commits
- [@Krishna Kishore Shetty](https://github.com/Krishna Kishore Shetty) — 4 commits
- @0xdf0xdf — 2 commits
📝Recent commits
Click to expand
Recent commits
b8e247e— Merge pull request #24 from DominicBreuker/golang-update (DominicBreuker)b36137b— update to go 1.26, which is all poor dominic gets done without AI these days - if you read this, consider recommending h (DominicBreuker)f9e6a15— update download link for v1.2.1 release (DominicBreuker)fdc50a6— Merge pull request #21 from DominicBreuker/fix-overlong-draining (DominicBreuker)d6985d7— avoid spamming trigger and event channels while draining (DominicBreuker)2bf9f91— Merge pull request #17 from kkaosninja/master (DominicBreuker)f63ecb2— Bump Go version to 1.18 (Krishna Kishore Shetty)3366148— Made changes as suggested by linter (Krishna Kishore Shetty)689117a— Removed unnecessary build flag (Krishna Kishore Shetty)bfcccab— Updated to use go mod dependency management (Krishna Kishore Shetty)
🔒Security observations
The pspy project demonstrates generally good security practices as a process monitoring tool. However, there are several dependency management concerns that should be addressed. The primary issues are: (1) an invalid Go version specification (1.26) that needs correction, and (2) significantly outdated dependencies (golang.org/x/sys from May 2022, spf13/cobra from 2022) that should be updated to receive latest security patches. The project structure is clean with no obvious SQL injection, XSS, or injection vulnerabilities visible. Docker configurations appear reasonable but require verification that no hardcoded credentials exist in scripts. Dependencies are minimal and well-known, which is a positive sign. Overall, the security posture is acceptable but requires immediate attention to dependency updates and Go version correction.
- High · Outdated Go Version Specified —
go.mod. The go.mod file specifies 'go 1.26', which is not a valid Go release version. Valid versions are up to 1.23 as of the latest stable releases. This indicates either a misconfiguration or potential tampering with the module file. This could lead to unexpected behavior or inability to build the project reliably. Fix: Update go.mod to specify a valid, current Go version (e.g., 'go 1.21' or later). Verify the integrity of the go.mod file and use 'go mod tidy' to ensure consistency. - Medium · Outdated Dependency: golang.org/x/sys —
go.mod. The golang.org/x/sys dependency is pinned to version 0.0.0-20220520151302-bc2c85ada10a (May 2022), which is significantly outdated. This package contains low-level system interactions and security fixes. Using an old version may expose the application to known vulnerabilities in system call handling. Fix: Update golang.org/x/sys to the latest stable version by running 'go get -u golang.org/x/sys'. This package receives regular security updates and should be kept current. - Medium · Outdated Dependency: github.com/spf13/cobra —
go.mod. The spf13/cobra CLI framework is pinned to version 1.4.0 (released in 2022). Newer versions may contain important bug fixes and security improvements for command-line argument parsing. Fix: Update to the latest version of spf13/cobra by running 'go get -u github.com/spf13/cobra' and verify compatibility with the current codebase. - Low · Potential Hardcoded Credentials in Docker Configuration —
docker/root/scripts/password_reset.py. The file path 'docker/root/scripts/password_reset.py' suggests credential management scripts exist in the repository. If this script or related files contain hardcoded passwords, API keys, or credentials, they could be exposed through version control history. Fix: Audit password_reset.py and related scripts to ensure no hardcoded credentials are present. Use environment variables or secure secret management instead. Remove any sensitive data from version control history using 'git filter-branch' or similar tools if necessary. - Low · Cron Job Configuration in Repository —
docker/etc/cron.d/changepwds, docker/var/spool/cron/crontabs/root. Docker cron job configuration files are committed to the repository (docker/etc/cron.d/changepwds, docker/var/spool/cron/crontabs/root). While necessary for Docker images, this approach requires careful handling to avoid exposing sensitive scheduled operations or commands. Fix: Review cron job configurations to ensure they don't contain sensitive information. Consider using Docker build arguments or environment variables for sensitive cron parameters. Document the purpose and security implications of each scheduled job.
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.