* fix: run Rust tests in CI
Fixes#670
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: run Rust tests in CI
Adds a separate test.yml workflow to run existing Rust unit tests.
Fixes#670
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: use mock TranscriptionManager in CI tests
Swap to a mock adapter during CI to avoid compiling whisper/Vulkan.
The mock has the same interface but no heavy dependencies.
Existing tests don't exercise transcription code, so this is safe.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* init attempt at new kb
* 0.1.1 handy-keys
* format
* cleanup
* support for capslock/shiftlock?
* move kb to experimental
* use hook
* fix macos bug
* attempt mouse buttons as well
* Add Portuguese translations for permission error messages
Add error message translations for the permission check flow in the Portuguese locale, covering both check failures and request failures.
* Fix history audio playback on Linux
WebKitGTK cannot play audio files via the asset:// protocol (or at least
not reliably), returning MEDIA_ERR_SRC_NOT_SUPPORTED. Additionally,
convertFileSrc was double- encoding the path (/ became %2F).
Changed to read audio files directly using the fs plugin and create
blob URLs instead. Also added APPDATA to fs:scope permissions to allow
reading recordings from the app data directory.
* Fix audio playback on macOS by using asset protocol on non-Linux
The blob URL approach for audio playback works on Linux but breaks
macOS.
This reverts the blob change to use convertFileSrc with the asset
protocol on macOS/Windows while keeping the blob approach for Linux
where it's needed. Also adds proper cleanup of blob URLs to prevent
memory leaks when history entries are unmounted.
* feat: add automatic filler word removal from transcriptions
Add filter_transcription_output() that removes filler words (uh, um, hmm,
etc.) and hallucination patterns ([AUDIO], (pause), <tag>...</tag>) from
transcriptions. Inspired by VoiceInk's approach.
- Add regex-based filter in audio_toolkit/text.rs
- Integrate into transcription pipeline after custom word correction
- Add comprehensive tests for filler word removal
- Add regex crate dependency
* feat: collapse repeated 1-2 letter stutters in transcriptions
Add collapse_stutters() to reduce model hallucination artifacts like
"wh wh wh wh wh why" -> "wh why" or "I I I I think" -> "I think".
Collapses any 1-2 letter word that repeats 3+ times consecutively
to a single instance (case-insensitive matching).
* remove bracket/xml stuff
* format
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* Add permission step to onboarding
* translations
* minor ui
* Update AccessibilityOnboarding.tsx
* claude suggestions
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* Fix race condition when toggling transcription via SIGUSR2
The toggle state was being set to false immediately when stop was called,
but the actual transcription runs asynchronously. If another signal arrived
before transcription completed, a new recording could start while the old
transcription was still running, causing the old text to paste unexpectedly.
Now the toggle state stays true until the async transcription task completes.
* remove import
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
Add ydotool as a fallback option for direct text input and key
combinations on Linux, after wtype/dotool (Wayland) and xdotool (X11).
ydotool uses uinput and works on both Wayland and X11, making it a
useful alternative when other tools are unavailable.
Requirements:
- ydotool installed
- ydotoold daemon running
- User in input group with uinput permissions
* feat: add Moonshine Base speech recognition model
Add support for the Moonshine Base ASR model, which offers:
- 5x faster transcription than Whisper
- Better accent recognition
- ~240MB model size (encoder + decoder + tokenizer)
Changes:
- Update transcribe-rs to v0.2 with moonshine feature
- Add EngineType::Moonshine variant
- Add Moonshine Base model definition (400MB, 80% accuracy, 90% speed)
- Add model loading and transcription logic
- Add i18n translation for Moonshine Base
Note: Model files must be hosted at blob.handy.computer/moonshine-base.tar.gz
Expected structure: encoder_model.onnx, decoder_model_merged.onnx, tokenizer.json
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update moonshine parameters.
* add translations
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: CJ Pais <cj@cjpais.com>
defer apple intelligence availability check from app initialization
to when the user actually tries to use the feature. accessing
SystemLanguageModel.default during early app startup causes SIGABRT
on macOS 26.x (tahoe) beta.
- remove availability check from default_post_process_providers()
- always include apple intelligence provider on macos arm64
- add checkAppleIntelligenceAvailable command for lazy checking
- show error message if apple intelligence unavailable when selected
- clear error on any dropdown selection for better UX
* fix: unload model on cancel when immediate unload enabled
adds model unload check to cancel_current_operation() to match
the behavior in transcribe(). previously, cancelling with escape
would leave the model loaded even with "unload immediately" enabled.
fixes#479
* also fix model not unloading if there is empty transcription
* refactor to util function
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* fix: replace async-openai library with post request to support custom providers
* move models call to llm_client too
* tweak post processing ui and add groq and cerebras
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* fix: prevent model auto-switch from interrupting active transcription
when a model download completes during an active recording/transcription,
the app now skips auto-switching to prevent data loss.
adds is_recording tauri command to check recording state before
auto-switching models on download or extraction completion.
fixes#418
* Update bindings.ts
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* feat: add Apple Intelligence post-processing provider
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
* feat: guide apple intelligence output
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
* fix(build): add fallback stub for Apple Intelligence on older SDKs
- Checks if 'FoundationModels.framework' is present in the macOS SDK.
- If missing, compiles a stub Swift file that returns 'unavailable' errors instead of failing the build.
- Prevents build errors on older Xcode versions (or macOS versions < 26.0) where the macros are not supported.
* fix(ui): hide Apple Intelligence option when unavailable
- Checks for runtime availability of Apple Intelligence (via 'check_apple_intelligence_availability') in 'settings.rs'.
- Only adds the Apple Intelligence provider to the default settings if it is actually available on the device.
- Ensures the option does not appear in the UI for unsupported Macs (e.g., Intel or older macOS versions), even if the app was built with support enabled.
* move some files around as well as some ui text
* format
---------
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: CJ Pais <cj@cjpais.com>
* fix: re-assert always-on-top for overlay on Windows
On Windows, the recording/transcribing overlay can lose its topmost
Z-order and fall behind other windows during certain window manager
events (e.g., dragging windows, alt-tabbing, or other apps asserting
focus).
This fix uses the Win32 SetWindowPos API directly with HWND_TOPMOST
to aggressively re-assert the overlay's Z-order immediately after
showing it. Key implementation details:
- Uses Tauri 2's WebviewWindow::hwnd() to get the native handle
- Calls SetWindowPos on the main UI thread via run_on_main_thread
- Applies flags: SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW
- SWP_NOACTIVATE prevents stealing focus from the active window
- SWP_SHOWWINDOW reinforces the topmost state during the show
The fix is called after .show() in both show_recording_overlay and
show_transcribing_overlay, which is more reliable than setting it
before the window is visible.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* keep the fix to windows only
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: CJ Pais <cj@cjpais.com>
* initial specta commands
* refactor to use the bindings in the ui
* merge fixes
* remove unused commands
* add clamshell to lib
* Remove Invoke from everything.
* fix settings not being loaded properly
* fix settings being overwritten due to deserialization failure + remove
provider kind
* fix model loading text bug
* feat: add conversion between Simplified and Traditional Chinese. If the selected language is Simplified or Traditional Chinese, it will convert the text to the selected variant(Simplified or Traditional) after been recognized, depends on opencc, if it is not installed, the conversion will skip.
* Adopting ferrous-opencc makes cross-platform packaging easier.
* feat: add sound duration retrieval for audio feedback
* Trim trailing silence from pop_start.wav and pop_stop.wav
* refactor: simplify sound file and base directory retrieval
* feat: only delay mute if audio feedback is enabled
* change the logic
* simplify new logic
* simplify get_sound_path and get_sound_base_dir, reorder functions
* add implicit blocking to playTestSound
* modify to my pref style
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* feat: add more options for deleting recordings automatically and added button to open the folder that olds the recordings
- deleting automatically options: after certain time, never or preserving certain number of recordings
- new button "Open Recordings Folder" located on History page
* refactor: moved "Delete Recordings" selector to Debug settings
* refactor: simplify opening recordings folder logic by using tauri's opener plugin
* clean up ui and code a bit
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* feat: add fallback microphone for clamshell/desktop mode
* refactor: moved "Closed Laptop Microphone" setting to Debug
* cleanup
* run format
* add check back
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* Fix unstable mute implementation on Windows/Linux
* add some delay before the mute so the audio feedback plays
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* Add LLM post-processing feature with settings management and UI integration
* Refactor LLM post-processing settings and prompt selection logic
* Rename CLAUDE.md to more standard AGENTS.md
* Replace Open Router with OpenAI Compatible endpoints for post-processing
* Fix post processing settings api styles
* refactor or something
* simplify
* cleanup a bit?
* remove useless code
* minor improvements
* fix laggy textarea
* Store post-processing results in db
* fix text color
* new default prompt
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* windows paste shift+ins instead of ctrl+v
Shift+Insert is older and more universal than Ctrl+V on windows. For example SSH terminal software often will not permit ctrl+v.
* add option for shift+ins on windows/linux
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* Use an optimal release profile... load managers & hotkeys first, add a
splash, simplify app handler
* removed splashscreen, hopefully app boots fast enough anyhow
* No need to load transcription model on start now that its loaded on
demand & cleanup
* Make an unloaded model status
* tiny modification to unloading
* update comment
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* Add custom sound and control notif volume
* Modularize the picker and slider, consolidate the playback and loading
* Move custom sounds to advanced
* pairs of audio
* custom sound handling
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* feat(settings): add autostart toggle in advanced settings
Enable users to configure autostart behavior through a new toggle in the advanced settings UI. The backend now checks user preferences on startup to enable or disable autostart accordingly, with the setting persisted and manageable via a new Tauri command. This provides better control over app initialization without affecting existing functionality.
* immediate toggle effect?
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
This change updates the recording and transcribing overlay to appear on the monitor that currently contains the mouse cursor, rather than always appearing on the primary monitor.
This improves the user experience for those with multi-monitor setups.
🤖 Generated with [Pochi](https://getpochi.com)
Co-authored-by: Pochi <noreply@getpochi.com>
* Add history limit setting
Dearest Reviewer,
I have added a history limit setting. The limit change is applied instantly.
If the limit is 0 then no recordings are saved.
Becker
* remove extra save
save happens on exit
* move to debug menu
* use the text color
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* fix: restore translate-to-english functionality
The translate option broke when migrating from whisper-rs to transcribe-rs.
This fix patches transcribe-rs to add translate parameter support and passes
the translate_to_english setting to the Whisper engine.
Additionally fixed AccessibilityPermissions API calls to match updated library.
Translation only works with Whisper multilingual models (not .en models).
Parakeet models don't support translation as they are transcription-only.
Fixes#152
* bump transcribe rs
---------
Co-authored-by: CJ Pais <cj@cjpais.com>
* wip: model manager support for parakeet
* working parakeet??git status
* Update LanguageSelector.tsx
* Use the published version of the crate.
* move word correction into audio toolkit