dsh-remote-tunnel-easy 1.4.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/LICENSE +21 -0
- package/README.md +166 -0
- package/assets/logo.svg +81 -0
- package/cordis.patch.yml +12 -0
- package/index.js +792 -0
- package/lib/client.js +617 -0
- package/lib/cloudflared.js +196 -0
- package/lib/qrcode.js +591 -0
- package/lib/update.js +221 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Raiyan007-gb
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# dsh-remote-tunnel-easy
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="assets/logo.svg" alt="dsh-remote-tunnel-easy" width="800">
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
**Open your DeepSeek Harness session on your phone — by pointing the camera at it.**
|
|
10
|
+
|
|
11
|
+
Scan the QR in **Settings → Plugins** and the harness opens in your phone's
|
|
12
|
+
browser, *inside the session you are already working in*. Same workspace, same
|
|
13
|
+
chat. No typing a URL. The `dsh web` terminal prints nothing.
|
|
14
|
+
|
|
15
|
+
[](LICENSE)
|
|
16
|
+
[](https://github.com/Raiyan007-gb/dsh-remote-tunnel-easy/stargazers)
|
|
17
|
+
[](https://github.com/Raiyan007-gb/dsh-remote-tunnel-easy/releases)
|
|
18
|
+
[](https://www.npmjs.com/package/dsh-remote-tunnel-easy)
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
A one-command **DeepSeek Harness web bundle** that brings QR-based remote
|
|
23
|
+
handoff to the Settings page. It starts a `cloudflared` quick tunnel, loops
|
|
24
|
+
your phone into the exact session the desktop is using, and draws the QR code
|
|
25
|
+
plus settings right next to your other plugins — no terminal noise, no
|
|
26
|
+
database, no Firebase, no app install.
|
|
27
|
+
|
|
28
|
+
- **Scan to open** — a real QR code in **Settings → Plugins**, fresh every run
|
|
29
|
+
- **Same session** — the phone lands inside the chat and workspace you are already in
|
|
30
|
+
- **Self-installing** — detects `cloudflared`, and downloads it (SHA-256 verified) when missing
|
|
31
|
+
- **Regenerate** — one click mints a fresh tunnel URL for the same session, without restarting
|
|
32
|
+
- **Editable settings** — tunnel target, `cloudflared` path, and session handoff from the page
|
|
33
|
+
- **Nothing stored** — the tunnel URL is random per run; nothing is saved anywhere
|
|
34
|
+
- **Everywhere** — Windows (x64/x86), macOS (Intel/Apple Silicon), and Linux (x64/arm64)
|
|
35
|
+
|
|
36
|
+
## At a Glance
|
|
37
|
+
|
|
38
|
+
| Question | Answer |
|
|
39
|
+
|----------|--------|
|
|
40
|
+
| **What is it?** | A `dsh` bundle that shows a scannable QR code and access link in the Settings page, so a phone opens the harness inside the active session. |
|
|
41
|
+
| **Who is it for?** | Anyone running `dsh web` who wants their phone on the same session without typing tunnel URLs and tokens. |
|
|
42
|
+
| **What do I get?** | A loopback edge proxy, a `cloudflared` quick tunnel, same-session handoff, and a live QR + settings card in **Settings → Plugins**. |
|
|
43
|
+
| **What does it run on?** | Windows, macOS, and Linux — anything `dsh` runs on. |
|
|
44
|
+
| **Is cloud required?** | No account or signup. `cloudflared` is used, and auto-downloaded on first run when missing; the tunnel is public, and the token in the link is the gate. |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Get Started
|
|
49
|
+
|
|
50
|
+
Run `dsh web` once so a profile exists — that is the only prerequisite.
|
|
51
|
+
`cloudflared` is no longer something you install by hand: on first tunnel start
|
|
52
|
+
the bundle probes your `PATH`, and when no `cloudflared` is found it downloads
|
|
53
|
+
the official pinned binary (SHA-256 verified), caches it under your user cache
|
|
54
|
+
directory, and reuses it from then on. Prefer your own install? Put it on
|
|
55
|
+
`PATH`, or set the **cloudflared path** field in the card to an absolute path —
|
|
56
|
+
an explicit path disables both probing and downloading.
|
|
57
|
+
|
|
58
|
+
The simplest path — install from the npm registry with the plugin name:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
dsh plugin --profile web add dsh-remote-tunnel-easy@latest --config.minimumReleaseAge=0
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The `--config.minimumReleaseAge=0` flag bypasses pnpm's ~24-hour release-age
|
|
65
|
+
gate, so a freshly published version installs immediately. Without it, a plain
|
|
66
|
+
`dsh plugin --profile web add dsh-remote-tunnel-easy` still works but may hold off
|
|
67
|
+
until the freshness window lapses.
|
|
68
|
+
|
|
69
|
+
Or, if you prefer, install straight from the GitHub repository URL:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
dsh plugin --profile web add https://github.com/Raiyan007-gb/dsh-remote-tunnel-easy
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For a local checkout instead, clone it and add the folder:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
git clone https://github.com/Raiyan007-gb/dsh-remote-tunnel-easy
|
|
79
|
+
dsh plugin --profile web add \./dsh-remote-tunnel-easy
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
These initialize the profile if needed, link the package, and register the
|
|
83
|
+
bundle. No build step — the package ships plain ESM with **zero runtime
|
|
84
|
+
dependencies** (the QR encoder and cloudflared resolver are vendored in-tree),
|
|
85
|
+
so `add` and `remove` stay fast and never run install scripts.
|
|
86
|
+
|
|
87
|
+
> **Security note:** installing from a git URL asks for permission to run the
|
|
88
|
+
> package's install scripts. This package has none (plain ESM, no
|
|
89
|
+
> `postinstall`), but pin a commit — `#<sha>` on the URL — to freeze what runs.
|
|
90
|
+
> To skip install permissions entirely, `pnpm pack` a tarball and
|
|
91
|
+
> `dsh plugin --profile web add ./dsh-remote-tunnel-easy-1.1.0.tgz`.
|
|
92
|
+
|
|
93
|
+
Then **restart** `dsh web` — the QR and settings appear on **Settings →
|
|
94
|
+
Plugins → DSH Remote** on every start.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## What it does
|
|
99
|
+
|
|
100
|
+
On every `dsh web` start the bundle:
|
|
101
|
+
|
|
102
|
+
1. Spawns a loopback edge proxy (127.0.0.1, ephemeral port) that forwards every
|
|
103
|
+
request and WebSocket upgrade to the harness, rewriting `Host` and `Origin`
|
|
104
|
+
to the loopback authority. This is what makes the harness's `/api`
|
|
105
|
+
browser-trust fence accept tunneled traffic — the fence requires
|
|
106
|
+
`Origin == Host`, and a phone's `Origin` is the tunnel hostname, which
|
|
107
|
+
`--http-host-header` rewriting alone can never satisfy. Without the proxy
|
|
108
|
+
the app loads but every API call 403s.
|
|
109
|
+
2. Locates `cloudflared` — the configured **cloudflared path** override, else a
|
|
110
|
+
binary on `PATH`, else a pinned download (`2026.8.2`) SHA-256 verified and
|
|
111
|
+
cached under the user cache directory. It then spawns
|
|
112
|
+
`cloudflared tunnel --no-autoupdate --url http://127.0.0.1:<proxy-port>`
|
|
113
|
+
pointed at that proxy.
|
|
114
|
+
3. Waits for cloudflared to print the random `https://<name>.trycloudflare.com` URL.
|
|
115
|
+
4. Resolves this process's launch token via the harness connection service
|
|
116
|
+
(`authenticatedUrl` — the same mint the console line prints).
|
|
117
|
+
5. Seeds the most recently active session id into every served index page (via
|
|
118
|
+
the webserver's index-injection table), gated to non-loopback origins and
|
|
119
|
+
once per tab — so any tunnel entry lands inside the session the desktop is
|
|
120
|
+
working in. The id is resolved on the Host at render time (cached, refreshed
|
|
121
|
+
every 15s); the phone makes no `/api` call for the seed itself.
|
|
122
|
+
6. Registers a token-gated `/remote-handoff` route as a fallback entry path:
|
|
123
|
+
same seeding, then the normal token→cookie login (SHA-256 constant-time
|
|
124
|
+
compare). Prefix-matched, so `/remote-handoff` and `/remote-handoff/` both work.
|
|
125
|
+
7. Registers a `remote-handoff` settings namespace and a loopback-only bridge
|
|
126
|
+
(`/api/dsh-remote-handoff-settings`). The card in **Settings → Plugins →
|
|
127
|
+
DSH Remote** reads the tunnel status (QR matrix + access link) from that
|
|
128
|
+
bridge and draws them in the page, alongside the editable `tunnelTarget` /
|
|
129
|
+
`cloudflaredPath` / `sessionHandoff` settings. The **Regenerate** button
|
|
130
|
+
restarts the tunnel in place for a brand-new URL on the same session, and an
|
|
131
|
+
empty **tunnel target** auto-fills the harness's own loopback address. The
|
|
132
|
+
`dsh web` terminal prints nothing.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Requirements
|
|
137
|
+
|
|
138
|
+
- No manual `cloudflared` install — downloaded automatically when missing
|
|
139
|
+
(Windows x64/x86, macOS Intel/Apple Silicon, Linux x64/arm64); any other
|
|
140
|
+
platform needs a `cloudflared` on `PATH` or an explicit **cloudflared path**.
|
|
141
|
+
- Network access on first run (to reach GitHub for the binary download)
|
|
142
|
+
- Node — already present where `dsh` runs
|
|
143
|
+
- Phone on any network — the tunnel is public; the token in the URL is the only
|
|
144
|
+
gate, so treat the shown link like a password.
|
|
145
|
+
|
|
146
|
+
## Removing
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
dsh plugin --profile web remove dsh-remote-tunnel-easy
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
and restart `dsh web`.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT — use it, modify it, ship it. See [LICENSE](LICENSE).
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
<div align="center">
|
|
163
|
+
|
|
164
|
+
*Built for the [DeepSeek Harness](https://github.com/Raiyan007-gb) — scan, open, keep working.*
|
|
165
|
+
|
|
166
|
+
</div>
|
package/assets/logo.svg
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="880" height="200" viewBox="0 0 880 200" role="img" aria-label="dsh-remote-tunnel-easy">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="wc" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#0c1229"/>
|
|
5
|
+
<stop offset="1" stop-color="#221a4e"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="wa" x1="0" y1="0" x2="1" y2="0">
|
|
8
|
+
<stop offset="0" stop-color="#6b8cff"/>
|
|
9
|
+
<stop offset="1" stop-color="#b887ff"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
</defs>
|
|
12
|
+
|
|
13
|
+
<rect x="0" y="0" width="880" height="200" rx="26" fill="url(#wc)"/>
|
|
14
|
+
<rect x="0.5" y="0.5" width="879" height="199" rx="25.5" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="1"/>
|
|
15
|
+
|
|
16
|
+
<rect x="36" y="36" width="128" height="128" rx="22" fill="#ffffff"/>
|
|
17
|
+
|
|
18
|
+
<g fill="#101c33">
|
|
19
|
+
<rect x="48" y="48" width="35" height="35" rx="4"/>
|
|
20
|
+
<rect x="53" y="53" width="25" height="25" rx="3" fill="#ffffff"/>
|
|
21
|
+
<rect x="58" y="58" width="15" height="15" rx="2"/>
|
|
22
|
+
<rect x="118" y="48" width="35" height="35" rx="4"/>
|
|
23
|
+
<rect x="123" y="53" width="25" height="25" rx="3" fill="#ffffff"/>
|
|
24
|
+
<rect x="128" y="58" width="15" height="15" rx="2"/>
|
|
25
|
+
<rect x="48" y="118" width="35" height="35" rx="4"/>
|
|
26
|
+
<rect x="53" y="123" width="25" height="25" rx="3" fill="#ffffff"/>
|
|
27
|
+
<rect x="58" y="128" width="15" height="15" rx="2"/>
|
|
28
|
+
<rect x="88" y="78" width="5" height="5"/>
|
|
29
|
+
<rect x="98" y="78" width="5" height="5"/>
|
|
30
|
+
<rect x="108" y="78" width="5" height="5"/>
|
|
31
|
+
<rect x="78" y="88" width="5" height="5"/>
|
|
32
|
+
<rect x="78" y="98" width="5" height="5"/>
|
|
33
|
+
<rect x="78" y="108" width="5" height="5"/>
|
|
34
|
+
<rect x="88" y="53" width="5" height="5" fill="#101c33"/>
|
|
35
|
+
<rect x="103" y="58" width="5" height="5" fill="#101c33"/>
|
|
36
|
+
<rect x="93" y="63" width="5" height="5" fill="#101c33"/>
|
|
37
|
+
<rect x="108" y="68" width="5" height="5" fill="#101c33"/>
|
|
38
|
+
<rect x="88" y="73" width="5" height="5" fill="#101c33"/>
|
|
39
|
+
<rect x="108" y="53" width="5" height="5" fill="#101c33"/>
|
|
40
|
+
<rect x="113" y="63" width="5" height="5" fill="#101c33"/>
|
|
41
|
+
<rect x="98" y="73" width="5" height="5" fill="#101c33"/>
|
|
42
|
+
<rect x="58" y="83" width="5" height="5" fill="#101c33"/>
|
|
43
|
+
<rect x="68" y="88" width="5" height="5" fill="#101c33"/>
|
|
44
|
+
<rect x="53" y="93" width="5" height="5" fill="#101c33"/>
|
|
45
|
+
<rect x="63" y="98" width="5" height="5" fill="#101c33"/>
|
|
46
|
+
<rect x="73" y="103" width="5" height="5" fill="#101c33"/>
|
|
47
|
+
<rect x="58" y="108" width="5" height="5" fill="#101c33"/>
|
|
48
|
+
<rect x="108" y="83" width="5" height="5" fill="#101c33"/>
|
|
49
|
+
<rect x="93" y="88" width="5" height="5" fill="#101c33"/>
|
|
50
|
+
<rect x="103" y="93" width="5" height="5" fill="#101c33"/>
|
|
51
|
+
<rect x="88" y="98" width="5" height="5" fill="#101c33"/>
|
|
52
|
+
<rect x="113" y="103" width="5" height="5" fill="#101c33"/>
|
|
53
|
+
<rect x="98" y="108" width="5" height="5" fill="#101c33"/>
|
|
54
|
+
<rect x="53" y="113" width="5" height="5" fill="#101c33"/>
|
|
55
|
+
<rect x="128" y="83" width="5" height="5" fill="#101c33"/>
|
|
56
|
+
<rect x="138" y="88" width="5" height="5" fill="#101c33"/>
|
|
57
|
+
<rect x="123" y="93" width="5" height="5" fill="#101c33"/>
|
|
58
|
+
<rect x="143" y="98" width="5" height="5" fill="#101c33"/>
|
|
59
|
+
<rect x="133" y="103" width="5" height="5" fill="#101c33"/>
|
|
60
|
+
<rect x="128" y="108" width="5" height="5" fill="#101c33"/>
|
|
61
|
+
<rect x="148" y="113" width="5" height="5" fill="#101c33"/>
|
|
62
|
+
<rect x="88" y="123" width="5" height="5" fill="#101c33"/>
|
|
63
|
+
<rect x="103" y="128" width="5" height="5" fill="#101c33"/>
|
|
64
|
+
<rect x="93" y="133" width="5" height="5" fill="#101c33"/>
|
|
65
|
+
<rect x="108" y="138" width="5" height="5" fill="#101c33"/>
|
|
66
|
+
<rect x="98" y="143" width="5" height="5" fill="#101c33"/>
|
|
67
|
+
<rect x="128" y="123" width="5" height="5" fill="#101c33"/>
|
|
68
|
+
<rect x="138" y="128" width="5" height="5" fill="#101c33"/>
|
|
69
|
+
<rect x="123" y="133" width="5" height="5" fill="#101c33"/>
|
|
70
|
+
<rect x="143" y="138" width="5" height="5" fill="#101c33"/>
|
|
71
|
+
<rect x="88" y="148" width="5" height="5" fill="#101c33"/>
|
|
72
|
+
<rect x="113" y="148" width="5" height="5" fill="#101c33"/>
|
|
73
|
+
<rect x="133" y="143" width="5" height="5" fill="#101c33"/>
|
|
74
|
+
<rect x="83" y="118" width="5" height="5" fill="#101c33"/>
|
|
75
|
+
<rect x="118" y="118" width="5" height="5" fill="#101c33"/>
|
|
76
|
+
</g>
|
|
77
|
+
|
|
78
|
+
<text x="196" y="88" font-family="Segoe UI, -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif" font-size="46" font-weight="700" fill="#f6f7ff" letter-spacing="0.5">dsh-remote-tunnel-easy</text>
|
|
79
|
+
<text x="198" y="122" font-family="Segoe UI, -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif" font-size="17" fill="#aeb9ff">Remote access for DeepSeek Harness — scan, open, keep working.</text>
|
|
80
|
+
<rect x="198" y="138" width="86" height="5" rx="2.5" fill="url(#wa)"/>
|
|
81
|
+
</svg>
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Bundle patch for dsh-remote-tunnel-easy: starts a cloudflared quick tunnel and
|
|
2
|
+
# publishes its access link and QR code to the Settings → Plugins page (the
|
|
3
|
+
# `dsh web` terminal prints nothing), and seeds the app's persisted session
|
|
4
|
+
# selection so a phone scan lands in the harness's most recently active
|
|
5
|
+
# session. No database, no Firebase, no persisted state — the link is
|
|
6
|
+
# regenerated fresh each run.
|
|
7
|
+
|
|
8
|
+
- insert:
|
|
9
|
+
- id: dsh-remote-tunnel-easy
|
|
10
|
+
name: 'dsh-remote-tunnel-easy'
|
|
11
|
+
config:
|
|
12
|
+
sessionHandoff: true
|