Uses the existing check_claude_cli Tauri command to detect the claude
binary at app startup and shows a status badge — green/neutral when
found, orange warning when missing with a click-to-install link.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The commit button was inside ChangesBadge which returned null when
modifiedCount was 0, hiding the button entirely. Extract it into a
standalone CommitButton component that is always visible in the
status bar with a "Commit" text label for discoverability.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The commit button inside ChangesBadge was being clipped by overflow:hidden
on the left status bar div when many badges were visible or at high zoom.
Removing the overflow constraint ensures the commit button is always visible.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add position: relative and zIndex: 10 to the StatusBar footer to
establish a proper stacking context, so the vault menu dropdown
(zIndex: 1000) renders above the sidebar instead of behind it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The left div in the status bar had no width constraint, causing items
at the end (commit button, Pulse) to overflow behind the right div
when the window is narrow or zoom is high.
Fixes:
- Add flex:1 + minWidth:0 + overflow:hidden to the left div
- Add flexShrink:0 to the right div so it stays visible
- Move ChangesBadge (with commit button) before SyncBadge so it
appears earlier and is less likely to be clipped
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Changes badge shows GitDiff icon with orange count badge, Pulse badge
sits next to it. Commit & Push is accessible via icon button beside
Changes. Sidebar is now cleaner with only nav filters and sections.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the entire QMD search engine (semantic indexing, hybrid search,
vector embeddings) and replace with a simple walkdir-based keyword
search. QMD never worked reliably in production, added bundle bloat,
and showed "Index failed" in the status bar.
What changed:
- Rust: deleted indexing.rs, rewrote search.rs as pure keyword search
- Frontend: removed useIndexing hook, IndexingBadge, hybrid search
- Menu: removed "Reindex Vault" command from palette and menu bar
- Config: removed qmd from bundle resources and build script
- Deleted tools/qmd/ (QMD CLI tool, MCP server, tests)
- Updated docs (ARCHITECTURE, ABSTRACTIONS, GETTING-STARTED)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When push is rejected due to remote having newer commits, the bottom bar
now shows "Pull required" (orange). Clicking it pulls then auto-pushes.
Conflicted notes show an inline banner with "Keep mine" / "Keep theirs"
buttons. A new "Pull from Remote" command is available in Cmd+K and the
Vault menu. Clicking the sync badge opens a popup showing branch name,
ahead/behind counts, and a Pull button.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add "Reindex Vault" command to command palette and menu bar
- Show "Indexed Xm ago" in status bar when idle, clickable to reindex
- After git pull with updates, auto-trigger incremental reindex
- Add lastIndexedTime state to useIndexing, populated from backend metadata
- Add triggerFullReindex to useIndexing (retryIndexing is now an alias)
- Add onSyncUpdated callback to useAutoSync
- Extract formatIndexedElapsed to utils/indexingHelpers.ts
- Tests: 20 new unit tests across 5 files, 2 Playwright smoke tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add check_mcp_status Tauri command that detects whether the MCP server
is installed, Claude CLI is missing, or config needs setup. The status
bar shows a warning badge (MCP ⚠) when not installed, clickable to
trigger install. Also available via command palette "Install MCP Server".
Replaces useMcpRegistration with useMcpStatus which combines detection
and registration in a single hook.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Separate 'unavailable' (qmd not installed) from 'error' (indexing failed)
phases. Unavailable state is hidden from the status bar instead of showing
a persistent orange error. Actual errors show "Index failed — retry" with
click-to-retry. Both phases auto-dismiss after a timeout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- build.rs: remove unreliable git rev-list --count logic
- lib.rs: parse build number from Tauri package version at runtime
- Release version 0.20260303.281 -> 'b281'
- Dev version 0.1.0 -> 'dev'
- StatusBar.tsx: build number is clickable (triggers check for updates)
- App.tsx: pass handleCheckForUpdates to StatusBar
- Tests: unit tests for parse_build_label + StatusBar click behavior
Remove the hardcoded "Claude Sonnet 4" stub label and unused Sparkles
import — no model picker is planned at this stage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add git_resolve_conflict and git_commit_conflict_resolution Rust commands
- Create useConflictResolver hook for per-file resolution state management
- Create ConflictResolverModal with keyboard shortcuts (K/T/O/Enter/Esc)
- Make StatusBar conflict chip clickable to open resolver modal
- Add 'Resolve Conflicts' command to command palette (conditional)
- Pause auto-pull while conflict resolver modal is open
- Tests: 5 new Rust tests, 10 new hook tests, 1 new auto-sync test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Search now works out of the box on any vault without manual qmd
installation. On vault open, the app checks the index status and
auto-triggers background indexing (qmd update + embed) when needed.
If qmd is not installed, it auto-installs via bun.
Changes:
- New indexing.rs module: find_qmd_binary (cached), check_index_status,
ensure_collection, run_full_index with progress callbacks,
run_incremental_update, auto_install_qmd
- search.rs: delegates to indexing::find_qmd_binary (removes duplication)
- lib.rs: new Tauri commands (get_index_status, start_indexing,
trigger_incremental_index)
- useIndexing hook: auto-triggers on vault open, listens for
indexing-progress events, auto-dismisses complete state after 5s
- StatusBar: IndexingBadge shows phase + progress counts with spinner
- App.tsx: wires up useIndexing, triggers incremental index on file save
- design/search-bundle-qmd.pen: documents indexing progress UI states
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ability to remove vaults from the app list without deleting files on disk,
and restore the bundled Getting Started demo vault when needed.
Changes:
- Rust: add hidden_defaults field to VaultList for tracking removed default vaults
- useVaultSwitcher: add removeVault() and restoreGettingStarted() with auto-switch
- useCommandRegistry: add 'Remove Vault from List' and 'Restore Getting Started Vault' commands
- StatusBar: add X button per vault item in vault menu dropdown
- 25 new tests covering removal, restore, edge cases, and command palette
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vault list was stored only in React useState, lost on every app restart
or update. Now persisted to ~/.config/com.laputa.app/vaults.json via
Rust backend commands (load_vault_list, save_vault_list).
- Add vault_list.rs module with VaultEntry/VaultList types and JSON I/O
- Register load_vault_list/save_vault_list Tauri commands
- Extract vaultListStore.ts utility for frontend persistence calls
- Rewrite useVaultSwitcher to load on mount and persist on change
- Show unavailable vaults greyed out with warning icon instead of
silently removing them
- Add mock handlers for browser/test environments
- Add useVaultSwitcher tests covering persistence, availability, dedup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: show dynamic build number in status bar (bNNN format)
Replace hardcoded v0.4.2 with a dynamic build number derived from
git rev-list --count HEAD at compile time. The count is embedded via
build.rs and exposed through a get_build_number Tauri command.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* design: add build-number-status-bar wireframes (status bar with dynamic b-number)
* fix: use runtime env var for BUILD_NUMBER (compile-time env! not available in CI)
* style: rustfmt format get_build_number
---------
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The commit hash link in the status bar used an <a href> tag which doesn't
open external URLs in Tauri's webview. Replaced with onClick handler that
calls openExternalUrl (Tauri opener plugin in native, window.open in browser).
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: show last commit hash in status bar, remove branch name
Replace the hardcoded "main" branch display with a clickable short SHA
linking to the GitHub commit. Add Rust get_last_commit_info command that
returns the last commit hash and constructs a GitHub URL from the remote.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add design/git-status-bar.pen with new status bar layout
Shows the updated status bar with commit hash link, no branch name,
and annotated change callouts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ci: retrigger — runner 3 pnpm not found (env issue)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add auto-pull vault sync with conflict handling
- Add git_pull, has_remote, get_conflict_files to Rust backend
- Add GitPullResult type and auto_pull_interval_minutes to Settings
- Create useAutoSync hook (pull on launch, focus, periodic interval)
- Update StatusBar with real sync status indicator
- Add pull interval setting to SettingsPanel
- Add mock handler for git_pull
- Update existing tests for new Settings field
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add tests for git pull, settings, and useAutoSync hook
- Add Rust tests: has_remote, git_pull (no_remote, up_to_date, updated),
get_conflict_files, parse_updated_files, GitPullResult serialization
- Add frontend tests: useAutoSync (mount pull, focus pull, conflict,
error, manual trigger, concurrent prevention, no_remote)
- Fix existing settings tests for new auto_pull_interval_minutes field
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* design: add auto-pull-vault wireframes
Frames showing: sync idle, syncing, conflict indicator,
settings sync section, and conflict toast notification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add auto_pull_interval_minutes to all Settings literals
Fix build error and test fixtures missing the new field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: cargo fmt
* ci: re-trigger CI after flaky test
* ci: retrigger after disk space cleanup
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Clicking "N pending" in the status bar or the "Changes" nav item in
the sidebar shows a filtered list of notes with uncommitted changes.
The view updates in real-time as files are saved or committed.
- Add 'changes' filter to SidebarSelection type
- Make StatusBar "N pending" indicator clickable
- Add "Changes" NavItem in sidebar (visible when modifiedCount > 0)
- Filter NoteList by modifiedFiles paths for changes view
- Show "No pending changes" empty state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- NoteItem: orange dot before title for uncommitted modified notes
- TabBar: orange dot on tabs with uncommitted changes
- StatusBar: "N pending" counter with CircleDot icon when modified files exist
- useEditorSave: onAfterSave callback to refresh modified files after save
- mock-tauri: track dynamically saved files as modified, clear on commit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add "Open local folder" and "Create new vault" options to the vault
picker dropdown. Uses tauri-plugin-dialog for native folder picker
in Tauri mode, falls back to prompt() in browser mode.
- Rust: add tauri-plugin-dialog, create_vault_dir command
- Frontend: pickFolder utility, StatusBar UI, App.tsx handlers
- Mock: create_vault_dir mock handler for browser testing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New GitHubVaultModal component with two tabs:
- Clone Existing: search/browse user's repos, select one, choose
local path, clone via HTTPS+token
- Create New: enter repo name, toggle private/public, create via
GitHub API then clone locally
Integration:
- "Connect GitHub repo" option in vault switcher menu
- GitHub token field added to Settings panel
- Cloned vaults auto-added to vault list and opened
- Mock handlers for github_list_repos, github_create_repo, clone_repo
- All existing tests updated for new github_token field (386 pass)
Product decision: GitHub token stored in settings rather than OAuth
flow — simpler first version, works with personal access tokens.
Users can upgrade to OAuth later.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove .dark CSS variables block from index.css
- Remove theme toggle state and Cmd+Shift+T shortcut from Sidebar
- Remove dark class initialization from main.tsx
- Hardcode BlockNote theme to 'light' in Editor
- shadcn dark: classes left in place (harmless, no-op without .dark class)