Repository navigation
How Unloading Hidden Tabs Works
This chapter explains how file tabs out of sight give their editors back to save memory. The user side is in Unload Hidden Tabs; the tabs themselves are in How the editor works.
EditorGroupContent.svelte keeps one FileView per file tab and only hides the inactive ones, so switching back is instant and keeps the cursor, scroll and unsaved edits. The price is a full CodeMirror editor, its DOM, blame and change marks for every tab: about 4 MB each, measured (Measuring Setting Memory). People keep many tabs open and look at a few. Memory is a feature here (see Architecture), so tabs nobody looks at should not hold it.
The app already had a sleeping state: tabs restored at start are dormant. repoStore.dormantTabs holds their keys (groupId plus path), Workspace.svelte renders no FileView for them, and showing one creates its editor at the saved position. Unloading reuses exactly that state.
sequenceDiagram
participant App as App.svelte
participant Store as repoStore
participant Plan as tabSleep.ts
participant View as FileView
loop every 30 s while the setting is on
App->>Store: sleepHiddenTabs(minutes * 60000)
Store->>Plan: tabsToSleep(entries, tabShownAt, now, delay)
Plan-->>Store: keys hidden long enough
Store->>Store: add them to dormantTabs
end
Store-->>View: unmount: notePosition, view.destroy()
Note over Store: the user clicks the tab
Store->>Store: tabsChanged: wake it, copy tabPositions to pendingPositions
Store-->>View: mount: load the file, takePendingPosition
-
When a tab was last seen.
repoStore.tabShownAtmaps each tab key to the last time it was on screen.tabsChangedstamps the active tab of every group, and every sweep stamps them again, so a tab that has been active for an hour starts counting when it is hidden, not an hour ago. -
The decision.
tabsToSleepinsrc/lib/stores/tabSleep.tsis pure: a shown tab, or one seen for the first time, getsnow; a hidden tab that iseligibleand older than the delay is returned. Closed tabs are forgotten. Eligible means a file tab (isFileTab) without unsaved edits that is not dormant already. -
Going to sleep.
sleepHiddenTabsadds the keys todormantTabs. Svelte unmounts theFileView, whose cleanup callsnotePosition(caret and the last measured top line) and destroys the view. -
Waking up. Clicking the tab makes it active;
tabsChangeddrops the key and copies the tab'stabPositionsentry intopendingPositions, which the new editor reads withtakePendingPosition, the same path Reopen tabs on start uses.
The Markdown view mode survives because viewMode.ts remembers it per file for the session.
| File | What it does |
|---|---|
src/lib/stores/tabSleep.ts |
tabsToSleep, UNLOAD_TAB_MINUTES, TAB_SLEEP_CHECK_MS, pickUnloadTabMinutes
|
src/lib/stores/repo.svelte.ts |
sleepHiddenTabs, tabShownAt, waking in tabsChanged
|
src/lib/App.svelte |
The 30 second interval, only while the setting is on |
src/lib/stores/settingsData.ts |
unloadHiddenTabs (true) and unloadHiddenTabsMinutes (15) |
src/lib/views/settings/EditorFeatureSettings.svelte |
The switch and the Unload after choices |
Reuse the dormant state. A second way to tear down and rebuild an editor would need its own position and wake logic. Dormant tabs already had both and were tested by every restart.
Never unsaved edits. Keeping unsaved text outside an editor would need a second copy and a new path back into the editor. Skipping dirty tabs keeps work safe with no new code.
Minutes, not a tab count. A tab limit already closes tabs by count. Time keeps the tabs you switch between often loaded, whatever their number.
A plain interval. The check is a few map lookups every 30 seconds with no IPC, so it also runs while the window is in the background, where freeing memory helps the most.
Undo history goes. CodeMirror's history lives in the editor state. Keeping it would mean keeping the state, which is most of the memory.
-
src/lib/stores/tabSleep.test.ts: counting from the first hidden sighting, the shown tab never sleeps, tabs that cannot sleep, closed tabs forgotten, the minute choices. -
src/lib/stores/settingsData.test.ts: the defaults and their checks.
- Update this page and Unload Hidden Tabs when dormant tabs,
FileViewpositions or the tab kinds change. - If another tab kind learns to sleep, add it to
eligibleinsleepHiddenTabsand to both pages. - Retake
settings-unload-hidden-tabs.pngwhen the rows change.
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