npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@emptyos/client

v0.1.12

Published

External EmptyOS client

Readme

EmptyOS external client

This package is the workstation-side empty command, published to npm as @emptyos/client. Run every empty command in the local terminal: the client either handles it locally or transports it to the selected EmptyOS computer. It requires Node.js 20 or newer.

Installing the client, connecting to a computer, putting files on it, sharing, and publishing are described at https://emptyos.com/docs/. This README keeps the contracts behind those pages: profile format, transport, publish mechanics, and development notes.

The companion agent skill is at skills/emptyos-computer/ and ships in the package. empty skill install copies it to ~/.agents/skills/emptyos-computer/; --dir <path> chooses another skills directory, and a re-run replaces the earlier copy. It is a small bootstrap into this client and the resident ~/EMPTY.md contract.

For checkout development, the repository root provides a managed local computer and isolated client profile. Run emptyos-dev from that worktree, then pair with emptyos-dev empty connect <printed-owner-url> --as owner and approve the request in its managed browser. Use emptyos-dev empty <command> after pairing. This exercises the normal client transport without linking the client or editing your real profiles. ./bin/emptyos-dev works from the root without installing the optional global dispatcher. The separate resident-only workflow uses npm run dev:native with npm run empty -- <command>. See the root README.md for setup, persistence, testing, and limitations.

Computer profiles

Registering a computer makes one noninteractive RPC call to confirm that the computer speaks protocol version 2. It does not make the new profile the default automatically.

empty computer add personal \
  --host [email protected]
empty computer use personal
empty computers
empty computer show --json
empty computer remove personal

empty connect <computer-url> pairs with an EmptyOS-managed computer without an exe.dev account; the walkthrough is at https://emptyos.com/docs/start/. On approval the client stores a new Ed25519 identity, tunnel token, and pinned host key under its private config directory. Pairing secrets and tunnel token contents are never placed in URLs, process arguments, or logs. connect selects the new profile when no default computer exists; otherwise the existing default remains unchanged.

Approval requests expire after 15 minutes. Retry connect with the same URL and alias to resume a valid pending request or finish saving a valid approval already retained locally, including after its request expires. Approval creates a grant on the computer before local installation finishes; it does not imply an active session. Verify saved access with the read-only empty --computer <alias> status --json. Report partial-save errors and inspect Client access for potentially unused grants after expired or unknown requests; do not keep requesting fresh approvals unattended.

empty computer remove <alias> removes only the local profile, preserving its credentials and pinned trust. To connect to an authorized replacement at the same hostname, inspect empty computers --json, remove the intended old profile, then run empty connect <computer-url> --as <alias> for a new owner approval. The new pairing uses a separate credential directory without overwriting old files. Do not manually delete key directories; a different hostname alone does not justify deleting existing credentials or trust.

Use an SSH config Host name when a connection needs a port, proxy, key, or other SSH option. Stored targets intentionally accept only a hostname or user@hostname so they cannot inject SSH options or remote shell text.

An EmptyOS-managed tunnel profile can use the same version 1 config format without requiring an exe.dev account for the person using the client. Its four tunnel fields are all required together:

{
  "target": "[email protected]",
  "ownerOrigin": "https://computer.example",
  "tunnelTokenPath": "/Users/me/.config/emptyos/computer.token",
  "sshIdentityPath": "/Users/me/.ssh/emptyos_computer",
  "sshKnownHostsPath": "/Users/me/.ssh/emptyos_known_hosts"
}

ownerOrigin must be a credential-free HTTPS origin. All three configured files must be regular files owned by the current user and use absolute paths. The token and private key must have mode 0600; the known-hosts file must not be group- or other-writable. The client reads the bearer token only inside its SSH proxy helper. Token contents never appear in process arguments, URLs, profile output, or logs. Tunnel SSH ignores user SSH configuration, uses only the configured identity, and requires the pinned known-hosts entry. Existing profiles containing only target continue to use direct SSH.

Profiles live at $XDG_CONFIG_HOME/emptyos/client.json, or at ~/.config/emptyos/client.json when XDG_CONFIG_HOME is unset. The directory is mode 0700 and the atomically replaced file is mode 0600.

--release-catalog is optional. It replaces the official HTTPS catalog used by empty computer update for that profile. Every profile can also update from an explicitly supplied catalog or local release artifact.

--computer <alias-or-url> overrides the default for a command that operates on a computer. An HTTPS URL selects the paired profile for that owner origin:

empty --computer work things --json
empty --computer https://work.example things --json

It is rejected for connect and the local profile-registry commands computers, computer add, computer use, and computer remove, where an override would otherwise be silently ignored.

Commands and help

empty --help is the complete command inventory. Help is resolved locally, so it works without a selected computer or SSH connection:

empty --help
empty thing --help
empty put --help
empty help dataset describe

The client handles computer profiles, help, and version output locally. put, clone, platform updates, and ssh combine local state with Git or SSH. A route outside the client's command families is checked against the computer's command inventory: a registered resident owner command is forwarded as structured argv so it works without a client release, while anything else fails locally with client usage. empty commands merges both command inventories.

Restricted sharing is transported like the other resident Thing mutations. empty share <id> --with <email> grants one existing EmptyOS account access to an eligible private static Thing, while empty unshare <id> --with <email> or --all revokes it. empty shared, empty shared add <url>, and empty shared remove <url> manage links saved under Shared with me on the selected computer. Services remain unshareable, and expose remains the separate anonymous-public operation.

Human catalog commands use the selected computer alias in useful empty states:

Computer personal is empty — no Things yet

Put its first Thing:
  empty put <path> [--as <id>]

The client checks emptiness through the existing JSON form. Non-empty tables remain resident-rendered and pass through unchanged. Explicit --json output preserves valid resident results; workstation, Git, transport, and resident failures return one JSON object with a stable code and human-readable error. thing add <path> remains unavailable from a workstation because its argument would be a path on the computer; its help explains the supported put workflow.

Forwarded commands use one fixed SSH remote command with a base64url-encoded JSON request. A Thing import uses a separate fixed endpoint for the same structured metadata and streams a Git bundle on stdin, so file bytes never enter the bounded argv payload. SSH runs with BatchMode=yes, a ten-second connection timeout, and no TTY. Human-mode remote output passes through; structured commands preserve valid resident JSON and normalize local or transport failures at the client error boundary. When SSH itself fails (exit 255), SSH or the tunnel helper reports the connection error, and the client ends with a hint naming the computer profile. DNS failures can result from an incorrect hostname, network trouble, or sandbox network restrictions; they do not prove that a computer was retired. Agents running in a restricted sandbox should request network access through their runtime's approval mechanism and retry a read-only check on the same computer before continuing.

Before put, the client reads the resident version response. put requires the type-neutral thingImport capability. The client and computer use protocol 3; unsupported forms stop before staging or upload with an explicit empty computer update remediation.

empty ssh without arguments opens the ordinary owner SSH session. Arguments after -- are an explicit raw remote command and consequently have the normal remote-shell semantics of ssh host command...; use transported empty commands for structured, injection-resistant RPC.

Koans

At a terminal, the client's quiet moments end with one of the landing page's koans: empty computers with no profiles, empty things / projects / data / changes on a computer that has none yet, and the top-level help. The koan rotates daily. Piped output, --json, errors, command help, and the resident CLI never carry one; set EMPTYOS_PLAIN=1 to turn them off entirely.

EmptyOS updates

empty status reports the computer's complete EmptyOS release version and a short release hash. empty status --json includes software with state, displayVersion, and the full release hash. The states are current, updating, resident-changed, and unknown; current means the completed vendor baseline, not that owner-editable files are unmodified. Older computers may report an unnumbered release or unavailable version. empty --version continues to identify the workstation client and protocol.

empty computer update updates Home, Gateway, the resident CLI and agent guidance, Recovery, and EmptyOS system services together. The complete version advances only after both the editable and protected components finish. This does not upgrade the underlying Linux distribution or kernel.

Check the selected computer without changing installed software, then apply the configured release when the plan is acceptable. Checks may retain an update stage on the computer; use its printed resume command to apply that exact plan:

empty computer update --check
empty computer update

--computer <alias-or-url> selects a different profile for either command by its local alias or paired HTTPS URL. --json returns the selected computer, release and artifact identifiers, status, per-path plan, warnings, updater output, and exit status without decorating them.

If apply reports needs-reconciliation, the structured result includes a retained complete-update stage, a resident candidate location, and exact next command. Continue from an agent: inspect that candidate's RECONCILE.md through empty ssh, merge only the declared conflicting paths, run the candidate tests, then resume the same transaction:

empty computer update --resume <stage-name>

Resume does not fetch a newer release. It reuses the retained target and rejects stale live state, edits outside the conflict set, or failed validators.

The default source is the official catalog at https://release.emptyos.com/emptyos/v1/catalog.json. A profile-level --release-catalog replaces it for that computer. Supply --catalog to override either catalog for one invocation, or use an immutable artifact that was obtained through a trusted operator channel:

empty computer update --catalog https://releases.example/emptyos/catalog.json
empty --computer work computer update --release ./emptyos-release.json

The client validates HTTPS on every redirect, bounds downloads, and checks the catalog's artifact digest and release identity. It then verifies the release's publisher signature against the public trust already installed on the selected computer, read through that profile's SSH connection. The root verifier on the computer independently checks its own pinned trust before executing signed update code. A different catalog or local file cannot supply a replacement key.

The owner account must have working noninteractive sudo, as on provisioned EmptyOS computers. Older computers also need one operator update to install the protected update configuration before this command can run. Losing the client connection does not stop the detached update: use the retained stage's resume command to inspect and finish or recover the same transaction.

Do not use resident-only tooling to fulfill empty computer update. That path is not an alias of the signed complete update, does not update Recovery or services, and does not advance the complete EmptyOS version.

Publish contract

put, clone, and put . are described at https://emptyos.com/docs/publish/. This section keeps the mechanics behind them.

put snapshots the selected content as one parentless commit without source history, remotes, hooks, or Git configuration, and streams it as a Git bundle on stdin to a fixed import endpoint. Upload happens before the resident mutation lock; installation is revalidated and atomic, and a failed validation leaves no partial Thing behind. Successful initial --json output reports the detected sourceKind, content counts, installed head and manifest facts, generated scaffolding, preparation, verification, installation, and service registration state.

clone first confirms the Thing exists, clones <ssh-target>:things/<id>, validates the top-level id in thing.yaml, and stores three clone-local Git keys:

  • emptyos.computer
  • emptyos.profileTarget
  • emptyos.target (thing://<id>)

The profile target snapshot prevents an alias that was later retargeted from silently publishing a checkout to another computer. Clone JSON reports the local root plus the computer, immutable profile target, and thing://<id> binding.

Publish never rewrites local history. It requires:

  • a bound repository on an attached branch;
  • a matching profile target and thing.yaml ID;
  • no tracked or untracked worktree changes;
  • a regular, executable, non-symlink ./verify that succeeds locally; and
  • exactly one non-merge commit on top of the current origin default-branch HEAD.

After fetching and validating the live head, publish pushes HEAD to refs/emptyos/candidates/<full-sha> and requests:

thing activate <id> --sha <sha> --expected-base <live-head> [--json]

The activation response and exit status are passed through to the caller.

Development

cd client
npm install
npm link      # optional: run this checkout as `empty`
npm test

Tests use temporary real Git repositories and fake ssh/git executables; they do not require a network connection or an EmptyOS computer.

client/lib/updater/ holds byte-identical copies of the complete update scripts and their dependencies. The published package must not reach outside its own tree. client/scripts/sync-updater.mjs declares the exact source file list; refresh copies from the repository root with node client/scripts/sync-updater.mjs. client/test/vendor.test.js rejects drift, and the packed-package test checks imports and executable availability.