* feat: add CLI parameters for Linux (--start-hidden, --no-tray, --toggle-transcription, --debug) Add command-line interface using clap for better Linux desktop integration: - --start-hidden: launch without showing the main window - --no-tray: launch without system tray icon (closing window quits app) - --toggle-transcription: toggle recording on/off on a running instance via tauri_plugin_single_instance - --debug: enable debug mode with Trace-level logging (runtime-only) Extract toggle_transcription() from signal_handle.rs into a reusable function shared between SIGUSR2 handler and CLI single-instance callback. Update CLAUDE.md and README.md with CLI documentation including setup instructions for GNOME, KDE Plasma, Sway/i3, and Hyprland. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * add cancel and post processs * cleanup * format * docs --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: CJ Pais <cj@cjpais.com>
6 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Development Commands
Prerequisites: Rust (latest stable), Bun
# Install dependencies
bun install
# Run in development mode
bun run tauri dev
# If cmake error on macOS:
CMAKE_POLICY_VERSION_MINIMUM=3.5 bun run tauri dev
# Build for production
bun run tauri build
# Linting and formatting (run before committing)
bun run lint # ESLint for frontend
bun run lint:fix # ESLint with auto-fix
bun run format # Prettier + cargo fmt
bun run format:check # Check formatting without changes
Model Setup (Required for Development):
mkdir -p src-tauri/resources/models
curl -o src-tauri/resources/models/silero_vad_v4.onnx https://blob.handy.computer/silero_vad_v4.onnx
Architecture Overview
Handy is a cross-platform desktop speech-to-text app built with Tauri 2.x (Rust backend + React/TypeScript frontend).
Backend Structure (src-tauri/src/)
lib.rs- Main entry point, Tauri setup, manager initializationmanagers/- Core business logic:audio.rs- Audio recording and device managementmodel.rs- Model downloading and managementtranscription.rs- Speech-to-text processing pipelinehistory.rs- Transcription history storage
audio_toolkit/- Low-level audio processing:audio/- Device enumeration, recording, resamplingvad/- Voice Activity Detection (Silero VAD)
commands/- Tauri command handlers for frontend communicationshortcut.rs- Global keyboard shortcut handlingsettings.rs- Application settings management
Frontend Structure (src/)
App.tsx- Main component with onboarding flowcomponents/settings/- Settings UI (35+ files)components/model-selector/- Model management interfacecomponents/onboarding/- First-run experiencehooks/useSettings.ts,useModels.ts- State management hooksstores/settingsStore.ts- Zustand store for settingsbindings.ts- Auto-generated Tauri type bindings (via tauri-specta)overlay/- Recording overlay window code
Key Patterns
Manager Pattern: Core functionality organized into managers (Audio, Model, Transcription) initialized at startup and managed via Tauri state.
Command-Event Architecture: Frontend → Backend via Tauri commands; Backend → Frontend via events.
Pipeline Processing: Audio → VAD → Whisper/Parakeet → Text output → Clipboard/Paste
State Flow: Zustand → Tauri Command → Rust State → Persistence (tauri-plugin-store)
Internationalization (i18n)
All user-facing strings must use i18next translations. ESLint enforces this (no hardcoded strings in JSX).
Adding new text:
- Add key to
src/i18n/locales/en/translation.json - Use in component:
const { t } = useTranslation(); t('key.path')
File structure:
src/i18n/
├── index.ts # i18n setup
├── languages.ts # Language metadata
└── locales/
├── en/translation.json # English (source)
├── es/translation.json # Spanish
├── fr/translation.json # French
└── vi/translation.json # Vietnamese
Code Style
Rust:
- Run
cargo fmtandcargo clippybefore committing - Handle errors explicitly (avoid unwrap in production)
- Use descriptive names, add doc comments for public APIs
TypeScript/React:
- Strict TypeScript, avoid
anytypes - Functional components with hooks
- Tailwind CSS for styling
- Path aliases:
@/→./src/
Commit Guidelines
Use conventional commits:
feat:new featuresfix:bug fixesdocs:documentationrefactor:code refactoringchore:maintenance
CLI Parameters
Handy supports command-line parameters on all platforms for integration with scripts, window managers, and autostart configurations.
Implementation files:
src-tauri/src/cli.rs- CLI argument definitions (clap derive)src-tauri/src/main.rs- Argument parsing before Tauri launchsrc-tauri/src/lib.rs- Applying CLI overrides (setup closure + single-instance callback)src-tauri/src/signal_handle.rs-send_transcription_input()reusable function
Available flags:
| Flag | Description |
|---|---|
--toggle-transcription |
Toggle recording on/off on a running instance (via tauri_plugin_single_instance) |
--toggle-post-process |
Toggle recording with post-processing on/off on a running instance |
--cancel |
Cancel the current operation on a running instance |
--start-hidden |
Launch without showing the main window (tray icon still visible) |
--no-tray |
Launch without the system tray icon (closing window quits the app) |
--debug |
Enable debug mode with verbose (Trace) logging |
Key design decisions:
- CLI flags are runtime-only overrides — they do NOT modify persisted settings
- Remote control flags (
--toggle-transcription,--toggle-post-process,--cancel) work by launching a second instance that sends its args to the running instance viatauri_plugin_single_instance, then exits send_transcription_input()insignal_handle.rsis shared between signal handlers and CLI to avoid code duplicationCliArgsis stored in Tauri managed state (.manage()) so it's accessible inon_window_eventand other handlers
Debug Mode
Access debug features: Cmd+Shift+D (macOS) or Ctrl+Shift+D (Windows/Linux)
Platform Notes
- macOS: Metal acceleration, accessibility permissions required
- Windows: Vulkan acceleration, code signing
- Linux: OpenBLAS + Vulkan, limited Wayland support, overlay disabled by default