Giving your agents a terminal: a first look at the tabstack CLI Mozilla released the tabstack CLI, a single Go binary that wraps the Tabstack AI API to turn any URL into clean Markdown or schema-shaped JSON, run natural-language browser automation, and answer research questions with cited sources. The tool ships as a static binary for macOS, Linux, and Windows, with credential handling via flag, environment variable, or config file. Commands follow a predictable `tabstack ` pattern, including structured extraction with JSON schema support. Every project I touch lately ends up needing the same awkward thing: a reliable way to pull the web into a script or an agent. Not a brittle scrape held together with CSS selectors and hope, but something that takes a URL and hands back clean, structured text I can actually pipe into the next step. I have built that wrapper more than once, and it is never as small as you think it will be. So when Mozilla dropped the tabstack CLI, a single Go binary that wraps the Tabstack AI API, I wanted to spend a proper afternoon with it. The pitch on the README is direct: every web interaction your agent or stack needs, from the terminal or a script. It turns any URL into clean Markdown or schema-shaped JSON, runs natural-language browser automation, and answers research questions with cited sources. The part that made me sit up is that the output is pretty in a terminal and pipeable into jq without a flag. That is a small detail, and it tells you the people who built it actually live on the command line. Let me walk you through it the way I poked at it myself. There is no runtime to install and nothing to bootstrap, because it ships as a single static binary built for macOS, Linux, and Windows. The quickest route is the install script: curl -fsSL https://tabstack.ai/install.sh | sh That fetches the right binary for your platform and puts it on your PATH , and you are ready to go. If you would rather not pipe a script into your shell, there are a couple of alternatives. With Go on your machine you can use: go install github.com/Mozilla-Ocho/tabstack-cli/cmd/tabstack@latest That drops the binary in $GOPATH/bin , which is usually ~/go/bin . If your shell cannot find tabstack afterwards, you almost certainly have not got that directory on your PATH : export PATH="$HOME/go/bin:$PATH" And if you want to avoid Go entirely, there are pre-built binaries on the Releases page, or you can clone the repo and run make install-local , which builds it and copies it to /usr/local/bin so it works in any terminal straight away. Several routes, all of them boring in the best possible way. This is the bit I want to praise first, because credential handling is where a lot of CLIs get careless. You log in once: tabstack auth login prompts for the key, input hidden, saved to the config file tabstack auth status shows how your key is being resolved, never prints it A key can come from three places, and the precedence is exactly the order you would hope for: --api-key flag TABSTACK API KEY environment variable $XDG CONFIG HOME/tabstack/config.toml , defaulting to ~/.config/tabstack/config.toml The config file is written 0600 , so it is not world-readable, and auth status will tell you which source won without ever leaking the value. This is the contract I want from any tool that holds a secret: a flag for one-off overrides, an environment variable for CI, and a locked-down file for everyday local use. If no key is found, the API commands exit with code 2 and tell you how to set one, rather than failing with a stack trace. We will come back to those exit codes, because they matter. Every command follows the same shape: tabstack