@hahahhh/sshx 0.0.5 → 0.0.6-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> Transparent SSH enhancement — add remote-to-local commands, auto port forwarding, and local domains to your SSH workflow. Zero side effects when you don't need them.
|
|
4
4
|
|
|
5
|
-
**sshx** is a drop-in wrapper around OpenSSH. Wrap it as `alias ssh=sshx` and your existing SSH workflow works exactly as before — every flag, config, and connection passes through verbatim. But when you connect to a host (or Docker container) with sshx-aware features enabled, you unlock a
|
|
5
|
+
**sshx** is a drop-in wrapper around OpenSSH. Wrap it as `alias ssh=sshx` and your existing SSH workflow works exactly as before — every flag, config, and connection passes through verbatim. But when you connect to a host (or Docker container) with sshx-aware features enabled, you unlock a connection-scoped shared remote server that gives you:
|
|
6
6
|
|
|
7
7
|
- 🔄 **Reverse command bridge** — run `sshx local <cmd>` *on the remote* to execute commands on your local machine, with stdout, stderr, exit code, and stdin all propagated.
|
|
8
|
-
- 📁 **
|
|
8
|
+
- 📁 **Remote-to-local filesystem** — opt in to let local tools work directly with files from the active remote session.
|
|
9
9
|
- 🔌 **Automatic port forwarding** — remote local listeners (loopback `127.0.0.1` and wildcard `0.0.0.0`; e.g., a dev server on `0.0.0.0:8080` or `localhost:8080`) are automatically detected and forwarded to your local machine.
|
|
10
10
|
- 🌐 **Local domain binding** — access forwarded ports as `<host>.<your-user>.sshx:<port>` in your local browser, no manual `-L` flags needed.
|
|
11
11
|
- 🐳 **Docker container support** — target running containers by name or ID: `sshx my-container`. Command bridge support works inside containers via `docker exec`.
|
|
@@ -24,6 +24,14 @@ sshx is designed to be **safe to alias**. Hosts without sshx configuration are u
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
+
## Architecture
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+
|
|
31
|
+
Each user-visible session remains a normal OpenSSH connection (or a `docker exec` session for container targets). One hidden multiplexed sidecar channel carries control and optional RemoteFS traffic to a shared target-side server, while one on-demand local daemon owns DNS records and TCP forwards across active client terminals. Automatic port forwarding uses SSH `direct-tcpip`; Docker targets support shells and the command bridge but do not use automatic port scanning.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
27
35
|
## Features
|
|
28
36
|
|
|
29
37
|
### 📦 Drop-in Compatibility
|
|
@@ -60,17 +68,17 @@ sshx local --timeout=30 npm test
|
|
|
60
68
|
- Commands have no implicit deadline. Put `--timeout=<duration>` immediately after the target to opt in; bare numbers mean seconds, and values such as `500ms`, `30s`, and `2m` are accepted. Timed-out commands exit with status 124.
|
|
61
69
|
- Policy: a configurable deny list controls which commands are blocked.
|
|
62
70
|
|
|
63
|
-
### 📁
|
|
71
|
+
### 📁 Remote-to-Local Filesystem (opt-in, beta)
|
|
64
72
|
|
|
65
|
-
Set `features.remoteFs: true` to
|
|
73
|
+
Set `features.remoteFs: true` to let a command launched with `sshx local <cmd>` access the remote working tree through a local FUSE mount:
|
|
66
74
|
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
75
|
+
- The remote home is exported lazily on the first local command. A working directory outside the remote home creates a separate lazy export for that root.
|
|
76
|
+
- The local command starts at the corresponding mounted working directory. Absolute command arguments are not rewritten.
|
|
77
|
+
- Mounts are reused for the sidecar session, so detached tools such as `open` and `code` can continue reading files after the bridge request returns.
|
|
78
|
+
- Local files are never exported or mounted on the remote host.
|
|
79
|
+
- With RemoteFS disabled, the command runs from the local home and receives `SSHX_REMOTE_CWD` plus `SSHX_REMOTE_FS=0`.
|
|
72
80
|
|
|
73
|
-
The mounted
|
|
81
|
+
The mounted remote tree permits reads, writes, and creation, but blocks file/directory deletion and rename. It can include sensitive remote files such as shell configuration and SSH credentials, so enable `remoteFs` only for targets you trust.
|
|
74
82
|
|
|
75
83
|
Set `FS_READ_ONLY=1` on the client when starting sshx to make the session mounts read-only:
|
|
76
84
|
|
|
@@ -78,15 +86,15 @@ Set `FS_READ_ONLY=1` on the client when starting sshx to make the session mounts
|
|
|
78
86
|
FS_READ_ONLY=1 sshx debian@orb pwd
|
|
79
87
|
```
|
|
80
88
|
|
|
81
|
-
The
|
|
89
|
+
The value is exported into the remote session, and later `sshx local <cmd>` mounts remain read-only.
|
|
82
90
|
|
|
83
|
-
FUSE is
|
|
91
|
+
FUSE is required only on the local machine receiving the mounted remote tree. A mount failure fails that `sshx local` invocation instead of running it from the wrong directory. Linux needs `/dev/fuse` plus `fusermount`/`fusermount3`; macOS needs a current macFUSE installation and is currently beta.
|
|
84
92
|
|
|
85
93
|
#### FUSE setup
|
|
86
94
|
|
|
87
|
-
The machine receiving the mounted view needs a working FUSE runtime. The
|
|
95
|
+
The local machine receiving the mounted view needs a working FUSE runtime. The remote Linux host exports files through the sshx protocol and does not need FUSE.
|
|
88
96
|
|
|
89
|
-
**Linux
|
|
97
|
+
**Linux client**
|
|
90
98
|
|
|
91
99
|
Install the FUSE 3 userspace tools (the kernel normally already includes the FUSE driver):
|
|
92
100
|
|
|
@@ -153,12 +161,13 @@ The URL port is the remote port. sshx does not bind `127.0.0.1:<port>`; it binds
|
|
|
153
161
|
|
|
154
162
|
### 🏗️ Shared Server Architecture
|
|
155
163
|
|
|
156
|
-
-
|
|
157
|
-
- Client connects
|
|
164
|
+
- Compatible runtime daemons live under `~/.sshx_server/targets/<TargetID>/runtimes/<RuntimeID>` and serve multiple application contexts and sessions.
|
|
165
|
+
- Client connects through one hidden multiplexed sidecar SSH channel.
|
|
158
166
|
- Server manages port sniffing, forwarding state, and command bridge routing centrally.
|
|
159
167
|
- Clients renew local and remote leases every 5 seconds. A daemon expires a client after 15 seconds without a heartbeat.
|
|
160
|
-
- The local daemon
|
|
161
|
-
-
|
|
168
|
+
- The on-demand local daemon and remote server keep a 10-second handoff window after their last lease, then exit.
|
|
169
|
+
- AppVersion is diagnostic only. Compatible clients coexist; incompatible RuntimeIDs use separate directories and daemons.
|
|
170
|
+
- `ClientInstallID` is stable across upgrades; `TargetID` identifies normalized OpenSSH destinations, `ContextID` identifies stable application contexts, and every live sidecar gets a fresh `SessionID`.
|
|
162
171
|
|
|
163
172
|
---
|
|
164
173
|
|
|
@@ -181,6 +190,19 @@ npm install -g @hahahhh/sshx
|
|
|
181
190
|
|
|
182
191
|
The npm wrapper auto-downloads the correct native binary for your platform from GitHub Releases.
|
|
183
192
|
|
|
193
|
+
### VS Code / Cursor Remote SSH
|
|
194
|
+
|
|
195
|
+
Install the CLI normally, then run the single integration command for each application you use:
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
sshx integrate install vscode
|
|
199
|
+
sshx integrate install cursor
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The command locates OpenSSH, installs paired `ssh`/`scp` shims backed by the same sshx binary, patches JSONC `remote.SSH.path`, and verifies the complete invocation chain. It is idempotent and rolls back settings and shims on failure; run it again to repair the integration after moving the sshx executable. No restart, integration-specific configuration, or extra binary is required.
|
|
203
|
+
|
|
204
|
+
Remote-SSH remains the user-visible OpenSSH connection. sshx creates a temporary ControlMaster so bootstrap, sidecar, forwarding, and scp reuse the same authentication. Only a stable `SSHX_CONTEXT_ID` and context-launcher path are injected into application terminals. Probe, unknown, and ambiguous calls are exact passthrough; an incompatible or failed sidecar receives the original bootstrap bytes and preserves normal OpenSSH behavior regardless of `strict`.
|
|
205
|
+
|
|
184
206
|
### Download Binary
|
|
185
207
|
|
|
186
208
|
Download the prebuilt binary directly from [GitHub Releases](https://github.com/xiaot623/sshx/releases):
|
|
@@ -292,8 +314,8 @@ features:
|
|
|
292
314
|
# <host>.<user>.sshx:<remote-port>.
|
|
293
315
|
autoForward: true
|
|
294
316
|
|
|
295
|
-
#
|
|
296
|
-
# Requires FUSE on the local machine
|
|
317
|
+
# Lazily mount remote files for local commands. Default: false.
|
|
318
|
+
# Requires FUSE only on the local machine.
|
|
297
319
|
remoteFs: false
|
|
298
320
|
|
|
299
321
|
commands:
|
|
@@ -319,8 +341,8 @@ commands:
|
|
|
319
341
|
└─────────────────────────────────┘ └─────────────────────────────────┘
|
|
320
342
|
```
|
|
321
343
|
|
|
322
|
-
1. **Connection**: `sshx remote` opens a normal SSH session and starts
|
|
323
|
-
2. **
|
|
344
|
+
1. **Connection**: `sshx remote` opens a normal SSH session and starts a compatible runtime under `~/.sshx_server/targets/<TargetID>/runtimes/<RuntimeID>`.
|
|
345
|
+
2. **Sidecar channel**: One hidden SSH channel multiplexes command, port, heartbeat, and optional RemoteFS traffic. ContextID routes VS Code/Cursor terminals to a healthy live session.
|
|
324
346
|
3. **Port sniffing**: The server reads `/proc/net/tcp*` (Linux) to detect loopback (`127.0.0.1` / `::1`) and wildcard (`0.0.0.0` / `::`) listeners.
|
|
325
347
|
4. **Forwarding**: Detected ports are forwarded through a single shared local daemon using `ssh -W`.
|
|
326
348
|
5. **Domains**: The local DNS responder maps `<target>.<suffix>` → localhost. The browser's URL port selects the local forwarded port.
|
|
@@ -335,7 +357,7 @@ When `sshx` is invoked for a **non-matching host** (no sshx config, or host not
|
|
|
335
357
|
- `SSHX_DISABLE=1 sshx ...` — same as `--no-wrap`, useful in scripts.
|
|
336
358
|
- `sshx local ...` on a **client** (not inside a remote session) — errors immediately with a clear message. `local` is globally reserved.
|
|
337
359
|
- `remoteFs` never silently falls back to an unmounted command. A failed FUSE mount fails the invocation.
|
|
338
|
-
-
|
|
360
|
+
- Remote exports are anchored with Go's `os.Root`; path traversal and symlink escapes are rejected.
|
|
339
361
|
- Docker containers that aren't running or can't be reached are pure passthrough — sshx falls back to raw `ssh` with no side effects.
|
|
340
362
|
- Unmatched hosts are pure passthrough — no files created, no processes started.
|
|
341
363
|
|
|
@@ -384,7 +406,7 @@ sshx/
|
|
|
384
406
|
|
|
385
407
|
- [x] **v1** — Command bridge (non-interactive), auto port forwarding, domain binding, shared server
|
|
386
408
|
- [ ] **v2** — Streaming stdin for command bridge, GitHub binary releases, Windows client support
|
|
387
|
-
- [x] **remoteFs beta** —
|
|
409
|
+
- [x] **remoteFs beta** — Lazy remote-to-local workspace mounting on Linux/macOS clients
|
|
388
410
|
|
|
389
411
|
---
|
|
390
412
|
|