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

pi-local2ssh

v0.1.1

Published

A pi extension that lets the local agent transparently operate on remote machines over SSH — read, write, edit, bash, ls, grep, and find all routed through a persistent ControlMaster connection.

Readme

pi-local2ssh

Let the local pi agent operate on a remote machine over SSH transparently — once connected, every read, write, edit, bash, ls, grep, and find call is automatically routed to the remote host. You barely have to think about the fact that you are working remotely.


Quick Start

Inside pi, type:

/ssh                          # interactive host picker
/ssh ubuntu.orb.local         # direct connect (reads ~/.ssh/config)
/ssh [email protected]      # direct connect (ad-hoc user@host)
/ssh ubuntu.orb.local:~/code/myapp    # connect and switch to remote cwd

After that, every tool the LLM invokes runs on the remote. Use /ssh off to disconnect back to local.

Commands

| Command | Description | |---------|-------------| | /ssh | Interactive host picker (from SSH config + custom JSON) | | /ssh <alias\|user@host> | Direct connect | | /ssh <alias\|user@host>:/path | Direct connect and switch remote cwd | | /ssh cd [path] | Switch remote cwd (interactive picker when no arg) | | /ssh pwd | Show remote cwd | | /ssh hosts | List all available hosts | | /ssh status | Current connection status | | /ssh off (aliases: disconnect, local) | Disconnect back to local | | /ssh help | Help |

Host Sources

Resolved in priority order:

1. ~/.pi/agent/ssh-remote.json (recommended)

Most readable; supports groups. Example:

{
  "hosts": [
    { "name": "dev-server", "target": "[email protected]", "path": "/srv/myapp" },
    { "name": "gpu-box",    "target": "[email protected]",           "path": "/home/ai/projects" }
  ],
  "groups": {
    "staging": [
      { "name": "stage-1", "target": "[email protected]", "path": "/var/www" }
    ]
  }
}

Each host may also set forwardX11, forwardAgent, and portForwards ([{ "remotePort": 8080, "localHost": "127.0.0.1", "localPort": 3000 }]).

2. ~/.ssh/config

Auto-reads every Host <name> entry, recognizing Hostname, User, Port, ForwardX11, ForwardAgent. Wildcard hosts like Host * are ignored.

Status

  • Status-bar widget shows the live connection: ⇄ dev-server @ /home/ai/projects, or stays empty in local mode
  • Run /ssh status for full details
  • System prompt is auto-augmented so the LLM knows "we are remote" and resolves relative paths against <remoteCwd>

Transparent Tool Forwarding

| Tool | In remote mode | |------|----------------| | read, write, edit | cat / base64 / chunked writes over SSH | | bash (including !bang user commands) | ssh <host> 'cd <rcwd> && <cmd>' with live streaming output | | ls, find, grep | Runs stat / ls / rg / fd on the remote; results mapped back to local-view paths | | grep | Uses remote rg (ripgrep). Supports context lines. | | find | Uses remote fd (preferred), falls back to find -name. | | Image detectImageMimeType | Remote file --mime-type |

The LLM never has to be aware it is on a remote. The only signal is a line in the system prompt noting the cwd is a remote path.

Binary I/O

All binary read/write goes through base64 chunked transfer — safe for any binary content. writeFile automatically mkdir -ps parent directories.

Example Session

> /ssh ubuntu.orb.local
✓ Connected ubuntu.orb.local @ /home/shingbd

> Show me package.json in ~/myapp
(LLM invokes read tool → reads /home/shingbd/myapp/package.json)

> Change scripts.test to "vitest run"
(LLM invokes edit tool → writes the remote file)

> /ssh cd myapp/src
✓ cd → /home/shingbd/myapp/src

> Run npm test
(LLM invokes bash tool → ssh ubuntu.orb.local 'cd /home/shingbd/myapp/src && npm test')

> /ssh off
Disconnected SSH. Local cwd: /Users/shingbd/...

Path Semantics

  • System prompt injects <remoteCwd> as the cwd
  • LLM-relative paths → resolved against <remoteCwd>
  • Local absolute paths (under the session's original local cwd) → mapped to <remoteCwd>
  • Absolute paths outside both cwds → passed through (for reading /etc/hosts, etc.)

Tip: If the LLM reports "file not found" after switching to remote mode, it is probably using an absolute local path. Use a relative path instead.

Failure Handling

  • Connection failure → TUI error toast, stays in local mode
  • Command timeout → error returned to the LLM so it can retry
  • SSH child interrupted → upstream AbortSignal propagates to the child
  • Output too large → > 100 MB auto-kills the child to prevent OOM

Performance / Limits

  • Large file read/write chunked via base64 (1024 bytes per chunk)
  • grep parses ripgrep JSON output, streamed (does not affect LLM-side truncation)
  • find uses fd, falls back to find + grep -E
  • bash is fully streaming (long-running outputs are fine)

Requirements

  • SSH key-based auth (password auth will hang)
  • Remote POSIX basics: cat, test, stat, mkdir, printf, base64
  • Recommended on remote (for search): ripgrep (rg), fd-find (fd)
  • Tested on macOS / Linux / WSL

Installation

npm install pi-local2ssh

Then enable it in your pi config (e.g. ~/.pi/agent/extensions.json):

{
  "extensions": [
    "pi-local2ssh"
  ]
}

Pi will dynamically import("pi-local2ssh") and activate the /ssh command. The extension's read/write/edit/bash/ls/grep/find tools will override the built-in ones while connected to a remote host.

Try without installing

If you'd rather not install globally, you can also load it from a local clone:

{
  "extensions": [
    "/absolute/path/to/pi-local2ssh/index.ts"
  ]
}

File Locations

~/.pi/agent/extensions/pi-local2ssh/   # (when loaded from local source)
~/.pi/agent/ssh-remote.json            # (optional) custom host config

FAQ

Q: After switching to remote mode the LLM keeps saying files don't exist? A: Check /ssh status to confirm the cwd. The LLM may be using an absolute local path; switch to relative.

Q: Want to use a jump host? A: Use ProxyJump in ~/.ssh/config, then /ssh <alias>.

Q: How do I make a host always start in a specific directory? A: Set path for that host in ~/.pi/agent/ssh-remote.json.

Q: Do I have to reconnect every time pi restarts? A: Yes — connection state is module-level. It persists across the session but resets on pi restart.

License

MIT