dsh-web-search-free
Paste SpecStream's SearXNG address into the SearXNG row of dsh-web-search-free, and DeepSeek Harness searches the web through SpecStream's Search API. There is no SearXNG instance to host and no settings.yml to change for JSON.
What you need
- DeepSeek Harness (dsh) with the dsh-web-search-free plugin in the
webprofile:dsh plugin --profile web add dsh-web-search-free, or Plugins, then Add plugin in the dsh app. - A SpecStream key. Get your key on the Search API screen of your SpecStream workspace. New accounts start with $10 of credit, no card.
- 1
1. Put your key in the address
The SearXNG row has no key field of its own: its "key" box holds instance addresses, one per line. So the key goes in the address. Put your key in place of
YOUR_SPECSTREAM_KEY.Leave
/searchoff. The plugin adds/searchandformat=jsonitself, and it drops anything after a?, so a?key=would be lost. The key has to sit in the path.SearXNG row - 2
2. Paste it into the SearXNG row
Run
dsh weband open the plugin's card. On dsh 0.1.6 and later it is under Plugins, then Installed, then web-search-free. On dsh 0.1.5 and earlier it is under Settings, then Plugins, then Web Search Free. On dsh 0.2, the globe icon in the session header opens the same form.Click the SearXNG row and paste the address.
- 3
3. Set the call order and save
Drag the
⋮⋮handle to place SearXNG in Call order. With the defaultfallbackstrategy the top engine is tried first, and a failure moves to the next, so SearXNG at the top makes SpecStream the first search and your other engines the fallback.Click Save. It applies from the next search, with no restart.
- 4
4. Test it
Click Test keys. It runs one small search per key and shows the result count and latency. The button needs a dsh that registers plugin routes, as 0.2.0-rc.2 does; on older versions, ask dsh about something from this week and check that the answer cites pages.
What the plugin sends, and what comes back
| dsh-web-search-free sends | SpecStream |
|---|---|
GET {address}/search?q=...&format=json | https://api.specstream.ai/searxng/<key>/search, with the key read from the path |
language, from Region / language under Advanced | Searches in that language |
time_range, from Time range (day, week, month, year) | Keeps results inside that window |
Reads results[].url, title, content and publishedDate | SearXNG's JSON shape. publishedDate is null on most results, so move Brave up if dates matter most |
Why a public or self-hosted instance fails here
The plugin asks for JSON, and SearXNG's own search API docs say: "Requesting an unset format will return a 403 Forbidden error." They add that many public instances have these formats disabled. A self-hosted instance works once json is in search.formats, but it then sends every query on to public engines from your own address.
SpecStream answers every request in SearXNG's JSON shape, and the search runs on SpecStream's servers. There is no format to turn on and no engine list to keep unblocked.
Or set it in cordis.patch.yml
If the card does not show up, edit ~/.dsh/profiles/web/cordis.patch.yml. The install already added a web-search-free entry, so override its config by id; do not add another insert. List any engine you keep after searxng, then restart dsh.
Keep the key out of shared files
The address is saved in the profile's cordis.patch.yml as searxngApiKey, so that file holds your key. The plugin's logs print only the host of a SearXNG address, api.specstream.ai, never the path with the key.
Before you uninstall the plugin, click Clear all settings on the card, as its README asks, or the key stays in dsh's config files.
What each search costs
Each search through the SearXNG address is one Search API call on the fast tier: $1 per 1,000 searches of up to 10 results, a fifth of the default search's $5. The plugin sends no result count, so each search gets one page of 10 at that price, and a search that returns nothing costs nothing. Test keys spends one search per address.
With the race or merge strategy, the plugin asks two to four engines at once, and SearXNG is one call of each search. Calls come out of your balance with no quote and no approval. New accounts start with $10 of credit, which covers 10,000 searches at this price.
Limits and errors
- When search is busy, SpecStream answers
429withRetry-Afterand charges nothing. The plugin moves the address to the back of the chain for 2 minutes and tries the next engine. - An address that answers
401,402or403is benched for 30 minutes. If Test keys shows one of these, check the key in the address. - If searches never reach the plugin at all, the profile's
cordis.patch.ymlholds a- id: webentry that overrides it. Point itssearchProviderandfetchProvideratweb-search-free, or delete the entry. - The SearXNG row only searches.
web_fetchreads pages with the fetch engines you keep, keyless Jina Reader or dsh's local fetcher.
Go back
Delete the address from the SearXNG row and click Save. Questions: [email protected].
More
SpecStream for dsh-web-search-free covers what it does in dsh-web-search-free on one page. Every other tool has its guide in Connect your tools. You see the most a request can cost before it starts, and the matches are paid from your balance. Billing has the details. For help, email [email protected].