CLI tool
zquestz/s avatar
zquestz/s

zquestz/s: web search from the terminal without leaving it

Open a web search in your terminal.

2,606 stars126 forksGoMIT

At a glance

What is it?
s is a Go CLI that turns a query into a search URL and hands it to your browser. Here is how the provider system works, how to install it, and where it stops being the right tool.
Who is it for?
Adopt s if you already live in a shell and want a fast, scriptable way to reach a specific site's search box, especially when you want a different provider per query. Skip it if you need results rendered in the terminal, since the README's own framing is that it just opens your browser, and the w3m example only works when a text browser is installed.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 67 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What zquestz/s replaces, and who it is for

The project describes itself as a way to do web search from the terminal that "just opens in your browser." That sentence is the whole design brief. s does not fetch results, rank them, or render them. It builds a URL for a named provider, substitutes your query, and launches a browser with that URL.

The people who get value from this are the ones who already have a terminal open and a browser running. If you are debugging a stack trace and want to jump straight to a Stack Overflow query, or you are comparing prices and want an Amazon search without navigating to Amazon first, s removes the intermediate steps. The provider list is long, and it is not limited to general search engines: it includes code-oriented targets such as pypi, crates, packagist, npm, godoc, pydoc, mdn and stackoverflow, plus reference targets like wikipedia, wolframalpha, arxiv and ietf.

The trade-off is explicit in the name of the mode. Everything happens in the browser, so s inherits the browser's session, cookies and extensions. That is a feature for people who want their logged-in accounts, and a problem for anyone who expected a terminal-native result list.

How provider resolution and partial matching work

The mechanism is a lookup table. Each provider has a name, a URL template containing a %s token for the query, and a set of tags. The --provider flag selects one, --tag selects a group, and the default is brave.

What makes the lookup pleasant is partial matching. The README gives the example s -p fa hamsters, which resolves to Facebook, and s -p am toasters, which resolves to Amazon. The same works for tags: s -t te ssd searches providers tagged tech-news, and s -t sh blankets searches shopping sites. This is a small convenience that saves typing on the providers you use most.

There is an obvious failure mode hiding in that design. Partial matching is ambiguous by construction, and the README does not document what happens when a prefix matches more than one provider. If you rely on a short prefix, you are relying on whatever disambiguation rule the binary applies, and that rule is not stated. Long prefixes, or full names, are the safer habit.

Custom providers extend the same table. A custom entry needs an alphanumeric name matching ^[a-zA-Z0-9_]*$, a %s token for the query string, and a valid URL scheme. Anything outside that shape is rejected by the validation the README describes.

Installing s and running a first search

The README gives three install paths. The Go toolchain route requires GOPATH and GOBIN to be set in your environment first:

bash
go install github.com/zquestz/s@latest

Homebrew users install the formula under a different name than the repository, so the command is brew install s-search. Arch users can install from the AUR with yay -S s.

Once the binary is on your PATH, the smallest useful invocation is a bare query. The default provider is brave, so this opens a Brave search for puppies in your browser:

bash
s puppies

To pick a different provider for one query, pass -p. These two examples come straight from the README's examples section:

bash
s -p google dragonflies
s -p wikipedia rhinos

If you want to know what is available before committing to a default, ask the binary. The list commands support a JSON mode, which is the form to use if you intend to pipe the output into something else:

bash
s -l -j
s --list-tags -j

Adding -v to either list command includes the tags for each provider, and the README notes the reverse also holds.

Choosing a browser, including text browsers

The -b flag overrides the browser binary. The README's example uses w3m, a text-mode browser, which is the closest thing s offers to a fully terminal experience:

bash
s -b w3m cats

Be careful about what that example promises. w3m is not bundled with s, and the README does not say the output is rendered inline in your current terminal session; it says s launches the binary you name. Whether you get a readable result depends on w3m being installed and configured on your machine.

The flag also handles browsers with spaces in their path, and the quoting rules differ depending on whether you are passing extra flags. For a plain path, quotes around the whole path are enough. To pass an incognito flag, the README shows the inner path quoted inside the outer argument:

bash
s -b "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" kittens
s -b '"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --incognito' kittens

That second form is the kind of shell quoting that breaks silently when copied carelessly. If your private-window searches are opening in a normal window, check the quoting before anything else.

The UCL config file and its trailing-newline trap

Defaults live in ~/.config/s/config, written in UCL format. The supported keys are blacklist, binary, cert, customProviders, json, key, output, port, provider, tag, verbose, and whitelist. Setting a default provider is a single line:

ucl
provider: duckduckgo

Restricting the searchable set uses whitelist, and removing providers you never want uses blacklist. Both take arrays:

ucl
whitelist: [google, amazon, wikipedia]
blacklist: [dumpert]

Custom providers are declared as an array of objects with name, url and tags:

ucl
customProviders [
  {
    name: example
    url: "https://example.com?q=%s"
    tags: [example]
  }
]

The README carries a warning that is easy to skim past: the configuration file must end with a trailing newline or it may fail to parse correctly. That is an unpleasant failure mode because a missing newline at the end of a file is invisible in most editors. If your config seems to be ignored, check the last byte before you check anything else.

One more configuration note worth flagging: setting json: true makes the list commands emit JSON by default, which is convenient for scripting and mildly surprising if you later run s -l interactively and get JSON when you expected a table.

Server mode, Docker, and what they are actually for

Passing -s starts a web interface instead of opening a browser. The default port is 8080, and TLS is available through the cert and key flags:

bash
s -s
s -s -c /path/to/cert.pem -k /path/to/key.pem --port 8443

The README points at a hosted instance at jumps.io as an example of the interface. The repository also ships a Dockerfile that builds the binary and sets the entrypoint to /go/bin/s -s, exposing port 8080. The Makefile has a docker target that wraps the build.

It is worth being clear about what server mode is not. It is a front end for the same URL-launching behavior, not a search index or a proxy. Running it does not give you results in the browser without a further redirect to the provider. For a single user on localhost that is fine. Exposing it on a network port means exposing a page that will forward queries to third-party sites, and the README does not describe authentication, rate limiting, or access control for that mode. Treat the -s flag as a local convenience unless you have read the server code yourself.

Where s is the wrong tool, and what to use instead

The clearest boundary is result rendering. s produces a URL. If you want search results printed in your terminal, ranked and scrollable without a browser, this is not that program, and no flag turns it into one. The w3m example is a workaround that depends on an external binary, not a built-in mode.

A second boundary is anything requiring structured output from a search. The JSON flag applies to --list-providers and --list-tags only. There is no documented JSON mode for search results, because there are no search results to serialize.

For translation specifically, a command-line translator such as translate-shell solves a different problem: it fetches and prints translated text in the terminal rather than opening a page. If your actual goal is reading a translation inline, s with a translation-oriented provider will still hand you off to a browser tab, which is a worse fit.

For a general terminal browsing workflow, a TUI file explorer or a text browser is the closer alternative, because those render content where you already are. s is a launcher, and judging it as a browser will always disappoint. Judging it as a launcher, it does one thing and does it with a large provider table.

Maintenance, licence, and upgrade cost

The repository is not archived, and the last push was on 2026-07-27, with release v0.8.1 tagged the same day. That is recent enough to treat the project as receiving changes, though the gap between v0.7.5 in December 2025 and v0.8.0 in July 2026 shows the cadence is not continuous.

The licence is MIT, which permits commercial and private use, modification, and redistribution provided the copyright notice and permission notice are included. That is a permissive arrangement and it is compatible with shipping the binary inside a larger product. This is a description of the licence text, not legal advice; if you are redistributing, read LICENSE in the repository and confirm the notice requirements with your own counsel.

Upgrade cost is low by construction. The program has no database, no daemon required for normal use, and no migration step mentioned in the README. The main upgrade risk is provider drift: search sites change their query parameters, and a provider whose URL template stops matching the site's current format will produce a broken page rather than an error, because the browser is the thing that discovers the problem. If you depend on a specific provider, that is the thing to re-check after an upgrade.

Editorial conclusion

Adopt s if you already live in a shell and want a fast, scriptable way to reach a specific site's search box, especially when you want a different provider per query. Skip it if you need results rendered in the terminal, since the README's own framing is that it just opens your browser, and the w3m example only works when a text browser is installed. Before committing, verify two things: that your network can reach the provider you intend to use as a default, and that your config file at ~/.config/s/config ends with a trailing newline, because the README warns it may fail to parse without one.

Frequently asked questions

How do I browse in the terminal with zquestz/s?

You can point s at a text browser with the -b flag, and the README's example is s -b w3m cats. The project itself does not render pages; it launches the binary you name, so w3m has to be installed separately.

How do I install zquestz/s?

The README gives three routes: go install github.com/zquestz/s@latest with GOPATH and GOBIN set, brew install s-search for Homebrew, and yay -S s from the AUR on Arch Linux.

Which search provider does zquestz/s use by default?

The default provider is brave, as shown in the flag listing where --provider defaults to "brave". You can change it per query with -p or set a new default in the config file with a provider line.

Where does zquestz/s store its configuration?

The README says to create ~/.config/s/config, written in UCL format. It also warns that the file must end with a trailing newline or it may fail to parse correctly.

Can zquestz/s run as a web server?

Yes. Passing the -s flag starts a web interface on port 8080 by default, and TLS is available by supplying cert and key files along with a --port value. The repository's Dockerfile sets the entrypoint to /go/bin/s -s and exposes port 8080.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. zquestz/s on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zquestz-s.svg)](https://hysenlabs.com/projects/zquestz-s)