whowns answers a deceptively simple question: "What installed and manages this command?"
which is commonly used to find the executable that a command resolves to on PATH. Even when which -a lists every matching executable, it does not explain which package or version manager owns them or how to maintain them. whowns starts where path lookup ends: it connects active and shadowed executables to their ownership chain, supporting evidence, and the manager command to use next.
The name compresses who owns into six characters. The tool focuses on explaining one command at a time instead of treating package inventory as its primary purpose. It answers:
- Which executable is active?
- Are other versions shadowed later in
PATH? - Which version manager or package manager owns the runtime?
- How was that manager itself installed?
- Which paths, symlinks, receipts, and manager queries support the conclusion?
- Which manager and command should be used to inspect, update, or remove it?
whowns is a standalone Rust binary. Users do not need Node.js, Python, or another runtime to run it.
- Installation
- Inspect a command
- List common runtimes
- JSON
- Confidence
- Recognized owners
- Development
- Current boundaries
GitHub Releases is the primary binary distribution channel. The recommended installer detects the host OS and CPU, downloads the matching archive, verifies it against the release checksum manifest, and installs the standalone binary.
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/shm11C3/whowns/releases/latest/download/install.sh | shThe default installation creates $HOME/.local/bin/whowns and the shorthand alias $HOME/.local/bin/wio. Pass installer options after sh -s --.
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/shm11C3/whowns/releases/latest/download/install.sh \
| sh -s -- --no-alias
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/shm11C3/whowns/releases/latest/download/install.sh \
| sh -s -- --bin-dir /usr/local/binYou can also download and inspect a release archive before installing it.
tar -xzf whowns-v0.1.0-aarch64-apple-darwin.tar.gz
cd whowns-v0.1.0-aarch64-apple-darwin
./install.shSee docs/RELEASING.md for supported architectures, checksums, artifact attestations, and the release process.
You can also install from source with Cargo.
cargo install --path . --locked
whowns node$ whowns node
node
├── ● active
│ ├── executable: /usr/local/bin/node
│ ├── ownership: node → macOS Installer (.pkg) [confirmed]
│ └── actions (macOS Installer (.pkg))
│ ├── inspect: pkgutil --pkg-info org.nodejs.node.pkg
│ └── note: Update by installing a newer package from the same vendor. ...
└── ○ shadowed
├── executable: /opt/homebrew/bin/node
├── resolves to: /opt/homebrew/Cellar/node/25.6.1_1/bin/node
├── ownership: node → Homebrew [probable]
└── actions (Homebrew)
├── inspect: brew info node
├── update: brew upgrade node
└── remove: brew uninstall nodeThe terminal tree keeps resolutions, ownership, and suggested actions visually connected. active is the executable selected by PATH. shadowed executables are installed but lose because they appear later in PATH. Action guides are suggestions only; whowns never runs update or removal commands.
whowns does execute other programs for inspection: recognized package and version managers (mise which, pyenv which, pkgutil --file-info, and similar) are invoked with read-only subcommands to confirm ownership. See Recognized owners for the safety policy around those queries.
Use --explain to show detailed evidence and every ownership layer.
whowns node --explain
whowns rustc cargo --explainWhen the environment provides enough evidence, an ownership chain can look like this:
node → nvm [probable] → Homebrew [probable]
rustc → rustup [confirmed] → rustup installer [probable]
Resolution continues upstream until an installation source is reached. Cycles and chains longer than eight owners stop with an unconfirmed source node whose evidence explains why traversal ended.
The summary is generated from the same OwnershipGraph used by individual inspection. The graph is the command-level model: it can contain multiple PATH resolutions, while each resolution contains one linear, nearest-first ownership chain. There is no separate ownership detector for this view.
whowns --all
whowns --all --explain
whowns --all --show-missingThe summary shows the active executable's owner chain, confidence, and shadowed count. --explain appends the detailed view of the same graphs.
Individual inspection and --all emit the same versioned machine-readable document.
whowns node --json
whowns --all --jsonJSON document
├── schema_version: 1
└── graphs: OwnershipGraph[] (commands and their PATH resolutions)
└── Resolution[] (active / shadowed, path, real_path)
└── OwnershipNode[] (ordered nearest-first)
├── id (stable) / name (display)
├── kind
├── package / version
├── Confidence
├── Evidence[]
└── ActionGuide
Resolution: the active executable and every shadowed executable found inPATHOwnershipNode: one member of an ordered, nearest-firstruntime -> manager -> upstream manager -> installation sourcechainid: the stable machine-readable owner identity, such ashomebrew,sdkman, ormacos_installer;nameis display text and can change without affectingidEvidence: paths, symlinks, filesystem targets, receipts, package queries, and manager queriesConfidence:confirmed,probable, orunknownActionGuide: suggested inspect, update, and removal commands with safety notes
schema_version versions the JSON contract independently from the whowns package version. During the 0.x series, adding optional fields is compatible within schema version 1. Removing or renaming fields, changing their types or meanings, or changing stable owner id values requires a new schema version. Consumers should select supported schema versions and ignore fields they do not recognize. The human-facing name may change without a schema-version change; use id for machine identity.
confirmed: a package database or receipt records ownership of the file, or a manager query returns the resolved executableprobable: a recognized managed-path layout, installed but non-file-specific receipt, or operating-system path strongly suggests an owner without a direct ownership recordunknown: no recognized owner was found, so a safe update or removal method cannot be selected
Confidence is derived from the typed evidence on each ownership claim. Detectors report what they observed; they cannot assign confirmed directly. --explain shows the receipt, package query, matching manager query, or weaker path evidence behind the result.
A file under /usr/local is not automatically labeled as manually installed. Vendor installers, package managers, and manual copies can all use that location. Without stronger evidence, whowns reports unconfirmed owner and does not generate update or removal commands.
- Nix, Homebrew, and MacPorts
- nvm, fnm, Volta, mise, and asdf
- pyenv, rbenv, SDKMAN!, uv, rustup, and
cargo install - Deno and Bun installer directories, and pnpm home
- macOS Installer receipts through
pkgutiland python.org framework installations - Linux packages owned by dpkg, RPM, pacman, or apk
- operating-system paths
For supported managers, whowns runs read-only queries such as which or current and records their results as Evidence. For a path under the MacPorts prefix, port -q provides <path> checks the local registry; the path alone is probable, while a registry match is confirmed.
These queries run through a single bounded execution policy, not raw, unbounded subprocess calls:
- Each query targets the executable
whownsalready resolved onPATH, not a bare command name handed to a freshPATHsearch. This keeps the query pointed at the same binarywhownsinspected, even ifPATHchanges between the two lookups. - Each query is killed if it does not finish within a few seconds, so a hung or slow manager cannot block a lookup or
--all. - Identical queries are only ever executed once per
whownsinvocation; repeated queries across runtimes or resolutions in--allreuse the cached result. - Captured output is bounded; a manager that misbehaves and writes excessive output cannot exhaust memory.
- A timed-out or unstartable query is always printed as a
note:line on stderr. A manager query — the confirmatorywhich/currentquery run after an owner is already identified — additionally records its outcome, including a non-zero exit, asEvidenceon that owner, so a degraded confirmatory query stays visible instead of silently changing the result. - Queries inherit the parent process environment unmodified. Managers resolve their own data directories from variables such as
HOME; clearing or fabricating environment state for them would make their answers wrong rather than safer.
Running the full test suite requires Python 3. The tests use its standard-library JSON parser to validate the public JSON contract; the whowns binary itself does not depend on Python.
cargo test
cargo build --release
./target/release/whowns nodeThe project has no external Rust crate dependencies. Documentation and code comments use English; README.ja.md is the Japanese localization.
whowns inspects executables found in PATH on macOS and Linux. It does not inventory every package registered with the operating system or package managers. Windows, tracing the source of shell configuration, and automatic uninstallation are currently out of scope.
If the installation source of a version manager cannot be determined, the ownership chain ends with unconfirmed source [unknown].