Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
0e669b6
ci: use `useblacksmith/stickydisk` on linux runners only (#13909)
goniz Feb 17, 2026
e35a413
core: keep message part order stable when files resolve asynchronousl…
rekram1-node Feb 17, 2026
4226097
ci: fixed Rust cache for 'cargo install' in publish.yml (#13907)
goniz Feb 17, 2026
ea2d089
ci: fixed missing if condition (#13934)
goniz Feb 17, 2026
d338bd5
Hide server CLI on windows (#13936)
Brendonovich Feb 17, 2026
ace63b3
zen: glm 5 free
fwang Feb 17, 2026
a93a1b9
wip: zen
fwang Feb 17, 2026
ed4e484
ci: update triage workflow (#13944)
rekram1-node Feb 17, 2026
0186a85
fix(app): keep Escape handling local to prompt input on macOS desktop…
itskritix Feb 17, 2026
8d0a303
docs(ko): improve Korean translation accuracy and clarity in Zen docs…
vynnlee Feb 17, 2026
4fd3141
docs: improve zh-cn and zh-tw documentation translations (#13942)
chenmijiang Feb 17, 2026
6e98437
fix(docs): correct reversed meaning in Korean plugins logging section…
hmu332233 Feb 17, 2026
4eed559
chore: generate
opencode-agent[bot] Feb 17, 2026
07947ba
tweak(tui): new session banner with logo and details (#13970)
iamdavidhill Feb 17, 2026
3dfbb70
fix(app): recover state after sse reconnect and harden sse streams (#…
nexxeln Feb 17, 2026
1098567
feat(app): session timeline/turn rework (#13196)
adamdotdevin Feb 17, 2026
277c68d
chore: app polish (#13976)
adamdotdevin Feb 17, 2026
e273a31
tweak(ui): icon button spacing
iamdavidhill Feb 17, 2026
703d634
chore: generate
opencode-agent[bot] Feb 17, 2026
9b1d704
tweak(app): keep file tree toggle visible
iamdavidhill Feb 17, 2026
0cb11c2
tweak(app): reduce titlebar right padding
iamdavidhill Feb 17, 2026
d31e9cf
tweak(app): use weak borders in titlebar actions
iamdavidhill Feb 17, 2026
a8669ab
tweak(app): match titlebar active bg to hover
iamdavidhill Feb 17, 2026
8fcfbd6
tweak(app): align titlebar search text size
iamdavidhill Feb 17, 2026
ce08442
tweak(ui): center titlebar search and soften keybind
iamdavidhill Feb 17, 2026
98f3ff6
tweak(app): refine titlebar search and open padding
iamdavidhill Feb 17, 2026
8e243c6
tweak(app): tighten titlebar action padding
iamdavidhill Feb 17, 2026
222b6cd
tweak(ui): update magnifying-glass icon
iamdavidhill Feb 17, 2026
4d5e86d
feat(desktop): more e2e tests (#13975)
neriousy Feb 17, 2026
7ed4499
chore: generate
opencode-agent[bot] Feb 17, 2026
5a3e0ef
tweak(ui): show user message meta on hover
iamdavidhill Feb 17, 2026
2cac848
tweak(ui): use provider catalog names
iamdavidhill Feb 17, 2026
14684d8
tweak(ui): refine user message hover meta
iamdavidhill Feb 17, 2026
57a5d5f
tweak(ui): show assistant response meta on hover
iamdavidhill Feb 17, 2026
1d78100
tweak(ui): allow full-width user message meta
iamdavidhill Feb 17, 2026
652a776
ui: add clearer 'Copy response' tooltip label for text parts
iamdavidhill Feb 17, 2026
adfbfe3
tui: increase prompt mode toggle height for better clickability
iamdavidhill Feb 17, 2026
d055c1c
fix(desktop): avoid sidecar health-check timeout on shell startup (#1…
ysm-dev Feb 17, 2026
46739ca
fix(app): ui flashing when switching tabs (#13978)
neriousy Feb 17, 2026
df59d14
fix: Homepage video section layout shift (#13987)
alexcarpenter Feb 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/setup-bun/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ runs:
using: "composite"
steps:
- name: Mount Bun Cache
if: ${{ runner.os == 'Linux' }}
uses: useblacksmith/stickydisk@v1
with:
key: ${{ github.repository }}-bun-cache-${{ runner.os }}
Expand Down
18 changes: 14 additions & 4 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,23 @@ jobs:
GH_TOKEN: ${{ github.token }}
GITHUB_RUN_ID: ${{ github.run_id }}

- name: Resolve tauri portable SHA
if: contains(matrix.settings.host, 'ubuntu')
run: echo "TAURI_PORTABLE_SHA=$(git ls-remote https://github.com/tauri-apps/tauri.git refs/heads/feat/truly-portable-appimage | cut -f1)" >> "$GITHUB_ENV"

# Fixes AppImage build issues, can be removed when https://github.com/tauri-apps/tauri/pull/12491 is released
- name: Install tauri-cli from portable appimage branch
uses: taiki-e/cache-cargo-install-action@v3
if: contains(matrix.settings.host, 'ubuntu')
run: |
cargo install tauri-cli --git https://github.com/tauri-apps/tauri --branch feat/truly-portable-appimage --force
echo "Installed tauri-cli version:"
cargo tauri --version
with:
tool: tauri-cli
git: https://github.com/tauri-apps/tauri
# branch: feat/truly-portable-appimage
rev: ${{ env.TAURI_PORTABLE_SHA }}

- name: Show tauri-cli version
if: contains(matrix.settings.host, 'ubuntu')
run: cargo tauri --version

- name: Build and upload artifacts
uses: tauri-apps/tauri-action@390cbe447412ced1303d35abe75287949e43437a
Expand Down
70 changes: 62 additions & 8 deletions .opencode/agent/triage.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
mode: primary
hidden: true
model: opencode/claude-haiku-4-5
model: opencode/minimax-m2.5
color: "#44BA81"
tools:
"*": false
Expand All @@ -12,6 +12,8 @@ You are a triage agent responsible for triaging github issues.

Use your github-triage tool to triage issues.

This file is the source of truth for ownership/routing rules.

## Labels

### windows
Expand Down Expand Up @@ -43,12 +45,30 @@ Desktop app issues:

**Only** add if the issue explicitly mentions nix.

If the issue does not mention nix, do not add nix.

If the issue mentions nix, assign to `rekram1-node`.

#### zen

**Only** add if the issue mentions "zen" or "opencode zen" or "opencode black".

If the issue doesn't have "zen" or "opencode black" in it then don't add zen label

#### core

Use for core server issues in `packages/opencode/`, excluding `packages/opencode/src/cli/cmd/tui/`.

Examples:

- LSP server behavior
- Harness behavior (agent + tools)
- Feature requests for server behavior
- Agent context construction
- API endpoints
- Provider integration issues
- New, broken, or poor-quality models

#### docs

Add if the issue requests better documentation or docs updates.
Expand All @@ -66,13 +86,47 @@ TUI issues potentially caused by our underlying TUI library:

When assigning to people here are the following rules:

adamdotdev:
ONLY assign adam if the issue will have the "desktop" label.
Desktop / Web:
Use for desktop-labeled issues only.

- adamdotdevin
- iamdavidhill
- Brendonovich
- nexxeln

Zen:
ONLY assign if the issue will have the "zen" label.

- fwang
- MrMushrooooom

TUI (`packages/opencode/src/cli/cmd/tui/...`):

- thdxr for TUI UX/UI product decisions and interaction flow
- kommander for OpenTUI engine issues: rendering artifacts, keybind handling, terminal compatibility, SSH behavior, and low-level perf bottlenecks
- rekram1-node for TUI bugs that are not clearly OpenTUI engine issues

Core (`packages/opencode/...`, excluding TUI subtree):

- thdxr for sqlite/snapshot/memory bugs and larger architectural core features
- jlongster for opencode server + API feature work (tool currently remaps jlongster -> thdxr until assignable)
- rekram1-node for harness issues, provider issues, and other bug-squashing

For core bugs that do not clearly map, either thdxr or rekram1-node is acceptable.

Docs:

- R44VC0RP

Windows:

- Hona (assign any issue that mentions Windows or is likely Windows-specific)

fwang:
ONLY assign fwang if the issue will have the "zen" label.
Determinism rules:

jayair:
ONLY assign jayair if the issue will have the "docs" label.
- If title + body does not contain "zen", do not add the "zen" label
- If "nix" label is added but title + body does not mention nix/nixos, the tool will drop "nix"
- If title + body mentions nix/nixos, assign to `rekram1-node`
- If "desktop" label is added, the tool will override assignee and randomly pick one Desktop / Web owner

In all other cases use best judgment. Avoid assigning to kommander needlessly, when in doubt assign to rekram1-node.
In all other cases, choose the team/section with the most overlap with the issue and assign a member from that team at random.
85 changes: 59 additions & 26 deletions .opencode/tool/github-triage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
/// <reference path="../env.d.ts" />
// import { Octokit } from "@octokit/rest"
import { tool } from "@opencode-ai/plugin"
import DESCRIPTION from "./github-triage.txt"

const TEAM = {
desktop: ["adamdotdevin", "iamdavidhill", "Brendonovich", "nexxeln"],
zen: ["fwang", "MrMushrooooom"],
tui: ["thdxr", "kommander", "rekram1-node"],
core: ["thdxr", "rekram1-node", "jlongster"],
docs: ["R44VC0RP"],
windows: ["Hona"],
} as const

const ASSIGNEES = [...new Set(Object.values(TEAM).flat())]

function pick<T>(items: readonly T[]) {
return items[Math.floor(Math.random() * items.length)]!
}

function getIssueNumber(): number {
const issue = parseInt(process.env.ISSUE_NUMBER ?? "", 10)
if (!issue) throw new Error("ISSUE_NUMBER env var not set")
Expand All @@ -29,60 +43,79 @@ export default tool({
description: DESCRIPTION,
args: {
assignee: tool.schema
.enum(["thdxr", "adamdotdevin", "rekram1-node", "fwang", "jayair", "kommander"])
.enum(ASSIGNEES as [string, ...string[]])
.describe("The username of the assignee")
.default("rekram1-node"),
labels: tool.schema
.array(tool.schema.enum(["nix", "opentui", "perf", "desktop", "zen", "docs", "windows"]))
.array(tool.schema.enum(["nix", "opentui", "perf", "web", "desktop", "zen", "docs", "windows", "core"]))
.describe("The labels(s) to add to the issue")
.default([]),
},
async execute(args) {
const issue = getIssueNumber()
// const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN })
const owner = "anomalyco"
const repo = "opencode"

const results: string[] = []
let labels = [...new Set(args.labels.map((x) => (x === "desktop" ? "web" : x)))]
const web = labels.includes("web")
const text = `${process.env.ISSUE_TITLE ?? ""}\n${process.env.ISSUE_BODY ?? ""}`.toLowerCase()
const zen = /\bzen\b/.test(text) || text.includes("opencode black")
const nix = /\bnix(os)?\b/.test(text)

if (labels.includes("nix") && !nix) {
labels = labels.filter((x) => x !== "nix")
results.push("Dropped label: nix (issue does not mention nix)")
}

const assignee = nix
? "rekram1-node"
: web
? pick(TEAM.desktop)
: args.assignee === "jlongster"
? "thdxr"
: args.assignee

if (args.assignee === "jlongster" && assignee === "thdxr") {
results.push("Remapped assignee: jlongster -> thdxr (jlongster not assignable yet)")
}

if (labels.includes("zen") && !zen) {
throw new Error("Only add the zen label when issue title/body contains 'zen'")
}

if (web && !nix && !(TEAM.desktop as readonly string[]).includes(assignee)) {
throw new Error("Web issues must be assigned to adamdotdevin, iamdavidhill, Brendonovich, or nexxeln")
}

if ((TEAM.zen as readonly string[]).includes(assignee) && !labels.includes("zen")) {
throw new Error("Only zen issues should be assigned to fwang or MrMushrooooom")
}

if (args.assignee === "adamdotdevin" && !args.labels.includes("desktop")) {
throw new Error("Only desktop issues should be assigned to adamdotdevin")
if (assignee === "Hona" && !labels.includes("windows")) {
throw new Error("Only windows issues should be assigned to Hona")
}

if (args.assignee === "fwang" && !args.labels.includes("zen")) {
throw new Error("Only zen issues should be assigned to fwang")
if (assignee === "R44VC0RP" && !labels.includes("docs")) {
throw new Error("Only docs issues should be assigned to R44VC0RP")
}

if (args.assignee === "kommander" && !args.labels.includes("opentui")) {
if (assignee === "kommander" && !labels.includes("opentui")) {
throw new Error("Only opentui issues should be assigned to kommander")
}

// await octokit.rest.issues.addAssignees({
// owner,
// repo,
// issue_number: issue,
// assignees: [args.assignee],
// })
await githubFetch(`/repos/${owner}/${repo}/issues/${issue}/assignees`, {
method: "POST",
body: JSON.stringify({ assignees: [args.assignee] }),
body: JSON.stringify({ assignees: [assignee] }),
})
results.push(`Assigned @${args.assignee} to issue #${issue}`)

const labels: string[] = args.labels.map((label) => (label === "desktop" ? "web" : label))
results.push(`Assigned @${assignee} to issue #${issue}`)

if (labels.length > 0) {
// await octokit.rest.issues.addLabels({
// owner,
// repo,
// issue_number: issue,
// labels,
// })
await githubFetch(`/repos/${owner}/${repo}/issues/${issue}/labels`, {
method: "POST",
body: JSON.stringify({ labels }),
})
results.push(`Added labels: ${args.labels.join(", ")}`)
results.push(`Added labels: ${labels.join(", ")}`)
}

return results.join("\n")
Expand Down
88 changes: 3 additions & 85 deletions .opencode/tool/github-triage.txt
Original file line number Diff line number Diff line change
@@ -1,88 +1,6 @@
Use this tool to assign and/or label a GitHub issue.

You can assign the following users:
- thdxr
- adamdotdevin
- fwang
- jayair
- kommander
- rekram1-node
Choose labels and assignee using the current triage policy and ownership rules.
Pick the most fitting labels for the issue and assign one owner.


You can use the following labels:
- nix
- opentui
- perf
- web
- zen
- docs

Always try to assign an issue, if in doubt, assign rekram1-node to it.

## Breakdown of responsibilities:

### thdxr

Dax is responsible for managing core parts of the application, for large feature requests, api changes, or things that require significant changes to the codebase assign him.

This relates to OpenCode server primarily but has overlap with just about anything

### adamdotdevin

Adam is responsible for managing the Desktop/Web app. If there is an issue relating to the desktop app or `opencode web` command. Assign him.


### fwang

Frank is responsible for managing Zen, if you see complaints about OpenCode Zen, maybe it's the dashboard, the model quality, billing issues, etc. Assign him to the issue.

### jayair

Jay is responsible for documentation. If there is an issue relating to documentation assign him.

### kommander

Sebastian is responsible for managing an OpenTUI (a library for building terminal user interfaces). OpenCode's TUI is built with OpenTUI. If there are issues about:
- random characters on screen
- keybinds not working on different terminals
- general terminal stuff
Then assign the issue to Him.

### rekram1-node

ALL BUGS SHOULD BE assigned to rekram1-node unless they have the `opentui` label.

Assign Aiden to an issue as a catch all, if you can't assign anyone else. Most of the time this will be bugs/polish things.
If no one else makes sense to assign, assign rekram1-node to it.

Always assign to aiden if the issue mentions "acp", "zed", or model performance issues

## Breakdown of Labels:

### nix

Any issue that mentions nix, or nixos should have a nix label

### opentui

Anything relating to the TUI itself should have an opentui label

### perf

Anything related to slow performance, high ram, high cpu usage, or any other performance related issue should have a perf label

### desktop

Anything related to `opencode web` command or the desktop app should have a desktop label. Never add this label for anything terminal/tui related

### zen

Anything related to OpenCode Zen, billing, or model quality from Zen should have a zen label

### docs

Anything related to the documentation should have a docs label

### windows

Use for any issue that involves the windows OS
If unsure, choose the team/section with the most overlap with the issue and assign a member from that team at random.
10 changes: 10 additions & 0 deletions infra/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,16 @@ const ZEN_MODELS = [
new sst.Secret("ZEN_MODELS18"),
new sst.Secret("ZEN_MODELS19"),
new sst.Secret("ZEN_MODELS20"),
new sst.Secret("ZEN_MODELS21"),
new sst.Secret("ZEN_MODELS22"),
new sst.Secret("ZEN_MODELS23"),
new sst.Secret("ZEN_MODELS24"),
new sst.Secret("ZEN_MODELS25"),
new sst.Secret("ZEN_MODELS26"),
new sst.Secret("ZEN_MODELS27"),
new sst.Secret("ZEN_MODELS28"),
new sst.Secret("ZEN_MODELS29"),
new sst.Secret("ZEN_MODELS30"),
]
const STRIPE_SECRET_KEY = new sst.Secret("STRIPE_SECRET_KEY")
const STRIPE_PUBLISHABLE_KEY = new sst.Secret("STRIPE_PUBLISHABLE_KEY")
Expand Down
15 changes: 15 additions & 0 deletions packages/app/e2e/commands/input-focus.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { test, expect } from "../fixtures"
import { promptSelector } from "../selectors"

test("ctrl+l focuses the prompt", async ({ page, gotoSession }) => {
await gotoSession()

const prompt = page.locator(promptSelector)
await expect(prompt).toBeVisible()

await page.locator("main").click({ position: { x: 5, y: 5 } })
await expect(prompt).not.toBeFocused()

await page.keyboard.press("Control+L")
await expect(prompt).toBeFocused()
})
Loading