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

oh-my-ssh

v1.1.2

Published

Self-hosted SSH host manager for the terminal. CLI + TUI, projects your hosts into ~/.ssh/config so ssh, scp, sftp and VSCode Remote work unchanged.

Readme

omssh

SSH host manager for the terminal. Dashboard, forms and a two-pane SFTP browser — keyboard and mouse driven.

Your hosts live in a vault you own. omssh projects them into ~/.ssh/config.d/omssh.conf, so ssh, scp, sftp, rsync and VSCode Remote work with them unchanged. No terminal emulator, no lock-in, no subscription.

┌ filter ───────────────────┐┌ nas ──────────────────────────┐
│ na▮                       ││ hostname   10.0.0.5           │
└───────────────────────────┘│ user       chap     port 22   │
┌ hosts 5/5 ────────────────┐│ password   stored (sealed)    │
│ ▾ home (2)                │├ ~/.ssh/config.d/omssh.conf ───┤
│   ❯ nas       10.0.0.5    ││ Host nas                      │
│     pi        10.0.0.6    ││   HostName 10.0.0.5           │
│ ▾ work (1)                ││   User chap                   │
│     bastion   1.2.3.4     ││   IdentityFile ~/.ssh/id_ed…  │
└───────────────────────────┘└───────────────────────────────┘
↵ connect · a add · e edit · d rm · s sftp · f files · y copy · p pass · q quit

Install

npm i -g oh-my-ssh
omssh

Node 22+ and OpenSSH. macOS and Linux.

Use

omssh                 # dashboard
omssh nas             # connect straight away
omssh nas -- -L 8080:localhost:8080
omssh ls --json       # machine-readable, for scripts and agents

Adding or editing a host writes ~/.ssh immediately — no apply step to forget.

Names ssh will not take

Call a host whatever you call it out loud — 개발_서버, NAS (attic). ssh(1) will not: it checks its destination argument before reading any config and refuses non-ASCII bytes, spaces and shell metacharacters, so ssh 개발_서버 dies with hostname contains invalid characters however the config is written.

So a host carries two names. The label is yours. The alias is the ASCII one omssh hands to ssh and writes into ~/.ssh/config.d/omssh.conf, romanized from the label and de-duplicated against the rest of the vault and any Host block you wrote by hand. omssh commands take either, or a fragment of either.

omssh add --label '개발_서버' --hostname 192.0.2.10
# warning: ssh cannot use "개발_서버" as a destination
#          — stored as gaebal-seobeo

omssh 개발_서버        # by label
omssh 개발             # by fragment, when it names one host
omssh gaebal-seobeo
ssh gaebal-seobeo      # and outside omssh: scp, rsync, VSCode Remote

# --alias is rejected when it is not something ssh accepts, rather than fixed
# silently. Pass the readable name as --label and the ASCII one as --alias.
omssh add --label '개발_서버' --alias dev-1 --hostname 192.0.2.10

omssh doctor            # aliases ssh would refuse, with replacements
omssh doctor --fix      # rename them; the old name becomes the label

Dashboard

| Key | | | ----------- | ----------------------------------- | | type | filter · tab switches to the list | | ↵ | connect | | a e d | add · edit · remove | | s f | sftp session · file browser | | y p | copy ssh <alias> · set a password | | space | collapse a group | | ? | all keys |

The footer is clickable, rows select on click and connect on double-click.

File browser — f

┌ local  ~/project/release ─────────┐    ┌ nas  /srv/www ────────────────────┐
│ ~/project/release▮                │    │ /srv/www                          │
└───────────────────────────────────┘    └───────────────────────────────────┘
┌───────────────────────────────────┐    ┌───────────────────────────────────┐
│    ../                            │    │    ../                            │
│    assets/                        │ →  │    assets/                        │
│ ✓  app-2.1.0.tar.gz               │    │    app-2.0.4.tar.gz               │
│ ✓  checksums.txt                  │ ←  │    index.html                     │
│  ❯ notes.md                       │    │    robots.txt                     │
└───────────────────────────────────┘    └───────────────────────────────────┘
████████████░░░░░░░░ 62%  4.1MB / 6.6MB
tab pane · ↑↓ move · ↵ open · - up · space mark · → upload · ← download · p path · r refresh · q close

Local on the left, remote on the right. space marks (✓), → uploads what the left pane has selected, ← downloads from the right — and both arrows are clickable. With nothing marked, the row under the cursor is the one that moves.

↵ or a double-click opens a directory, ../ walks up, and the path boxes take typed input including ~. Directories transfer whole. Local changes appear as they happen; the remote side refreshes after a transfer or on r.

One multiplexed ssh connection serves the session, so changing directory costs a round trip rather than a reconnect.

Passwordless

omssh key setup           # device key, loaded into the agent
omssh key deploy --all    # each host's password, one last time

Or keep the password instead — omssh seals it to this device and hands it to ssh on demand, leaving nothing on the server:

omssh password set nas

Where things live

~/.config/oh-my-ssh/vault.json    hosts, no secrets
~/.config/oh-my-ssh/secrets.json  passwords, sealed
~/.config/oh-my-ssh/device.key    X25519 private key
~/.local/share/oh-my-ssh/install.key
~/.ssh/config.d/omssh.conf        generated, rewritten on every change

Passwords are sealed with X25519 + ChaCha20-Poly1305. Both the device key and the install key are required to decrypt, and they sit in different directories. Crypto is node:crypto only — no native modules.

Security

What it does: keeps passwords out of prompts, shell history, process arguments and agent transcripts; writes nothing to the remote host; and refuses to answer host-key questions, so a man-in-the-middle cannot collect a stored password by presenting an unknown key.

What it does not do: protect against code running as your user. Unattended decryption and resistance to local code execution cannot both hold — if the machine can decrypt without a human, so can anything running on it. That includes AI agents, which are ordinary code with your privileges.

Status

A personal project, offered as-is. No SLA.

Apache-2.0