Open-source project
vtemian/octto avatar
vtemian/octto

octto: an OpenCode plugin that turns a vague idea into a branching question form

Interactive brainstorming UI for OpenCode agents - multi-question forms, decisions, and real-time feedback

525 stars30 forksTypeScriptMIT

At a glance

What is it?
octto is an OpenCode plugin that opens a browser UI where an agent asks a branching set of questions as pick-one, rank, slider, code or diff inputs, then produces a reviewable plan. It suits someone who finds agent brainstorming tedious to type through, and it runs as a plugin inside OpenCode rather than as a separate service.
Who is it for?
octto fits an OpenCode user whose agent sessions stall on long typed question sequences, and it does not fit someone who wants the questions to stay in the terminal, since the whole premise is moving them into a browser.
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 5 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

The premise, and the setup

octto is an interactive browser UI for AI brainstorming, and the pitch in the readme is blunt about the problem it is solving: stop typing in terminals, start clicking in browsers.

When you describe an idea, octto opens an interactive UI. You click options instead of typing, you see all the questions at once, you answer in any order, follow-ups appear instantly, and the final plan is reviewed visually. The readme summarises the intended saving as ten minutes of terminal typing becoming two minutes of clicking.

The setup is short. You add the plugin to your OpenCode configuration file.

json
{ "plugin": ["octto"] }

Then you select the octto agent and give it a request.

code
I want to add a caching layer to the API

A browser window opens, you click your answers, and you are done.

That is the entire first-run experience, and it is worth noticing what it does not require. There is no separate service to run, no port to reserve, no account, no API key. The plugin is loaded into OpenCode itself and it starts a browser session when it needs one.

The primary language is TypeScript, the licence is MIT, the default branch is main, and the last push was on 2026-10-18. The recent releases are v0.4.5 from 2026-09-23, v0.4.4 and v0.4.3 from 2026-09-11, and the package description says it turns rough ideas into designs through branch-based exploration.

The version line is worth keeping in view. This is a 0.4.x project with releases roughly every week or two over the last few months, which is the pace of something still finding its shape rather than something with a settled API.

Fourteen question types, and why the type matters

The readme says no more typing everything, and lists fourteen visual input types with what you see for each.

The single choice types are pick_one, rendered as radio buttons, pick_many as checkboxes, and confirm as yes and no buttons. The numeric ones are slider as a draggable range and rate as a star rating. The ordering one is rank, drag to reorder. The opinion one is thumbs, thumbs up and down. The comparison ones are show_options as cards with pros and cons, and show_diff as a side-by-side code diff. The free-form ones are ask_code as a syntax-highlighted editor, ask_text as text input for when it is needed, ask_image as image upload, and ask_file as file upload. And emoji_react gives you an emoji picker.

The reason this list matters more than it looks is that the type is chosen by the agent, not by you. If the agent decides the question is a choice between two approaches, it renders cards; if it decides you need to look at a diff, it renders a diff. So the question types are really the vocabulary the agent has for asking, and the fourteen of them are a constraint on what an agent can ask in this interface.

That constraint is also the risk. The show_diff and ask_code types are the ones that make this more than a form filler, because a code diff is the natural thing to ask about when designing a change to existing code. But it also means an agent that wants to ask something outside those fourteen types has to fall back to something like ask_text, which is exactly the terminal-typing experience the tool is meant to replace.

Two of the entries are unusual. show_options with cards carrying pros and cons is a different interaction from a radio button, because the trade-off has to be read rather than recognised. And emoji_react is the most lightweight of the fourteen, a reaction rather than an answer, which suggests the tool allows for questions where the only useful signal is a preference.

Branches, live updates and the three agents

The branching model is the core of the design, and the readme draws it as a diagram.

code
         ┌─ Branch 1: [question card]
Request ─┼─ Branch 2: [question card]
         └─ Branch 3: [question card]
                ↓
        Answer any, in any order

Your request is split into two to four exploration branches, and all the initial questions appear at once. Each branch goes as deep as needed, with some finishing in two questions and others taking four.

That last sentence is the important one. The branches are not a fixed questionnaire applied uniformly; they are independent explorations of different aspects of the same request, and the agent decides when each one is done.

The live update behaviour covers the rest. Questions appear as you answer previous ones, a progress indicator shows the remaining questions, completed answers stay visible for context, and the final plan is rendered as reviewable sections.

The mechanism is three agents with distinct jobs.

The bootstrapper splits your request into branches, the probe decides if a branch needs more questions, and octto orchestrates the session.

And the flow is seven steps. The bootstrapper creates two to four branches from your request. Each branch gets an initial question and all of them are shown in the browser. You answer, clicking rather than typing. The probe agent evaluates whether the branch needs more questions or is done. That repeats until all branches are complete. The final plan is shown for approval. And the design is saved to docs/plans/.

The probe agent is the interesting one, because it is a model making a per-branch termination decision, and the fact that it is a separate agent with its own configurable model means you can change how long it interrogates you. That matters: an over-eager probe turns a two-minute session into a questionnaire, and the configuration gives you a lever for it.

Configuration, precedence and the fragments mechanism

Configuration is optional and lives in a separate file at ~/.config/opencode/octto.json.

json
{
  "model": "anthropic/claude-sonnet-4",
  "port": 3000,
  "agents": {
    "probe": { "model": "openai/gpt-4o" }
  }
}

Four options are documented. The model option is a string that overrides the model for all agents at once. The port option is a number with a default of 0, which means a random port, for the browser UI server. The agents option is an object for per-agent overrides, covering model and temperature and so on. And fragments is an object holding custom instructions injected into agent prompts.

The precedence rule is stated explicitly: a per-agent agents.<name>.model beats the top-level model, which beats the built-in default. That ordering is the one to remember, because it is easy to set a top-level model and then wonder why one agent is still using something else.

Fragments are the more interesting of the two less obvious options. They inject custom instructions into agent prompts, and the readme says this is useful for customizing agent behaviour per project or globally. The global form lives in the same octto.json file.

json
{
  "fragments": {
    "octto": ["Always suggest 3 implementation approaches"],
    "probe": ["Include emoji in every question"],
    "bootstrapper": ["Focus on technical feasibility"]
  }
}

And the project form lives in .octto/fragments.json in your project root.

json
{
  "octto": ["This project uses React - focus on component patterns"],
  "probe": ["Ask about testing strategy for each feature"]
}

The merge rule is precise: global fragments load first and project fragments append, and each fragment becomes a bullet point in a user-instructions block that is prepended to the agent's system prompt.

So fragments are not a config file in the usual sense but a way of editing the prompts of the three agents. The project-level example is the more useful of the two, because a rule like this project uses React is exactly the context a general-purpose agent lacks, and prepending it to the system prompt is a more direct way to supply it than trying to express it in every request.

There is one environment variable, OCTTO_PORT, which overrides the port and takes precedence over the config file. For Docker workflows the readme shows how to set a fixed port.

bash
OCTTO_PORT=3000 opencode

A fixed port in a container is necessary anyway, because a random port inside the container is not reachable from the host.

How it is built, and what it costs you

The repository layout shows a Bun project with both unit and end-to-end tests. There are src/ and tests/ directories, an e2e/ directory, a package.json with a long scripts section, biome.json and an eslint.config.js, tsconfig.json and tsconfig.eslint.json, a lefthook.yml, a flake.nix and flake.lock, and the usual project documents including ARCHITECTURE.md, CODE_STYLE.md and CLAUDE.md.

The build is Bun-based. The build script runs bun build on src/index.ts into dist with the bun target and esm format, then runs tsc with emitDeclarationOnly to produce the type declarations. The test script is bun test tests, and there is a separate test:e2e script that builds a Docker image from e2e/Dockerfile and runs it.

The dependencies are minimal for what it does. The runtime dependencies are the OpenCode plugin SDK at a pinned version, plus valibot and zod for validation. Having both validation libraries is a little unusual, but it is consistent with a plugin that has to accept configuration written by users in several shapes.

The development workflow in the readme is three commands.

bash
bun install
bun run build
bun test

There is also a check script that runs biome check, eslint, the typecheck and the unit tests together, and that check script is what prepublishOnly runs before publishing.

The costs of the approach are worth naming plainly.

The first is that this is a plugin, not a tool. It runs inside OpenCode, it uses OpenCode's own agents and your own model providers, and the quality of the questions is entirely the quality of the models you point it at. The per-agent model configuration exists precisely because different models are good at different parts of this.

The second is that a browser-based question flow is a change in how you work, not just where you type. You cannot answer from a terminal over SSH, and if your OpenCode session is running headless in a container, the browser has to reach it. The OCTTO_PORT override for Docker exists because of exactly that.

The third is that plans are written to docs/plans/ in your project, which means the output of a session ends up in your repository and can end up in a commit. That is convenient for review and a consideration for what you commit.

And the last is the pace. A 0.4.x version number with frequent releases means the interface described in this readme may shift, so a team standardising on it should treat the plugin version as part of its own tooling baseline.

Editorial conclusion

octto fits an OpenCode user whose agent sessions stall on long typed question sequences, and it does not fit someone who wants the questions to stay in the terminal, since the whole premise is moving them into a browser. Before enabling it, decide which model each agent should use, because the precedence rule is that a per-agent model setting beats the top-level model setting and both beat the built-in default, and note that the design is saved to docs/plans/ in your project without further prompting.

Frequently asked questions

How do I install and start octto?

Add { "plugin": ["octto"] } to your OpenCode configuration at ~/.config/opencode/opencode.json, then select the octto agent and describe your request. A browser window opens and you answer the questions by clicking.

What question types does octto support?

Fourteen: pick_one, pick_many, confirm, slider, rank, rate, thumbs, show_options, show_diff, ask_code, ask_text, ask_image, ask_file and emoji_react. The agent chooses the type, so the fourteen are the vocabulary it has for asking.

What are the three agents octto uses?

The bootstrapper splits your request into two to four branches, the probe decides whether a branch needs more questions or is done, and octto orchestrates the session. The flow repeats until all branches are complete, then shows the final plan for approval and saves the design to docs/plans/.

How do I configure octto and which model wins?

Put an optional octto.json in ~/.config/opencode. It accepts model, port, agents and fragments. A per-agent agents.<name>.model takes precedence over the top-level model, which takes precedence over the built-in default, and the OCTTO_PORT environment variable overrides the port from the config file.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. vtemian/octto 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/vtemian-octto.svg)](https://hysenlabs.com/projects/vtemian-octto)

Was this useful?