Install an npm package using a domain you already know.
di verify zuraai.xyz
di zuraai.xyz
Here’s the idea: a domain owner publishes a small DNS record that points to an
npm package. domaininstall reads that record, shows you exactly what it found,
and asks before installing anything.
Status: available on npm as an early release. The command and DNS format are intentionally small while real-world use shapes what comes next.
npm install --global domaininstallThen check a domain without installing its package:
di verify zuraai.xyz
Package names are easy to mistype, and unfamiliar scopes are hard to judge. A
domain is often a clearer starting point: if you already trust example.com,
you can ask what package that domain declares instead of guessing its npm name.
That’s useful evidence — not a magic safety stamp. domaininstall shows the
package declared by the current resolved DNS record and checks that declaration
against a local continuity pin after first use. It does not prove that the
package code is safe or that the domain owner controls the npm publisher account.
A publisher adds one TXT record:
_dnstall.example.com. TXT "dnstall=pkg:npm/example-package"
You can inspect it without installing:
di verify example.com
When you’re ready:
di example.com
Before anything is installed, di prints the resolved package, version policy,
registry, destination, and the exact npm command it will run. It waits for your
confirmation, then installs with lifecycle scripts disabled.
To install a command-line tool for your whole machine (instead of the current
project), add --global:
di example.com --global
On first use, domaininstall saves the domain-to-package mapping in
~/.domaininstall/pins.json. If the domain later points to a different package,
you’ll see a clear warning — and you can’t wave it away with --yes.
This is trust on first use (TOFU). It helps returning users notice a changed mapping. It can’t protect a first-time user from a compromised, expired, or mistyped domain.
The pin also records the DNS version policy and the effective npm registry. A one-off version override on the command line won’t silently replace the domain’s policy.
di trust list shows what is remembered, and di trust forget <domain> removes
a single mapping without disturbing the others. Both confirm before changing
anything, and forgetting a domain means its next install is treated as a first
use again.
domaininstall does not prove that:
- the package is safe, audited, or free of malware
- you typed the intended domain on first use
- a newly published package version is trustworthy
- the domain owner also controls the npm publisher account or source code
Keep using lockfiles, registry provenance, dependency review, and security scanning. They solve different parts of the problem.
If you own a domain and an npm package, di setup prints the exact record to
add at your DNS provider:
di setup example.com my-package
di setup example.com my-package@^2 declare a version policy
di setup example.com/react @acme/ui declare a sub-package
It runs entirely offline, so you can generate the record before it exists. It
reports the name relative to your zone (what most DNS provider forms expect),
the fully-qualified name, and a zone-file line. Once the record is live,
di verify example.com confirms it resolves.
The basic record lives at _dnstall.<domain>:
_dnstall.example.com. TXT "dnstall=pkg:npm/example-package"
Publishers can pin a version or range:
_dnstall.example.com. TXT "dnstall=pkg:npm/example-package@^2"
A path-like sub-package becomes another DNS label:
di example.com/react
That looks up _dnstall.react.example.com.
Publishing a mapping is a DNS TXT record and a quick check with
di verify <your-domain>. Step-by-step unassisted setup lives in the
publisher guide. The project is in a quiet beta —
if you maintain an npm package and want to try a domain mapping, start there.
The DNS record format is the implementation-oriented reference for record location, scoped package encoding, version policy, metadata, duplicate and conflict handling, and producer/consumer conformance.
di <domain>[/sub][@version] resolve, confirm, and install
di <domain> --global install globally instead of into this project
di verify <domain> inspect a declaration without installing
di setup <domain> <package> print the TXT record a publisher must add
di trust list show every remembered mapping
di trust forget <domain> remove one remembered mapping
di trust reset --all back up and reset all saved mappings
di --help show the complete command reference
di --version print the CLI version
The npm package exposes di as the primary command, with domaininstall and
dnstall as aliases.
Progress and previews go to standard output; warnings and errors go to standard
error — so di plays nicely with scripts and CI logs.
- Node.js 22.14 or newer
- npm available on
PATH - macOS, Linux, or Windows
The first release supports npm projects only. pnpm, Yarn, and Bun are refused until their install behavior has been tested to the same standard.
Every install uses the effective HTTPS npm registry explicitly and includes
--ignore-scripts. If a dependency needs a lifecycle script, review that step
and run it yourself afterward — domaininstall won’t enable it for you.
If your npm config routes a package’s scope to a different registry than the
default (@scope:registry), di refuses the install instead of showing one
registry and fetching from another. Install that package with npm directly until
scope-specific registries are supported.
The trust store is schema-validated, written atomically, and locked while it’s
being updated. On macOS and Linux it also enforces owner-only permissions and
no-follow file access. Windows relies on the user-profile ACL, because Node
doesn’t expose the same POSIX ownership and no-follow guarantees there. Corrupt
state fails closed. Resetting trust keeps a backup and asks for confirmation
unless you intentionally pass --force.
To work on the project locally:
git clone https://github.com/solnikhil/domaininstall.git
cd domaininstall
npm ci
npm test
npm run test:e2e
npm run verify:packagenpm test uses deterministic, mocked DNS responses. The E2E command is
separate because it performs a live DNS lookup and a real npm installation.
The documentation index links the protocol reference, security boundary, roadmap, release runbook, changelog, and historical design material. The roadmap is the live source of project status; older release checklists are retained as snapshots.
The security policy explains what we claim, what we don’t, and how to report a vulnerability. The release roadmap tracks hardening and validation work still in progress.
MIT