Repository navigation
How Updates Work
Nibtree checks GitHub for newer releases and tells you when one is out. It never downloads or installs anything by itself. After you update, it shows What's New from the changelog built into the app. For the user side, see Updates.
Without an update check, most people stay on their first version and miss fixes. Silent auto-install needs an update-signing key and more setup. A notify-only check gives most of the benefit without that: the app asks GitHub, shows the notes, and the Download button opens the release in the browser.
Testers also need betas without pushing betas on everyone. So releases have two channels, and a stable install is never offered a beta.
Everything lives in src/lib/update/. updates (the UpdateStore singleton in updates.svelte.ts) is started by App.svelte with updates.init(), right after settings.init().
stateDiagram-v2
[*] --> Starting: updates.init()
Starting --> [*]: mergetool mode, no checks
Starting --> WhatsNew: lastRunVersion is older than this build
Starting --> Waiting: same version or first run
WhatsNew --> Waiting: dialog closed
Waiting --> Checking: timer, 30 s after start, then every 6 h
Waiting --> Checking: Check Now in Settings
Waiting --> Waiting: timer fires while checks are turned off
Checking --> Available: newer release on the channel
Checking --> Waiting: up to date
Checking --> Waiting: offline, timeout or error, kept in updates.error
Checking --> SkippedShown: Check Now, newest is skipped
Available --> Waiting: Skip This Version
Available --> Waiting: Later
SkippedShown --> Available: Stop Skipping
SkippedShown --> Waiting: Later
init() reads this build's version with Tauri's getVersion(). If that fails, it stops and no check ever runs. In mergetool mode (api.getLaunchMode()), init() stops after reading the version: no timer, no What's New, and lastRunVersion is not touched. If settings.lastRunVersion is older, it opens What's New once. It saves the new lastRunVersion right away, whether or not the dialog opened, and arms the timer with FIRST_CHECK_DELAY_MS (30 seconds), so starting the app never waits on the network. After that schedule() re-arms every CHECK_INTERVAL_MS (6 hours). When settings.checkForUpdates is off, the timer still runs but skips the request.
sequenceDiagram
participant U as UpdateStore
participant GH as api.github.com
participant R as releases.ts
participant SB as StatusBar
U->>GH: GET /repos/shibbirweb/nibtree/releases?per_page=30
Note over U,GH: 20 s timeout with AbortController
GH-->>U: JSON list, or 403 or 404
U->>R: parseReleases(json, platform)
R-->>U: Release list without drafts or non-version tags
U->>R: newerReleases(current, channel, releases)
R-->>U: newer releases, newest first
U->>SB: available is newer[0] unless it or a newer version was skipped
check(manual) uses the web view's fetch. The CSP in tauri.conf.json allows it with connect-src ... https://api.github.com. A 403 becomes "GitHub rate limit reached". An automatic check that fails stays quiet: it only sets updates.error, which Settings, Updates shows as "Last check failed". A manual check shows a toast or opens the dialog. Check Now and the menu item Nibtree > Check for Updates... (app.checkForUpdates in menu/menuActions.ts) both call updates.check(true); Help > What's New sets updates.whatsNewOpen.
flowchart TD
A["settings.updateChannel"] --> B{"auto?"}
B -->|"stable or beta"| C["Use it"]
B -->|"auto"| D{"This build has a pre-release part?"}
D -->|"yes, like 0.3.0-beta.1"| E["beta"]
D -->|"no"| F["stable"]
C --> G["newerReleases"]
E --> G
F --> G
G --> H{"channel is stable?"}
H -->|"yes"| I["Drop pre-releases and any version<br/>with a pre-release part"]
H -->|"no"| J["Keep all"]
I --> K["Keep versions newer than this build"]
J --> K
Betas are GitHub pre-releases (see Releases and CI). The stable channel drops a release when GitHub marks it as a pre-release or its version has a pre-release part, so a beta published without the flag never reaches stable users.
Version order comes from compareVersions in version.ts, which follows semver precedence, so 0.3.0-beta.2 is older than 0.3.0.
UpdateDialog.svelte shows the notes of every newer release (with Beta badges and dates), a View on GitHub link and three buttons. Download calls updates.download(release), which opens the download downloadAsset picks for the platform (the .dmg on macOS, the -setup.exe installer or else an .msi on Windows), or the release page. Skip This Version stores settings.skippedVersion. isSkipped treats that version and anything older as skipped, so available (announcedRelease) hides the status bar item and automatic checks stay quiet. A manual Check Now still opens the dialog. When updates.newestSkipped is true, it shows "You skipped this version." and a Stop Skipping button (updates.unskip()) in place of Skip This Version. A release newer than the skipped one is announced as usual. Later just closes.
WhatsNewDialog.svelte imports CHANGELOG.md?raw, so the changelog is bundled at build time and works offline. A beta build shows the Unreleased section (betas ship those notes), a stable build shows its own dated section, and older entries can be expanded.
ReleaseNotes.svelte renders Markdown with renderMarkdown from markdown.ts. It escapes all HTML, emits only a fixed set of tags, and only turns https links into links. Clicks on them go through updates.open, which uses the opener plugin (openUrl, allowed by opener:allow-open-url plus the http, https, mailto and tel scope of opener:allow-default-urls in capabilities/default.json), so the page opens in the user's browser, never inside the app.
| File | What it does |
|---|---|
src/lib/update/updates.svelte.ts |
UpdateStore: timers, check, channel, skip, download, links |
src/lib/update/releases.ts |
parseReleases, downloadAsset, newerReleases, defaultChannel, isSkipped, announcedRelease, osLabel, issue link helpers |
src/lib/update/version.ts |
parseVersion, compareVersions, isNewer
|
src/lib/update/changelog.ts |
parseChangelog, entryFor, releasedEntries
|
src/lib/update/markdown.ts |
Safe Markdown renderer |
src/lib/update/UpdateDialog.svelte |
Update available dialog (library Dialog, panel variant) |
src/lib/update/WhatsNewDialog.svelte |
What's New from the bundled changelog (library Dialog) |
src/lib/update/ReleaseNotes.svelte |
Renders notes, opens links in the browser |
src-tauri/tauri.conf.json |
CSP that allows https://api.github.com
|
src-tauri/capabilities/default.json |
opener:allow-open-url and opener:allow-default-urls
|
Notify only. Tauri's updater could install updates, but it needs an update-signing key stored as a GitHub secret. Opening the release page needs no keys and can be revisited later.
Ask GitHub from the web view, not from Rust. A fetch needs no new Rust dependency or HTTP client, which keeps the binary small. The CSP entry keeps the app from talking to any other host.
The changelog is the only source of notes. Release notes on GitHub and What's New both come from CHANGELOG.md, so they can never disagree. See Versioning and Changelog.
Two filters for the stable channel. Trusting only GitHub's pre-release flag would let one wrong click ship a beta to everyone.
Quiet when offline. An error toast every six hours on a plane would be noise.
The update and link bugs and their fixes are in Update Bugs We Fixed.
One known trap: the repository must be public. For a private repository, GitHub answers 404 to the anonymous request, and Settings shows "GitHub answered 404".
-
src/lib/update/update.test.ts: changelog sections with dates, one version's body without link definitions, released versions only, tags with or withoutv, and semver ordering. -
src/lib/update/releases.test.ts:parseReleaseskeeps published version tags and finds the.dmg;downloadAssetpicks per platform;newerReleasesfor stable, beta, up to date, and the default channel of a beta build;renderMarkdownformatting, HTML escaping and non-https links;isSkippedandannouncedRelease; the bug report link,osLabeland the user agent fallback.
When you change channel rules or parsing, add a case to releases.test.ts first. The store itself is not unit tested because it needs the network and Tauri.
- Update this page when anything in
src/lib/update/, the CSP or the opener capability changes. - Update Updates when intervals, channels or buttons change.
- Retake
settings-updates.png,update-dialog.png,update-dialog-skipped.pngandwhats-new.pngwhen those screens change. - Related: Update Bugs We Fixed, Releases and CI, How Settings Work, How the Status Bar Works.
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