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
Auto update should never auto upgrade from v1 to v2 #54066
OpenCode v1 and v2 are incompatible. For example, session database are different. Plugin API are different. Thus, upgrading from v1 to v2 should always a human decision. Even when auto update is enabled, auto update should never automatically upgrade from v1 to v2.
Otherwise, plugins would fail, human tasks would be interrupted. This also make session database not possible to downgrade if human try to reinstall v1 to resume working.
Thanks for raising this, @jeffhung. Moving from v1 to v2 is a big change, and we agree it shouldn't happen without the user deciding to.
For context: the current v1 auto-updater installs only patch releases by itself. For a minor or major release (including 1.x → 2.x), it only shows an "update available" notice. Its npm path also updates the v1 package opencode-ai, not v2's @opencode/cli. So we'd like to find out whether this actually happened to you, and if so, how. Could you share:
The v1 version you were running before (opencode --version, if you still know it) and the v2 version you ended up on.
How OpenCode was installed (npm/bun/pnpm, Homebrew, the curl install script, Scoop, Chocolatey, desktop app, …).
Your autoupdate setting, if you set one.
What you saw: did OpenCode upgrade itself while running, or did the new version show up after something else, such as brew upgrade, opencode upgrade or reinstalling?
Your operating system.
If this is a general suggestion rather than something that happened to you, please say so too.
You can reply here with the details, or edit the issue. If you edit it, please also leave a comment saying you've updated it, so we know you're done editing.
I didn't find an existing report of the same thing. These issues are related (ordered by how closely they relate):
I also asked immediately: "Why you upgrade opencode to v2 without my agreement?"
Below is the results:
I investigated this thoroughly. Here's what actually happened.
It wasn't me — OpenCode upgraded itself
I found the exact event in OpenCode's own log (~/.local/share/opencode/log/opencode.log):
2026-10-09T05:40:52Z message=upgraded method=brew target=2.0.25
opencode 1.18.30 -> 2.0.20
The timeline today (13:40 local time):
1. You launched a new OpenCode session in ai-fearlessly running 1.18.30 (V1).
2. Nine seconds later, OpenCode's built-in auto-update kicked in — it detected a newer release and ran brew upgrade opencode by itself, taking you from 1.18.30 → 2.0.20.
3. Homebrew then cleaned up the old version (Removing: /opt/homebrew/Cellar/opencode/1.18.30).
Why this crossed the 1.x → 2.x line
A few things combined:
- You installed OpenCode via Homebrew (installed_on_request: True in the install receipt), and OpenCode knows how to self-upgrade through Homebrew (method=brew).
- Auto-update was enabled — it wasn't disabled in your config. Your ~/.config/opencode/opencode.json only sets plugin and instructions; there's no auto-update opt-out.
- The Homebrew formula now points at the 2.x line, so "newest version" meant "V2". A 1.x → 2.x jump is what a major release does; the updater doesn't hold back major versions.
I also checked your shell history — there's no brew upgrade or opencode upgrade in it. This wasn't a manual command, and no agent session ran one either. The log line is emitted by OpenCode's own upgrade routine (run=87e976ba, the server process), not by a spawned shell command.
Thanks for the details and the log line, @jeffhung. They made this reproducible.
I reproduced it with 1.18.30 set up as a Homebrew install (on Linux, with a stand-in brew and the real Homebrew formula data, which now reports opencode at 2.0.25):
A few seconds after the TUI starts, an "Update Available — A new release v2.0.25 is available. Would you like to update now?" dialog opens, with Confirm already selected.
Typing a first prompt and pressing Enter confirms that dialog instead. OpenCode shows "Updating to v2.0.25" and runs brew upgrade opencode. Running opencode upgrade directly logs upgraded method=brew target=2.0.25, the same target as in your log.
So the background auto-update did not install 2.x on its own; it only installs patch releases by itself. The upgrade comes from this dialog: it defaults to Confirm and doesn't warn that 2.x is a separate, incompatible line, so an Enter meant for your prompt can start it. The current v1 code has the same dialog. It mainly affects Homebrew installs, because the Homebrew formula now points to 2.x, while npm and the GitHub releases still point to 1.18.35.
The script below reproduces it. It drives the v1 TUI in a pseudo-terminal, so there is no video. The maintainers will look at it.
Until then, to stay on v1 you can set "autoupdate": "notify" or false in your config, choose Skip when the dialog appears, and pin the formula with brew pin opencode so brew upgrade leaves it alone.
Reproduction script (repro.py)
#!/usr/bin/env python3"""Reproduce #54066: opencode v1 (1.18.30) installed via Homebrew upgrades to 2.xwith a single Enter keypress shortly after startup.Setup (done before running): npm pack opencode-linux-x64@1.18.30 && tar xzf opencode-linux-x64-1.18.30.tgz -> ./v1/package/bin/opencode ./fakebin/brew : fake Homebrew that reports the core formula "opencode" as installed and logs calls.The real formulae.brew.sh API is queried for "latest" (currently 2.0.25).The script starts the v1 TUI in a pseudo-terminal, waits a few seconds (as a userwould before typing), types a prompt and presses Enter, then checks the fake brew log."""importos, pty, select, time, re, shutil, sysROOT=os.path.dirname(os.path.abspath(__file__))
BIN=os.path.join(ROOT, "v1/package/bin/opencode")
HOME="/tmp/oc-v1-home"LOG=os.path.join(ROOT, "fake-brew.log")
shutil.rmtree(HOME, ignore_errors=True)
os.makedirs(HOME+"/project", exist_ok=True)
ifos.path.exists(LOG):
os.remove(LOG)
env= {
"HOME": HOME,
"PATH": os.path.join(ROOT, "fakebin") +":/usr/bin:/bin", # no npm/bun: only brew detected"TERM": "xterm-256color",
"FAKE_BREW_LOG": LOG,
**({"OPENCODE_ALWAYS_NOTIFY_UPDATE": "1"} ifos.environ.get("ALWAYS") else {}),
"COLUMNS": "120", "LINES": "40",
**{k: vfork, vinos.environ.items() ifkin ("SSL_CERT_DIR", "SSL_CERT_FILE", "NODE_EXTRA_CA_CERTS", "FAKE_BREW_DELAY")},
}
pid, fd=pty.fork()
ifpid==0:
os.chdir(HOME+"/project")
os.execve(BIN, [BIN] +sys.argv[1:], env)
buf=b""defpump(sec):
globalbufend=time.time() +secwhiletime.time() <end:
r, _, _=select.select([fd], [], [], 0.2)
ifr:
try:
d=os.read(fd, 65536)
exceptOSError:
returnbuf+=d# answer cursor position / terminal queries minimallyifb"\x1b[6n"ind:
os.write(fd, b"\x1b[1;1R")
deftext():
returnre.sub(rb"\x1b\[[0-9;?<>=]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(\x07|\x1b\\)|\x1b.", b"", buf).decode("utf8", "ignore")
pump(int(os.environ.get("WAIT","30")))
t=text()
print("Update dialog shown:", "Update Available"int)
m=re.search(r"A new release v[0-9.]+ is available[^\n]*", t)
print("Dialog text:", m.group(0) ifmelseNone)
# User starts typing their first prompt and presses Enterforchin"hello":
os.write(fd, ch.encode()); time.sleep(0.05)
os.write(fd, b"\r")
pump(8)
t=text()
print("Updating toast:", re.search(r"Updating to v[0-9.]+", t).group(0) ifre.search(r"Updating to v[0-9.]+", t) elseNone)
print("Update complete:", re.search(r"Successfully updated to OpenCode v[0-9.]+", t).group(0) ifre.search(r"Successfully updated to OpenCode v[0-9.]+", t) elseNone)
print("--- fake brew log ---")
print(open(LOG).read() ifos.path.exists(LOG) else"(none)")
open(os.path.join(ROOT,"screen.txt"),"w").write(text())
os.kill(pid, 9)
ok=os.path.exists(LOG) and"brew upgrade opencode"inopen(LOG).read()
print("REPRODUCED"ifokelse"NOT REPRODUCED")
sys.exit(0ifokelse1)
Yes. I was entering my prompt. The dialog flashed and it must thought it received confirmation from human, though I was just typing my prompt. I even have no chance to see what the dialog say and it vanished.
This is fixed in the v1.19.1 updater: background checks only notify, and updates happen only when you explicitly run /update or opencode upgrade. Moving from v1 to v2 requires opencode upgrade --major, rather than an automatic startup confirmation dialog. If you choose to move to v2, you can also install it with npm i -g @opencode/cli@latest. If you still see this on v2, please open a new issue with the details.
Activity
opencode-agent commentedon Oct 9, 2026
Thanks for raising this, @jeffhung. Moving from v1 to v2 is a big change, and we agree it shouldn't happen without the user deciding to.
For context: the current v1 auto-updater installs only patch releases by itself. For a minor or major release (including 1.x → 2.x), it only shows an "update available" notice. Its npm path also updates the v1 package
opencode-ai, not v2's@opencode/cli. So we'd like to find out whether this actually happened to you, and if so, how. Could you share:opencode --version, if you still know it) and the v2 version you ended up on.curlinstall script, Scoop, Chocolatey, desktop app, …).autoupdatesetting, if you set one.brew upgrade,opencode upgradeor reinstalling?If this is a general suggestion rather than something that happened to you, please say so too.
You can reply here with the details, or edit the issue. If you edit it, please also leave a comment saying you've updated it, so we know you're done editing.
I didn't find an existing report of the same thing. These issues are related (ordered by how closely they relate):
Could not detect the installation method#53340: v2 updater can't detect the installation method after moving to v2/updateoffers 2.0.7 on a pacman-managed install that can't be upgraded that wayjeffhung commentedon Oct 9, 2026
I have edited the issue to supply more fields.
I also asked immediately: "Why you upgrade opencode to v2 without my agreement?"
Below is the results:
opencode-agent commentedon Oct 9, 2026
Thanks for the details and the log line, @jeffhung. They made this reproducible.
I reproduced it with 1.18.30 set up as a Homebrew install (on Linux, with a stand-in
brewand the real Homebrew formula data, which now reportsopencodeat 2.0.25):brew upgrade opencode. Runningopencode upgradedirectly logsupgraded method=brew target=2.0.25, the same target as in your log.So the background auto-update did not install 2.x on its own; it only installs patch releases by itself. The upgrade comes from this dialog: it defaults to Confirm and doesn't warn that 2.x is a separate, incompatible line, so an Enter meant for your prompt can start it. The current v1 code has the same dialog. It mainly affects Homebrew installs, because the Homebrew formula now points to 2.x, while npm and the GitHub releases still point to 1.18.35.
The script below reproduces it. It drives the v1 TUI in a pseudo-terminal, so there is no video. The maintainers will look at it.
Until then, to stay on v1 you can set
"autoupdate": "notify"orfalsein your config, choose Skip when the dialog appears, and pin the formula withbrew pin opencodesobrew upgradeleaves it alone.Reproduction script (repro.py)
Run it:
python3 repro.pyjeffhung commentedon Oct 9, 2026
Yes. I was entering my prompt. The dialog flashed and it must thought it received confirmation from human, though I was just typing my prompt. I even have no chance to see what the dialog say and it vanished.
neriousy commentedon Oct 19, 2026
This is fixed in the v1.19.1 updater: background checks only notify, and updates happen only when you explicitly run
/updateoropencode upgrade. Moving from v1 to v2 requiresopencode upgrade --major, rather than an automatic startup confirmation dialog. If you choose to move to v2, you can also install it withnpm i -g @opencode/cli@latest. If you still see this on v2, please open a new issue with the details.