theopfr/somo
A human-friendly alternative to netstat for socket and port monitoring on Linux and macOS.
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 4d ago
- ✓4 active contributors
- ✓MIT licensed
Show all 7 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Small team — 4 contributors active in recent commits
- ⚠Concentrated ownership — top contributor handles 55% 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/theopfr/somo)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/theopfr/somo on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: theopfr/somo
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/theopfr/somo 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 4d ago
- 4 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Small team — 4 contributors active in recent commits
- ⚠ Concentrated ownership — top contributor handles 55% 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 theopfr/somo
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/theopfr/somo.
What it runs against: a local clone of theopfr/somo — 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 theopfr/somo | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | Last commit ≤ 34 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of theopfr/somo. If you don't
# have one yet, run these first:
#
# git clone https://github.com/theopfr/somo.git
# cd somo
#
# 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 theopfr/somo and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "theopfr/somo(\\.git)?\\b" \\
&& ok "origin remote is theopfr/somo" \\
|| miss "origin remote is not theopfr/somo (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT 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 34 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~4d)"
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/theopfr/somo"
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
Somo is a human-friendly CLI tool written in Rust that replaces netstat for monitoring active sockets and ports on Linux and macOS. It displays network connections in an interactive table view with filtering, sorting, and the ability to kill processes directly—essentially netstat -tulpn reimagined with a modern, pleasing UI instead of cryptic text output. Modular single-binary structure: src/main.rs and src/cli.rs handle argument parsing (clap), src/connections/ abstracts Linux vs macOS socket reading with platform-specific files (linux.rs using procfs, macos.rs using libproc), src/view.rs renders the table UI, src/services.rs maps processes, and src/schemas.rs defines data structures. Tests use mock /proc directories for deterministic testing.
👥Who it's for
Systems administrators, DevOps engineers, and developers on Linux/macOS who need to quickly inspect which processes are holding ports, identify listening services, and manage connections without memorizing netstat flags. They want the information fast and in a readable format.
🌱Maturity & risk
Actively developed and production-ready. The project is at v1.3.3 with a published crate on crates.io, includes cross-platform support (Linux + macOS), has CI/CD pipelines (.github/workflows/ci.yml, release.yml), and integrates with package managers (Homebrew, Arch, Debian). The codebase shows ~106K lines of Rust with established test structure, indicating maturity and regular maintenance.
Low risk overall. Single maintainer (theopfr) is a minor concern, but the codebase is simple and self-contained with modest dependencies (clap, serde, procfs for Linux, netstat2/libproc for macOS). The platform-specific code (src/connections/linux.rs vs src/connections/macos.rs) could diverge over time, but the test suite with mock /proc trees mitigates this. No heavy transitive dependency chains visible.
Active areas of work
The project is stable and focused on incremental improvements. Version 1.3.3 is the latest release. The CI pipeline (ci.yml) runs on each commit, suggesting active maintenance. No major architectural changes visible in the file structure, indicating the design is settled. Dependabot is configured (dependabot.yaml) for automated dependency updates.
🚀Get running
git clone https://github.com/theopfr/somo
cd somo
cargo build --release
./target/release/somo # or sudo ./target/release/somo
Or install directly: cargo install somo and run sudo somo (requires sudo to see all processes/ports).
Daily commands:
cargo run -- -h # show help
cargo run # run with defaults (may need sudo)
sudo cargo run -- -l # list listening sockets
sudo cargo run -- -p 8080 # filter by port
sudo cargo run -- --tcp --kill # interactive TCP kill mode
🗺️Map of the codebase
- src/main.rs: Entry point orchestrating CLI parsing, connection gathering, filtering, and view rendering
- src/cli.rs: Defines all command-line arguments using clap derive; router for filter/format/kill options
- src/connections/mod.rs: Platform-agnostic connection abstraction; dispatches to linux.rs or macos.rs at runtime
- src/connections/linux.rs: Reads /proc filesystem (via procfs crate) to extract TCP/UDP sockets, process mappings, and command names on Linux
- src/connections/macos.rs: Uses libproc + netstat2 crates to query network state on macOS; platform-specific implementation
- src/schemas.rs: Defines core data structures: Connection, Process; used throughout for type safety and serialization
- src/view.rs: Renders filtered/sorted connections as termimad tables; handles interactive mode with inquire for killing processes
- src/config.rs: Loads user configuration from ~/.config/somo (via etcetera); applies defaults and user overrides
- tests/integration_tests.rs: Integration test suite using mock /proc trees; ensures consistent behavior across platform-specific code paths
- .github/workflows/ci.yml: CI pipeline: builds, tests, and validates on Linux and macOS for each commit
🛠️How to make changes
Adding a filter: src/cli.rs defines clap args, src/schemas.rs holds the Connection struct, src/view.rs filters/displays. Adding output format: src/schemas.rs + handlebars templates (see markdown.rs for format examples). Improving socket discovery: src/connections/linux.rs (procfs parsing) or src/connections/macos.rs (libproc wrapping). Testing: Add mock /proc files in tests/mock/proc/ and cases to tests/integration_tests.rs.
🪤Traps & gotchas
Sudo requirement: Most filtering and process data is inaccessible without root; non-root runs will show only the user's own connections silently. Platform divergence: Linux uses /proc parsing (procfs crate dependency), macOS uses libproc syscalls; they may report slightly different socket states under edge conditions. Config path: Respects XDG_CONFIG_HOME or ~/.config/somo; setting wrong permissions here silently fails config load. Mock testing: Tests with hardcoded mock /proc IDs (11, 13, 15) in tests/mock/proc/; if you add new test PIDs, update the mock structure accordingly.
💡Concepts to learn
- /proc filesystem abstraction — On Linux, all network and process data comes from /proc; understanding /proc/net/tcp, /proc/[pid]/fd, and /proc/[pid]/cmdline layout is essential to extend somo's Linux backend
- Platform abstraction layer (trait-based dispatch) — Somo uses src/connections/mod.rs to abstract OS differences; learning how this pattern decouples Linux-specific procfs calls from macOS-specific libproc calls teaches clean multiplatform Rust design
- Socket state lifecycle (TCP/UDP states) — Understanding LISTEN, ESTABLISHED, TIME_WAIT, CLOSE_WAIT states helps interpret why somo shows certain connections and how to filter them meaningfully
- Process file descriptor mapping (fd symlinks) — Somo reads /proc/[pid]/fd to find which sockets a process owns; understanding that these are symlinks to socket inode numbers is key to tracing connections to processes
- libproc and getprocs() syscall (macOS) — macOS lacks /proc; instead it uses libproc library and getprocs() to enumerate process info; somo's macOS code depends on this, making it worth understanding for maintenance
- Handlebars templating engine (custom output formatting) — Somo uses handlebars to let users define custom output formats (JSON, CSV, custom text); understanding the template syntax and how somo passes Connection structs to it enables building custom report generators
- Signal-based process termination (SIGKILL vs SIGTERM) — The --kill interactive mode sends signals to processes via the nix crate; understanding signal semantics (graceful shutdown vs forceful kill) is important for safely extending the kill feature
🔗Related repos
nicolaka/netstat-nat— Similar netstat replacement focused on NAT translation state; complements somo for users needing advanced network debugginghadialqattan/netmangler— Python-based network diagnostics tool; alternative approach to socket monitoring with different UI/output strategiessharkdp/bat— Not network-related, but same ecosystem (Rust CLI tools with beautiful output); demonstrates termimad/modern TUI patterns somo adoptsBurntSushi/ripgrep— Rust CLI benchmark and pattern for fast, user-friendly replacements of legacy Unix tools (like somo does for netstat)procfs/procfs— Upstream Rust crate that somo depends on for Linux /proc parsing; understanding its API is essential for extending socket discovery
🪄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 integration tests for macOS connection parsing in src/connections/macos.rs
The repo has mock /proc filesystem data for Linux testing in tests/mock/proc/, but no equivalent mock data or integration tests for macOS. The macOS implementation uses netstat2 and libproc crates, making it harder to test portably. Adding mock-based tests would improve coverage for the macOS-specific code path and catch regressions when dependencies update.
- [ ] Create tests/mock/macos/ directory structure with sample netstat output or libproc mock data
- [ ] Add integration tests in tests/integration_tests.rs that specifically exercise src/connections/macos.rs parsing logic
- [ ] Test edge cases like IPv6 addresses, TIME_WAIT states, and process name resolution on macOS
- [ ] Ensure tests can run on CI without requiring actual macOS-specific system calls (use mocks)
Add comprehensive unit tests for src/config.rs configuration parsing
The src/config.rs file handles user configuration but lacks explicit unit tests in tests/integration_tests.rs. Configuration files interact with etcetera for path resolution and handlebars for templating, creating multiple failure points. Unit tests would ensure configuration loading, validation, and template rendering work correctly across platforms.
- [ ] Add test module to src/config.rs or create tests/config_tests.rs with unit tests
- [ ] Test valid and invalid configuration file parsing (JSON schema validation)
- [ ] Test handlebars template rendering with various output format strings
- [ ] Test config file discovery logic on both Linux and macOS using tempfile for isolation
Expand src/view.rs tests to cover all output formatters (table, json, custom)
The view module handles rendering output in multiple formats (table, JSON, custom templates), but tests/integration_tests.rs appears to lack specific coverage of the formatting logic. This is a high-risk area since output is user-facing and format errors directly impact usability.
- [ ] Add unit tests in src/view.rs or tests/view_tests.rs covering table rendering with various column widths and data edge cases
- [ ] Test JSON serialization for all connection and process fields, including null/empty handling
- [ ] Test custom template rendering through handlebars integration with mock connection data
- [ ] Test sorting and filtering logic applied before rendering in each format
🌿Good first issues
- Add filtering by protocol state (ESTABLISHED, LISTENING, TIME_WAIT, etc.): requires extending src/schemas.rs Connection struct to capture socket state, parsing it from /proc/net/tcp on Linux (already present in procfs output) and from libproc on macOS, then adding a --state flag to src/cli.rs.
- Improve macOS performance for high-connection-count systems: src/connections/macos.rs currently iterates all processes; profile and cache process lookup or batch libproc queries. Add a performance benchmark to tests/ to prevent regression.
- Add --json-output mode that respects custom Handlebars templates: src/view.rs currently hardcodes table rendering; refactor to delegate to markdown.rs template engine (already used for custom formats), allowing users to define custom JSON schemas via config files in ~/.config/somo.
⭐Top contributors
Click to expand
Top contributors
- @theopfr — 55 commits
- @dependabot[bot] — 43 commits
- @liv — 1 commits
- @aychun — 1 commits
📝Recent commits
Click to expand
Recent commits
fb752c9— Merge pull request #161 from theopfr/release/1.3.3 (theopfr)773162f— release: 1.3.3 (theopfr)a8e02c7— Merge pull request #160 from Jeidnx/fix-proc-race (theopfr)9aa0400— fix: racy access to proc (liv)6497aac— Merge pull request #159 from theopfr/dependabot/cargo/libc-0.2.186 (theopfr)2445f0b— Merge pull request #158 from theopfr/dependabot/cargo/clap-4.6.1 (theopfr)5c0f125— Merge pull request #157 from theopfr/dependabot/cargo/assert_cmd-2.2.1 (theopfr)64138df— build(deps): bump libc from 0.2.184 to 0.2.186 (dependabot[bot])f82753f— build(deps): bump clap from 4.6.0 to 4.6.1 (dependabot[bot])fa15025— build(deps): bump assert_cmd from 2.2.0 to 2.2.1 (dependabot[bot])
🔒Security observations
The codebase demonstrates reasonable security practices for a system monitoring tool, but has notable concerns around privilege escalation via sudo and potential sensitive data exposure. The main risks stem from the requirement to run with elevated privileges, lack of sensitive data filtering in output formats, and the symlink-based installation method. Dependencies are generally well-maintained and up-to-date. The tool operates at a low level (process/socket inspection), which inherently requires careful privilege management. Recommendations focus on implementing capability-based security, sanitizing output, and hardening installation procedures.
- Medium · Privilege Escalation via sudo —
README.md, src/main.rs (process access patterns). The README suggests running somo with sudo to see all processes and ports. This grants the binary elevated privileges, which increases the attack surface. Any vulnerability in somo or its dependencies could potentially compromise the entire system. Fix: Implement capability-based security (CAP_NET_ADMIN, CAP_SYS_PTRACE) instead of requiring full sudo. Use setcap for minimal required capabilities. Validate all inputs and implement proper error handling. - Medium · Use of libc without safety wrapper validation —
Cargo.toml (libc dependency), src/connections/. The dependency on libc (0.2.186) for low-level system calls requires careful unsafe code handling. Direct libc usage for process manipulation could introduce memory safety issues if not properly validated. Fix: Audit all unsafe libc calls in connection handling code. Consider using higher-level abstractions where possible. Ensure proper error handling for all system calls. - Low · Symlink Attack Potential —
README.md (installation instructions). The README mentions creating symlinks for sudo access, which could be vulnerable to symlink attacks if not properly configured. An attacker could create a malicious symlink to redirect execution. Fix: Document secure installation practices. Recommend using package managers or verified installation methods. If symlinks are used, ensure proper validation of link targets and file permissions (0755 for binary, proper ownership). - Low · Process Information Disclosure —
src/cli.rs, src/view.rs, src/connections/. somo displays process information including command-line arguments, which may contain sensitive information (passwords, API keys, database credentials). No filtering of sensitive data is evident in the codebase. Fix: Implement filtering to mask sensitive patterns in command-line arguments (e.g., password parameters, API keys). Add configuration options to control verbosity of displayed information. - Low · JSON Output Could Leak Sensitive Data —
src/schemas.rs, Cargo.toml (serde_json dependency). The JSON output format (serde_json) serializes all process information without sanitization, potentially exposing sensitive command-line arguments or environment variables. Fix: Implement data sanitization for JSON output. Filter out sensitive fields or patterns before serialization. Add documentation warning about sensitive data exposure. - Low · Config File Permissions Not Validated —
src/config.rs, Cargo.toml (etcetera dependency). The config.rs file suggests configuration file handling via etcetera, but no explicit validation of file permissions is evident. Misconfigured permissions could allow unauthorized users to modify settings. Fix: Validate configuration file permissions (should be readable only by owner). Document recommended file permissions (0600). Warn users if permissions are too permissive.
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.