Repository navigation
How Clear Cache Works
This chapter explains the Clear Cache button and command, which restart a window's page in a new WebKit process. The user side is in Clear Cache.
The interface runs in a WebKit web content process (see How Memory Is Measured). Closing a tab drops our references, but WebKit keeps much of the freed memory for reuse instead of returning it to macOS. Measured on the release app: a project at 124 MB, 435 MB with four Markdown files with diagrams, and still 328 MB after closing them all. It stayed there after three minutes.
We tried the cheaper ways first:
- Waiting: no change between one and three minutes.
-
location.reload(): 260 MB before, 253 MB after. A reload keeps the same process and most of its memory. -
A simulated memory pressure warning (
memory_pressure -S): needs root, so it is not something the app can do.
Ending the web content process does work: Tauri notices and reloads the page in a new process, which measured 127 MB. Clear Cache does that on purpose, after saving everything.
sequenceDiagram
participant UI as clearCache.ts
participant Store as repoStore and settings
participant Cmd as commands/config.rs
participant Mem as memory.rs
participant Tauri as tauri-runtime-wry
UI->>UI: clearCachePlan: blocked or go
UI->>Store: saveTabsNow, settings.flushNow
UI->>UI: stashForClearCache: each terminal's place and screen
UI->>Cmd: clear_cache(stash)
Cmd->>Mem: web_content_pid(window)
Mem->>Mem: _webProcessIdentifier, is_own_web_content
Cmd->>Cmd: stash_terminals: links hold output
Cmd-->>UI: Ok
Mem->>Mem: 150 ms later, SIGKILL the pid
Tauri->>Tauri: web content process terminated, reload
Note over UI: the page starts like a launch and restores the folder and tabs
-
The rules are pure, in
src/lib/debug/clearCachePlan.ts: unsaved files (counted only while Remember unsaved changes is off; with it on,repoStore.keepUnsavedwrites them first, see How New File and unsaved changes work), a running git operation (repoStore.busy) or the open merge tool block it with a message; otherwise it goes. -
Saving first.
repoStore.saveTabsNowwrites the tab session at once instead of after its one second delay, andsettings.flushNowwritessettings.jsonandstate.jsonand waits for both. -
One command, in order.
clear_cachefirst finds the process to end; only then does it hand the terminals to their links and end the process. A failure before that leaves every terminal connected. -
Only our own process.
web_content_pidasks the window'sWKWebViewfor_webProcessIdentifieron the main thread, thenis_own_web_contentchecks that the pid is acom.apple.WebKit.WebContentprocess thatmemory::usagealready counts as ours. Anything else is refused. The kill waits 150 ms so the command's answer still reaches the page. -
The restart is Tauri's own:
tauri-runtime-wryregisters a handler forwebViewWebContentProcessDidTerminatethat reloads the webview. The new page goes through the normal start, which reopens the window's folder and, with Reopen tabs on start, its tabs as dormant tabs.
A terminal's shell lives in the backend, but what it shows lives in the page, and a starting page closes the shells its window left (terminal_close_all). Clear Cache hands them over instead:
-
Before.
terminalStore.stashForClearCachewrites each terminal's place (terminalStash.ts: key, name, location, split group, Run spec, exit state) and its screen as text, from xterm's serialize addon, loaded only then. The panel layout (open, tab, shown terminal, split sizes) goes along. -
Holding. Every terminal and Run session sends its output through a link (
src-tauri/src/terminal_link.rs).stash_terminalsswitches the window's links from the page's channel to a buffer of up to 4 MB, and keeps an exit that happens meanwhile. Flow control resumes by itself after a second without acks, so a shell never stalls. -
After.
terminalStore.inittakes the stash (terminal_unstash) beforeterminal_close_all, which skips terminals waiting for a page. Once the workspace is open,restoreAfterClearCacherebuilds the entries with their old keys, groups and layout and reopens terminal editor tabs. EachTerminalViewwrites its old screen, thenterminal_reattachsends the held output and switches the link back to the new channel. -
Never orphaned. A terminal nobody reconnects to within two minutes is closed (
DETACHED_TIMEOUT); closing the window drops its stash.
| File | What it does |
|---|---|
src/lib/debug/clearCachePlan.ts |
Blocked, confirm or go |
src/lib/debug/clearCache.ts |
Asks, saves, closes terminals, calls the command |
src/lib/views/MemoryStatus.svelte |
The button beside Memory |
src/lib/menu/menuSpec.ts, menuActions.ts
|
View > Clear Cache |
src-tauri/src/memory.rs |
web_content_pid, end_web_content, is_own_web_content
|
src-tauri/src/commands/config.rs |
The clear_cache command |
src-tauri/src/terminal_link.rs |
Links: output to the page or held, the stash, reattach, expiry |
src-tauri/src/commands/terminal.rs |
stash_terminals, terminal_unstash, terminal_reattach, terminal_close_all
|
src/lib/terminal/terminalStash.ts |
What a terminal keeps across the restart, checked when read back |
src/lib/terminal/terminalStore.svelte.ts, terminalController.svelte.ts, terminalShell.svelte.ts
|
Saving, rebuilding, the screen, reconnecting |
Restart the process, not the page. Only a new process gives the memory back; a reload alone did not.
A button, not an automatic restart. The screen blinks, so the user decides when. The readout next to the button shows when it is worth it.
The page keeps the screen, the backend only the gap. Keeping all output in the backend for every terminal would cost memory all the time. The serialized screen is taken only at Clear Cache, and the backend holds only what is printed during the restart.
A private WebKit getter. _webProcessIdentifier is not public API, but WebKit has had it for years and the app is not sold through the App Store. If it ever returns nothing, the pid check refuses and the user sees an error instead of a wrong process being ended.
-
src/lib/debug/clearCachePlan.test.ts: going at once, waiting for unsaved files, a git operation and the merge tool. -
src/lib/terminal/terminalStash.test.ts: descriptors and layout round-trip, bad ones are refused, the shown terminals exist. -
src-tauri/src/terminal_link.rs: output held and replayed in order, an exit while waiting, the 4 MB limit, expiry, unknown terminals.src-tauri/src/terminal.rs:a_restarted_page_keeps_the_shells_waiting_for_it. -
src-tauri/src/memory.rs:clear_cache_only_ends_our_web_content_processchecks that our own pid, launchd and invalid pids are refused. - Measured end to end on the release app with the MCP tools: 328 MB with every tab closed, 127 MB after Clear Cache, folder restored; with one diagram file open it came back too.
- A terminal across Clear Cache, on the release app: the same terminal came back running in the panel, the shell kept its pid, a counter it ran in the background wrote every second without a gap, and typing after the restart reached it. The old screen was checked by hand in the app and stays.
- Update this page and Clear Cache when the rules, the restart or terminals change.
- Retake
status-bar-clear-cache.pngandstatus-bar.pngwhen the button changes.
These pages are generated from docs/wiki. To correct something, open a pull request against the source file; edits made here are overwritten.
Using Nibtree
- Getting Started
- Welcome Screen
- Workspaces
- Files Panel
- File Operations
- File Icons
- Rounded Panels
- Editor and Tabs
- Pin Reorder and Wrap Tabs
- Single Tab Title
- Split Editor
- New File and Unsaved Changes
- Unload Hidden Tabs
- Editing Code
- Code Appearance
- Markdown Editor
- Image and PDF Preview
- Search Everywhere
- Recent Files
- Navigation Bar
- Find and Replace
- Changes and Commits
- Sign In Prompts
- Commit Box Layout
- Repository Actions
- Commit Options
- Ignoring Files
- Diffs
- Inline Diffs
- Staging View
- Revert a Change
- Resolving Conflicts
- Merge Tool
- Blame
- History and Log
- Merge Commits
- Branches and Tags
- Branches Popup
- Remotes
- Stashes
- Shelf
- Git Menu
- Git Dialogs
- Interactive Rebase
- Worktrees
- AI Agents
- AI Tasks
- AI Usage
- Keep Computer Awake
- Submodules
- Git LFS
- GitHub
- Git Console
- Terminal
- Terminal Features
- Scripts
- Navigation
- Menus
- Settings
- Settings Search
- Color Themes
- Settings Terminal and Automation
- Settings Files
- Updates
- Status Bar and Help
- Notifications
- Memory Use
- Clear Cache
- MCP and CLI
- Git Mergetool
- Keyboard Shortcuts
- Keyboard Shortcuts Editor
- Troubleshooting
- Troubleshooting Git
Developers
- Developer Guide
- Architecture
- Project Layout
- Backend
- How Folder Watching Works
- Folder Watching Bugs We Fixed
- How Workspace Files Work
- How the Preview Scheme Works
- Backend Services
- How Terminal Features Work
- Terminal Bugs We Fixed
- Frontend
- How the Rich Markdown Editor Works
- Rich Markdown Bugs We Fixed
- Git Menu Links
- Menu Keys and Routing
- Frontend Modules
- Blame Bugs We Fixed
- Project Color And Title Bar
- One Diff View
- Diff Bugs We Fixed
- Merge Tool Layouts
- Merge Tool Bugs We Fixed
- Color Theme Bugs We Fixed
- How the Connected Diff Works
- Rounded Panels Bugs We Fixed
- Update Bugs We Fixed
- Status Bar Bugs We Fixed
- MCP and CLI Bugs We Fixed
- Repository Actions Bugs We Fixed
- How the Changes Tab Works
- CodeMirror Patterns
- How the Cursor Works
- How Editor Features Work
- How the Path Bar Works
- Commands and Events
- Settings Reference
- Commands Workspace and Changes
- Commands Branches and Remotes
- Commands History and Extras
- Commands App and Tools
- Testing
- Test Suites
- Debugging
- Debugging with MCP
- Measuring Setting Memory
- How Terminal Memory Is Measured
- How Markdown Diagrams Work
- Releases and CI
- Publishing the Wiki
- Versioning and Changelog
- Browser Version Packages
- Browser Release Checks
- Docker Image
- Platforms and Signing
- Windows Support
- Windows Bugs We Fixed
- Windows MCP and CLI
- Docs and Screenshots
- UI Library
- UI Library MCP
- UI Library Bugs
- UI Library Migration
- Contributing
How features work
- Welcome screen
- Workspaces and folders
- Files panel
- File operations
- File icons
- Editor and tabs
- Pin, reorder and wrap tabs
- Single tab title
- Split editor
- New File and unsaved changes
- Unload hidden tabs
- Editing code
- Code appearance
- Markdown editor
- Image and PDF preview
- Search Everywhere
- Recent Files
- Navigation Bar
- Find and replace
- Changes and commits
- Sign-in prompts
- Commit box layout
- Repository actions
- Commit options
- Ignoring files
- Diffs
- Inline diffs
- Staging view
- Revert a change
- Resolving conflicts
- Merge tool
- Blame
- History and log
- Merge commits
- Commit tabs
- Branches and tags
- Branches popup
- Remotes
- Stashes
- Shelf
- Git menu
- Git dialogs
- Interactive rebase
- Worktrees
- AI agents
- AI usage
- Keep computer awake
- AI tasks
- Submodules
- Git LFS
- GitHub account
- Git Console
- Back and Forward
- Integrated terminal
- Scripts tool window
- Menu bar
- Settings
- Search in Settings
- Color themes
- Rounded panels
- Updates and release channels
- Status bar and help links
- Notifications
- Memory readout and memory log
- Clear Cache
- MCP server and command line tool
- git mergetool mode