Project status: active again
zelynic is active again after the v2.0.0 Renaissance release. Core features such as monitor, list, profile, watch, QoS, auto-throttle, Backend Doctor, and per-process bandwidth limiting through
zelynic stricthave been validated on a modern Arch/CachyOS cgroup v2 host.Validation scope: strict limiting is validated on tested modern cgroup v2 systems, including CachyOS/Arch with kernel
6.18.33-1-cachyos-lts, nftablesv1.1.6, tc/iproute27.0.0, pure cgroup v2, and interfacewlp1s0. This is not yet a universal all-distro guarantee.Troubleshooting: use
zelynic strict --diagnose ...to print target PID selection, cgroup v2, nftables, and tc diagnostics when validating a host.
A serious Linux bandwidth control system for process-aware monitoring, shaping, and validation.
Built around `tc`, `nftables`, and cgroup v2 to make per-process network behavior inspectable and controllable from the terminal.
zelynic is a Rust CLI tool for monitoring, limiting, and shaping per-process network bandwidth on Linux. It uses Linux traffic control (tc) with HTB qdisc, nftables for packet marking, and cgroup v2 for process-aware rate limiting. Real-time monitoring is powered by ss, while the built-in TUI dashboard provides a live, htop-like view of network traffic.
Zelynic was previously named Oxy. The old repository and package name were oxy, and the command is now zelynic. Runtime state, cgroups, and nftables identifiers now use the zelynic namespace; v2.0.0-era oxy runtime artifacts are treated as legacy cleanup targets.
The v2.0.0 Renaissance release validates zelynic strict on tested modern cgroup v2 systems. On CachyOS/Arch with kernel 6.18.33-1-cachyos-lts, nftables v1.1.6, tc/iproute2 7.0.0, pure cgroup v2, and interface wlp1s0, Brave bandwidth limiting was observed within the expected range for both byte-based and bit-based limits.
This does not guarantee identical behavior on every Linux distribution. Hosts need cgroup v2, nftables, and tc support, and zelynic strict --diagnose should be used when validating or troubleshooting a new environment. See docs/validation.md for details.
Zelynic detects host capabilities and recommends the safest available backend. The read-only Backend Doctor checks kernel, cgroup, nftables, tc, conntrack, systemd, and eBPF signals without modifying nftables, tc, or cgroups:
zelynic backend # Summary and eBPF capability check
zelynic backend doctor # Detailed capability matrix
zelynic backend doctor --jsonThe zelynic run command provides systemd scope wrapper planning and a live
probe lab for system-scope units. zelynic run --dry-run renders the planned
scope/cgroup wiring and preview-only systemd-run launch command without
launching a process or modifying nftables, tc, cgroups, or state. The v2.5 Scope
Runner adds --probe-live for a root-only, system-scope live probe that
launches a real transient systemd scope, discovers ControlGroup and PID(s) via
cgroup.procs, and renders a non-mutating Future Attach Preview. User scope is
the default planning mode to avoid accidental system Polkit prompts; system
scope can be previewed explicitly with --scope-mode system. zelynic run --execute without --probe-live remains gated as an experimental opt-in
and returns a non-mutating not-implemented boundary. --attach-live exists
but is hard-blocked. Full live limiting still needs a privilege handoff design
because user-scope launch and root-required limiter attachment have different
requirements. zelynic strict remains the only validated active limiter path.
See docs/scope-lab.md for the full Scope Lab design and
probe findings.
Support matrix — see docs/distro-matrix.md for the full distribution support matrix with validation status:
| Host type | Status |
|---|---|
| Arch/CachyOS pure cgroup v2 | Validated |
| Modern systemd + cgroup v2 distros (Fedora, Ubuntu 22.04+, Debian 12+) | Candidate |
| Older Ubuntu/Debian, hybrid cgroup, containers, WSL, non-systemd distros | Partial / Unsupported |
| systemd-scope backend, cgroup v1 fallback, eBPF backend | Future |
The strict limiter path is validated on tested modern cgroup v2 Linux hosts. Other distributions are listed as candidates pending explicit validation. See the distro matrix for details and the validation reports for per-distro evidence.
- Monitor bandwidth usage per process/program with cumulative and real-time rates
- Limit download and/or upload speeds per process with tc + nftables + cgroup v2
- Experimental run planning and live probe — preview future systemd scope wrapper wiring, live system-scope probe with PID discovery and attach preview
- QoS priority shaping — assign high/low priority tiers instead of hard limits
- TUI dashboard — live bandwidth monitor with sparklines, scrolling, and dual RX/TX graphs
- Auto-throttle daemon — background mode that auto-limits when thresholds are exceeded
- Watch & alert — background monitor with desktop notifications on bandwidth thresholds
- Bandwidth profiles — save, load, and apply named bandwidth limit presets
- Bandwidth logging — snapshot and review historical bandwidth usage
- Shell completions — bash, zsh, fish, elvish, powershell
- Man page generation — roff format for system manual installation
- Interface management — auto-detect or explicitly specify network interfaces
- Strict CLI validation — invalid commands, interfaces, and values are rejected with clear errors
- Supports multiple bandwidth units:
byte/bs,kb,mb,gb,kbit,mbit,gbit - Built-in presets:
gaming,streaming,background - Clean, colored terminal output (respects
NO_COLOR) - JSON output mode for scripting integration
- Persistent state across invocations (survives restarts)
- Linux (kernel 5.4+ recommended for full cgroup v2 support)
- Root privileges (for bandwidth limiting, QoS, and auto-throttle operations)
- iproute2 package (provides
tcandipcommands) - nftables (for packet marking on download limiting)
- Rust 1.88+ (for building from source)
Download the latest release from GitHub Releases:
# Download tarball and checksum
curl -L -O https://github.com/oxyzenQ/zelynic/releases/download/v3.0.1/zelynic-v3.0.1-x86_64-linux.tar.gz
curl -L -O https://github.com/oxyzenQ/zelynic/releases/download/v3.0.1/zelynic-v3.0.1-x86_64-linux.tar.gz.sha256
# Verify checksum
sha256sum -c zelynic-v3.0.1-x86_64-linux.tar.gz.sha256
# Extract (creates zelynic-v3.0.1-x86_64-linux/ directory)
tar -xzf zelynic-v3.0.1-x86_64-linux.tar.gz
cd zelynic-v3.0.1-x86_64-linux
# Verify binary
./zelynic --version
# Install system-wide
sudo install -Dm755 zelynic /usr/local/bin/zelynic
zelynic --versionThe tarball extracts into zelynic-v3.0.1-x86_64-linux/ with the binary at
zelynic-v3.0.1-x86_64-linux/zelynic. SHA256 checksums are published alongside
each release for download verification.
The release tarball includes a pre-generated man page at man/zelynic.1.gz.
# View man page from extracted tarball
man ./man/zelynic.1.gz
# Or install system-wide
sudo install -Dm644 man/zelynic.1.gz /usr/share/man/man1/zelynic.1.gz
man zelynicMinimal systems may need man-db or mandoc installed to view man pages.
The usage --sample --delta --json output is machine-readable and pipes well
with jq for monitoring scripts and dashboards:
zelynic usage --sample --delta --json | jq '.command'
zelynic usage --sample --delta --json | jq '.totals.total_delta_combined_bytes'
zelynic usage --sample --delta --json | jq '.interfaces[] | {name, delta: .delta_combined_bytes}'Release naming convention:
- Tag:
v3.0.1 - Title:
Zelynic v3.0.1 Post-Release Docs + Install Polish
See the v3.0.1 changelog entry for release details.
git clone https://github.com/oxyzenQ/zelynic.git
cd zelynic
cargo build --release
# Install system-wide
sudo install -Dm755 target/release/zelynic /usr/local/bin/zelyniccargo build --release
sudo install -Dm755 target/release/zelynic /usr/local/bin/zelynic# Bash
zelynic completions bash | sudo tee /usr/share/bash-completion/completions/zelynic > /dev/null
# Zsh
zelynic completions zsh > ~/.zsh/completions/_zelynic
# Fish
zelynic completions fish > ~/.config/fish/completions/zelynic.fishzelynic [FLAGS] [COMMAND] [ARGS]
FLAGS:
-i, --info Print detailed package information
-v, --ver Print version (short)
-V, --version Print complete version and build information
--check-update Check the latest upstream release
--check-updated Alias for --check-update
--help-all Show comprehensive help with all commands and examples
--iface [INTERFACE] Specify network interface (no value = list available)
--no-color Disable colored output
COMMANDS:
list List network bandwidth usage per process
strict Set bandwidth limits for a process
unstrict Remove all bandwidth limits
refresh Refresh an existing limit after process respawn
status Show active bandwidth limits
clean Clean up orphaned bandwidth limits
profile Manage named bandwidth profiles
qos QoS priority-based bandwidth shaping
watch Monitor and alert on bandwidth threshold
auto Auto-throttle daemon mode
log Bandwidth usage history
backend Show backend info and capability checks
completions Generate shell completions
man Generate man page
usage Show live interface usage (single snapshot or delta)
Show all programs/ports with active bandwidth usage:
# List all processes with bandwidth usage (default)
zelynic list
# Real-time TUI dashboard (like htop for network)
zelynic list --live
# Live mode with custom refresh interval (2 seconds)
zelynic list --live --interval 2
# Sort by highest to lowest bandwidth usage
zelynic list --high-to-low-usage-net
# Show individual socket connections per process
zelynic list --verbose
# Output as JSON for scripting
zelynic list --jsonApply download and/or upload speed limits to a specific process:
# Limit both download and upload
sudo zelynic strict -d 500kb -u 500kb brave
# Limit only download (omit -u)
sudo zelynic strict -d 1mb firefox
# Limit only upload (omit -d)
sudo zelynic strict -u 250kb 1234
# Limit by PID
sudo zelynic strict -d 1mb -u 1mb 8100
# Use a preset profile
sudo zelynic strict --preset gaming discord
sudo zelynic strict --preset background steam
sudo zelynic strict --preset streaming zoomNote: PID 0 (kernel idle thread) and user names (e.g.,
root) cannot be limited. zelynic targets processes by PID or binary name. PID 0 is not a userspace process and has no network sockets or cgroup association.
Re-limiting without unstrict first is supported — old rules are auto-cleaned:
sudo zelynic strict -d 500kb brave # apply limit
sudo zelynic strict -d 10mb brave # auto-overrides to 10mbReloads, tabs, and child processes normally remain limited while the browser
process tree stays inside the target cgroup. If the application is closed
completely and reopened, run refresh to move the new PIDs into the existing
limit without duplicating nftables or tc rules:
sudo zelynic refresh braveStrict applies to new connections after the target has been moved into the
Zelynic cgroup. An already-running download or speed test can keep using its
existing socket until the request reconnects. Apply zelynic strict before
starting the network activity, or reload/restart the target's network request
after strict is applied. Zelynic does not flush conntrack entries or forcibly
reset existing connections by default.
Remove all bandwidth restrictions from a process:
# By process name
sudo zelynic unstrict brave
# By PID
sudo zelynic unstrict 8100When available, strict records the process's original cgroup before moving it.
unstrict tries to restore live PIDs to that recorded cgroup safely; if the
destination cannot be validated, Zelynic warns and falls back to the Zelynic
parent cgroup instead of guessing systemd paths.
zelynic statusRemove tc/cgroup rules for processes that have already exited:
sudo zelynic cleanAuto-detect is used by default. Explicitly specify an interface with --iface:
# List available interfaces
zelynic --iface
# Use a specific interface for any command
zelynic --iface wlan0 list --live
sudo zelynic --iface eth0 strict -d 1mb brave
sudo zelynic --iface enp3s0 qos high firefoxFor strict limits, the interface is auto-detected when zelynic strict is applied by reading the current default route. If the host later switches from WiFi to Ethernet, VPN, tethering, or another default route, upload shaping can remain attached to the old interface. For now, run sudo zelynic unstrict <target> and re-apply zelynic strict after the network changes. zelynic status warns when saved limits are attached to a different interface than the current default route.
Assign priority tiers instead of hard limits. High priority processes get bandwidth first; idle bandwidth from low-priority processes redistributes automatically:
# High priority for browser
sudo zelynic qos high brave
# Low priority for download manager
sudo zelynic qos low wget
# Show current QoS assignments
zelynic qos status
# Clear all QoS rules
sudo zelynic qos resetSave and load custom bandwidth profiles:
# Save a profile
zelynic profile save slow --dl 50kb --ul 50kb
zelynic profile save streaming --dl 5mb --ul 2mb
# Apply a profile
sudo zelynic profile apply slow steam
# List all profiles
zelynic profile list
# Delete a profile
zelynic profile delete slowMonitor a process and send a desktop notification when bandwidth exceeds a threshold:
# Alert when wget rate exceeds 500KB/s
zelynic watch -a 500kb wget
# Check every 30 seconds
zelynic watch -a 5mb firefox -i 30Continuously monitor and automatically apply limits when thresholds are exceeded:
# Auto-limit when download exceeds 100MB/s and upload exceeds 50MB/s
sudo zelynic auto --download 100mb --upload 50mb
# Kill heavy processes instead of limiting
sudo zelynic auto --download 80mb --kill firefox
# Run as a background daemon
sudo zelynic auto --daemonRecord and review historical bandwidth usage:
# Show recent history
zelynic log
# Record a snapshot of current state
zelynic log --snapshot
# Show last hour
zelynic log --last 1h
# JSON output for analysis
zelynic log --jsonShow live interface counters from /proc/net/dev — single snapshot or delta between two samples:
# Single snapshot (text)
zelynic usage --sample
# Single snapshot (JSON)
zelynic usage --sample --json
# Delta between two samples (text)
zelynic usage --sample --delta
# Delta between two samples (JSON)
zelynic usage --sample --delta --jsonAll usage commands are read-only, interface-level only, single-shot. No loop, no watch, no persistence, no enforcement.
Built-in presets for common use cases:
| Preset | Download | Upload | Use Case |
|---|---|---|---|
gaming |
50 mb/s | 50 mb/s | Low latency, prioritizes responsive gameplay |
streaming |
10 mb/s | 5 mb/s | Balanced for video calls and streaming |
background |
500 kb/s | 100 kb/s | Minimal bandwidth for background downloads |
| Unit | Description | Example |
|---|---|---|
b, byte, bs |
Bytes per second | 100bs, 500byte |
kb, kbs |
Kilobytes per second (1 KB = 1024 B) | 500kb, 2kbs |
mb, mbs |
Megabytes per second (1 MB = 1024 KB) | 1mb, 50mbs |
gb, gbs |
Gigabytes per second (1 GB = 1024 MB) | 1gb, 2gbs |
kbit, kbits |
Kilobits per second | 100kbit, 500kbits |
mbit, mbits |
Megabits per second | 10mbit, 100mbits |
gbit, gbits |
Gigabits per second | 1gbit |
Note: Minimum rate is 1 KB/s (1024 B/s). Values below this are rejected because the Linux kernel's HTB scheduler cannot accurately enforce sub-KB/s rates due to clock tick granularity.
zelynic works by combining several Linux kernel features:
Uses the ss (socket statistics) command to discover all active TCP/UDP sockets on the system, maps them to their owning processes via /proc filesystem, and extracts per-socket byte counters (available on kernels 4.6+).
Uses a layered approach:
- Cgroup v2 — Places target PIDs in
/sys/fs/cgroup/zelynic/target_<name>. - nftables socket matching — Matches target sockets with
socket cgroupv2. - Packet and conntrack marks — Marks target flows so upload and download can be identified.
- tc fw filter + HTB class — Shapes upload/egress traffic on the selected interface.
- nftables input policer — Limits marked download/ingress responses with
limit/drop.
Upload / egress
Process PID
-> cgroup v2 target (/sys/fs/cgroup/zelynic/target_<name>)
-> nft output: socket cgroupv2 match
-> meta mark / ct mark
-> tc fw filter
-> HTB class
-> network interface
Download / ingress
Process opens connection
-> nft output marks socket/flow
-> conntrack mark is stored
Incoming response
-> nft input matches ct mark
-> nft limit/drop policer
-> process receives limited download
# Print version
zelynic -v
# Print complete version and build info
zelynic -V
# Check the latest upstream release
zelynic --check-updateExample output of zelynic -V:
Version: v3.0.1
Build: linux-x86_64 (COMMIT_HASH)
Copyright: (c) 2026 rezky_nightky (oxyzenQ)
License: GPL-3.0
Source: https://github.com/oxyzenQ/zelynic
# Recommended local quality gate for Rust/core changes
./build.sh check-all
# Build release binary
./build.sh release
# Full CI pipeline (checks + release build)
./build.sh ciManual fallback:
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo audit
cargo deny check all
python3 scripts/check-policy.pySee RULES.md for source policy rules and docs/supply-chain.md for dependency policy and supply-chain check details.
GNU General Public License v3.0 — Copyright (c) 2026 rezky_nightky (oxyzenQ)
See LICENSE for details.
rezky_nightky (oxyzenQ) — GitHub
