A reusable pi package that adds a /port slash command for SSH local port forwarding.
It lists listening TCP ports on configured SSH remotes, shows the process name / PID when available, and lets you toggle forwards from inside pi.
- Configurable slash command name, default
/port - Multiple SSH remotes via
settings.json - Configurable allowed ports and port ranges
- Configurable local bind host, remote target host, SSH options, and local port offsets
- Interactive picker:
Spacetoggles the highlighted port and keeps the picker openEntertoggles the highlighted port and closesEsccloses
- Persistent
Forwarded portswidget above the input editor - Forwards are stopped when untoggled, when pi reloads/shuts down, or when the parent pi process disappears
- pi with extension/package support
- SSH access to each configured remote
- Key-based or otherwise non-interactive SSH auth; the extension uses
BatchMode=yes ssornetstaton the remote host- Free local ports for the forwards you start
After this package is published:
pi install npm:@zackify/pi-port-forwardThen reload pi:
/reload
Copy the extension into your global pi extensions directory:
mkdir -p ~/.pi/agent/extensions
cp index.ts ~/.pi/agent/extensions/pi-port-forward.tsOr install it only for one project:
mkdir -p .pi/extensions
cp index.ts .pi/extensions/pi-port-forward.tsThen add config to ~/.pi/agent/settings.json and reload pi.
The extension reads portForward from ~/.pi/agent/settings.json.
Minimal example using an SSH config alias named dev:
{
"portForward": {
"providers": [
{
"id": "dev",
"remote": "dev",
"label": "dev",
"allowedPorts": [3000, 5173, { "from": 8000, "to": 8999 }]
}
]
}
}Multiple remotes are supported:
{
"portForward": {
"command": "port",
"providers": [
{
"id": "dev",
"remote": "me@dev.example.com",
"label": "dev",
"allowedPorts": [3000, { "from": 8080, "to": 9000 }]
},
{
"id": "staging",
"remote": "staging",
"label": "staging",
"allowedPorts": [5173, { "from": 8000, "to": 8999 }]
}
]
}
}Avoid local port collisions with localPortOffset:
{
"portForward": {
"providers": [
{
"id": "dev",
"remote": "dev",
"allowedPorts": [3000]
},
{
"id": "staging",
"remote": "staging",
"allowedPorts": [3000],
"localPortOffset": 10000
}
]
}
}This maps dev:3000 to 127.0.0.1:3000 and staging:3000 to 127.0.0.1:13000.
| Field | Type | Default | Description |
|---|---|---|---|
command |
string | "port" |
Slash command name, with or without leading /. |
maxVisible |
number | 15 |
Maximum visible picker rows before scrolling. |
providers |
array | [] |
SSH remotes to scan. No personal default remote is configured. |
providers[].id |
string | derived from label | Stable unique provider ID used for forward state. |
providers[].remote |
string | required | SSH target, e.g. user@host or an SSH config alias. ssh is also accepted as an alias. |
providers[].label |
string | host part of remote | Display label. hostLabel is also accepted as an alias. |
providers[].allowedPorts |
array | [3000, {"from":8080,"to":9000}] |
Ports shown in the picker. Entries may be numbers or { "from": number, "to": number } ranges. |
providers[].localHost |
string | "127.0.0.1" |
Local bind address for ssh -L. |
providers[].remoteHost |
string | "127.0.0.1" |
Target host as seen from the remote SSH server. |
providers[].localPortOffset |
number | 0 |
Added to the remote port to choose the local port. Useful when two remotes expose the same port. |
providers[].sshOptions |
string[] | [] |
Extra arguments passed to ssh, for example ["-J", "jump-host"]. |
Reload pi after installing/configuring:
/reload
Then run:
/port
Use arrow keys to select a port. Press Space to toggle and keep the picker open, or Enter to toggle and close.
Only configure remotes you trust. The extension runs ssh <remote> "ss ... || netstat ..." to list listening ports and opens local SSH forwards. Use allowedPorts to limit what appears in the picker.
Forwards bind to 127.0.0.1 by default so they are only reachable from your local machine unless you explicitly change localHost.
- Check that the service is running on the remote.
- Check that its port is included in
allowedPorts. - Run
ssh <remote> 'ss -H -ltnp || netstat -ltnp'manually to verify output.
- Check SSH connectivity:
ssh <remote>. - Ensure non-interactive auth works. Password prompts fail because
BatchMode=yesis used. - Check SSH aliases in
~/.ssh/config.
- Stop the local process using that port, or configure
localPortOffsetfor that provider.
- Some systems hide process info from
ss/netstatunless run with elevated permissions. - The forward can still work even if the process name is unknown.
This repository includes a GitHub Actions workflow that publishes to npm when a GitHub release is created.
- Add an
NPM_TOKENrepository secret. - Create a GitHub release named like
v1.2.3or1.2.3. - The workflow sets
package.jsonto that version and runsnpm publish --provenance --access public.
index.ts— extension sourcepackage.json— pi package metadata for@zackify/pi-port-forward, including thepi-packagekeyword.github/workflows/publish.yml— npm publish workflow
