dsh-glm-web-search
Use your Z.AI (GLM) subscription as DeepSeek Harness's search, fetch and vision backend.
Sign in with the Z.AI account you already have — no API key, no separate billing.
dsh plugin --profile desktop add dsh-glm-web-search
Why this exists
DeepSeek Harness ships its own web_search / web_fetch backends, which means another API key
and another bill. But plenty of people already pay for a Z.AI plan — and that quota can already
run web_search_prime and webReader server-side. Nobody had wired it up.
This plugin does exactly that. One email login turns your existing subscription into the harness's search and fetch capability. Installing it is enough; the tool names and arguments the model sees do not change, only the service behind them.
Features
| Capability | What it does |
|---|---|
| Web search | Replaces the official web_search backend with web_search_prime |
| Web reader | Replaces the official web_fetch backend with webReader |
| Vision | Adds a zai_vision tool for image description, OCR and visual Q&A |
| Zero dependencies | No node_modules, no dependencies, no peerDependencies |
| Status line | /dsh-glm-status shows token age, plan expiry and remaining quota |
Install
From the Plugin Manager
Open Plugins → Add plugin, type the package name, and press Install:
dsh-glm-web-search
Leave the install source on npm — or switch it to Mainland China mirror (npmmirror) if the official registry is slow; both serve the same tarball. Restart the harness afterwards: plugin code is loaded at startup, so a freshly installed plugin is not active until then.
From the command line
dsh plugin --profile desktop add dsh-glm-web-search
From this repository
For a local checkout, or to pin an exact commit:
dsh plugin --profile desktop add github:czpGhost/dsh-glm-web-search
dsh plugin --profile desktop add /absolute/path/to/dsh-glm-web-search
Nothing here runs a build script, so pnpm never asks you to allowlist one.
Then sign in once
/dsh-glm-web-search login
Your browser opens the authorization page; the token is stored automatically on approval.
From then on web_search and web_fetch resolve to Z.AI.
Usage
/dsh-glm-web-search login # sign in (opens your browser)
/dsh-glm-web-search logout # sign out, forget the local credential
/dsh-glm-web-search status # token, plan and quota
/dsh-glm-login /dsh-glm-logout /dsh-glm-status # equivalent aliases
Each subcommand is also a standalone command because the menu matches on a command's name:
typing /dsh-glm-log is what surfaces both login and logout.
Upgrading
The Plugin Manager does not auto-update installed plugins. Remove the old version first, then add the new one:
dsh plugin --profile desktop remove dsh-glm-web-search
dsh plugin --profile desktop add dsh-glm-web-search
Then restart. Your credential lives outside the package, so it survives an upgrade.
Screenshot
/dsh-glm-status:
▸ token 30m · Start Plan · GLM-5.3 2.95M left · resets 2h 57m
account you@example.com
token valid 30m
plan ZCode Start Plan [active] · ends 10-12 23:59 (3d 2h)
quota GLM-5.3 ██████████ 98% 2.95M/3M resets 2h 57m
quota GLM-5.3-Flash ██████████ full resets 2h 57m
cycle daily grant, refills at 00:00 Asia/Shanghai
The quota bar draws remaining, not used. Drawn as used, a brand-new account would render as an empty bar — which reads as "exhausted", exactly backwards.
Configuration
| Field | Default | Purpose |
|---|---|---|
origin |
https://zcode.z.ai |
Gateway origin |
model |
unset (resolved live) | Model that runs search and fetch |
appVersion |
probed | Client version advertised to the gateway |
jwtEnv |
ZAI_JWT |
Credential reference |
tokenPath |
$DSH_HOME/dsh-glm-web-search/token.json |
Local token file |
vision |
true |
Register the zai_vision tool |
timeoutMs |
90000 |
Per-request deadline |
Credential order: managed record → $ZAI_JWT → the local token file.
On a headless host, set ZAI_BROWSER_OPEN=0; the URL is still printed so you can open it yourself.
Two things worth knowing
Search results are capped. Upstream returns at most 10 sources per web_search call, and the
harness's dsh-tool-web then truncates sources[] to 8 (setting truncated: true). One call
may carry up to 4 queries, run concurrently; the merged result still hits the 8-source cap.
It has no dependency tree at all. src/ reaches the harness only through injected services
(ctx.web, ctx.tools, ctx.commands), and imports nothing outside its own tree except Node
builtins — so there is no node_modules, no dependencies, and no peerDependencies. That matters
beyond tidiness: declaring a @deepseek-ai/dsh-* peer makes the harness's install preflight compare
your range against the runtime version and reject the whole installation when they disagree.
The subtler hazard is a second copy of a stateful harness package. Same version, byte-identical
files, and it still breaks: two files mean two module instances, and a module-local
Symbol() differs between them. @deepseek-ai/dsh-tools keys its internal scheduler on exactly
that (const TOOL_RUNTIME_SCHEDULER = Symbol("@deepseek-ai/dsh-tools.scheduler")), so
@deepseek-ai/dsh-agent-loop reaching through ctx.tools[TOOL_RUNTIME_SCHEDULER] finds
undefined and the turn dies with Cannot read properties of undefined (reading 'prepare').
Symbol.for() keys live in a global registry and survive duplication — schemastery uses one,
which is why it is safe to appear twice and dsh-tools is not.
Roadmap
- Search, fetch and vision
- Email OAuth login, no API key
- Status line with quota
- Published on npm
- Real screenshots and a demo GIF
- Documentation polish (PRs welcome)
FAQ
Do I need a paid Z.AI plan? No. A free account gets an experience plan that already covers search and fetch. Vision needs the Flash model, which the same plan includes.
Where is my credential stored?
$DSH_HOME/dsh-glm-web-search/token.json — one file, no environment variables required. Delete it
or run logout to revoke locally.
Why do I only get 8 results?
That is the harness's own cap, not Z.AI's. Upstream returns 10; dsh-tool-web trims to
searchMaxResults (default 8). Raise it in that plugin's config if you need more.
Does this work headless?
Yes. Set ZAI_BROWSER_OPEN=0 and login prints the URL instead of opening a browser.
Will it break when Z.AI ships a new client? Possibly — the gateway fingerprints the client, so a new ZCode build can invalidate the identity constants. That is a one-line fix here, not a redesign.
Star History
Disclaimer
This project is for technical sharing and learning purposes only. Please comply with the relevant terms of service and applicable laws, and use it at your own risk.
No comments yet. Be the first to write one.