Skip to content

Install OpenCode and meet the TUI

You’re eyeing a terminal coding agent with the suspicion it deserves. You already have an editor you trust and a workflow that works, and “type a sentence, watch a program rewrite your code” is not a thing you hand the keys to on faith. Fair. So before you commit to anything, the move is to install OpenCode, start it inside the repo you’re going to spend this course on, and look at what it actually is — because most of the unease about terminal agents is really unease about a black box, and OpenCode’s box opens cleanly into two parts you can see.

The repo is feedmill — a self-hosted feed aggregator you’ve just inherited. A small Go CLI plus an HTTP sync server that pulls dozens of RSS, Atom, and JSON feeds, dedupes them, and serves a reading queue you read from the terminal and can run unattended on a cron. It mostly works. It’s lightly documented. It’s exactly the kind of typed, parser-heavy, many-moving-parts codebase where you’d want a competent pair — and exactly the kind you don’t want a black box let loose in. Good test subject.

OpenCode is an open-source, terminal-first coding agent built by the team behind SST and Terminal — now operating as Anomaly (github.com/anomalyco/opencode). The one-liner that works everywhere is the install script:

$ curl -fsSL https://opencode.ai/install | bash

If you’d rather go through a package manager you already trust, all of these land the same binary:

$ npm install -g opencode-ai # npm (package is opencode-ai, not opencode)
$ brew install anomalyco/tap/opencode # Homebrew (project-maintained tap, updated often)
$ paru -S opencode-bin # Arch / AUR

Confirm it’s on your path before you point it at anything that matters (-v is the short form):

$ opencode --version

That’s the whole install. No account wall to clear before you can look around — authentication is the next lesson, because OpenCode is provider-agnostic and choosing a model is a real decision you shouldn’t rush. For now you just want to see the surfaces.

Drop into feedmill and run the bare command:

$ cd feedmill
$ opencode

What comes up is not a line-by-line REPL waiting for one command at a time. It’s a full-screen TUI — a terminal user interface that takes over the window, with your conversation filling the pane and an input box pinned at the bottom. OpenCode is built by terminal people (the same team behind terminal.shop), and the TUI is the front door, not an afterthought. You navigate it with the keyboard, scroll the transcript, switch models and agents inline, and run slash commands. One of those, /init, runs a guided setup that creates or updates the project’s AGENTS.md context file.

Type a read-only question as your first move — nothing that can touch a file. A stylized version of what comes back:

> what is this project, and how does the CLI talk to the sync server?
read README.md
read cmd/feedmill/main.go, internal/sync/server.go (2 files)
feedmill is a self-hosted feed aggregator in Go. It's split in two:
a CLI (cmd/feedmill) you run locally to read and manage your queue,
and a sync server (internal/sync) that fetches feeds on a schedule
and exposes them over HTTP. The CLI is a client of that server — it
hits the server's HTTP endpoints rather than reading the feed store
directly, which is what lets you run the server unattended on a cron
and still read from any terminal.

You’ve spent nothing and learned two things. You’ve learned the lay of feedmill — a clean answer to a question you’d otherwise have spent twenty minutes spelunking for. And you’ve learned how this agent behaves: it reads the relevant files first and tells you which ones, then answers. That’s the loop you’ll meet properly two lessons from now; for the moment just note that the first thing it did was read, not write.

To leave the TUI, the agent’s own /exit command (or ctrl+x q) drops you back to your shell.

The second surface: it’s a client of a server

Section titled “The second surface: it’s a client of a server”

Here’s the part that turns the black box transparent. When you ran opencode just now, you didn’t only start a chat window — you started a server, and the TUI is a client talking to it. OpenCode has a genuine client/server architecture under the hood, and you can run the server by itself with no UI attached at all:

$ opencode serve
opencode server listening on http://127.0.0.1:4096

That’s a headless HTTP server exposing an OpenAPI-described API — sessions, messages, files, agents, the lot. It’s the same engine the TUI drives; the TUI is just the most convenient of several possible clients. You can browse the API surface in a running server’s docs endpoint:

$ curl http://127.0.0.1:4096/doc

Why does a skeptic care about this on day one? Because it’s the proof that OpenCode isn’t a magic terminal wrapper — it’s a controllable program with a documented interface. The same server is what makes feedmill’s eventual automation story possible: you’ll be able to drive OpenCode against your repo with no human at the keyboard at all, which for a tool whose whole job is running unattended on a cron is the right kind of rhyme. And it’s what underlies the non-interactive form you’ll use for scripting:

$ opencode run "list the feed-source parsers and which formats each handles"

Same engine, no TUI — one prompt in, an answer out, suitable for a pipe or a cron line. You’ll lean on opencode run hard in the automation chapter; today it’s enough to know the headless path exists and is the same brain as the pretty one.

So the box is open. There’s an interactive surface — the full-screen TUI you just talked to — and a programmatic one — the server it’s quietly a client of, also reachable as opencode serve and opencode run. Nothing is hidden, and nothing has touched a file yet. The one thing standing between you and real work is the decision you deliberately skipped: which model does the thinking. OpenCode runs almost any provider you can name, and that choice is yours to make rather than a default to accept. Next: bring your own model.