- Remove fixed min-width constraints from comparison tables
- compare.tsx: remove min-w-[860px]
- alternatives.tsx: remove min-w-[600px]
- privacy.tsx: remove min-w-[500px]
- Tables now use native overflow-x-auto for horizontal scroll
- Fix subpage navigation overflow on mobile:
- Show only icons on mobile (no text labels)
- Add horizontal scroll support
- Add proper aria-labels for accessibility
- Add hover states for better touch feedback
Fixes responsive design issues identified during mobile audit.
New Pages Added:
- /changelog/ - Release history showing project growth
- /faq/ - SEO-optimized FAQ with JSON-LD schema
- /privacy/ - Privacy policy (trust signal for voice software)
- /shortcuts/ - Keyboard shortcuts and voice commands reference
- /troubleshooting/ - Common issues and solutions
- /use-cases/ - Target audience pages (developers, writers, students, accessibility)
- /alternatives/ - Comparison vs Dragon, Otter.ai, Google Voice Typing
Changes:
- Updated SeoSubpageShell navigation with new pages
- Updated sitemap.xml with all new URLs
- Updated homepage footer with links to new pages
- All pages include proper metadata, JSON-LD schema, and internal linking
SEO Improvements:
- FAQ page with FAQPage schema for rich snippets
- Comparison pages for high-intent keywords
- Use case pages targeting specific audiences
- Privacy page as trust signal for voice software
* chore(release): prepare v0.6.3-beta
- Fix#220: Installer default tag now points to correct version
- Update version from 0.6.2-beta to 0.6.3-beta
- Update documentation version references
- Update website schema and badges
- Add v0.6.3-beta changelog entry
The v0.6.2-beta installer was defaulting to v0.6.1-beta which is
missing the psutil dependency, causing fresh installs to fail.
* docs(update): simplify update guide, remove duplicate version history
install.sh:
- Add check_running_processes() function to detect running Vocalinux
- Prompt user to kill processes before proceeding with installation
- Auto-kill in non-interactive mode
uninstall.sh:
- Add confirmation prompt before killing processes
- Add interactive prompt for keeping data (models, config)
- Simplified --keep-data flag behavior (also keeps config)
This prevents issues during install/upgrade when Vocalinux is
still running, and gives users more control over data preservation.
The command processor was adding a leading space when processing action
commands with text after them (e.g., 'delete that text' -> ' text').
This was causing the first speech to always have an unwanted leading space.
Changes:
- Modified command_processor.py to only add space when there's text BEFORE
the action command, not at the beginning of the transcription
- Updated test cases to reflect the correct behavior without leading spaces
Fixes leading space issue on first speech.
- Add new section explaining nightly releases
- Include installation command for nightly channel
- Add warning about stability vs beta releases
- Clarify release channels (Beta vs Nightly)
- Add IBus text injection engine for Wayland support
- Add X11 IBus support for non-US keyboard layouts
- Add thread-safe model access improvements
- Update bug fix list with all included fixes (#216, #227-229)
- Mark Wayland support via IBus as completed in roadmap
The previous fix used `suppress_non_speech_tokens` which doesn't exist
in pywhispercpp's C++ bindings (whisper.cpp uses `suppress_nst` but it's
not exposed). This caused initialization error:
"_pywhispercpp.whisper_full_params object has no attribute suppress_non_speech_tokens"
Changes:
- Remove invalid `suppress_non_speech_tokens` parameter
- Add `no_speech_thold=0.6` and `entropy_thold=2.4` for better filtering
- Add `_filter_non_speech()` post-processing function that filters:
- [BLANK_AUDIO] and other bracketed tokens
- Music notes (♪♫♬♩♭♮♯)
- Pure punctuation sequences
- Low speech-content text (<30% alphanumeric)
Fixes#219
pkg-config is included in the package list to install, so the script
should not exit with an error if it's not already installed. The check
was preventing installation on fresh systems like WSL Ubuntu 24.04.
The script already has proper fallbacks for when pkg-config is not
available (detect_vulkan and detect_typelib_path both check before
calling pkg-config).
IBus sends Unicode directly via commit_text(), bypassing keyboard layout
issues entirely. This provides the same reliable text injection on X11
that we already have on Wayland.
Changes:
- Add X11_IBUS desktop environment enum
- Prefer IBus on both X11 and Wayland (before falling back to xdotool)
- Add tests for X11 IBus preference and fallback behavior
This supersedes the layout-switching approach in PR #206, which only
worked on X11 and had overhead from layout switching.
Closes#199
Fixes#215
The crash (segfault at ffffffff in libstdc++.so.6) was caused by a race
condition between the transcription thread and model reconfiguration:
1. When recording finishes, `_transcribe_with_whispercpp()` accesses
`self.model.transcribe()` which is a C++ object via pywhispercpp
2. If settings change simultaneously, `reconfigure()` sets `self.model = None`
3. The transcription thread then accesses null/freed memory → segfault
This fix adds a `_model_lock` to protect concurrent access to:
- `self.model` (Whisper and whisper.cpp engines)
- `self.recognizer` (VOSK engine)
The lock is now used in:
- `_transcribe_with_whisper()` - protects model.transcribe()
- `_transcribe_with_whispercpp()` - protects model.transcribe()
- `_process_final_buffer()` - protects recognizer for VOSK
- `reconfigure()` - protects model reinitialization
Each transcription method also checks if model/recognizer is None before
proceeding, returning an empty result gracefully if reconfiguration is in
progress.
* fix(test): add missing mocks for IBus engine test
The test_init_auto_activate test was missing mocks for:
- install_ibus_component
- start_engine_process
Without these mocks, the test would fail in CI where IBus is not
installed, as _setup_engine() would fail early and never reach
switch_engine().
* style: fix black formatting in test_ibus_engine.py
* feat(text-injection): add IBus engine for Wayland text injection
Add a custom IBus input method engine for reliable text injection on
Wayland, solving keyboard layout issues with xdotool/wtype.
Key features:
- IBus proxy engine that passes through normal keyboard input
- Text injection via Unix socket IPC
- User-level component installation (no sudo required)
- Auto-reactivation when user switches keyboard layouts
- Graceful fallback when IBus is unavailable
Changes:
- New ibus_engine.py with VocalinuxEngine and IBusTextInjector
- TextInjector now prefers IBus on Wayland for best compatibility
- Add IBus GObject bindings to system dependencies in install.sh
- Add comprehensive tests for IBus engine
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* security: secure IBus socket with permissions and peer verification
- Set directory to 0o700 (owner-only access)
- Set socket to 0o600 (owner-only read/write)
- Add SO_PEERCRED verification to reject connections from other users
This provides defense-in-depth: even if directory permissions are
bypassed, the socket server verifies the connecting process UID.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: address PR review feedback for IBus text injection
- Fix infinite loop in socket server by adding _server_running flag
- Use sys.executable instead of hardcoded python3 for venv compatibility
- Also inherit environment (env=os.environ.copy()) for venv deps
- Fix component XML to use sys.executable in <exec> tag
- Replace unsafe pgrep with PID file tracking and /proc verification
- Integrate TextInjector.stop() in TrayIndicator._quit() for cleanup
- Remove unused is_engine_registered import
- Fix redundant hasattr check to use proper None comparison
- Auto-detect and update stale IBus component XML on startup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: AntoineMontane <monnet.antoine@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* chore(release): prepare v0.6.2-beta
- Update version from 0.6.1-beta to 0.6.2-beta
- Update documentation version references
- Update website schema and badges
Changes since v0.6.1-beta:
- Fix#221: Add missing psutil dependency
- Fix#219: Suppress [BLANK_AUDIO] tokens in whisper.cpp output
- Fix#204: Resolve PyAudio paInt16 attribute error
- Fix#205: Ensure whisper module installed with --auto
- Improve Vulkan shader package detection for multiple distros
- CI: Fix nightly build tag cleanup
* docs(agents): update AGENTS.md with current project structure
- Update speech recognition engines list (whisper.cpp is now default)
- Add key dependencies section
- Update project structure with whispercpp_model_info.py and vosk_model_info.py
- Add release process quick summary
* docs(agents): add important rules about PR workflow
- Never push directly to main
- All changes require a PR
- Wait for CI before merging
- Squash merge PRs
pywhispercpp requires psutil internally but doesn't declare it as a dependency,
causing vocalinux to fail on fresh installs with:
Failed to import pywhispercpp: No module named 'psutil'
Adding psutil>=5.9.0 to vocalinux's dependencies as a workaround.
- Add suppress_blank=True and suppress_non_speech_tokens=True parameters
to whisper.cpp Model initialization to prevent blank audio tokens
from being output when transcribing silent audio
- This implements Option 2 from the investigation: suppress at the
whisper.cpp level rather than post-processing filtering
- Root cause: whisper.cpp outputs a special [BLANK_AUDIO] token
when transcribing silent audio, which was being inserted into the
text field when users paused with the mic on
The nightly workflow fails when re-running on the same day because
after deleting the remote tag, the local tag still exists in the
runner's checkout. GitHub CLI sees this local tag and expects it
to be pushed to remote.
This fix adds 'git tag -d' to delete local tags in both the
cleanup and create release steps, ensuring clean state before
creating new releases.
The previous cleanup logic sorted releases by column 3 which contained
relative dates like '3 days ago' as text. This doesn't work reliably
for sorting because '3 days ago' and '4 days ago' are compared as
strings, not dates.
This fix:
- Uses gh release list --json to get actual ISO 8601 creation timestamps
- Calculates a proper cutoff date (3 days ago in seconds since epoch)
- Parses and compares actual timestamps
- Only deletes releases that are truly older than 3 days
Fixes the nightly build retention policy.
* fix(install): correct package detection for Void and Solus, fix git fetch syntax
- Fix git fetch syntax: remove incorrect quoting around 'tag' argument
- Fix Void Linux: use 'xbps-query' instead of 'xbps-query -S' which checks
remote repos instead of installed packages
- Fix Solus: use 'eopkg list-installed | grep' instead of 'eopkg info' which
queries repository info, not installed status
These bugs caused the installer to always attempt reinstalling packages on
Void Linux and Solus, even when they were already installed.
* fix(install): correct package names for Arch, Void, and Gentoo
- Arch Linux: libappindicator-gtk3 -> libappindicator (package was renamed)
- Void Linux: libappindicator -> libappindicator-gtk3 (correct package name)
- Gentoo: dev-libs/libappindicator:3 -> dev-libs/libayatana-appindicator
(libappindicator is deprecated, use ayatana fork)
Added glslang and vulkan-tools to distributions that were missing them:
- Gentoo: dev-util/glslang
- Alpine: glslang vulkan-tools
- Void: glslang Vulkan-Tools
- Solus: glslang vulkan-tools
Validated package names against official repositories for each distro.
- Try glslc first (available on Ubuntu 24.04+)
- Fall back to glslang-tools if glslc not available (Ubuntu 22.04)
- Update user-facing messages to mention both packages
- Fixes#212 while maintaining compatibility with newer Ubuntu versions
* feat(web): overhaul SEO structure and landing pages
Add distro-specific install pages and an engine comparison hub to capture high-intent organic queries. Centralize metadata and structured data handling to improve crawl consistency, internal linking, and rich-result eligibility.
* feat(web): add subpage navigation and visual polish
Make SEO landing pages easier to discover and navigate by adding persistent subpage header/footer links to home and key routes. Refresh install and comparison pages with colorful icon-driven sections while expanding homepage footer links for stronger internal linking.
* fix(ci): make web version sync robust to schema location
CI assumed softwareVersion lived in layout.tsx, but SEO refactors moved SoftwareApplication JSON-LD to page.tsx. Update workflow sync steps to patch whichever file currently contains softwareVersion so website build and release jobs keep working.
* chore(web): remove SEO audit artifact
Drop the internal SEO audit markdown from the PR so only production website and workflow changes are included.
Swap the website Open Graph image with the provided design and regenerate both PNG and WebP assets at the standard 1200x630 share size so previews render consistently across platforms.
When installing with --engine=whisper, the installer would continue even
if the whisper package installation failed, creating a config file with
engine=whisper. This caused the app to crash on startup with
'No module named whisper'.
Changes:
- Add proper verification of whisper installation by importing the module
- Only create whisper config if installation succeeds
- Fall back to whisper.cpp if whisper installation fails
- Provide clear error messages during installation
Fixes#190
The _attempt_audio_reconnection method was incorrectly accessing
paInt16 as an attribute of the PyAudio instance instead of the
pyaudio module. Added local import and fixed the reference.
Fixes#203
Bump version from 0.6.0-beta to 0.6.1-beta with installation improvements:
Version Updates:
- src/vocalinux/version.py: 0.6.0-beta → 0.6.1-beta
- install.sh: Default tag and help text updated
- web/package.json: 0.6.0 → 0.6.1
- web/src/app/layout.tsx: schema.org softwareVersion updated
- web/src/app/page.tsx: version badge updated
Documentation Updates:
- README.md: New 'What's New' section for v0.6.1-beta
- docs/UPDATE.md: Added v0.6.1-beta release notes with new features
- docs/INSTALL.md: Version references updated
- docs/RELEASE_PROCESS.md: Example commands updated
- tests/distro-testing-checklist.md: Version references updated
- src/vocalinux/main.py: Error message updated
New Features in v0.6.1-beta:
- Interactive backend selection for whisper.cpp (GPU vs CPU)
- Enhanced welcome message with testing instructions
- Simplified install commands (tag-based URLs)
- Better GPU support with proper library detection
Bug Fixes:
- Fixed bash arithmetic with set -e
- Fixed TTY detection for interactive mode
- Auto-install git if missing
- Fixed GPU installation commands
Changed install commands to download install.sh directly from the release
tag instead of from main branch with --tag parameter. This ensures:
1. The install script version matches the release being installed
2. No version mismatch between script and code
3. Simpler, cleaner install commands
Changes:
- install.sh: Updated error message to use v0.6.0-beta URL
- README.md: All install commands now use v0.6.0-beta/install.sh
- docs/INSTALL.md: Updated quick install command
- docs/UPDATE.md: Updated update command examples
- docs/RELEASE_PROCESS.md: Updated example command
- src/vocalinux/main.py: Updated error message install command
- tests/distro-testing-checklist.md: Updated download URL
- web/src/app/page.tsx: Now uses dynamic tag in URL (not main)
- .github/workflows/release.yml: Release notes use tag-based URL
Before:
curl .../main/install.sh | bash -s -- --tag=v0.6.0-beta
After:
curl .../v0.6.0-beta/install.sh | bash
Fixes version consistency between install script and installed code.
The previous fix stored the pip command in a variable:
PYWHISPERCPP_INSTALL_CMD="GGML_CUDA=1 pip install ..."
$PYWHISPERCPP_INSTALL_CMD
This doesn't work because bash interprets "GGML_CUDA=1" as a
command, not as an environment variable prefix.
Fix: Use conditional logic to run the commands directly:
if GGML_CUDA=1 pip install ...; then
GPU_INSTALL_SUCCESS=true
fi
The basic `pip install pywhispercpp` only includes CPU support.
For GPU acceleration, pywhispercpp must be installed with special
environment flags:
- NVIDIA GPU: GGML_CUDA=1 pip install git+...
- Vulkan (AMD/Intel): GGML_VULKAN=1 pip install git+...
This fix:
- Detects GPU type during whisper.cpp installation
- Installs pywhispercpp with appropriate GPU support flag
- Falls back to CPU version if GPU install fails
Fixes#193
The previous implementation directly interpolated the commit message
into the shell script, which broke when messages contained newlines.
Words like "not" were being interpreted as shell commands.
Fix: Pass commit message via environment variable and write to temp file
before grepping, avoiding shell injection issues.
Users running the install script via curl | bash may not have git
installed. This adds a check before attempting to clone the repo
and auto-installs git using the appropriate package manager for
the detected distribution.
Fixes issue reported on Reddit where install failed on Linux Mint
with "git command not found" error at line 170.
The previous mobile fix broke desktop behavior by only taking the last result.
This fix uses resultIndex properly while also tracking processed results to
prevent duplication on mobile browsers where resultIndex stays at 0.
- Track processed results using a Set to avoid duplication
- Still use resultIndex for proper accumulation on desktop
- Clear processed results when starting a new session
Fixes speech result duplication issue on mobile while restoring
proper accumulation behavior on desktop browsers.
* docs: update all documentation for whisper.cpp as default engine
Comprehensive documentation update highlighting whisper.cpp as the new
default speech recognition engine:
README.md:
- Added 'Major Change: whisper.cpp is Now Default!' section
- Updated Features to highlight whisper.cpp and Vulkan GPU support
- Updated Quick Install section with engine choices
- Changed default engine from whisper to whisper_cpp in examples
- Updated configuration examples
- Updated roadmap to mark whisper.cpp as complete
docs/INSTALL.md:
- Added whisper.cpp section with performance benefits
- Updated installation options (--engine flag)
- Added GPU support matrix and Vulkan detection info
- Added installation time comparison table
- Updated system requirements (lower disk space for whisper.cpp)
docs/USER_GUIDE.md:
- Added comprehensive 'Choosing Your Engine' section
- Added GPU acceleration information
- Updated tips to mention whisper.cpp benefits
- Added model size recommendations
web/src/app/page.tsx:
- Updated hero to mention whisper.cpp (C++ optimized, Vulkan support)
- Changed installation time from ~5-10 min to ~1-2 min
- Updated Features section to mention Vulkan GPU support
- Added whisper.cpp as default engine card (3-column layout)
- Updated installation commands (--engine flags)
- Updated FAQ about switching engines
This ensures all documentation reflects whisper.cpp as the new default
and highlights its major benefits: 10x faster install, universal GPU
support, and C++ optimized performance.
* chore(release): prepare v0.6.0-beta
This release brings whisper.cpp as the new default speech recognition engine:
Version Updates:
- Bump version from 0.5.0-beta to 0.6.0-beta
- Update src/vocalinux/version.py
- Update web/package.json
Documentation Updates:
- README.md: Update all v0.5.0-beta references to v0.6.0-beta
- docs/INSTALL.md: Update version references and installation commands
- docs/UPDATE.md: Add new 'What's New' section highlighting whisper.cpp
- SECURITY.md: Update supported versions table (0.6.x now supported)
Website Updates:
- web/src/app/layout.tsx: Update softwareVersion to 0.6.0-beta
Release Highlights:
- whisper.cpp is now the default engine (10x faster install!)
- Universal GPU support via Vulkan (AMD, Intel, NVIDIA)
- C++ optimized inference with multi-threading
- ~1-2 minute installation vs ~5-10 minutes before
Testing:
- All 472 tests passing
- Black formatting clean
- Flake8 linting clean
- isort import ordering clean
* ui(website): improve hero section layout
* docs(readme): remove duplicate What's New section
The sed pattern didn't correctly match tar.gz files which don't have
a dash after the version number. Fixed by explicitly handling both
.whl and .tar.gz file extensions with proper naming patterns.
Fixes the error: 'mv: source and destination are the same file'
The nightly build workflow was not creating accessible releases for users.
This fix addresses several issues:
- Add write permissions (contents: read → contents: write) to create GitHub releases
- Create a persistent 'nightly' pre-release that users can easily find and download
- Add workflow_dispatch trigger for manual testing
- Improve version naming: {base_version}.dev{date}+{short_sha}
- Extend artifact retention from 7 to 30 days
- Add clear installation instructions in release notes
Users can now access nightly builds at:
https://github.com/jatinkrmalik/vocalinux/releases/tag/nightlyFixes#186
The nightly build workflow was not creating accessible releases for users.
This fix addresses several issues:
- Add write permissions (contents: read → contents: write) to create GitHub releases
- Create a persistent 'nightly' pre-release that users can easily find and download
- Add workflow_dispatch trigger for manual testing
- Improve version naming: {base_version}.dev{date}+{short_sha}
- Extend artifact retention from 7 to 30 days
- Add clear installation instructions in release notes
Users can now access nightly builds at:
https://github.com/jatinkrmalik/vocalinux/releases/tag/nightlyFixes#186
* feat(speech): add whisper.cpp with Vulkan support for GPU acceleration
Add whisper.cpp as a new speech recognition engine with the following features:
- Vulkan GPU acceleration support (AMD, Intel, NVIDIA)
- Fallback to CUDA for NVIDIA GPUs
- CPU-only mode with automatic thread optimization
- Support for all model sizes: tiny, base, small, medium, large
- Hardware detection to recommend best model/backend
- Models downloaded from Hugging Face (ggml format)
- Updated UI to show compute backend info in settings
- pywhispercpp as the Python binding library
- whisper_cpp as the new default engine
Changes:
- New whispercpp_model_info.py with model metadata and hardware detection
- Updated recognition_manager.py with whisper.cpp init and transcription
- Updated settings_dialog.py with whisper.cpp UI support
- Updated config_manager.py with whisper_cpp_model_size config
- Updated main.py with whisper_cpp CLI option
- Updated pyproject.toml with pywhispercpp dependency
- Updated install.sh with vulkan-tools for GPU detection
Closes#104
* style: fix black and isort formatting issues
* test: update config manager test for whisper_cpp default engine
* feat(install): interactive mode with 3 engine choices and whisper.cpp as default
Major changes to install.sh:
- Interactive mode is now the DEFAULT (not --auto)
- Added --auto flag for non-interactive automatic installation
- New --engine flag to specify engine directly
- Interactive mode shows 3 engine options with visual boxes:
1. whisper.cpp (recommended) - Vulkan/CUDA/CPU support
2. whisper (OpenAI) - PyTorch-based, NVIDIA-only
3. VOSK - lightweight option
- Hardware detection with recommendations:
- Detects Vulkan support (AMD/Intel/NVIDIA)
- Detects NVIDIA CUDA
- Checks available RAM
- Recommends best engine based on hardware
- Updated help text with new options and examples
- Removed old --with-whisper, --whisper-cpu, --no-whisper flags
- whisper.cpp is now the default engine for automatic mode
* feat(uninstall): kill running vocalinux processes before uninstall
* fix(whisper.cpp): auto-download model, use all CPU cores, hide unavailable engines
Three fixes for whisper.cpp implementation:
1. Auto-download model during install
- Added install_whispercpp_model() function to install.sh
- Downloads ggml-tiny.bin (~39MB) from Hugging Face
- Runs automatically when whisper.cpp engine is selected
2. Use all CPU cores for transcription
- Added n_threads parameter to Model initialization
- Uses multiprocessing.cpu_count() to get all cores
- Significantly improves transcription speed
3. Hide unavailable engines from dropdown
- Added get_available_engines() function to detect installed engines
- Settings dialog now only shows engines that are actually installed
- Falls back to first available engine if current not available
Fixes user-reported issues with whisper.cpp integration.
* ui(settings): display whisper.cpp correctly and increase dialog height
- Changed engine display name from 'whisper_cpp' to 'whisper.cpp'
- Added format_engine_display_name() helper function
- Dialog now uses 75% of screen height for better visibility
- More options visible by default without scrolling
* revert(settings): remove display name change, keep dialog height increase
- Reverted engine display name change (was breaking engine selection)
- Kept dialog height at 75% of screen for better visibility
* style: fix black and isort formatting for whisper.cpp logging
* style: fix black formatting in settings_dialog.py
* ci: fix Fedora 39 container package installation
Add dnf cache update and fallback with --nogpgcheck for Fedora containers
that may have stale or missing package metadata.
- Add language mapping with flag emojis for 40+ locales
- Display detected browser language in header with flag badge
- Show Listening in Language indicator when active
- Responsive design: language name hidden on mobile, flag always visible
Improves UX by making users aware of which language the speech recognition is configured for.
Use navigator.language instead of hardcoded 'en-US' so the demo works
for users with non-English browser settings (French, German, Spanish, etc.)
Fixes#165