getinvoke 0.5.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. getinvoke-0.5.3/.env.example +40 -0
  2. getinvoke-0.5.3/.github/workflows/build-installer.yml +107 -0
  3. getinvoke-0.5.3/.github/workflows/ci.yml +36 -0
  4. getinvoke-0.5.3/.github/workflows/publish-pypi.yml +33 -0
  5. getinvoke-0.5.3/.gitignore +24 -0
  6. getinvoke-0.5.3/LICENSE +21 -0
  7. getinvoke-0.5.3/PKG-INFO +312 -0
  8. getinvoke-0.5.3/README.md +267 -0
  9. getinvoke-0.5.3/THIRD-PARTY-LICENSES.txt +86 -0
  10. getinvoke-0.5.3/installer/build.ps1 +108 -0
  11. getinvoke-0.5.3/installer/generate_icon.py +87 -0
  12. getinvoke-0.5.3/installer/invoke.ico +0 -0
  13. getinvoke-0.5.3/installer/invoke.iss +74 -0
  14. getinvoke-0.5.3/installer/invoke.spec +114 -0
  15. getinvoke-0.5.3/pyproject.toml +55 -0
  16. getinvoke-0.5.3/ruff.toml +15 -0
  17. getinvoke-0.5.3/setup.cfg +4 -0
  18. getinvoke-0.5.3/src/getinvoke/__init__.py +8 -0
  19. getinvoke-0.5.3/src/getinvoke/__main__.py +5 -0
  20. getinvoke-0.5.3/src/getinvoke/app.py +93 -0
  21. getinvoke-0.5.3/src/getinvoke/cli.py +536 -0
  22. getinvoke-0.5.3/src/getinvoke/clipboard.py +38 -0
  23. getinvoke-0.5.3/src/getinvoke/config.py +187 -0
  24. getinvoke-0.5.3/src/getinvoke/context.py +525 -0
  25. getinvoke-0.5.3/src/getinvoke/engine.py +393 -0
  26. getinvoke-0.5.3/src/getinvoke/feedback.py +62 -0
  27. getinvoke-0.5.3/src/getinvoke/history.py +152 -0
  28. getinvoke-0.5.3/src/getinvoke/hotkey.py +133 -0
  29. getinvoke-0.5.3/src/getinvoke/icon.py +16 -0
  30. getinvoke-0.5.3/src/getinvoke/license.py +349 -0
  31. getinvoke-0.5.3/src/getinvoke/license_gui.py +163 -0
  32. getinvoke-0.5.3/src/getinvoke/modes/__init__.py +5 -0
  33. getinvoke-0.5.3/src/getinvoke/modes/prompts.py +253 -0
  34. getinvoke-0.5.3/src/getinvoke/modes/registry.py +84 -0
  35. getinvoke-0.5.3/src/getinvoke/overlay.py +175 -0
  36. getinvoke-0.5.3/src/getinvoke/recorder.py +112 -0
  37. getinvoke-0.5.3/src/getinvoke/reformatter.py +262 -0
  38. getinvoke-0.5.3/src/getinvoke/settings_gui.py +503 -0
  39. getinvoke-0.5.3/src/getinvoke/setup_cli.py +221 -0
  40. getinvoke-0.5.3/src/getinvoke/terminal.py +144 -0
  41. getinvoke-0.5.3/src/getinvoke/transcriber.py +108 -0
  42. getinvoke-0.5.3/src/getinvoke/tray.py +347 -0
  43. getinvoke-0.5.3/src/getinvoke/updater.py +233 -0
  44. getinvoke-0.5.3/src/getinvoke/window.py +147 -0
  45. getinvoke-0.5.3/src/getinvoke/wizard.py +484 -0
  46. getinvoke-0.5.3/src/getinvoke.egg-info/PKG-INFO +312 -0
  47. getinvoke-0.5.3/src/getinvoke.egg-info/SOURCES.txt +58 -0
  48. getinvoke-0.5.3/src/getinvoke.egg-info/dependency_links.txt +1 -0
  49. getinvoke-0.5.3/src/getinvoke.egg-info/entry_points.txt +5 -0
  50. getinvoke-0.5.3/src/getinvoke.egg-info/requires.txt +24 -0
  51. getinvoke-0.5.3/src/getinvoke.egg-info/top_level.txt +1 -0
  52. getinvoke-0.5.3/tests/conftest.py +11 -0
  53. getinvoke-0.5.3/tests/test_config.py +111 -0
  54. getinvoke-0.5.3/tests/test_context.py +283 -0
  55. getinvoke-0.5.3/tests/test_history.py +89 -0
  56. getinvoke-0.5.3/tests/test_license.py +246 -0
  57. getinvoke-0.5.3/tests/test_modes.py +104 -0
  58. getinvoke-0.5.3/tests/test_reformatter.py +215 -0
  59. getinvoke-0.5.3/tests/test_transcriber.py +85 -0
  60. getinvoke-0.5.3/tests/test_updater.py +121 -0
@@ -0,0 +1,40 @@
1
+ ## Reformatter backend: "none" (fastest), "openrouter", "claude-cli", or "ollama"
2
+ ## Use "none" if you paste into Claude Code / Cursor — they'll interpret raw speech fine
3
+ REFORMATTER_BACKEND=none
4
+
5
+ ## OpenRouter settings (when REFORMATTER_BACKEND=openrouter)
6
+ OPENROUTER_API_KEY=sk-or-REPLACE-ME
7
+ DICTATION_MODEL=anthropic/claude-sonnet-4-6
8
+
9
+ ## Claude CLI settings (when REFORMATTER_BACKEND=claude-cli)
10
+ # CLAUDE_CLI_PATH=claude
11
+ # CLAUDE_CLI_MODEL=haiku
12
+
13
+ ## Ollama settings (when REFORMATTER_BACKEND=ollama)
14
+ # OLLAMA_URL=http://localhost:11434
15
+ # OLLAMA_MODEL=llama3.2
16
+
17
+ ## Target mode: claude-code, cursor, windsurf, copilot, raw, commit, pr
18
+ MODE=claude-code
19
+
20
+ ## Whisper settings
21
+ WHISPER_MODEL=distil-large-v3
22
+ # WHISPER_DEVICE=auto
23
+
24
+ ## Language: "en", "auto" (auto-detect), or any Whisper language code (es, fr, de, zh, ja, ko, etc.)
25
+ # LANGUAGE=en
26
+
27
+ ## Hotkey (mouse5, mouse4, or keyboard combo)
28
+ # HOTKEY=mouse5
29
+
30
+ ## Auto-paste: "true" = insta-dump (types at cursor), "false" = clipboard only (Ctrl+V yourself)
31
+ # AUTO_PASTE=false
32
+
33
+ ## Custom vocabulary (comma-separated, boosts Whisper recognition)
34
+ # CUSTOM_VOCAB=KeyGrip,OpenRouter,pyproject,FastAPI
35
+
36
+ ## History
37
+ # HISTORY_ENABLED=true
38
+ # HISTORY_RETENTION_DAYS=30
39
+
40
+ LOG_LEVEL=INFO
@@ -0,0 +1,107 @@
1
+ name: Build Windows Installer
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: write
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: windows-latest
15
+ env:
16
+ HAS_SIGNING_CERT: ${{ secrets.CODE_SIGNING_CERT_BASE64 != '' }}
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: "3.12"
24
+ cache: "pip"
25
+
26
+ - name: Install dependencies
27
+ run: |
28
+ pip install -e ".[gui,dev]"
29
+ pip install pyinstaller
30
+
31
+ - name: Install CUDA runtime libraries
32
+ run: pip install nvidia-cublas-cu12 nvidia-cuda-runtime-cu12
33
+
34
+ - name: Build with PyInstaller
35
+ run: python -m PyInstaller installer/invoke.spec --noconfirm --clean
36
+
37
+ - name: Bundle CUDA DLLs
38
+ shell: powershell
39
+ run: |
40
+ $sitePackages = python -c "import site; print(site.getsitepackages()[0])"
41
+ $cudaDlls = Get-ChildItem -Path $sitePackages -Recurse -Include "cublas64_*.dll","cublasLt64_*.dll","cudart64_*.dll"
42
+ foreach ($dll in $cudaDlls) {
43
+ Copy-Item $dll.FullName -Destination "dist\invoke\" -Force
44
+ Write-Host "Bundled: $($dll.Name) ($([math]::Round($dll.Length / 1MB, 1)) MB)"
45
+ }
46
+ if ($cudaDlls.Count -eq 0) { Write-Warning "No CUDA DLLs found - GPU will require system CUDA" }
47
+
48
+ - name: Smoke test
49
+ run: dist\invoke\invoke-cli.exe health
50
+ continue-on-error: true
51
+
52
+ - name: Import code signing certificate
53
+ if: env.HAS_SIGNING_CERT == 'true'
54
+ env:
55
+ CODE_SIGNING_CERT: ${{ secrets.CODE_SIGNING_CERT_BASE64 }}
56
+ shell: powershell
57
+ run: |
58
+ $certBytes = [Convert]::FromBase64String($env:CODE_SIGNING_CERT)
59
+ [IO.File]::WriteAllBytes("$env:RUNNER_TEMP\cert.pfx", $certBytes)
60
+
61
+ - name: Sign executables
62
+ if: env.HAS_SIGNING_CERT == 'true'
63
+ env:
64
+ CODE_SIGNING_PASSWORD: ${{ secrets.CODE_SIGNING_PASSWORD }}
65
+ shell: cmd
66
+ run: |
67
+ signtool sign /f "%RUNNER_TEMP%\cert.pfx" /p "%CODE_SIGNING_PASSWORD%" /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /d "Invoke" dist\invoke\invoke.exe
68
+ signtool sign /f "%RUNNER_TEMP%\cert.pfx" /p "%CODE_SIGNING_PASSWORD%" /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /d "Invoke" dist\invoke\invoke-cli.exe
69
+
70
+ - name: Install Inno Setup
71
+ run: choco install innosetup -y --no-progress
72
+
73
+ - name: Set version from tag
74
+ shell: bash
75
+ run: |
76
+ VERSION="${GITHUB_REF_NAME#v}"
77
+ echo "VERSION=$VERSION" >> $GITHUB_ENV
78
+ sed -i "s/#define MyAppVersion \".*\"/#define MyAppVersion \"$VERSION\"/" installer/invoke.iss
79
+
80
+ - name: Build installer
81
+ run: iscc installer/invoke.iss
82
+
83
+ - name: Sign installer
84
+ if: env.HAS_SIGNING_CERT == 'true'
85
+ env:
86
+ CODE_SIGNING_PASSWORD: ${{ secrets.CODE_SIGNING_PASSWORD }}
87
+ shell: cmd
88
+ run: |
89
+ for %%f in (dist\invoke-setup-*.exe) do signtool sign /f "%RUNNER_TEMP%\cert.pfx" /p "%CODE_SIGNING_PASSWORD%" /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /d "Invoke Setup" "%%f"
90
+
91
+ - name: Clean up certificate
92
+ if: always()
93
+ shell: powershell
94
+ run: Remove-Item "$env:RUNNER_TEMP\cert.pfx" -ErrorAction SilentlyContinue
95
+
96
+ - name: Upload installer artifact
97
+ uses: actions/upload-artifact@v4
98
+ with:
99
+ name: invoke-installer
100
+ path: dist/invoke-setup-*.exe
101
+
102
+ - name: Upload to release
103
+ if: startsWith(github.ref, 'refs/tags/')
104
+ uses: softprops/action-gh-release@v2
105
+ with:
106
+ files: dist/invoke-setup-*.exe
107
+ generate_release_notes: true
@@ -0,0 +1,36 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_call:
9
+
10
+ jobs:
11
+ lint:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install ruff
19
+ - run: ruff check src/ tests/
20
+ - run: ruff format --check src/ tests/
21
+
22
+ test:
23
+ runs-on: ${{ matrix.os }}
24
+ strategy:
25
+ matrix:
26
+ os: [ubuntu-latest, windows-latest]
27
+ python-version: ["3.11", "3.12"]
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: ${{ matrix.python-version }}
33
+ - name: Install dependencies
34
+ run: pip install -e ".[dev]"
35
+ - name: Run tests
36
+ run: pytest tests/ -v --ignore=tests/test_gpu.py
@@ -0,0 +1,33 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ test:
10
+ uses: ./.github/workflows/ci.yml
11
+
12
+ publish:
13
+ needs: test
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ id-token: write # Trusted publishing
17
+ contents: read # Checkout private repo
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - uses: actions/setup-python@v5
23
+ with:
24
+ python-version: "3.12"
25
+
26
+ - name: Install build tools
27
+ run: pip install build
28
+
29
+ - name: Build sdist + wheel
30
+ run: python -m build
31
+
32
+ - name: Publish to PyPI
33
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,24 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ *.egg
9
+
10
+ venv/
11
+ .venv/
12
+ env/
13
+
14
+ .env
15
+ *.wav
16
+ *.mp3
17
+
18
+ .ruff_cache/
19
+ .pytest_cache/
20
+ .mypy_cache/
21
+ htmlcov/
22
+ .coverage
23
+
24
+ *.log
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zach Roth
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,312 @@
1
+ Metadata-Version: 2.4
2
+ Name: getinvoke
3
+ Version: 0.5.3
4
+ Summary: Voice-to-prompt for developers. Hold a button, speak, release — structured prompts on your clipboard in under a second.
5
+ Author-email: Zach Roth <zach@scrn.co>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://getinvoke.dev
8
+ Project-URL: Repository, https://github.com/zmroth/invoke
9
+ Keywords: voice,dictation,whisper,coding,prompt,speech-to-text,developer-tools,claude,cursor,copilot
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: Microsoft :: Windows
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: faster-whisper>=1.1.0
24
+ Requires-Dist: httpx>=0.28.0
25
+ Requires-Dist: python-dotenv>=1.0.0
26
+ Requires-Dist: pynput>=1.8.0
27
+ Requires-Dist: sounddevice>=0.5.0
28
+ Requires-Dist: numpy>=1.24.0
29
+ Requires-Dist: scipy>=1.11.0
30
+ Requires-Dist: pyperclip>=1.9.0
31
+ Requires-Dist: click>=8.0.0
32
+ Requires-Dist: rich>=13.0.0
33
+ Provides-Extra: gui
34
+ Requires-Dist: pystray>=0.19.0; extra == "gui"
35
+ Requires-Dist: Pillow>=10.0.0; extra == "gui"
36
+ Provides-Extra: cuda
37
+ Requires-Dist: nvidia-cublas-cu12; extra == "cuda"
38
+ Requires-Dist: nvidia-cuda-runtime-cu12; extra == "cuda"
39
+ Provides-Extra: dev
40
+ Requires-Dist: pytest; extra == "dev"
41
+ Requires-Dist: pytest-asyncio; extra == "dev"
42
+ Requires-Dist: ruff; extra == "dev"
43
+ Requires-Dist: pyinstaller; extra == "dev"
44
+ Dynamic: license-file
45
+
46
+ # Invoke
47
+
48
+ [![PyPI](https://img.shields.io/pypi/v/getinvoke)](https://pypi.org/project/getinvoke/)
49
+ [![Python](https://img.shields.io/pypi/pyversions/getinvoke)](https://pypi.org/project/getinvoke/)
50
+ [![License](https://img.shields.io/pypi/l/getinvoke)](https://github.com/zmroth/invoke/blob/main/LICENSE)
51
+
52
+ **Voice-to-prompt for developers.**
53
+
54
+ Hold a button, speak, release. Your words hit the clipboard (or auto-paste at your cursor) in under a second. GPU-accelerated local transcription via Whisper — no cloud round-trip for speech-to-text.
55
+
56
+ Optionally run your transcription through an AI reformatter to clean it up into structured prompts for Claude Code, Cursor, Windsurf, Copilot, or raw text.
57
+
58
+ ## Install
59
+
60
+ ```bash
61
+ # CLI only (headless, any platform)
62
+ pip install getinvoke
63
+
64
+ # With GUI (system tray + overlay)
65
+ pip install getinvoke[gui]
66
+
67
+ # Or use pipx for isolated install
68
+ pipx install getinvoke
69
+ ```
70
+
71
+ > **Note:** The CLI command is `dictate`, not `invoke`, to avoid conflict with the pyinvoke task runner.
72
+
73
+ ## Quick Start
74
+
75
+ ```bash
76
+ # Check your setup (GPU, mic, settings)
77
+ dictate health
78
+
79
+ # Run the setup wizard
80
+ dictate setup
81
+
82
+ # Start dictating (headless mode)
83
+ dictate run
84
+
85
+ # Start with GUI (requires [gui] extras)
86
+ dictate run # auto-detects GUI availability
87
+ ```
88
+
89
+ **Default workflow:** Hold **Mouse5** (forward side button) → speak → release → text on clipboard.
90
+
91
+ ## How It Works
92
+
93
+ ```
94
+ YOU SPEAK into your mic
95
+
96
+
97
+ ┌─────────────────────────────┐
98
+ │ WHISPER (runs locally) │
99
+ │ Model: distil-large-v3 │
100
+ │ GPU (CUDA) or CPU │
101
+ │ No internet. No API key. │
102
+ │ │
103
+ │ Output: raw transcription │
104
+ │ "uh so like fix the um │
105
+ │ auth middleware thing" │
106
+ └──────────────┬──────────────┘
107
+
108
+
109
+ ┌─────────────────────────────┐
110
+ │ AI REFORMATTER (optional) │
111
+ │ │
112
+ │ Takes raw speech and │
113
+ │ reshapes it based on the │
114
+ │ selected MODE: │
115
+ │ │
116
+ │ Claude Code → conversational│
117
+ │ Cursor → @file references │
118
+ │ Commit → git commit msg │
119
+ │ Raw → just clean up speech │
120
+ │ none → SKIP (no AI call) │
121
+ │ │
122
+ │ Backend options: │
123
+ │ • openrouter (cloud API) │
124
+ │ • claude-cli (local CC) │
125
+ │ • ollama (fully local) │
126
+ │ • none (skip AI entirely) │
127
+ └──────────────┬──────────────┘
128
+
129
+
130
+ ┌─────────────────────────────┐
131
+ │ CLIPBOARD + AUTO-PASTE │
132
+ │ "Fix the auth middleware │
133
+ │ to validate JWT tokens │
134
+ │ before checking roles" │
135
+ └─────────────────────────────┘
136
+ ```
137
+
138
+ ## Platform Support
139
+
140
+ | Platform | CLI (headless) | GUI (tray + overlay) | Installer |
141
+ |---|---|---|---|
142
+ | Windows | `pip install getinvoke` | `pip install getinvoke[gui]` | `.exe` via GitHub Releases |
143
+ | Linux | `pip install getinvoke` | `pip install getinvoke[gui]` | — |
144
+ | macOS | `pip install getinvoke` | Planned | — |
145
+
146
+ ## Comparison
147
+
148
+ | Feature | Invoke | whisper.cpp CLI | nerd-dictation | macOS Dictation |
149
+ |---|---|---|---|---|
150
+ | Local Whisper | Yes | Yes | Yes | No |
151
+ | AI reformatting | Yes (4 backends) | No | No | No |
152
+ | Code-aware modes | 7 modes | No | No | No |
153
+ | Project context | Auto-detected | No | No | No |
154
+ | GPU acceleration | CUDA | CUDA/Metal | No | — |
155
+ | Cross-platform | Win/Linux/Mac | Win/Linux/Mac | Linux | Mac only |
156
+ | pip installable | Yes | No | No | — |
157
+
158
+ ## Requirements
159
+
160
+ - Python 3.11+
161
+ - NVIDIA GPU recommended (CUDA) — works on CPU but slower
162
+ - Windows, Linux, or macOS
163
+
164
+ ## CLI Commands
165
+
166
+ | Command | Description |
167
+ |---|---|
168
+ | `dictate run` | Start Invoke (auto-detects GUI vs headless) |
169
+ | `dictate run --headless` | Force headless mode |
170
+ | `dictate run --no-beep` | Start without audio feedback |
171
+ | `dictate health` | Check GPU, model, mic, API keys, config |
172
+ | `dictate devices` | List audio input devices |
173
+ | `dictate modes` | List available target modes |
174
+ | `dictate history` | View dictation history |
175
+ | `dictate setup` | Run setup wizard |
176
+ | `dictate setup --cli` | Force CLI wizard (no GUI) |
177
+ | `dictate config` | View all configuration |
178
+ | `dictate config mode cursor` | Set a config value |
179
+ | `dictate license status` | Check license status |
180
+ | `dictate license activate <key>` | Activate a license |
181
+ | `dictate install` | Create Windows Startup shortcut |
182
+ | `dictate transcribe <file>` | One-shot WAV transcription |
183
+ | `dictate logs` | View log file |
184
+
185
+ ## Configuration
186
+
187
+ ### Key Settings
188
+
189
+ | Setting | Default | Options |
190
+ |---|---|---|
191
+ | `reformatter_backend` | `none` | `openrouter`, `claude-cli`, `ollama`, `none` |
192
+ | `mode` | `claude-code` | `claude-code`, `cursor`, `windsurf`, `copilot`, `raw`, `commit`, `pr` |
193
+ | `whisper_model` | `distil-large-v3` | Any [faster-whisper model](https://huggingface.co/Systran) |
194
+ | `whisper_device` | `auto` | `auto`, `cuda`, `cpu` |
195
+ | `hotkey` | `mouse5` | `mouse5`, `mouse4`, or keyboard combo |
196
+ | `auto_paste` | `false` | `true` = insta-dump at cursor |
197
+ | `audio_device` | system default | Device index from `dictate devices` |
198
+ | `beep_enabled` | `true` | `true` / `false` |
199
+
200
+ Set values quickly from the terminal:
201
+ ```bash
202
+ dictate config mode cursor
203
+ dictate config reformatter_backend claude-cli
204
+ dictate config auto_paste true
205
+ ```
206
+
207
+ ### AI Reformatter Backends
208
+
209
+ | Backend | Where it runs | What you need | Cost |
210
+ |---|---|---|---|
211
+ | `openrouter` | Cloud (OpenRouter API) | `OPENROUTER_API_KEY` | ~$0.001/dictation |
212
+ | `claude-cli` | Local (your Claude Code) | Claude Code installed | Part of your CC plan |
213
+ | `ollama` | Local (your machine) | Ollama, LM Studio, or any local LLM server | Free, no internet |
214
+ | `none` | Skipped entirely | Nothing | Free — raw Whisper output only |
215
+
216
+ ### Target Modes
217
+
218
+ | Mode | What the AI does with your speech |
219
+ |---|---|
220
+ | `claude-code` | Formats as a conversational prompt for Claude Code |
221
+ | `cursor` | Adds `@file` references, structured for Cursor's chat |
222
+ | `windsurf` | Cascade-style prompt for Windsurf |
223
+ | `copilot` | GitHub Copilot Chat format |
224
+ | `raw` | Cleans up filler/grammar only — no prompt structure |
225
+ | `commit` | Turns your description into a git commit message |
226
+ | `pr` | Turns your description into a PR title + body |
227
+
228
+ ### Custom Vocabulary
229
+
230
+ Boost Whisper recognition for domain-specific terms:
231
+
232
+ ```bash
233
+ dictate config custom_vocab "KeyGrip,OpenRouter,pyproject,FastAPI,pynput"
234
+ ```
235
+
236
+ ### History
237
+
238
+ ```bash
239
+ dictate history # Recent entries
240
+ dictate history -n 20 # Last 20
241
+ dictate history -s "fix" # Search
242
+ ```
243
+
244
+ ## Audio Feedback
245
+
246
+ - **Short high tick** — recording started (hotkey pressed)
247
+ - **Rising chirp** — done, text is on clipboard / pasted
248
+ - Disable with `dictate run --no-beep` or `dictate config beep_enabled false`
249
+
250
+ ## System Tray (GUI mode)
251
+
252
+ When installed with `pip install getinvoke[gui]`, Invoke runs in the system tray with:
253
+ - State indicator (idle / recording / processing / error)
254
+ - Current AI backend + model displayed
255
+ - Mode switcher (right-click menu)
256
+ - License management
257
+ - Settings editor
258
+ - Open logs
259
+ - Quit
260
+
261
+ Use `dictate-gui` to launch without a console window.
262
+
263
+ ## Building the Windows Installer
264
+
265
+ See the [installer README](installer/) for details on building the `.exe` installer with PyInstaller + Inno Setup.
266
+
267
+ ## Development
268
+
269
+ ```bash
270
+ pip install -e ".[dev,gui]"
271
+ ruff check src/ tests/
272
+ ruff format src/ tests/
273
+ pytest
274
+ ```
275
+
276
+ ## Architecture
277
+
278
+ ```
279
+ src/getinvoke/
280
+ engine.py # Core pipeline engine (FrontendProtocol + InvokeEngine)
281
+ app.py # GUI frontend wrapper (GuiFrontend + InvokeApp)
282
+ terminal.py # Rich terminal frontend (TerminalFrontend)
283
+ cli.py # Click CLI commands
284
+ setup_cli.py # Terminal-based setup wizard
285
+ clipboard.py # Copy + auto-paste via pynput
286
+ config.py # Settings from config.json / env vars / .env
287
+ context.py # Project context loader (18 file types + git)
288
+ feedback.py # Audio cues (beeps/chirps)
289
+ history.py # SQLite dictation history
290
+ hotkey.py # Global hotkey listener (mouse/keyboard)
291
+ license.py # Lemon Squeezy license validation (7-day trial)
292
+ license_gui.py # License activation dialog (tkinter, GUI only)
293
+ modes/ # 7 target mode system prompts
294
+ overlay.py # Recording/processing overlay (tkinter, GUI only)
295
+ recorder.py # Push-to-talk audio capture (sounddevice)
296
+ reformatter.py # LLM reformatting (OpenRouter/Claude CLI/Ollama/none)
297
+ settings_gui.py # Settings editor (tkinter, GUI only)
298
+ transcriber.py # Whisper model loading + transcription
299
+ tray.py # System tray icon + menu (pystray, GUI only)
300
+ updater.py # Auto-updater (GitHub releases + pip-aware)
301
+ window.py # Active window/file detection
302
+ wizard.py # First-run setup wizard (tkinter, GUI only)
303
+
304
+ installer/
305
+ invoke.spec # PyInstaller build config
306
+ invoke.iss # Inno Setup installer script
307
+ build.ps1 # Local build script
308
+ ```
309
+
310
+ ## License
311
+
312
+ MIT — see [THIRD-PARTY-LICENSES.txt](THIRD-PARTY-LICENSES.txt) for bundled dependency licenses.