You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FEATURE]: Restore the legacy UI with the persistent left sidebar as an option #48882
I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
The recent sidebar redesign (#20242) replaced the classic two-panel layout
(persistent left sidebar + session panel) with a Codex-style unified view.
For me this is not a visual refresh — it removed the single most important
part of my daily workflow, and there is currently no way to go back.
What I want changed / added:
Keep the legacy UI with the persistent left sidebar available as an
option (a legacy / classic UI toggle or config flag is enough — it
doesn't have to be the default).
If the legacy layout can't be maintained, at minimum restore an always-visible left sidebar — not hover-only menus or a collapsed rail
that requires extra clicks.
Why this matters (the benefit):
I live inside opencode for hours every day. The left sidebar gives me an
at-a-glance, persistent view of my projects, workspaces, and sessions:
I can see and switch between projects/contexts without breaking flow.
Sessions are one click away, not buried behind hover or search.
Context switching stays fast and predictable.
The new interface hides all of this behind a single unified list with
hover/focus interactions. Every session feels slower and more disoriented.
This is not an aesthetic preference — removing the sidebar with no escape
hatch is a functional regression for anyone who relies on it.
Happy to provide screenshots, my opencode version, and platform details if
that helps. Please don't leave those of us who depend on the left sidebar
behind.
Reacted by intlex, hxl11Zzz, diuwu, 严浩, ellamas-grupoarpada, Kevin Riemens, beliefchen398, Eugene, Igor Chakrygin, Florian Buenzli and 37 more
写了个powersell脚本,替换opencode打包后的 asar 里面的新布局判断逻辑强制使用旧布局,执行powershell,输入asar的文件夹,通常是: C:\Users\%Username%\AppData\Local\Programs\@opencode-aidesktop\resources
注意替换路径里面的用户名,脚本会自动备份当前的asar,执行完成后重启opencode即可,支持 1.18.30 版本
注意:每次更新opencode后需要重新执行
I wrote a PowerShell script that replaces the new layout detection logic inside the packaged asar of opencode, forcing it to use the old layout. Run PowerShell and enter the asar folder, which is usually: C:\Users\%Username%\AppData\Local\Programs\@opencode-aidesktop\resources
Note: replace the username in the path. The script will automatically back up the current asar. After it finishes, just restart opencode. It supports version 1.18.30.
Note: You need to run it again after each opencode update.
script
generated by ai
Copy and save it as a .ps1 file, then run it.
$ErrorActionPreference="Stop"# Wait for a key press so the console window does not close before the result is visible.functionWait-Key {
Write-Host""Write-Host"Press any key to exit ..."
[void][Console]::ReadKey($true)
}
# ---------- Step 0: locate app.asar ----------Write-Host"[1/8] Resolve app.asar path from the folder you provide ..."$inputPath=Read-Host"Enter the opencode install folder"$inputPath=$inputPath.Trim().Trim('"',"'")
if ([string]::IsNullOrWhiteSpace($inputPath)) {
Write-Host"Error: path cannot be empty."Wait-Keyexit1
}
if (-not (Test-Path-LiteralPath $inputPath-PathType Container)) {
Write-Host"Error: folder not found: $inputPath"Wait-Keyexit1
}
# 只接受文件夹:优先找其下的 resources\app.asar,其次文件夹内直接存在的 app.asar$item=Get-Item-LiteralPath $inputPath$candidates=@(
(Join-Path$item.FullName"resources\app.asar"),
(Join-Path$item.FullName"app.asar")
)
$AsarPath=$nullforeach ($candidatein$candidates) {
if (Test-Path-LiteralPath $candidate-PathType Leaf) {
$AsarPath=$candidatebreak
}
}
if (-not$AsarPath) {
Write-Host"Error: no app.asar found under: $($item.FullName)"Write-Host"Expected at 'resources\app.asar' or 'app.asar'."Wait-Keyexit1
}
Write-Host" app.asar: $AsarPath"# ---------- Step 1: prepare equal-length replacement ----------Write-Host"[2/8] Building equal-length replacement string ..."$target="if (layoutUpgrade()) return true;"$replacement="return false;"$pad=""* ($target.Length-$replacement.Length)
$newString=$replacement+$pad# Equal-length invariant must hold, otherwise the ASAR header offsets break.if ($newString.Length-ne$target.Length) {
Write-Host"Error: equal-length invariant broken."Wait-Keyexit1
}
Write-Host" target len: $($target.Length) / replacement len: $($newString.Length)"# ---------- Step 2: read bytes ----------Write-Host"[3/8] Reading bytes from $AsarPath ..."$targetBytes= [System.Text.Encoding]::ASCII.GetBytes($target)
$newBytes= [System.Text.Encoding]::ASCII.GetBytes($newString)
$bytes= [System.IO.File]::ReadAllBytes($AsarPath)
Write-Host" read $($bytes.Length) bytes"# Naive scan for a byte sub-sequence; good enough for a short needle.functionFind-Bytes {
param(
[byte[]]$Data,
[byte[]]$Pattern,
[int]$StartIndex=0
)
$last=$Data.Length-$Pattern.Lengthfor ($i=$StartIndex; $i-le$last; $i++) {
if ($Data[$i] -ne$Pattern[0]) { continue }
$ok=$truefor ($j=1; $j-lt$Pattern.Length; $j++) {
if ($Data[$i+$j] -ne$Pattern[$j]) {
$ok=$falsebreak
}
}
if ($ok) { return$i }
}
return-1
}
# ---------- Step 3: search for target ----------Write-Host"[4/8] Searching for target string ..."$index=Find-Bytes-Data $bytes-Pattern $targetBytesif ($index-lt0) {
Write-Host" Target string not found; maybe already locked."Wait-Keyexit0
}
Write-Host" found at offset $index"# Ensure the match is unique so we never patch the wrong spot.$second=Find-Bytes-Data $bytes-Pattern $targetBytes-StartIndex ($index+1)
if ($second-ne-1) {
Write-Host"Error: multiple matches found (offset $second); aborting."Wait-Keyexit1
}
# ---------- Step 4: backup ----------Write-Host"[5/8] Creating backup ..."$bakPath= [System.IO.Path]::ChangeExtension($AsarPath,"asar.bak")
if (-not (Test-Path-LiteralPath $bakPath)) {
Copy-Item-LiteralPath $AsarPath-Destination $bakPathWrite-Host" Backup created: $bakPath"
}
else {
Write-Host" Backup exists, skip: $bakPath"
}
# ---------- Step 5: patch in memory ----------Write-Host"[6/8] Applying equal-length replacement ..."$originalLength=$bytes.Length# Overwrite the matched region with the equal-length replacement.
[System.Array]::Copy($newBytes,0,$bytes,$index,$newBytes.Length)
if ($bytes.Length-ne$originalLength) {
Write-Host"Error: array length changed; aborting before write."Wait-Keyexit1
}
# ---------- Step 6: write back ----------Write-Host"[7/8] Writing patched bytes back ..."
[System.IO.File]::WriteAllBytes($AsarPath,$bytes)
# ---------- Step 7: verify ----------Write-Host"[8/8] Verifying patched region ..."$verifyBytes= [System.IO.File]::ReadAllBytes($AsarPath)
$verifySlice=$verifyBytes[$index..($index+$newBytes.Length-1)]
$verifyText= [System.Text.Encoding]::ASCII.GetString($verifySlice)
if (-not$verifyText.StartsWith($replacement)) {
Write-Host"Error: verification failed; unexpected content after write."Wait-Keyexit1
}
Write-Host"Success: old layout locked."Wait-Key
Reacted by 0-SamboNZ-0, 理查德, qingfengguoyun, QQQ27, beliefchen398, Meepo268, Axel Po, Kirill Lebedinov, Liu Peng and ANXETY
Keep legacy layout option
If the new layout is used, I never want to use it again.
Reacted by 0-SamboNZ-0, kapaandyy, 理查德, qingfengguoyun, ellamas-grupoarpada, Axel Po, tommy-codez, beliefchen398, Magnus Shaffer, ZenDevMaster and 2 more
写了个powersell脚本,替换opencode打包后的 asar 里面的新布局判断逻辑强制使用旧布局,执行powershell,输入asar的文件夹,通常是: C:\Users\%Username%\AppData\Local\Programs\@opencode-aidesktop\resources 注意替换路径里面的用户名,脚本会自动备份当前的asar,执行完成后重启opencode即可,支持 1.18.30 版本 注意:每次更新opencode后需要重新执行
I wrote a PowerShell script that replaces the new layout detection logic inside the packaged asar of opencode, forcing it to use the old layout. Run PowerShell and enter the asar folder, which is usually: C:\Users\%Username%\AppData\Local\Programs\@opencode-aidesktop\resources Note: replace the username in the path. The script will automatically back up the current asar. After it finishes, just restart opencode. It supports version 1.18.30. Note: You need to run it again after each opencode update.
script
generated by ai
Copy and save it as a .ps1 file, then run it.
$ErrorActionPreference = "Stop"
Wait for a key press so the console window does not close before the result is visible.
function Wait-Key {
Write-Host ""
Write-Host "Press any key to exit ..."
[void][Console]::ReadKey($true)
}
---------- Step 0: locate app.asar ----------
Write-Host "[1/8] Resolve app.asar path from the folder you provide ..."
$inputPath = Read-Host "Enter the opencode install folder"
$inputPath = $inputPath.Trim().Trim('"', "'")
if ([string]::IsNullOrWhiteSpace($inputPath)) {
Write-Host "Error: path cannot be empty."
Wait-Key
exit 1
}
if (-not (Test-Path -LiteralPath $inputPath -PathType Container)) {
Write-Host "Error: folder not found: $inputPath"
Wait-Key
exit 1
}
Write-Host "[1/8] Resolve app.asar path from the folder you provide ..."
$inputPath = Read-Host "Enter the opencode install folder"
$inputPath = $inputPath.Trim().Trim([char[]]@([char]34, [char]39))
if ([string]::IsNullOrWhiteSpace($inputPath)) {
Write-Host "Error: path cannot be empty."
Wait-Key
exit 1
}
if (-not (Test-Path -LiteralPath $inputPath -PathType Container)) {
Write-Host "Error: folder not found: $inputPath"
Wait-Key
exit 1
}
if (-not $asarPath) {
Write-Host "Error: no app.asar found under: $($item.FullName)"
Write-Host "Expected at 'resources\app.asar' or 'app.asar'."
Wait-Key
exit 1
}
Write-Host " app.asar: $asarPath"
I HATE the new layout. I stayed on an old version for quite a while for the old layout, and then forgot one day and updated. HATE IT. PLEASE add a toggle to restore the old layout. The new one is AWFUL.
Reacted by Eugene, daudef, Kyle Anderson, 0-SamboNZ-0 and 理查德
The recent change to force the new layout completely breaks the mental model that the previous layout encouraged. I no longer have easy visibility over which one of my projects has active agent activity. I'm left to try to infer the activity from the thread's title, which might not always be relevant or accurate. This adds friction and confusion that is completely unnecessary.
The old layout needs to stay as a configurable option in order to support the workflows we've grown to love as we've used this tool.
Thanks for the detailed write-up! You're asking for the classic layout, with an always-visible left sidebar showing projects, workspaces and sessions, to come back as an option (it doesn't have to be the default). If that isn't possible, you'd like at least a left sidebar that stays visible instead of hover menus or a collapsed rail. Maintainers will consider it, and this issue is where the request is being tracked. Others asking for the same thing are pointed here, so 👍 reactions and use cases on this issue help.
Until then, Settings → Appearance → Tabs → Vertical puts session tabs in a sidebar on the left instead of across the top. It isn't the old project → workspace → session tree, but it may get you closer.
Why to change things? Go and create another application instead. Oh my god whata fucking imitation of improvements. I mean you made UI once, don't touch it anymore. My bank application changed 100 times and still piece of shit. Don't touch UI, why I should revert your changes every time!
i think they have changed it but seems nobody is reading the issues here.
This is the current settings of opencode and i see this with a brand new installation. On my existing one, which is a continuous upgrade, i can't.
For anyone landing here: a persistent project sidebar is in v2.2.7, behind two settings.
Settings → General → Interface layout → Side tabs
Settings → Experimental → Organize vertical sidebar → Projects
From the code (sidebar-organized.tsx), that gives you a sidebar that stays open next to the session, grouped by project. It lists the project's sessions, not just open tabs: 5 per project and 7 projects, each with Show more. Each session shows a spinner while it's running and a dot when it's unread, and you can drag projects to reorder them.
That covers most of what's asked above: seeing which project has a running session, and switching in one click without going Home. What it doesn't cover yet: workspaces as their own level, and phones (side tabs are desktop-only).
A small suggestion for maintainers: once it leaves Experimental, a one-click "Classic sidebar" choice in Interface layout would help the people in this thread, and in the closed duplicates (#48837, #37012, #39835, #37546), find it.
Activity
github-actions commentedon Sep 14, 2026
This issue might be a duplicate of existing issues. Please check:
Please review these issues and consider adding your feedback there instead, or linking them as related.
HRronaldo commentedon Sep 14, 2026
win11 opencode desktop
version:v1.18.30
zhengxingjian commentedon Sep 14, 2026
准备换deepseek-harness,新布局生产力不行
aa2013 commentedon Sep 14, 2026
新UI太难用了,完全没用旧UI好用,新UI操作太反人类
0-SamboNZ-0 commentedon Sep 14, 2026
I also agree that the original layout was MUCH easier to use; this is a significant loss for usability!
aa2013 commentedon Sep 14, 2026
写了个powersell脚本,替换opencode打包后的
asar里面的新布局判断逻辑强制使用旧布局,执行powershell,输入asar的文件夹,通常是:C:\Users\%Username%\AppData\Local\Programs\@opencode-aidesktop\resources注意替换路径里面的用户名,脚本会自动备份当前的asar,执行完成后重启opencode即可,支持 1.18.30 版本
注意:每次更新opencode后需要重新执行
I wrote a PowerShell script that replaces the new layout detection logic inside the packaged
asarof opencode, forcing it to use the old layout. Run PowerShell and enter the asar folder, which is usually:C:\Users\%Username%\AppData\Local\Programs\@opencode-aidesktop\resourcesNote: replace the username in the path. The script will automatically back up the current asar. After it finishes, just restart opencode. It supports version 1.18.30.
Note: You need to run it again after each opencode update.
script
JamesLi2013 commentedon Sep 14, 2026
Keep legacy layout option
If the new layout is used, I never want to use it again.
diuwu commentedon Sep 14, 2026
We strongly demand that the old layout be restored. Ever since it was changed to the new layout, my colleagues and I have all given up on opencode.
0-SamboNZ-0 commentedon Sep 14, 2026
Beautiful! Works perfectly! Thank you for sharing!
ellamas-grupoarpada commentedon Sep 14, 2026
Works! Thanks!
Made opencode check for security, and it added timestamped .bak (just in case of repetition):
$ErrorActionPreference = "Stop"
Wait for a key press so the console window does not close before the result is visible.
function Wait-Key {
Write-Host ""
Write-Host "Press any key to exit ..."
[void][Console]::ReadKey($true)
}
function Find-Bytes {
param(
[byte[]]$Data,
[byte[]]$Pattern,
[int]$StartIndex = 0
)
}
Write-Host "[1/8] Resolve app.asar path from the folder you provide ..."
$inputPath = Read-Host "Enter the opencode install folder"
$inputPath = $inputPath.Trim().Trim([char[]]@([char]34, [char]39))
if ([string]::IsNullOrWhiteSpace($inputPath)) {
Write-Host "Error: path cannot be empty."
Wait-Key
exit 1
}
if (-not (Test-Path -LiteralPath $inputPath -PathType Container)) {
Write-Host "Error: folder not found: $inputPath"
Wait-Key
exit 1
}
$item = Get-Item -LiteralPath $inputPath
$candidates = @(
(Join-Path $item.FullName "resources\app.asar"),
(Join-Path $item.FullName "app.asar")
)
$asarPath = $null
foreach ($candidate in $candidates) {
if (Test-Path -LiteralPath $candidate -PathType Leaf) {
$asarPath = $candidate
break
}
}
if (-not $asarPath) {
Write-Host "Error: no app.asar found under: $($item.FullName)"
Write-Host "Expected at 'resources\app.asar' or 'app.asar'."
Wait-Key
exit 1
}
Write-Host " app.asar: $asarPath"
Write-Host "[2/8] Building equal-length replacement string ..."
$target = "if (layoutUpgrade()) return true;"
$replacement = "return false;"
$paddingLength = $target.Length - $replacement.Length
if ($paddingLength -lt 0) {
Write-Host "Error: replacement is longer than target."
Wait-Key
exit 1
}
$newString = $replacement + (" " * $paddingLength)$target.Length) / replacement len: $ ($newString.Length)"
if ($newString.Length -ne $target.Length) {
Write-Host "Error: equal-length invariant broken."
Wait-Key
exit 1
}
Write-Host " target len: $(
Write-Host "[3/8] Reading bytes from $asarPath ..."
$targetBytes = [System.Text.Encoding]::ASCII.GetBytes($target)
$newBytes = [System.Text.Encoding]::ASCII.GetBytes($newString)
$bytes = [System.IO.File]::ReadAllBytes($asarPath)
Write-Host " read $($bytes.Length) bytes"
Write-Host "[4/8] Searching for target string ..."
$index = Find-Bytes -Data $bytes -Pattern $targetBytes
if ($index -lt 0) {
Write-Host " Target string not found; no changes were made."
Wait-Key
exit 0
}
Write-Host " found at offset $index"
$second = Find-Bytes -Data $bytes -Pattern $targetBytes -StartIndex ($index + 1)
if ($second -ne -1) {
Write-Host "Error: multiple matches found (second offset: $second); aborting."
Wait-Key
exit 1
}
Write-Host "[5/8] Creating timestamped backup ..."
$timestamp = Get-Date -Format "yyyyMMddHHmmss"
$backupPath = "$asarPath.$timestamp.bak"
if (Test-Path -LiteralPath $backupPath) {
Write-Host "Error: backup already exists: $backupPath"
Wait-Key
exit 1
}
Copy-Item -LiteralPath $asarPath -Destination $backupPath
Write-Host " Backup created: $backupPath"
Write-Host "[6/8] Applying equal-length replacement ..."
$originalLength = $bytes.Length
[System.Array]::Copy($newBytes, 0, $bytes, $index, $newBytes.Length)
if ($bytes.Length -ne $originalLength) {
Write-Host "Error: array length changed; aborting before write."
Wait-Key
exit 1
}
try {
Write-Host "[7/8] Writing patched bytes back ..."
[System.IO.File]::WriteAllBytes($asarPath, $bytes)
}$($ .Exception.Message)"
catch {
Write-Host "Error: patch failed:
Write-Host " Restoring backup ..."
try {
Copy-Item -LiteralPath $backupPath -Destination $asarPath -Force
Write-Host " Original file restored."
}
catch {
Write-Host "CRITICAL: automatic restore failed: $($.Exception.Message)"
Write-Host " Restore manually from: $backupPath"
}
}
Write-Host "Success: old layout locked."
Write-Host "Backup: $backupPath"
Wait-Key
pav18 commentedon Sep 14, 2026
Thank you so much for your script!!!!!
enngins commentedon Sep 14, 2026
Guys WTH!
We really need to patch it for old (NORMAL) layout? I can't image who can work with this new dumb's interface.
drobin04 commentedon Sep 14, 2026
I HATE the new layout. I stayed on an old version for quite a while for the old layout, and then forgot one day and updated. HATE IT. PLEASE add a toggle to restore the old layout. The new one is AWFUL.
kmanderson12 commentedon Sep 14, 2026
The recent change to force the new layout completely breaks the mental model that the previous layout encouraged. I no longer have easy visibility over which one of my projects has active agent activity. I'm left to try to infer the activity from the thread's title, which might not always be relevant or accurate. This adds friction and confusion that is completely unnecessary.
The old layout needs to stay as a configurable option in order to support the workflows we've grown to love as we've used this tool.
30 remaining items
hq20211124 commentedon Oct 28, 2026
看了下两个左侧的模式,都不对,不便于使用,不直观,反而搞太复杂了:1.应该是按照项目空间,在左侧用二级菜单可以展开收起;2.正在运行中的项目也不用可以搞个模式,只需要在对应对话标题标一个绿色气泡就好了;3.需要大空间可以直接一键折叠左侧;
nippur72 commentedon Oct 28, 2026
I had to switch to Cline desktop or DSH because of this :-(
opencodejr commentedon Oct 28, 2026
Thanks for the detailed write-up! You're asking for the classic layout, with an always-visible left sidebar showing projects, workspaces and sessions, to come back as an option (it doesn't have to be the default). If that isn't possible, you'd like at least a left sidebar that stays visible instead of hover menus or a collapsed rail. Maintainers will consider it, and this issue is where the request is being tracked. Others asking for the same thing are pointed here, so 👍 reactions and use cases on this issue help.
Until then, Settings → Appearance → Tabs → Vertical puts session tabs in a sidebar on the left instead of across the top. It isn't the old project → workspace → session tree, but it may get you closer.
Related issues:
albgen commentedon Oct 28, 2026
we are talking about the Desktop version here you dumb bot
Evil-Spirit commentedon Nov 3, 2026
Why to change things? Go and create another application instead. Oh my god whata fucking imitation of improvements. I mean you made UI once, don't touch it anymore. My bank application changed 100 times and still piece of shit. Don't touch UI, why I should revert your changes every time!
albgen commentedon Nov 3, 2026
i think they have changed it but seems nobody is reading the issues here.

This is the current settings of opencode and i see this with a brand new installation. On my existing one, which is a continuous upgrade, i can't.
ngutech21 commentedon Nov 3, 2026
@albgen The tabs are not grouped by project. It‘s just a flat list
VL4DST3R commentedon Nov 3, 2026
They virtually never do. Wish someone with enough claude tokens would just vibecode the v1 ui back at this point.
albgen commentedon Nov 3, 2026
True. Way better though than having only horisontal tabs.
boesbo commentedon Nov 3, 2026
I will contribute to this: #60867
joe-ieta commentedon Nov 4, 2026
Side tab mode is just a simple list. far behind from competitors.
joe-ieta commentedon Nov 4, 2026
实在忍不了了,最近修改了一个Side bar模式,看看 #60867
pav18 commentedon Nov 10, 2026
YEEESSSSS Projects in the sidebar (Experimental Settings)
balabommablock-cpu commentedon Nov 13, 2026
For anyone landing here: a persistent project sidebar is in v2.2.7, behind two settings.
From the code (
sidebar-organized.tsx), that gives you a sidebar that stays open next to the session, grouped by project. It lists the project's sessions, not just open tabs: 5 per project and 7 projects, each with Show more. Each session shows a spinner while it's running and a dot when it's unread, and you can drag projects to reorder them.That covers most of what's asked above: seeing which project has a running session, and switching in one click without going Home. What it doesn't cover yet: workspaces as their own level, and phones (side tabs are desktop-only).
A small suggestion for maintainers: once it leaves Experimental, a one-click "Classic sidebar" choice in Interface layout would help the people in this thread, and in the closed duplicates (#48837, #37012, #39835, #37546), find it.