Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
ddffb34
ignore: update download stats 2026-01-27
actions-user Jan 27, 2026
b6565c6
fix(app): auto-scroll button sometimes sticks
adamdotdevin Jan 27, 2026
c0a5f85
chore(app): missing tooltips
adamdotdevin Jan 27, 2026
58b9b54
feat(app): forward and back buttons
adamdotdevin Jan 27, 2026
2180be2
chore: cleanup
adamdotdevin Jan 27, 2026
1f93138
feat(core): add worktree to plugin tool context
adamdotdevin Jan 27, 2026
743e83d
fix(app): agent fallback colors
adamdotdevin Jan 27, 2026
095328f
fix(app): non-fatal error handling
adamdotdevin Jan 27, 2026
b4e0cdb
docs(core): plugin tool context updates
adamdotdevin Jan 27, 2026
3862b1a
fix(ui): set filetree tablist height to 48px with centered content
iamdavidhill Jan 27, 2026
03b9317
fix(app): center filetree empty state with 32px top margin
iamdavidhill Jan 27, 2026
ebfa2b5
fix(app): update review empty states to 14px and align select file em…
iamdavidhill Jan 27, 2026
52387e7
fix(app): only show left border on plus button when sticky
iamdavidhill Jan 27, 2026
2d0049f
fix(app): use smaller close icon on tabs to match comment cards
iamdavidhill Jan 27, 2026
c68261f
fix(ui): add max-width 280px to tabs with text truncation
iamdavidhill Jan 27, 2026
ad624f6
fix(app): don't show session skeleton after workspace reset
adamdotdevin Jan 27, 2026
3e420bf
perf(app): don't keep parts in memory
adamdotdevin Jan 27, 2026
c7e2f19
perf(app): cleanup connect provider timers
adamdotdevin Jan 27, 2026
27bb827
perf(app): shared terminal ghostty-web instance
adamdotdevin Jan 27, 2026
19c7874
fix(app): select model anchor
adamdotdevin Jan 27, 2026
c3d8d2b
Revert "fix(app): select model anchor"
adamdotdevin Jan 27, 2026
3297e52
fix(app): open markdown links in external browser
adamdotdevin Jan 27, 2026
eac2d4c
fix(app): navigate to tabs when opening file
adamdotdevin Jan 27, 2026
099ab92
chore(app): cleanup tailwind vs pure css
adamdotdevin Jan 27, 2026
00e7921
fix(app): tooltips causing getComputedStyle errors in model select
adamdotdevin Jan 27, 2026
712d2b7
fix(app): swallow file search errors
adamdotdevin Jan 27, 2026
d8e7e91
feat(opencode): Handle Venice cache creation tokens (#10735)
dpuyosa Jan 27, 2026
dbc8d7e
chore: generate
actions-user Jan 27, 2026
0aa9337
chore(docs): Better explanation on how to allow tools in external dir…
OpeOginni Jan 27, 2026
f12f7e7
tweak: adjust retry check to be more defensive
rekram1-node Jan 27, 2026
8c00818
ci: make tests passing a requirement pre-release
rekram1-node Jan 27, 2026
173faca
zen: kimi k2.5 and minimax m2.1
fwang Jan 27, 2026
2f5a238
feat(app): update settings in general settings
adamdotdevin Jan 27, 2026
06e3c4a
chore(app): translations
adamdotdevin Jan 27, 2026
b9edd23
test(app): new e2e smoke tests
adamdotdevin Jan 27, 2026
07d84fe
feat(app): show loaded agents.md files
adamdotdevin Jan 27, 2026
e2c5773
fix(app): session diffs not always loading
adamdotdevin Jan 27, 2026
7de42ca
feat(app): improved layout
adamdotdevin Jan 27, 2026
6284565
chore: generate
actions-user Jan 27, 2026
32ce0f4
tweak: add recommended topP/temp for kimi k2.5
rekram1-node Jan 27, 2026
bb63d16
Set temperature for kimi k2.5
fwang Jan 27, 2026
2649dca
Revert "ci: make tests passing a requirement pre-release"
fwang Jan 27, 2026
df8b23d
Revert "Set temperature for kimi k2.5"
fwang Jan 27, 2026
8206895
feat(app): color filetree change dots by diff kind
iamdavidhill Jan 27, 2026
8ee5376
feat(app): add filetree tooltips with diff labels
iamdavidhill Jan 27, 2026
2ca69ac
fix(app): shorten nav tooltips
iamdavidhill Jan 27, 2026
1fffbc6
fix(app): adjust titlebar left spacing
iamdavidhill Jan 27, 2026
d15201d
fix(app): delay nav tooltips
iamdavidhill Jan 27, 2026
18d6c21
fix(app): align filetree change styling
iamdavidhill Jan 27, 2026
00c7729
fix(app): set filetree padding to 6px
iamdavidhill Jan 27, 2026
f2bf620
fix(app): highlight selected change
iamdavidhill Jan 27, 2026
892113a
chore(app): show 5 highlights
adamdotdevin Jan 27, 2026
d7948c2
fix(app): auto-scroll
adamdotdevin Jan 27, 2026
1ebf63c
fix(app): don't connect to localhost through vpn
adamdotdevin Jan 27, 2026
842f17d
perf(app): better memory management
adamdotdevin Jan 27, 2026
acf0df1
chore: cleanup
adamdotdevin Jan 27, 2026
51edf68
feat(desktop): i18n for tauri side
adamdotdevin Jan 27, 2026
e5b1867
feat(desktop): tauri locales
adamdotdevin Jan 27, 2026
1d5ee3e
fix(app): not auto-navigating to last project
adamdotdevin Jan 27, 2026
95632d8
chore: update nix node_modules hashes
actions-user Jan 27, 2026
b8e7265
fix(tui): handle 4-5 codes too in c to copy logic
rekram1-node Jan 27, 2026
33d400c
fix(app): spinner color
adamdotdevin Jan 27, 2026
605e533
fix(app): file tree not always loading
adamdotdevin Jan 27, 2026
13b2587
test(app): fix outdated e2e test
adamdotdevin Jan 27, 2026
5c8580a
test(app): fix outdated e2e test
adamdotdevin Jan 27, 2026
d17ba84
fix(app): file tree not always loading
adamdotdevin Jan 27, 2026
df7f9ae
fix(app): terminal corruption
adamdotdevin Jan 27, 2026
15ffd3c
feat(app): add 'connect provider' button to the manage models dialog …
alexyaroshuk Jan 27, 2026
b4a9e1b
fix(app): auto-scroll
adamdotdevin Jan 27, 2026
898118b
feat: support headless authentication for chatgpt/codex (#10890)
rgodha24 Jan 28, 2026
d974186
fix(app): reintroduce review tab
adamdotdevin Jan 28, 2026
e3be4c9
release: v1.1.37
Jan 28, 2026
7988f52
feat(app): use opentui markdown component behind experimental flag (#…
remorses Jan 28, 2026
5f2a7c6
chore: generate
actions-user Jan 28, 2026
b73e024
docs: add Daytona OpenCode plugin to ecosystem (#10917)
jamesmurdza Jan 28, 2026
6da9fb8
chore: generate
actions-user Jan 28, 2026
aedd760
fix(cli): restore brand integrity of CLI wordmark (#10912)
mynameistito Jan 28, 2026
284441f
timeline tokens
pschiel Jan 15, 2026
f6312b4
Message stats and details dialog
xl0 Jan 25, 2026
f55aecb
Fix viewport scrolling for agent messages in session timeline
ariane-emory Jan 26, 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 STATS.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,4 @@
| 2026-01-24 | 6,371,019 (+274,783) | 2,156,870 (+60,635) | 8,527,889 (+335,418) |
| 2026-01-25 | 6,639,082 (+268,063) | 2,187,853 (+30,983) | 8,826,935 (+299,046) |
| 2026-01-26 | 6,941,620 (+302,538) | 2,232,115 (+44,262) | 9,173,735 (+346,800) |
| 2026-01-27 | 7,208,093 (+266,473) | 2,280,762 (+48,647) | 9,488,855 (+315,120) |
31 changes: 16 additions & 15 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions nix/hashes.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"nodeModules": {
"x86_64-linux": "sha256-AkI3guNjnE+bLZQVfzm0z14UENOECv2QBqMo5Lzkvt8=",
"aarch64-linux": "sha256-dBfdyVTqW+fBZKCxC9Ld+1m3cP+nIbS6UDo0tUfPOSk=",
"aarch64-darwin": "sha256-tOw31AMnHkW2cEDi+iqT3P93lU3SiMve26TEIqPz97k=",
"x86_64-darwin": "sha256-wL/DmdZmxCmh+r4dsS1XGXuj8VPwR4pUqy5VIA76jl0="
"x86_64-linux": "sha256-9oI1gekRbjY6L8VwlkLdPty/9rCxC20EJlESkazEX8Y=",
"aarch64-linux": "sha256-vn+eCVanOSNfjyqHRJn4VdqbpdMoBFm49REuIkByAio=",
"aarch64-darwin": "sha256-0dMP5WbqDq3qdLRrKfmCjXz2kUDjTttGTqD3v6PDbkg=",
"x86_64-darwin": "sha256-9dEWluRXY7RTPdSEhhPsDJeGo+qa3V8dqh6n6WsLeGw="
}
}
5 changes: 3 additions & 2 deletions packages/app/e2e/file-tree.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { test, expect } from "./fixtures"
test("file tree can expand folders and open a file", async ({ page, gotoSession }) => {
await gotoSession()

await page.getByRole("button", { name: "Toggle file tree" }).click()

const toggle = page.getByRole("button", { name: "Toggle file tree" })
const treeTabs = page.locator('[data-component="tabs"][data-variant="pill"][data-scope="filetree"]')

if ((await toggle.getAttribute("aria-expanded")) !== "true") await toggle.click()
await expect(treeTabs).toBeVisible()

await treeTabs.locator('[data-slot="tabs-trigger"]').nth(1).click()
Expand Down
86 changes: 86 additions & 0 deletions packages/app/e2e/models-visibility.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { test, expect } from "./fixtures"
import { modKey, promptSelector } from "./utils"

test("hiding a model removes it from the model picker", async ({ page, gotoSession }) => {
await gotoSession()

await page.locator(promptSelector).click()
await page.keyboard.type("/model")

const command = page.locator('[data-slash-id="model.choose"]')
await expect(command).toBeVisible()
await command.hover()
await page.keyboard.press("Enter")

const picker = page.getByRole("dialog")
await expect(picker).toBeVisible()

const target = picker.locator('[data-slot="list-item"]').first()
await expect(target).toBeVisible()

const key = await target.getAttribute("data-key")
if (!key) throw new Error("Failed to resolve model key from list item")

const name = (await target.locator("span").first().innerText()).trim()
if (!name) throw new Error("Failed to resolve model name from list item")

await page.keyboard.press("Escape")
await expect(picker).toHaveCount(0)

const settings = page.getByRole("dialog")

await page.keyboard.press(`${modKey}+Comma`).catch(() => undefined)
const opened = await settings
.waitFor({ state: "visible", timeout: 3000 })
.then(() => true)
.catch(() => false)

if (!opened) {
await page.getByRole("button", { name: "Settings" }).first().click()
await expect(settings).toBeVisible()
}

await settings.getByRole("tab", { name: "Models" }).click()
const search = settings.getByPlaceholder("Search models")
await expect(search).toBeVisible()
await search.fill(name)

const toggle = settings.locator('[data-component="switch"]').filter({ hasText: name }).first()
const input = toggle.locator('[data-slot="switch-input"]')
await expect(toggle).toBeVisible()
await expect(input).toHaveAttribute("aria-checked", "true")
await toggle.locator('[data-slot="switch-control"]').click()
await expect(input).toHaveAttribute("aria-checked", "false")

await page.keyboard.press("Escape")
const closed = await settings
.waitFor({ state: "detached", timeout: 1500 })
.then(() => true)
.catch(() => false)
if (!closed) {
await page.keyboard.press("Escape")
const closedSecond = await settings
.waitFor({ state: "detached", timeout: 1500 })
.then(() => true)
.catch(() => false)
if (!closedSecond) {
await page.locator('[data-component="dialog-overlay"]').click({ position: { x: 5, y: 5 } })
await expect(settings).toHaveCount(0)
}
}

await page.locator(promptSelector).click()
await page.keyboard.type("/model")
await expect(command).toBeVisible()
await command.hover()
await page.keyboard.press("Enter")

const pickerAgain = page.getByRole("dialog")
await expect(pickerAgain).toBeVisible()
await expect(pickerAgain.locator('[data-slot="list-item"]').first()).toBeVisible()

await expect(pickerAgain.locator(`[data-slot="list-item"][data-key="${key}"]`)).toHaveCount(0)

await page.keyboard.press("Escape")
await expect(pickerAgain).toHaveCount(0)
})
67 changes: 67 additions & 0 deletions packages/app/e2e/server-default.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { test, expect } from "./fixtures"
import { serverName, serverUrl } from "./utils"

const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl"

test("can set a default server on web", async ({ page, gotoSession }) => {
await page.addInitScript((key: string) => {
try {
localStorage.removeItem(key)
} catch {
return
}
}, DEFAULT_SERVER_URL_KEY)

await gotoSession()

const status = page.getByRole("button", { name: "Status" })
await expect(status).toBeVisible()
const popover = page.locator('[data-component="popover-content"]').filter({ hasText: "Manage servers" })

const ensurePopoverOpen = async () => {
if (await popover.isVisible()) return
await status.click()
await expect(popover).toBeVisible()
}

await ensurePopoverOpen()
await popover.getByRole("button", { name: "Manage servers" }).click()

const dialog = page.getByRole("dialog")
await expect(dialog).toBeVisible()

const row = dialog.locator('[data-slot="list-item"]').filter({ hasText: serverName }).first()
await expect(row).toBeVisible()

const menu = row.locator('[data-component="icon-button"]').last()
await menu.click()
await page.getByRole("menuitem", { name: "Set as default" }).click()

await expect.poll(() => page.evaluate((key) => localStorage.getItem(key), DEFAULT_SERVER_URL_KEY)).toBe(serverUrl)
await expect(row.getByText("Default", { exact: true })).toBeVisible()

await page.keyboard.press("Escape")
const closed = await dialog
.waitFor({ state: "detached", timeout: 1500 })
.then(() => true)
.catch(() => false)

if (!closed) {
await page.keyboard.press("Escape")
const closedSecond = await dialog
.waitFor({ state: "detached", timeout: 1500 })
.then(() => true)
.catch(() => false)

if (!closedSecond) {
await page.locator('[data-component="dialog-overlay"]').click({ position: { x: 5, y: 5 } })
await expect(dialog).toHaveCount(0)
}
}

await ensurePopoverOpen()

const serverRow = popover.locator("button").filter({ hasText: serverName }).first()
await expect(serverRow).toBeVisible()
await expect(serverRow.getByText("Default", { exact: true })).toBeVisible()
})
56 changes: 56 additions & 0 deletions packages/app/e2e/settings-providers.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { test, expect } from "./fixtures"
import { modKey, promptSelector } from "./utils"

test("smoke providers settings opens provider selector", async ({ page, gotoSession }) => {
await gotoSession()

const dialog = page.getByRole("dialog")

await page.keyboard.press(`${modKey}+Comma`).catch(() => undefined)

const opened = await dialog
.waitFor({ state: "visible", timeout: 3000 })
.then(() => true)
.catch(() => false)

if (!opened) {
await page.getByRole("button", { name: "Settings" }).first().click()
await expect(dialog).toBeVisible()
}

await dialog.getByRole("tab", { name: "Providers" }).click()
await expect(dialog.getByText("Connected providers", { exact: true })).toBeVisible()
await expect(dialog.getByText("Popular providers", { exact: true })).toBeVisible()

await dialog.getByRole("button", { name: "Show more providers" }).click()

const providerDialog = page.getByRole("dialog").filter({ has: page.getByPlaceholder("Search providers") })

await expect(providerDialog).toBeVisible()
await expect(providerDialog.getByPlaceholder("Search providers")).toBeVisible()
await expect(providerDialog.locator('[data-slot="list-item"]').first()).toBeVisible()

await page.keyboard.press("Escape")
await expect(providerDialog).toHaveCount(0)
await expect(page.locator(promptSelector)).toBeVisible()

const stillOpen = await dialog.isVisible().catch(() => false)
if (!stillOpen) return

await page.keyboard.press("Escape")
const closed = await dialog
.waitFor({ state: "detached", timeout: 1500 })
.then(() => true)
.catch(() => false)
if (closed) return

await page.keyboard.press("Escape")
const closedSecond = await dialog
.waitFor({ state: "detached", timeout: 1500 })
.then(() => true)
.catch(() => false)
if (closedSecond) return

await page.locator('[data-component="dialog-overlay"]').click({ position: { x: 5, y: 5 } })
await expect(dialog).toHaveCount(0)
})
Loading