A tiny, dependency-free system inspector for Linux.
Born from the frustration of SSHing into an embedded board and realizing that lspci, lsusb, and all the rest of most essential info-oriented tools are nowhere to be found. kv is a single static binary that tells you what hardware you've got, reading directly from /sys and /proc like nature intended.
Pre-built static binaries are available from GitHub Releases.
Each release includes SHA256 checksums for verification.
x86_64 (most Linux servers and desktops):
curl -LO https://github.com/walruscraft/kv/releases/latest/download/kv-x86_64
curl -LO https://github.com/walruscraft/kv/releases/latest/download/kv-x86_64.sha256
sha256sum -c kv-x86_64.sha256
mv kv-x86_64 kv && chmod +x kv
./kv --versionARM64 (Raspberry Pi 4/5, Jetson, Apple Silicon VMs):
curl -LO https://github.com/walruscraft/kv/releases/latest/download/kv-arm64
curl -LO https://github.com/walruscraft/kv/releases/latest/download/kv-arm64.sha256
sha256sum -c kv-arm64.sha256
mv kv-arm64 kv && chmod +x kv
./kv --versionOther architectures:
Use kv-x86 (32-bit PC), kv-arm (32-bit ARM), kv-riscv64 (64-bit RISC-V),
kv-ppc64le (PowerPC64 LE), or kv-mipsel (MIPS LE).
Each has corresponding .sha256, .sig, and .crt files.
Releases are signed with cosign keyless signing via GitHub Actions OIDC. This proves the binary was built by the official release workflow, not a compromised maintainer machine.
# Install cosign (https://docs.sigstore.dev/cosign/system_config/installation/)
# Then verify:
cosign verify-blob kv-x86_64 \
--signature kv-x86_64.sig \
--certificate kv-x86_64.crt \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp 'https://github.com/walruscraft/kv/\.github/workflows/release\.yml@refs/tags/v.*'Quick install (skip verification):
curl -Lo kv https://github.com/walruscraft/kv/releases/latest/download/kv-x86_64 && chmod +x kvCopy to an embedded board:
scp kv-arm64 user@board:/tmp/kv
ssh user@board chmod +x /tmp/kv
ssh user@board /tmp/kv snapshot -jpNote
If using a Windows machine to copy the file to the target, chmod it on the target to make it runnable.
kv pci # PCI devices
kv usb # USB devices
kv block # Disks and partitions
kv net # Network interfaces
kv cpu # CPU info
kv mem # Memory stats
kv mounts # Mount points
kv thermal # Temperature sensors
kv power # Power supplies / batteries
kv dt # Device tree (ARM/RISC-V)
kv snapshot # Everything as JSONkv mem # Text: KEY=VALUE pairs
kv mem -j # JSON
kv mem -jp # Pretty JSON
kv mem -v # Verbose (more fields)
kv mem -h # Human-readable sizes (16G not 16324656)
kv mem -jpvh # Combine flagskv block -f nvme # Only NVMe devices
kv pci -f nvidia # Only NVIDIA PCI devices
kv dt -f gpu # Device tree nodes matching "gpu"
kv net -jv -f eth # Combine with other flags (keep -f last)Note: -f takes an argument, so keep it separate from combined flags (use -jv -f pattern, not -jvf pattern).
Requires Rust nightly (uses build-std for no_std) and Rust 2024 edition.
Important
See CONTRIBUTING.md for full cross-compilation setup.
# Debug build
cargo build
# Release build (static, ~113 KB stripped)
cargo build --releaseCargo aliases for embedded targets (all use gnu targets with build-std):
cargo x86_64 # x86_64-unknown-linux-gnu
cargo x86 # i686-unknown-linux-gnu (32-bit)
cargo arm64 # aarch64-unknown-linux-gnu
cargo aarch64 # same as arm64
cargo arm # arm-unknown-linux-gnueabihf (32-bit ARM)
cargo riscv64 # riscv64gc-unknown-linux-gnu
cargo ppc64 # powerpc64le-unknown-linux-gnu
cargo mips # mipsel-unknown-linux-gnuARM, RISC-V, PowerPC64, and MIPS builds automatically include the dt (device tree) feature.
Prerequisites (Debian/Ubuntu):
# Nightly toolchain required for build-std
rustup default nightly
# Cross-compiler for ARM64
sudo apt install gcc-aarch64-linux-gnuDon't need USB? Don't compile it:
cargo build --release --no-default-features --features "mem,cpu,block"| Feature | Description |
|---|---|
| pci | PCI device enumeration |
| usb | USB device enumeration |
| block | Block devices and partitions |
| net | Network interfaces, IPs, wireless signal |
| cpu | CPU topology and info |
| mem | Memory information |
| mounts | Mount points |
| thermal | Temperature sensors and cooling devices |
| power | Power supplies and batteries |
| dt | Device tree (ARM/RISC-V) |
| snapshot | Combined JSON dump |
$ kv mem -h
MEM_TOTAL=16G MEM_FREE=121M MEM_AVAILABLE=12G SWAP_TOTAL=2G SWAP_FREE=2G
$ kv pci
BDF=0000:01:00.0 VENDOR_ID=0x10de DEVICE_ID=0x1b80 CLASS=0x030000 DRIVER=nouveau
$ kv net
NAME=eth0 MAC=dc:a6:32:56:76:50 MTU=1500 STATE=up SPEED_MBPS=1000 IP=192.168.1.100
NAME=wlan0 MAC=dc:a6:32:56:76:51 MTU=1500 STATE=up IP=192.168.1.101 SIGNAL=-52dBm
$ kv thermal -h
SENSOR=cpu-thermal TEMP=44.5°C
SENSOR=gpu-thermal TEMP=41.2°C
$ kv block -h
NAME=mmcblk0 TYPE=disk SIZE=16G MODEL="SC16G"
NAME=mmcblk0p1 TYPE=part SIZE=512M PARENT=mmcblk0 MOUNTPOINT="/boot"
NAME=mmcblk0p2 TYPE=part SIZE=15G PARENT=mmcblk0 MOUNTPOINT="/"- Minimal dependencies. no_std with direct syscalls, no libc. Just 3 crates: origin (startup), rustix (syscalls), itoa (number formatting). Zero heap allocation.
- Single static binary. ~113 KB stripped, copy it anywhere, it just works.
- Read-only. We observe, we don't touch.
- Graceful degradation. Missing /sys/bus/pci? We say so and move on.
- Stable output. Scripts can depend on the format.
We want kv to work on every Linux system. Help us by testing on your hardware!
If you have unusual embedded boards, custom SoCs, or systems where kv doesn't work correctly, we'd love to hear from you.
Ways to contribute:
- Open an issue - Bug reports, test results from your hardware
- Start a discussion - Feature requests, questions, ideas
- Submit a pull request - Code contributions
New to open source? No problem! See CONTRIBUTING.md for step-by-step instructions on how to submit test results or report issues.
| Target | Alias | Notes |
|---|---|---|
| x86_64-unknown-linux-gnu | cargo x86_64 |
64-bit x86 |
| i686-unknown-linux-gnu | cargo x86 |
32-bit x86 |
| aarch64-unknown-linux-gnu | cargo arm64 / cargo aarch64 |
64-bit ARM |
| arm-unknown-linux-gnueabihf | cargo arm |
32-bit ARM, hard float |
| riscv64gc-unknown-linux-gnu | cargo riscv64 |
64-bit RISC-V |
| powerpc64le-unknown-linux-gnu | cargo ppc64 |
64-bit PowerPC (LE) |
| mipsel-unknown-linux-gnu | cargo mips |
32-bit MIPS (LE) |
All targets produce static binaries (~113 KB stripped) using no_std with build-std. Zero heap allocation.
Note on big-endian PPC64/MIPS: Big-endian variants are blocked upstream by rustix (which has no linux_raw backend for these ABIs). Only little-endian targets are supported. This may change when rustix adds BE support.
QEMU user-mode 10.0.7 (Debian 1:10.0.7+ds-0+deb13u1+b1) has a bug in
PPC64 emulation: argv[1] is always NULL on the initial process stack,
regardless of what arguments are passed. argc is correct and argv[0],
argv[2], etc. are fine -- only the second slot is zeroed. This causes any
program that reads command-line arguments to crash.
The kv binary itself is correct. CI uses GitHub Actions' QEMU which may or may not have this bug. If PPC64 smoke tests fail in CI with a segfault, this is the likely cause.
MIPS LE (qemu-mipsel) works correctly with the same QEMU version.
kv is designed for untrusted environments. See the security table below.
| Protection | Implementation |
|---|---|
| Memory safety | Rust's type system prevents buffer overflows, use-after-free |
| JSON escaping | Control chars, quotes, backslashes properly escaped |
| Path traversal | Rejects .. in devicetree paths |
| Input limits | Filter patterns truncated to 1024 chars |
| Recursion limits | Devicetree traversal stops at 64 levels |
| Safe parsing | Returns None on overflow instead of panicking |
| Read-only | Only reads from /sys and /proc, never writes |
| No shell | No command execution, no injection surface |
| No network | Pure local filesystem operations |
| Signed releases | Cosign keyless signatures via GitHub Actions OIDC |
MIT
Leon Vak leonvak@gmail.com