Repository navigation
Description
Feature hasn't been suggested before
- I have verified this feature I'm about to request hasn't been suggested before.
Related prior requests. #30661, #18504, and #32496 requested manual refresh actions, while #52941 tracks the underlying stale-tree problem. We did not find this exact combined design: a static header button, refresh of all loaded directories, preserved view state, and configurable concurrency.
#30661 was automatically closed for not meeting the contributing guidelines within the two-hour correction window. Its closing comment explicitly says: “Feel free to open a new issue that follows our issue templates.”
Design review requested before implementation
This issue is a design review request. Nothing described here is implemented or tested yet. We ask maintainers to review the design before implementation starts.
Summary
Add a Refresh file tree button to the visible file-tree header on web, desktop, and mobile. The button uses a static circular-arrow icon and appears before Open in.
The action rereads the workspace root and every already loaded directory, including collapsed directories. It preserves expansion, selection, and scroll for surviving paths.
Concurrent refreshes are configurable through file_tree.refresh_concurrency in opencode.json(c). This proposal complements filesystem watcher correctness; it does not replace it.
Problem and motivation
The file tree loads directories on demand and uses filesystem events to invalidate loaded entries. When an event is missed or not emitted, the visible tree remains stale.
#52941 reproduces this problem. PR #55540 addresses event publication, but manual recovery remains useful when notifications are unavailable or delayed.
Users currently have no focused recovery action in the file-tree UI. Reloading the window or changing workspaces is broader than necessary and can disrupt unrelated state.
Prior art: VS Code
VS Code provides Refresh Explorer in the Explorer title actions using Codicon.refresh. This is a standard manual action alongside filesystem watching.
This proposal follows that interaction pattern, not VS Code's watcher implementation. OpenCode keeps its existing lazy directory model and adds a configurable concurrency limit for the manual batch.
Reference: VS Code Explorer actions.
Design
Button placement and appearance
- Place Refresh file tree before Open in in the visible tree header.
- Use the existing
refreshicon from the UI catalog. - Keep the icon static in every state: no rotation, animation, or replacement with a loader.
- Expose translated tooltip and accessible-label text.
- Support web, desktop, and mobile independently of Open in availability.
- Do not show the action in the preview toolbar when the tree itself is hidden.
While refreshing, the button is disabled and exposes aria-busy. Repeated clicks do not start another batch.
Refresh targets
At the start of an action, capture the current server and workspace root, then find refresh targets through the existing GUI APIs:
- Always include the root directory
"". - Enumerate loaded entries with
tree.list(path). - Recurse into directory nodes only when
tree.state(path)?.loadedis true. - Ignore the
expandedstate, so loaded collapsed directories are included. - Call
tree.sync(path, { force: true })for each scheduled target.
Previously unloaded directories are not discovered recursively. Newly revealed directories remain collapsed until the user opens them.
No public Files.tree.refresh() method is required. The existing GUI SDK, workspace host, HTTP file API, and watcher implementation remain unchanged apart from configuration plumbing.
View state
The existing per-directory forced reload is retained; the tree is not reset.
For paths that survive the refresh:
- Expansion remains unchanged.
- Selection remains unchanged.
- Existing tree scrolling remains in place.
- Updates use the current incremental rendering path.
Deleted paths and their descendants are pruned normally. A delayed target that has already been pruned is skipped instead of being recreated.
Search results
When search results replace the tree, Refresh file tree updates only the hidden workspace tree.
It does not:
- rerun the search;
- clear or change the query;
- update the currently visible search results;
- claim that search results were refreshed.
After clearing the filter, the user sees the refreshed workspace tree.
Concurrency and configuration
A new optional configuration property controls the maximum number of started directory sync operations:
{
"file_tree": {
"refresh_concurrency": 4,
},
}| Property | Value | Default | Application |
|---|---|---|---|
file_tree.refresh_concurrency |
Any positive integer | 4 |
Captured when a refresh starts |
The usual configuration precedence applies, so project configuration can override the global value.
The value is read through config.get for the current workspace at the beginning of each action. Changing it during a running refresh affects the next refresh, not the current queue.
The default of four matches the application's general HTTP request-queue capacity. Larger values are accepted, but they do not increase transport parallelism and can increase queue waiting and directory-timeout risk.
One plugin state machine owns the target queue, active operations, duplicate-click guard, and workspace identity. When one operation settles, at most one pending operation starts.
There is no additional whole-batch timeout. Existing per-directory timeout behavior remains in force.
Failures and completion
The UI must not promise more than the current sync API can prove.
- Completion means all scheduled operations have settled, not that every directory was successfully reread.
- Successful partial updates are retained.
- Existing entries remain visible after a failed forced reload.
- No success toast is shown.
- Rejected configuration or sync calls produce at most one error notification per action.
- The button becomes available for retry after settlement.
Adding reliable per-directory success reporting would require a richer sync-result contract and is outside this proposal.
Workspace changes and disposal
Each batch captures its server, workspace root, and attempt identity.
After a workspace change or disposal:
- No additional targets from the old batch are started.
- Pending old targets are discarded.
- Late completions do not change the new button state.
- Existing host and store protections prevent stale writes into the new workspace.
Already started HTTP operations are not forcibly cancelled because the current sync API does not expose cancellation.
Limitations
- Manual refresh does not fix missing or delayed watcher events.
- Open file previews, Ctrl+P, and the
@index are not refreshed. - Visible search results remain unchanged until the next search.
- A settled sync does not confirm successful rereading of every directory.
- Already started HTTP requests cannot be cancelled through the current API.
- Directory timeout currently includes time spent waiting for a transport slot.
- Concurrency values above four can reproduce queue-wait timeouts and should not be presented as a performance optimization.
Questions for maintainers
- Configuration: Is
file_tree.refresh_concurrencythe right public key? Should positive integers remain unbounded, or should there be an upper limit? - Search behavior: Is refreshing only the hidden tree acceptable while search results are visible?
- Failure semantics: Is settled-operation reporting sufficient for the first version, or is a richer per-directory outcome required?
- Release: Should this ship as a bug-recovery fix without a flag, or as a feature behind a
file_tree_refreshrollout flag?
Planned verification
No tests exist yet.
The proposed coverage assigns each contract one owner:
- Enumeration of root and loaded collapsed directories: the existing tree-model tests.
- Queue limits, duplicate clicks, stale attempts, pruning, and disposal: pure refresh-machine tests.
- Configuration decoding and validation: focused schema tests.
- User-visible refresh, preserved view state, static icon behavior, mobile visibility, and unchanged search requests: a new case in the existing app review E2E suite.
Related
- #52941 — stale file tree and preview — open and reproduced.
- PR #55540 — publish filesystem events for workspace edits — open, not merged.
- #30661 — Add refresh Folder Tree — automatically closed for template compliance; a new issue is explicitly invited.
- #18504 — stale web file tree — closed after inactivity; included a manual-refresh suggestion.
- #32496 — missing manual refresh — closed after inactivity.
- VS Code Refresh Explorer implementation.
Activity
opencodejr commentedon Nov 13, 2026
Thanks for the detailed design, @akaRem. This asks for a Refresh file tree action in the file-tree header. It would reread the root and every directory already loaded and keep expansion, selection and scroll, with the number of concurrent rereads set by a new setting. It's a way to recover when the tree goes stale, alongside fixing the watcher itself. Maintainers will look at the design and your questions. I can't say what they'll decide or when.
Related issues and PRs I found: