Bundle
dsh-web-url-view
Settings page that shows the Web GUI access URLs, including a stable fixed address that survives restarts and is reachable from other devices on the same LAN · 设置页「查看 URL」:显示长期不变的固定访问地址,局域网内其他设备也能直接打开
- Source
- 1032740078
- License
- MIT
- Updated
- Updated yesterday
Readme
# dsh-web-url-view
[](LICENSE)
[](https://github.com/deepseek-ai/deepseek-harness)
[](https://github.com/topics/dsh-plugin)
English | [中文](README.zh.md)
Adds a **View URL** page to the left menu of **Settings** in DSH Desktop
(DeepSeek Harness desktop) and in any `dsh web` GUI running the same profile.
The page shows two Web GUI addresses, and the fixed one is **stable across
restarts and reachable from other devices on the same LAN**.
- **Fixed address** (bookmark this): `http://<LAN-IP>:47524/`, e.g.
`http://192.168.1.88:47524/` — it stays the same no matter how often the
desktop restarts or how the port and launch token rotate.
- **Current address (one-time)**: the tokenized URL of the running session,
which changes on every desktop restart.
## Why it exists
The desktop picks a random Web port and a per-process launch token on every
start (the token is a replay-protection secret). The native URL therefore
changes constantly, so it cannot be bookmarked or kept on a phone. The token
should not — and cannot — be pinned, so this plugin pins the **entry point**
instead: an in-process fixed-port forwarder holds one stable address and
performs the authentication handshake against the current session by itself.
## Install
### 1. Plugin market (recommended, once listed)
```sh
dsh plugin --profile web add dshmarket
```
Restart, then search `web-url-view` in **Settings → Plugin Market** and install
with one click.
### 2. From GitHub
```sh
dsh plugin --profile web add github:1032740078/dsh-web-url-view
```
The repository ships **prebuilt artifacts** (`lib/`), so install runs no build
script (pnpm ≥10 blocks them by default anyway).
### 3. Local development
1. Edit `~/Library/Application Support/dsh-desktop/harness/profiles/web/package.json`:
- add to `dependencies` (use your own absolute path):
```json
"dsh-web-url-view": "link:/absolute/path/to/dsh-web-url-view"
```
- append `"dsh-web-url-view"` to `dsh.profile.bundles`
2. Quit and reopen DSH Desktop (startup heals the profile and applies the
bundle patch).
3. Open **Settings → View URL**.
## Verify the install
Open **Settings → View URL**; you should see two rows:
| Row | Expected |
| --- | --- |
| Fixed address | `http://<your-LAN-IP>:47524/`, unchanged after restarting the desktop |
| Current address (one-time) | `http://127.0.0.1:<random-port>/?token=<random>`, new on every restart |
Copy the fixed address onto your phone or another device on the same LAN — the
Web GUI should open.
## How it works
The **fixed address is an in-process fixed-port forwarder**
(`FixedEntryServer`), running entirely inside the plugin's host half:
- It binds `0.0.0.0:47524` (configurable) as a reverse proxy and advertises the
machine's LAN IP.
- It targets the CURRENT harness instance: on the first request it performs the
same `?token=` handshake a browser would, using the in-process launch token,
and holds the browser-session cookie internally — tokens and cookies never
leave the process or reach a browser.
- After a desktop restart the new harness process rebinds the SAME fixed port
and refreshes the session against the new launch token, so the address never
changes from a browser's point of view.
- Both plain HTTP and WebSocket upgrades (`/api/remote.mux`, the live session
channel) are forwarded; `Host`/`Origin` are rewritten per the harness trust
fence, and response `Set-Cookie` headers are absorbed by the forwarder so they
never pollute the browser's cookie jar.
- The one-time address still uses the original `webUrlView/current` RPC backed
by the host's `connection.authenticatedUrl()` — the same function the `dsh web`
supervisor uses to print its startup URL.
## Configuration (port / bind host / off switch)
Default fixed port `47524`, bound to `0.0.0.0` (all interfaces). To change the
port, restrict the bind, or disable the fixed address, override the row config in
the desktop profile's `cordis.patch.yml` and restart the desktop:
```yaml
- id: web-url-view
name: dsh-web-url-view
config:
# Fixed entry listen port; 0 disables the fixed address. Default 47524.
fixedPort: 47524
# Bind interface. Default 0.0.0.0 (all interfaces, LAN-reachable); use 127.0.0.1 for localhost only.
fixedHost: 0.0.0.0
```
| Option | Type | Default | Meaning |
| --- | --- | --- | --- |
| `fixedPort` | number | `47524` | Fixed entry listen port. `0` or an invalid value (>65535) disables the fixed address, leaving only the one-time address. |
| `fixedHost` | string | `0.0.0.0` | Fixed entry bind interface. `0.0.0.0` = all interfaces (LAN-reachable); `127.0.0.1` = localhost only. |
The LAN address is **auto-detected**: it prefers the IPv4 of the default-route
interface and skips loopback, link-local (`169.254.*`) and common virtual
interfaces (docker/veth/vmnet/utun/…). When nothing usable is found it falls
back to `127.0.0.1`, so localhost keeps working.
## Security boundary (important)
The fixed entry **holds a session cookie inside the proxy**, therefore:
- With the default `0.0.0.0` bind, **any device on the same LAN can open the Web
GUI, with no extra password.** That default exists to serve the "open it on my
phone" use case.
- Use it on trusted LANs only. On public or shared networks set
`fixedHost: 127.0.0.1` (localhost only) or `fixedPort: 0` (disable the fixed
address entirely).
- The forwarder listens on the fixed port and nothing else: it opens no extra
API and never writes browser cookies.
## Troubleshooting
Log lines are prefixed with `[dsh-web-url-view]`:
- macOS: `~/Library/Logs/DSH Desktop/harness.log`
- Windows: `%APPDATA%\DSH Desktop\Logs\harness.log`
| Symptom | What to check |
| --- | --- |
| Fixed address shows "unavailable" | Port already taken → change `fixedPort`; or `fixedPort` is `0` |
| No "View URL" entry in Settings | `dsh.profile.bundles` in the profile `package.json` must list `dsh-web-url-view` |
| Fixed address will not open | Find `fixed entry listening on ...` in the log — it reports the bind result and the advertised address |
| Desktop exits unexpectedly | Search the log for `unhandled rejection` and paste the stack carrying the `lib/index.js` line number into an issue |
## Repository layout
```
src/ Plugin sources (TypeScript)
index.ts apply(): mounts the service and the fixed-entry forwarder
service.ts webUrlView Typert Remote service (returns both addresses)
fixed-entry.ts Fixed-port reverse proxy (HTTP + WebSocket, internal handshake)
lan.ts LAN IPv4 detection (prefers the default-route interface)
wire.ts RPC descriptor + zod codecs shared by host and client
typert.host.ts TYPERT manifest
client/ Settings-page UI (React + CSS Modules + zh/en dictionaries)
lib/ Prebuilt artifacts (committed so github: installs need no build)
index.js Host bundle (zero bare imports, node builtins only)
client.js Browser bundle (module-loader format, react as the only external)
types/** Type declarations emitted by tsc
cordis.patch.yml Bundle patch: inserts the web-url-view row into the profile
tsconfig.json Build config (valid only inside the harness monorepo, see below)
tsdown.config.ts Build config (same)
```
## Rebuilding from source
`src/` is the complete readable source. `tsconfig.json` and `tsdown.config.ts`
reuse the deepseek-harness monorepo's shared UI-plugin preset
(`packages/client/tsdown.client.ts`, which owns CSS Modules compilation, the
bundle-purity gate and the module-loader wrapper), so a build **requires the
harness checkout**:
```sh
# 1. Clone the harness sources
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
# 2. Place this repository at the conventional path
git clone https://github.com/1032740078/dsh-web-url-view.git packages/client/dsh-web-url-view
# 3. Install and build (tsc emits types, tsdown emits both bundles)
pnpm install
pnpm --filter dsh-web-url-view typecheck # tsc -b
pnpm --filter dsh-web-url-view bundle # tsdown
```
Artifacts land in `packages/client/dsh-web-url-view/lib/`. After changing either
half, sync the new `lib/` back into your plugin directory and restart the desktop.
## Compatibility
- Requires DSH `>=0.1.2-rc.1` (`engines.dsh` in `package.json`); developed and
verified against that version.
- Host capabilities used: `connection.authenticatedUrl()`, `webServer.port`, the
`settings.section` slot, and Typert Remote
(`@deepseek-ai/dsh-typert-protocol`).
- The browser bundle externalizes `react` only; the host bundle has zero bare
imports (every runtime value is inlined).
## License
[MIT](LICENSE) © RobinLiang
Install
dsh plugin --profile web add github:1032740078/dsh-web-url-view
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-web-url-view from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.