OpenCode with prompt caching + vim keybindings + tool use/result fix
This repository combines three unmerged upstream patches into a single OpenCode binary, built automatically for 4 platforms.
1. Prompt Caching Improvements (PR #5422)
Fetched at build time from opencode-cached. Adds provider-specific cache configuration for 19+ providers, reducing cache write costs by ~44% and effective costs by ~73%.
2. Vim Keybindings (PR #12679)
Stored locally as patches/vim.patch. Adds optional vim motions to the prompt input. Disabled by default -- enable with tui.vim: true or toggle from the command palette.
Supported motions:
- Mode switching:
i I a A o O S,cc,cw,Esc - Motions:
h j k l,w b e,W B E,0 ^ $ - Deletes:
x,dd,dw - Session navigation:
gg/G - Scrolling:
Ctrl+e/y/d/u/f/b Enterin normal mode submits
3. Tool Use/Result Mismatch Fix (PR #16751)
Stored locally as patches/tool-fix.patch. Fixes the widespread tool_use ids were found without tool_result blocks error (#16749) that corrupts sessions when stream errors cause lost step boundaries. Injects synthetic step-start boundaries at message reconstruction time to prevent interleaved tool_use/text in assistant messages that the Anthropic API rejects.
curl -sL https://github.com/johnnymo87/opencode-patched/releases/latest/download/opencode-linux-arm64.tar.gz | tar xz
sudo mv bin/opencode /usr/local/bin/
opencode --versioncurl -sL https://github.com/johnnymo87/opencode-patched/releases/latest/download/opencode-linux-x64.tar.gz | tar xz
sudo mv bin/opencode /usr/local/bin/
opencode --versioncurl -sL https://github.com/johnnymo87/opencode-patched/releases/latest/download/opencode-darwin-arm64.zip -o opencode.zip
unzip opencode.zip
sudo mv bin/opencode /usr/local/bin/
opencode --versioncurl -sL https://github.com/johnnymo87/opencode-patched/releases/latest/download/opencode-darwin-x64.zip -o opencode.zip
unzip opencode.zip
sudo mv bin/opencode /usr/local/bin/
opencode --versionSee the workstation repo for Nix integration example.
Timing Chain (every 8 hours):
:00 opencode-cached/sync-upstream -- detects new upstream release
|-> builds v{VER}-cached -- applies caching patch, publishes
:01 opencode-patched/sync-cached -- detects new -cached release
|-> builds v{VER}-patched -- applies caching + vim + tool fix patches, publishes
:01 opencode-patched/sync-vim-pr -- checks PR #12679 for changes
:01 opencode-patched/sync-tool-fix-pr -- checks PR #16751 for changes
:02 workstation/update-opencode-patched -- updates Nix config, opens PR
- Clone upstream OpenCode at the release tag
- Fetch
caching.patchfrom opencode-cached (always latest frommain) - Apply
caching.patch, then localvim.patch, then localtool-fix.patch - Build with Bun for 4 platforms (linux/darwin x arm64/x64)
- Publish release as
v{VERSION}-patched
The three patches modify completely different areas of the codebase:
- Caching:
provider/config.ts,provider/transform.ts,session/prompt.ts,config/config.ts - Vim:
cli/cmd/tui/component/vim/*,cli/cmd/tui/component/prompt/index.tsx,cli/cmd/tui/app.tsx - Tool fix:
session/message-v2.ts,test/session/message-v2.test.ts
Zero file overlap between any pair of patches.
Each patch is owned by a specific repo. Do not edit a patch in the wrong repo.
| Patch | Owned by | Upstream PR guide |
|---|---|---|
caching.patch |
opencode-cached (patches/caching.patch) |
PR #5422 |
vim.patch |
this repo (patches/vim.patch) |
PR #12679 |
tool-fix.patch |
this repo (patches/tool-fix.patch) |
PR #16751 |
When an upstream PR is merged, the corresponding patch can be dropped. caching.patch is
managed in the sibling repo ~/projects/opencode-cached; edits belong there, not here.
This is handled by opencode-cached. If the caching patch fails on a new upstream version, opencode-cached won't release, and this repo won't attempt a build.
To refresh: edit ~/projects/opencode-cached/patches/caching.patch (not this repo).
The build fails and creates a GitHub issue automatically. This blocks publication.
Use PR #12679 as the behavioral guide when rebasing: the PR defines the intended vim motions and config surface. Port only behavior still missing upstream; drop anything already present.
- Fetch the PR as a behavioral reference:
gh pr diff 12679 --repo anomalyco/opencode > /tmp/vim-pr-12679.patch - Rebase
patches/vim.patchonto the new upstream, using the PR diff as the source of truth for intended behavior - Review, commit, push
- Re-trigger:
gh workflow run build-release.yml --field version=X.Y.Z
sync-vim-pr.yml checks every 8 hours whether PR #12679's raw diff matches patches/vim.patch.
If the hashes differ, it opens a GitHub issue labeled patch-drift.
Drift does not mean the build is broken. The build continues to use the committed
patches/vim.patch as-is. The build/release workflow is the source of truth for whether
publication is blocked. The drift issue is a prompt to review what changed upstream and
decide whether to adopt it.
The build fails and creates a GitHub issue automatically. This blocks publication.
Use PR #16751 as the behavioral guide when refreshing. If the upstream release already includes the fix (verify by running the regression test), drop patches/tool-fix.patch entirely rather than refreshing it.
- Check whether upstream already has the fix: run the regression test from PR #16751 against a plain upstream checkout
- If fix is present upstream: remove
patches/tool-fix.patchand updatepatches/apply.sh - If fix is absent: regenerate from the PR:
gh pr diff 16751 --repo anomalyco/opencode > patches/tool-fix.patch - Review, commit, push
- Re-trigger:
gh workflow run build-release.yml --field version=X.Y.Z
sync-tool-fix-pr.yml checks every 8 hours whether PR #16751's raw diff matches patches/tool-fix.patch.
If the hashes differ, it opens a GitHub issue labeled patch-drift.
Drift does not mean the build is broken. The build continues to use the committed
patches/tool-fix.patch as-is. The build/release workflow is the source of truth for whether
publication is blocked. The drift issue is a prompt to review what changed upstream and
decide whether to adopt it.
Monthly automated check (check-sunset.yml) monitors all upstream PRs:
- Any PR merged: Drop the corresponding patch from
apply.sh - All merged: Switch workstation to upstream OpenCode, archive this repo and opencode-cached
- OpenCode: anomalyco/opencode
- Caching PR: PR #5422 by @ormandj
- Caching builds: opencode-cached
- Vim PR: PR #12679 by @leohenon
- Tool fix PR: PR #16751 by @altendky
MIT (same as upstream OpenCode)