Merge pull request #1 from outis1one/claude/create-bash-installer-GSmST
Add single-file bash installer for OpenWhispr
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Report a problem with the installer
|
||||||
|
title: "[Bug] "
|
||||||
|
labels: bug
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
## Describe the bug
|
||||||
|
|
||||||
|
A clear and concise description of what went wrong.
|
||||||
|
|
||||||
|
## Steps to reproduce
|
||||||
|
|
||||||
|
1. Run `bash setup-openwhispr.sh`
|
||||||
|
2. Choose option ...
|
||||||
|
3. See error ...
|
||||||
|
|
||||||
|
## Expected behaviour
|
||||||
|
|
||||||
|
What you expected to happen.
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
|
||||||
|
- **Distro**: (e.g., Ubuntu 24.04)
|
||||||
|
- **Architecture**: (e.g., x86_64 / aarch64)
|
||||||
|
- **Session type**: (X11 / Wayland)
|
||||||
|
- **Desktop**: (GNOME / KDE / other)
|
||||||
|
- **OpenWhispr version**: (if already installed)
|
||||||
|
- **Script version**: (run `head -5 setup-openwhispr.sh`)
|
||||||
|
|
||||||
|
## Terminal output
|
||||||
|
|
||||||
|
```
|
||||||
|
Paste relevant output here
|
||||||
|
```
|
||||||
|
|
||||||
|
## Additional context
|
||||||
|
|
||||||
|
Anything else that might help.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
name: Distro compatibility report
|
||||||
|
about: Report whether the installer works on your distro
|
||||||
|
title: "[Distro] "
|
||||||
|
labels: distro-report
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
## Distribution details
|
||||||
|
|
||||||
|
- **Distro**: (e.g., Pop!_OS 24.04)
|
||||||
|
- **Based on**: (e.g., Ubuntu / Debian / Arch / independent)
|
||||||
|
- **Architecture**: (x86_64 / aarch64)
|
||||||
|
- **Session type**: (X11 / Wayland)
|
||||||
|
- **Desktop environment**: (GNOME / KDE / Sway / other)
|
||||||
|
|
||||||
|
## Result
|
||||||
|
|
||||||
|
- [ ] Script detected distro correctly
|
||||||
|
- [ ] OpenWhispr installed successfully
|
||||||
|
- [ ] Paste dependencies installed correctly
|
||||||
|
- [ ] API keys stored correctly
|
||||||
|
- [ ] OpenWhispr launched after install
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Any issues, workarounds, or suggestions for this distro.
|
||||||
|
|
||||||
|
## Terminal output
|
||||||
|
|
||||||
|
```
|
||||||
|
Paste full script output here
|
||||||
|
```
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
## What does this PR do?
|
||||||
|
|
||||||
|
Brief description of the change.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] `bash -n setup-openwhispr.sh` passes (no syntax errors)
|
||||||
|
- [ ] ShellCheck passes with no new warnings
|
||||||
|
- [ ] Tested on at least one supported distro
|
||||||
|
- [ ] Updated CHANGELOG.md if user-facing
|
||||||
|
- [ ] No hardcoded paths or usernames (uses YOUR_USERNAME placeholder or is generic)
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Describe how you tested this change.
|
||||||
|
|
||||||
|
## Related issues
|
||||||
|
|
||||||
|
Closes #
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
name: ShellCheck
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
shellcheck:
|
||||||
|
name: ShellCheck
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install ShellCheck
|
||||||
|
run: sudo apt-get install -y shellcheck
|
||||||
|
|
||||||
|
- name: Run ShellCheck
|
||||||
|
run: shellcheck -x setup-openwhispr.sh
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Editor
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Temp
|
||||||
|
/tmp/
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
|
## [1.0.0] — 2026-03-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Single-file bash installer `setup-openwhispr.sh`
|
||||||
|
- Automatic distro detection (Ubuntu, Debian, Mint, Fedora, openSUSE, Arch)
|
||||||
|
- Architecture detection (amd64, arm64)
|
||||||
|
- GitHub releases integration — fetches latest OpenWhispr automatically
|
||||||
|
- Paste dependency detection (xdotool / kdotool / wtype / D-Bus)
|
||||||
|
- STT provider selection: local Whisper/Parakeet, Groq, OpenAI Realtime
|
||||||
|
- AI cleanup provider selection: OpenAI, Anthropic, Groq, Ollama, skip
|
||||||
|
- Safe API key storage in `~/.bashrc` (never overwrites existing keys)
|
||||||
|
- Idempotent — safe to re-run, skips already-installed versions
|
||||||
|
- ShellCheck CI via GitHub Actions
|
||||||
|
- README with cost table, privacy table, and one-command install
|
||||||
|
- Issue templates for bug reports and distro compatibility reports
|
||||||
|
- Pull request template
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# GitHub Repository Setup Guide
|
||||||
|
|
||||||
|
Step-by-step instructions to publish this project on GitHub.
|
||||||
|
|
||||||
|
## 1. Create a new GitHub repository
|
||||||
|
|
||||||
|
Go to [github.com/new](https://github.com/new) and create a repository:
|
||||||
|
|
||||||
|
- **Name**: `openwhispr-easy-setup`
|
||||||
|
- **Description**: `One-command installer for OpenWhispr on Linux — distro detection, dependencies, API keys, first-run setup`
|
||||||
|
- **Visibility**: Public
|
||||||
|
- **Do NOT** initialize with README, .gitignore, or license (we already have them)
|
||||||
|
|
||||||
|
## 2. Push local files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd openwhispr-easy-setup
|
||||||
|
git init
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial release v1.0.0"
|
||||||
|
git branch -M main
|
||||||
|
git remote add origin https://github.com/YOUR_USERNAME/openwhispr-easy-setup.git
|
||||||
|
git push -u origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Replace YOUR_USERNAME placeholder
|
||||||
|
|
||||||
|
Replace `YOUR_USERNAME` with your actual GitHub username in all files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sed -i 's/YOUR_USERNAME/your-actual-username/g' setup-openwhispr.sh README.md GITHUB_SETUP.md LICENSE
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A
|
||||||
|
git commit -m "Replace YOUR_USERNAME with actual username"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Tag the v1.0.0 release
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag -a v1.0.0 -m "v1.0.0 — Initial release"
|
||||||
|
git push origin v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
Then go to **Releases → Draft a new release**:
|
||||||
|
- **Tag**: `v1.0.0`
|
||||||
|
- **Title**: `v1.0.0 — Initial release`
|
||||||
|
- **Description**: Copy the [CHANGELOG.md](CHANGELOG.md) entries for v1.0.0
|
||||||
|
- Click **Publish release**
|
||||||
|
|
||||||
|
## 5. Add GitHub topics
|
||||||
|
|
||||||
|
Go to your repository page → click the gear icon next to **About** → add these topics:
|
||||||
|
|
||||||
|
```
|
||||||
|
linux
|
||||||
|
voice-dictation
|
||||||
|
openwhispr
|
||||||
|
speech-to-text
|
||||||
|
whisper
|
||||||
|
easy-install
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Set repository description
|
||||||
|
|
||||||
|
In the same **About** section, set the description to:
|
||||||
|
|
||||||
|
> One-command installer for OpenWhispr on Linux — distro detection, dependencies, API keys, first-run setup
|
||||||
|
|
||||||
|
## 7. Verify
|
||||||
|
|
||||||
|
- [ ] README renders correctly with badges
|
||||||
|
- [ ] ShellCheck CI runs on push (check **Actions** tab)
|
||||||
|
- [ ] Issue templates appear when creating new issues
|
||||||
|
- [ ] PR template appears when opening a pull request
|
||||||
|
- [ ] `bash <(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/openwhispr-easy-setup/main/setup-openwhispr.sh)` works
|
||||||
|
|
||||||
|
## Done!
|
||||||
|
|
||||||
|
Share the one-liner with anyone who wants to install OpenWhispr:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/openwhispr-easy-setup/main/setup-openwhispr.sh)
|
||||||
|
```
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 YOUR_USERNAME
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# OpenWhispr Easy Setup
|
||||||
|
|
||||||
|
[](LICENSE)
|
||||||
|
[](https://github.com/YOUR_USERNAME/openwhispr-easy-setup/actions/workflows/lint.yml)
|
||||||
|
|
||||||
|
**One-command installer for [OpenWhispr](https://github.com/OpenWhispr/openwhispr) on Linux** — distro detection, dependencies, API keys, first-run setup.
|
||||||
|
|
||||||
|
> *Your voice stays on your machine. Always. The only question is whether you want AI to clean up the text after transcription.*
|
||||||
|
|
||||||
|
## Quick install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/openwhispr-easy-setup/main/setup-openwhispr.sh)
|
||||||
|
```
|
||||||
|
|
||||||
|
Or clone and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/YOUR_USERNAME/openwhispr-easy-setup.git
|
||||||
|
cd openwhispr-easy-setup
|
||||||
|
bash setup-openwhispr.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
| Step | Action | Details |
|
||||||
|
|------|--------|---------|
|
||||||
|
| 1/8 | **Intro** | Explains OpenWhispr and the privacy model |
|
||||||
|
| 2/8 | **Detect distro + arch** | Ubuntu, Debian, Mint, Fedora, openSUSE, Arch — amd64/arm64 |
|
||||||
|
| 3/8 | **Install OpenWhispr** | Fetches latest release from GitHub, picks correct package |
|
||||||
|
| 4/8 | **Paste dependencies** | xdotool (X11), wtype (Wayland), kdotool (KDE), or D-Bus (GNOME) |
|
||||||
|
| 5/8 | **STT provider** | Local Whisper/Parakeet, Groq, or OpenAI Realtime |
|
||||||
|
| 6/8 | **AI cleanup** | OpenAI, Anthropic, Groq, Ollama, or skip |
|
||||||
|
| 7/8 | **First launch** | Opens OpenWhispr for model download and hotkey setup |
|
||||||
|
| 8/8 | **Summary** | Prints config, useful commands, and next steps |
|
||||||
|
|
||||||
|
## STT options
|
||||||
|
|
||||||
|
| Option | Method | Streaming | Cost | Audio sent to |
|
||||||
|
|--------|--------|-----------|------|---------------|
|
||||||
|
| 1 (default) | Local Whisper/Parakeet | No | Free | Nobody, ever |
|
||||||
|
| 2 | Groq whisper-large-v3-turbo | No | $0.04/hr* | Groq servers |
|
||||||
|
| 3 | OpenAI Realtime API | Yes | $0.06/min | OpenAI servers |
|
||||||
|
|
||||||
|
\*Groq free tier: ~2,000 audio seconds/day.
|
||||||
|
|
||||||
|
## AI cleanup options
|
||||||
|
|
||||||
|
| Provider | Model | Per use | 50/day/mo | 200/day/mo |
|
||||||
|
|----------|-------|---------|-----------|------------|
|
||||||
|
| OpenAI | gpt-4o-mini-2024-07-18 | $0.000058 | $0.09 | $0.35 |
|
||||||
|
| Anthropic | claude-haiku-4-5 | $0.000450 | $0.68 | $2.70 |
|
||||||
|
| Groq | llama-3.3-70b-versatile | Free* | Free* | Free* |
|
||||||
|
| Ollama | Local (fully offline) | Free | Free | Free |
|
||||||
|
| Skip | Raw transcription only | Free | Free | Free |
|
||||||
|
|
||||||
|
\*Groq free: 1,000 req/day, 100K tokens/day.
|
||||||
|
|
||||||
|
## Privacy
|
||||||
|
|
||||||
|
| Data | Where it goes | Condition |
|
||||||
|
|------|---------------|-----------|
|
||||||
|
| **Audio** | Stays on your machine | Default (local Whisper/Parakeet) |
|
||||||
|
| **Audio** | Groq or OpenAI servers | Only if you choose cloud STT |
|
||||||
|
| **Text** | AI cleanup provider | Only if you choose AI cleanup |
|
||||||
|
| **API keys** | `~/.bashrc` on your machine | Never sent anywhere by this script |
|
||||||
|
|
||||||
|
No provider uses your data for training. Cloud data is deleted within 30 days.
|
||||||
|
|
||||||
|
## Useful commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openwhispr # Launch the app
|
||||||
|
openwhispr --help # Show options
|
||||||
|
source ~/.bashrc # Reload API keys in current shell
|
||||||
|
```
|
||||||
|
|
||||||
|
In the app:
|
||||||
|
- **Settings → Hotkey** — change your hotkey (default: backtick `` ` ``)
|
||||||
|
- **Settings → Models** — download better speech models
|
||||||
|
- **Settings → Processing** — change STT or AI provider
|
||||||
|
|
||||||
|
## Supported distros
|
||||||
|
|
||||||
|
| Distro | Package format | Status |
|
||||||
|
|--------|---------------|--------|
|
||||||
|
| Ubuntu / Debian / Mint | `.deb` | Supported |
|
||||||
|
| Fedora | `.rpm` (dnf) | Supported |
|
||||||
|
| openSUSE | `.rpm` (zypper) | Supported |
|
||||||
|
| Arch / Manjaro / EndeavourOS | `.tar.gz` | Supported |
|
||||||
|
|
||||||
|
Architecture: `x86_64` (amd64) and `aarch64` (arm64).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- **bash 4+**
|
||||||
|
- **curl** — for downloading
|
||||||
|
- **jq** — for parsing GitHub API (script offers to install if missing)
|
||||||
|
|
||||||
|
## Safe to re-run
|
||||||
|
|
||||||
|
The script is idempotent:
|
||||||
|
- Skips OpenWhispr install if the latest version is already present
|
||||||
|
- Never overwrites existing API keys in `~/.bashrc`
|
||||||
|
- Detects already-installed paste dependencies
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- [OpenWhispr Troubleshooting Guide](https://github.com/OpenWhispr/openwhispr/blob/main/TROUBLESHOOTING.md)
|
||||||
|
- [Open an issue](https://github.com/YOUR_USERNAME/openwhispr-easy-setup/issues/new/choose)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
Executable
+619
@@ -0,0 +1,619 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# setup-openwhispr.sh — One-command installer for OpenWhispr on Linux
|
||||||
|
# https://github.com/YOUR_USERNAME/openwhispr-easy-setup
|
||||||
|
# License: MIT
|
||||||
|
|
||||||
|
# Do NOT use set -e — we handle errors explicitly
|
||||||
|
|
||||||
|
readonly SCRIPT_VERSION="1.0.0"
|
||||||
|
readonly BASHRC="$HOME/.bashrc"
|
||||||
|
readonly MARKER="# Added by openwhispr-easy-setup"
|
||||||
|
readonly GITHUB_API="https://api.github.com/repos/OpenWhispr/openwhispr/releases/latest"
|
||||||
|
readonly TMP_DIR="/tmp/openwhispr-install"
|
||||||
|
|
||||||
|
# ── Colours & formatting ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if [[ -t 1 ]]; then
|
||||||
|
BOLD='\033[1m'
|
||||||
|
DIM='\033[2m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
RESET='\033[0m'
|
||||||
|
else
|
||||||
|
BOLD='' DIM='' GREEN='' YELLOW='' RED='' CYAN='' RESET=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Helper functions ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
info() { printf "${GREEN}[✓]${RESET} %s\n" "$*"; }
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
warn() { printf "${YELLOW}[!]${RESET} %s\n" "$*"; }
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
err() { printf "${RED}[✗]${RESET} %s\n" "$*" >&2; }
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
step() { printf "\n${BOLD}${CYAN}[%s]${RESET} ${BOLD}%s${RESET}\n" "$1" "$2"; }
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
divider() { printf "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"; }
|
||||||
|
|
||||||
|
prompt_default() {
|
||||||
|
# Usage: prompt_default "prompt text" "default" VARNAME
|
||||||
|
local prompt="$1" default="$2" varname="$3" reply
|
||||||
|
printf "%s [default: %s]: " "$prompt" "$default"
|
||||||
|
read -r reply
|
||||||
|
reply="${reply:-$default}"
|
||||||
|
printf -v "$varname" '%s' "$reply"
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_hidden() {
|
||||||
|
# Usage: prompt_hidden "prompt text" VARNAME
|
||||||
|
local prompt="$1" varname="$2" reply
|
||||||
|
printf "%s: " "$prompt"
|
||||||
|
read -rs reply
|
||||||
|
printf "\n"
|
||||||
|
printf -v "$varname" '%s' "$reply"
|
||||||
|
}
|
||||||
|
|
||||||
|
store_api_key() {
|
||||||
|
# Usage: store_api_key VARNAME value
|
||||||
|
local keyname="$1" keyval="$2"
|
||||||
|
if [[ -z "$keyval" ]]; then
|
||||||
|
warn "Empty value for $keyname — skipping."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# Check if already present in bashrc
|
||||||
|
if grep -q "^export ${keyname}=" "$BASHRC" 2>/dev/null; then
|
||||||
|
info "$keyname already set in $BASHRC — not overwriting."
|
||||||
|
else
|
||||||
|
printf '\n%s\nexport %s="%s"\n' "$MARKER" "$keyname" "$keyval" >> "$BASHRC"
|
||||||
|
info "$keyname stored in $BASHRC"
|
||||||
|
fi
|
||||||
|
# Also export for current session
|
||||||
|
export "$keyname=$keyval"
|
||||||
|
}
|
||||||
|
|
||||||
|
command_exists() { command -v "$1" >/dev/null 2>&1; }
|
||||||
|
|
||||||
|
# ── Variables set during the run ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
DISTRO="" # debian, ubuntu, mint, fedora, arch, opensuse
|
||||||
|
DISTRO_FAMILY="" # deb, rpm-dnf, rpm-zypper, arch
|
||||||
|
ARCH="" # amd64, arm64
|
||||||
|
SESSION_TYPE="" # x11, wayland
|
||||||
|
DESKTOP="" # GNOME, KDE, etc.
|
||||||
|
STT_CHOICE=""
|
||||||
|
CLEANUP_CHOICE=""
|
||||||
|
STT_LABEL=""
|
||||||
|
CLEANUP_LABEL=""
|
||||||
|
INSTALLED_VERSION=""
|
||||||
|
LATEST_VERSION=""
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# [1/8] Intro
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
step "1/8" "Welcome to OpenWhispr Easy Setup v${SCRIPT_VERSION}"
|
||||||
|
divider
|
||||||
|
cat <<'INTRO'
|
||||||
|
OpenWhispr is an Electron-based voice dictation app for Linux.
|
||||||
|
Press a hotkey, speak, and your words appear wherever the cursor is.
|
||||||
|
|
||||||
|
Your voice stays on your machine. Always.
|
||||||
|
The only question is whether you want AI to clean up
|
||||||
|
the text after transcription.
|
||||||
|
|
||||||
|
Speech-to-text (STT) is local Whisper/Parakeet by default.
|
||||||
|
Audio never leaves your machine unless YOU explicitly choose a cloud option.
|
||||||
|
|
||||||
|
This script will:
|
||||||
|
1. Detect your distro and architecture
|
||||||
|
2. Install OpenWhispr (latest release)
|
||||||
|
3. Install paste/typing dependencies
|
||||||
|
4. Configure STT provider
|
||||||
|
5. Configure AI text cleanup
|
||||||
|
6. Launch OpenWhispr for first-run setup
|
||||||
|
INTRO
|
||||||
|
divider
|
||||||
|
printf "\nPress Enter to continue or Ctrl-C to cancel... "
|
||||||
|
read -r
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# [2/8] Detect distro + arch
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
step "2/8" "Detecting distribution and architecture"
|
||||||
|
|
||||||
|
detect_distro() {
|
||||||
|
if [[ -f /etc/os-release ]]; then
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
. /etc/os-release
|
||||||
|
case "${ID,,}" in
|
||||||
|
ubuntu) DISTRO="ubuntu"; DISTRO_FAMILY="deb" ;;
|
||||||
|
debian) DISTRO="debian"; DISTRO_FAMILY="deb" ;;
|
||||||
|
linuxmint) DISTRO="mint"; DISTRO_FAMILY="deb" ;;
|
||||||
|
fedora) DISTRO="fedora"; DISTRO_FAMILY="rpm-dnf" ;;
|
||||||
|
opensuse*|sles) DISTRO="opensuse"; DISTRO_FAMILY="rpm-zypper" ;;
|
||||||
|
arch|manjaro|endeavouros) DISTRO="arch"; DISTRO_FAMILY="arch" ;;
|
||||||
|
*)
|
||||||
|
err "Unsupported distribution: ${ID} (${PRETTY_NAME:-unknown})"
|
||||||
|
err "Supported: Ubuntu, Debian, Mint, Fedora, openSUSE, Arch"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
err "Cannot detect distribution (/etc/os-release not found)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
detect_arch() {
|
||||||
|
local machine
|
||||||
|
machine="$(uname -m)"
|
||||||
|
case "$machine" in
|
||||||
|
x86_64) ARCH="amd64" ;;
|
||||||
|
aarch64) ARCH="arm64" ;;
|
||||||
|
*)
|
||||||
|
err "Unsupported architecture: $machine"
|
||||||
|
err "Supported: x86_64 (amd64), aarch64 (arm64)"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
detect_distro
|
||||||
|
detect_arch
|
||||||
|
info "Distro: ${DISTRO} (${DISTRO_FAMILY}) | Arch: ${ARCH}"
|
||||||
|
|
||||||
|
# ── Check base dependencies ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
if ! command_exists curl; then
|
||||||
|
err "curl is required but not installed."
|
||||||
|
err "Install it with your package manager and re-run this script."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command_exists jq; then
|
||||||
|
warn "jq is required but not installed."
|
||||||
|
printf "Install jq now? [Y/n]: "
|
||||||
|
read -r jq_reply
|
||||||
|
jq_reply="${jq_reply:-Y}"
|
||||||
|
if [[ "${jq_reply,,}" == "y" ]]; then
|
||||||
|
case "$DISTRO_FAMILY" in
|
||||||
|
deb) sudo apt update && sudo apt install -y jq ;;
|
||||||
|
rpm-dnf) sudo dnf install -y jq ;;
|
||||||
|
rpm-zypper) sudo zypper install -y jq ;;
|
||||||
|
arch) sudo pacman -S --noconfirm jq ;;
|
||||||
|
esac
|
||||||
|
if ! command_exists jq; then
|
||||||
|
err "Failed to install jq. Please install it manually and re-run."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
info "jq installed."
|
||||||
|
else
|
||||||
|
err "jq is required. Please install it and re-run."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# [3/8] Install OpenWhispr
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
step "3/8" "Installing OpenWhispr"
|
||||||
|
|
||||||
|
# Check currently installed version
|
||||||
|
get_installed_version() {
|
||||||
|
if command_exists openwhispr; then
|
||||||
|
openwhispr --version 2>/dev/null || true
|
||||||
|
elif command_exists open-whispr; then
|
||||||
|
open-whispr --version 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTALLED_VERSION="$(get_installed_version)"
|
||||||
|
|
||||||
|
# Fetch latest release info
|
||||||
|
info "Fetching latest release info..."
|
||||||
|
RELEASE_JSON="$(curl -sf "$GITHUB_API")" || {
|
||||||
|
err "Failed to fetch release info from GitHub."
|
||||||
|
err "Check your internet connection and try again."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
LATEST_VERSION="$(printf '%s' "$RELEASE_JSON" | jq -r '.tag_name // empty')"
|
||||||
|
if [[ -z "$LATEST_VERSION" ]]; then
|
||||||
|
err "Could not determine latest version from GitHub."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
info "Latest version: ${LATEST_VERSION}"
|
||||||
|
|
||||||
|
# Strip leading 'v' for comparison
|
||||||
|
LATEST_CLEAN="${LATEST_VERSION#v}"
|
||||||
|
INSTALLED_CLEAN="${INSTALLED_VERSION#v}"
|
||||||
|
|
||||||
|
if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_CLEAN" == "$LATEST_CLEAN" ]]; then
|
||||||
|
info "OpenWhispr ${LATEST_VERSION} is already installed — skipping."
|
||||||
|
else
|
||||||
|
if [[ -n "$INSTALLED_VERSION" ]]; then
|
||||||
|
info "Upgrading from ${INSTALLED_VERSION} to ${LATEST_VERSION}..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine asset pattern
|
||||||
|
case "$DISTRO_FAMILY" in
|
||||||
|
deb) ASSET_EXT=".deb" ;;
|
||||||
|
rpm-dnf|rpm-zypper) ASSET_EXT=".rpm" ;;
|
||||||
|
arch) ASSET_EXT=".tar.gz" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Map arch names (assets may use different conventions)
|
||||||
|
case "$ARCH" in
|
||||||
|
amd64) ARCH_PATTERNS=("amd64" "x86_64" "x64") ;;
|
||||||
|
arm64) ARCH_PATTERNS=("arm64" "aarch64") ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Find matching asset URL
|
||||||
|
ASSET_URL=""
|
||||||
|
for arch_pat in "${ARCH_PATTERNS[@]}"; do
|
||||||
|
ASSET_URL="$(printf '%s' "$RELEASE_JSON" | jq -r \
|
||||||
|
--arg ext "$ASSET_EXT" --arg arch "$arch_pat" \
|
||||||
|
'.assets[] | select(.name | (endswith($ext) and contains($arch))) | .browser_download_url' \
|
||||||
|
| head -1)"
|
||||||
|
[[ -n "$ASSET_URL" ]] && break
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ASSET_URL" ]]; then
|
||||||
|
err "No ${ASSET_EXT} asset found for ${ARCH} in release ${LATEST_VERSION}."
|
||||||
|
err "Check: https://github.com/OpenWhispr/openwhispr/releases/latest"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ASSET_NAME="$(basename "$ASSET_URL")"
|
||||||
|
info "Downloading ${ASSET_NAME}..."
|
||||||
|
|
||||||
|
mkdir -p "$TMP_DIR"
|
||||||
|
curl --progress-bar -fL -o "${TMP_DIR}/${ASSET_NAME}" "$ASSET_URL" || {
|
||||||
|
err "Download failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
info "Installing..."
|
||||||
|
case "$DISTRO_FAMILY" in
|
||||||
|
deb)
|
||||||
|
sudo apt install -y "${TMP_DIR}/${ASSET_NAME}" || {
|
||||||
|
err "Installation failed. Try: sudo dpkg -i ${TMP_DIR}/${ASSET_NAME}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
rpm-dnf)
|
||||||
|
sudo dnf install -y "${TMP_DIR}/${ASSET_NAME}" || {
|
||||||
|
err "Installation failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
rpm-zypper)
|
||||||
|
sudo zypper install -y "${TMP_DIR}/${ASSET_NAME}" || {
|
||||||
|
err "Installation failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
arch)
|
||||||
|
sudo mkdir -p /opt/openwhispr
|
||||||
|
sudo tar -xzf "${TMP_DIR}/${ASSET_NAME}" -C /opt/openwhispr || {
|
||||||
|
err "Extraction failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
# Find the binary and symlink
|
||||||
|
local_bin="$(find /opt/openwhispr -maxdepth 2 -name 'openwhispr' -o -name 'open-whispr' 2>/dev/null | head -1)"
|
||||||
|
if [[ -n "$local_bin" ]]; then
|
||||||
|
sudo ln -sf "$local_bin" /usr/local/bin/openwhispr
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
info "OpenWhispr ${LATEST_VERSION} installed successfully."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# [4/8] Install paste dependencies
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
step "4/8" "Installing paste/typing dependencies"
|
||||||
|
|
||||||
|
SESSION_TYPE="${XDG_SESSION_TYPE:-}"
|
||||||
|
DESKTOP="${XDG_CURRENT_DESKTOP:-}"
|
||||||
|
|
||||||
|
if [[ -z "$SESSION_TYPE" ]]; then
|
||||||
|
# Try to detect
|
||||||
|
if [[ -n "${WAYLAND_DISPLAY:-}" ]]; then
|
||||||
|
SESSION_TYPE="wayland"
|
||||||
|
elif [[ -n "${DISPLAY:-}" ]]; then
|
||||||
|
SESSION_TYPE="x11"
|
||||||
|
else
|
||||||
|
warn "Cannot detect session type (X11/Wayland). Skipping paste deps."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Session: ${SESSION_TYPE:-unknown} | Desktop: ${DESKTOP:-unknown}"
|
||||||
|
|
||||||
|
install_paste_dep() {
|
||||||
|
local pkg="$1"
|
||||||
|
if command_exists "$pkg"; then
|
||||||
|
info "$pkg is already installed."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
info "Installing $pkg..."
|
||||||
|
case "$DISTRO_FAMILY" in
|
||||||
|
deb) sudo apt install -y "$pkg" ;;
|
||||||
|
rpm-dnf) sudo dnf install -y "$pkg" ;;
|
||||||
|
rpm-zypper) sudo zypper install -y "$pkg" ;;
|
||||||
|
arch) sudo pacman -S --noconfirm "$pkg" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$SESSION_TYPE" in
|
||||||
|
x11)
|
||||||
|
install_paste_dep "xdotool"
|
||||||
|
;;
|
||||||
|
wayland)
|
||||||
|
if [[ "$DESKTOP" == *"GNOME"* ]]; then
|
||||||
|
info "GNOME on Wayland — OpenWhispr uses D-Bus natively. No extra deps."
|
||||||
|
elif [[ "$DESKTOP" == *"KDE"* ]]; then
|
||||||
|
install_paste_dep "kdotool"
|
||||||
|
else
|
||||||
|
install_paste_dep "wtype"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
warn "Skipping paste dependency install (unknown session type)."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# [5/8] STT provider
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
step "5/8" "Speech-to-text (STT) provider"
|
||||||
|
|
||||||
|
cat <<'STT_MENU'
|
||||||
|
|
||||||
|
How should OpenWhispr transcribe your voice?
|
||||||
|
|
||||||
|
Option Method Streaming Cost Audio sent to
|
||||||
|
─────────────────────────────────────────────────────────────────────────────
|
||||||
|
1) Local Whisper/Parakeet (default) no free nobody, ever
|
||||||
|
2) Groq whisper-large-v3-turbo no $0.04/hr* Groq servers
|
||||||
|
3) OpenAI Realtime API YES $0.06/min OpenAI servers
|
||||||
|
|
||||||
|
*Groq free tier: ~2,000 audio seconds/day (~600 dictations/day free).
|
||||||
|
NOT used for training. 30-day retention max.
|
||||||
|
Verify: https://console.groq.com/docs/your-data
|
||||||
|
|
||||||
|
Streaming (option 3) = text appears word-by-word as you speak.
|
||||||
|
Options 1 and 2 transcribe after you stop speaking.
|
||||||
|
|
||||||
|
All cloud options send audio to a server (like Siri/Google Assistant)
|
||||||
|
but unlike Siri/Google: NOT tied to your identity, NOT used for
|
||||||
|
training, deleted within 30 days.
|
||||||
|
|
||||||
|
Best free combo: option 1 (local) + Groq cleanup [step 6]
|
||||||
|
Best free cloud combo: option 2 (Groq STT) + Groq cleanup [same key]
|
||||||
|
Best streaming: option 3 (OpenAI Realtime) + any cleanup
|
||||||
|
|
||||||
|
STT_MENU
|
||||||
|
|
||||||
|
prompt_default "Enter 1-3" "1" STT_CHOICE
|
||||||
|
|
||||||
|
case "$STT_CHOICE" in
|
||||||
|
1)
|
||||||
|
STT_LABEL="Local Whisper/Parakeet (offline)"
|
||||||
|
info "STT: Local — audio never leaves your machine."
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
STT_LABEL="Groq whisper-large-v3-turbo (cloud)"
|
||||||
|
info "STT: Groq cloud transcription."
|
||||||
|
if [[ -n "${GROQ_API_KEY:-}" ]]; then
|
||||||
|
info "GROQ_API_KEY already set — reusing."
|
||||||
|
else
|
||||||
|
prompt_hidden "Enter your Groq API key (from https://console.groq.com)" GROQ_KEY_INPUT
|
||||||
|
store_api_key "GROQ_API_KEY" "$GROQ_KEY_INPUT"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
STT_LABEL="OpenAI Realtime API (cloud, streaming)"
|
||||||
|
info "STT: OpenAI Realtime (streaming)."
|
||||||
|
if [[ -n "${OPENAI_API_KEY:-}" ]]; then
|
||||||
|
info "OPENAI_API_KEY already set — reusing."
|
||||||
|
else
|
||||||
|
prompt_hidden "Enter your OpenAI API key (from https://platform.openai.com/api-keys)" OPENAI_KEY_INPUT
|
||||||
|
store_api_key "OPENAI_API_KEY" "$OPENAI_KEY_INPUT"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
warn "Invalid choice '$STT_CHOICE' — defaulting to local."
|
||||||
|
STT_CHOICE="1"
|
||||||
|
STT_LABEL="Local Whisper/Parakeet (offline)"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# [6/8] AI cleanup provider
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
step "6/8" "AI text cleanup provider"
|
||||||
|
|
||||||
|
cat <<'CLEANUP_MENU'
|
||||||
|
|
||||||
|
After transcription, AI can fix grammar, spelling, and filler words.
|
||||||
|
Only transcribed TEXT is sent — your voice stays local regardless.
|
||||||
|
None of these providers use your text for training.
|
||||||
|
|
||||||
|
Provider Model Per use 50/day/mo 200/day/mo
|
||||||
|
──────────────────────────────────────────────────────────────────────────
|
||||||
|
1) OpenAI gpt-4o-mini-2024-07-18 $0.000058 $0.09 $0.35
|
||||||
|
2) Anthropic claude-haiku-4-5 $0.000450 $0.68 $2.70
|
||||||
|
3) Groq llama-3.3-70b-versatile free* free* free*
|
||||||
|
4) Local Ollama (fully offline) free free free
|
||||||
|
5) Skip raw transcription only free free free
|
||||||
|
|
||||||
|
*Groq free: 1,000 req/day, 100K tokens/day. NOT used for training.
|
||||||
|
Verify: https://console.groq.com/docs/your-data
|
||||||
|
|
||||||
|
Pricing based on ~50 words per dictation (~125 input + 65 output tokens).
|
||||||
|
Verify current pricing:
|
||||||
|
OpenAI: https://openai.com/api/pricing
|
||||||
|
Anthropic: https://www.anthropic.com/pricing
|
||||||
|
Groq: https://groq.com/pricing
|
||||||
|
|
||||||
|
CLEANUP_MENU
|
||||||
|
|
||||||
|
prompt_default "Enter 1-5" "1" CLEANUP_CHOICE
|
||||||
|
|
||||||
|
case "$CLEANUP_CHOICE" in
|
||||||
|
1)
|
||||||
|
CLEANUP_LABEL="OpenAI gpt-4o-mini"
|
||||||
|
info "Cleanup: OpenAI gpt-4o-mini."
|
||||||
|
if [[ -n "${OPENAI_API_KEY:-}" ]]; then
|
||||||
|
info "OPENAI_API_KEY already set — reusing."
|
||||||
|
else
|
||||||
|
prompt_hidden "Enter your OpenAI API key (from https://platform.openai.com/api-keys)" OPENAI_KEY_INPUT
|
||||||
|
store_api_key "OPENAI_API_KEY" "$OPENAI_KEY_INPUT"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
CLEANUP_LABEL="Anthropic claude-haiku-4-5"
|
||||||
|
info "Cleanup: Anthropic claude-haiku-4-5."
|
||||||
|
if [[ -n "${ANTHROPIC_API_KEY:-}" ]]; then
|
||||||
|
info "ANTHROPIC_API_KEY already set — reusing."
|
||||||
|
else
|
||||||
|
prompt_hidden "Enter your Anthropic API key (from https://console.anthropic.com)" ANTHROPIC_KEY_INPUT
|
||||||
|
store_api_key "ANTHROPIC_API_KEY" "$ANTHROPIC_KEY_INPUT"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
CLEANUP_LABEL="Groq llama-3.3-70b (free)"
|
||||||
|
info "Cleanup: Groq llama-3.3-70b."
|
||||||
|
if [[ -n "${GROQ_API_KEY:-}" ]]; then
|
||||||
|
info "GROQ_API_KEY already set — reusing."
|
||||||
|
else
|
||||||
|
prompt_hidden "Enter your Groq API key (from https://console.groq.com)" GROQ_KEY_INPUT
|
||||||
|
store_api_key "GROQ_API_KEY" "$GROQ_KEY_INPUT"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
CLEANUP_LABEL="Local Ollama (offline)"
|
||||||
|
info "Cleanup: Local Ollama."
|
||||||
|
if command_exists ollama; then
|
||||||
|
info "Ollama is already installed."
|
||||||
|
else
|
||||||
|
warn "Ollama is not installed."
|
||||||
|
cat <<'OLLAMA_INFO'
|
||||||
|
|
||||||
|
To install Ollama:
|
||||||
|
curl -fsSL https://ollama.ai/install.sh | sh
|
||||||
|
|
||||||
|
Then pull a model:
|
||||||
|
ollama pull llama3.1
|
||||||
|
|
||||||
|
OLLAMA_INFO
|
||||||
|
printf "Install Ollama now? [Y/n]: "
|
||||||
|
read -r ollama_reply
|
||||||
|
ollama_reply="${ollama_reply:-Y}"
|
||||||
|
if [[ "${ollama_reply,,}" == "y" ]]; then
|
||||||
|
curl -fsSL https://ollama.ai/install.sh | sh || {
|
||||||
|
warn "Ollama install failed. Install manually later."
|
||||||
|
}
|
||||||
|
else
|
||||||
|
warn "Skipping Ollama install — you can install it later."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
CLEANUP_LABEL="None (raw transcription)"
|
||||||
|
info "Cleanup: Skipped — raw transcription only."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
warn "Invalid choice '$CLEANUP_CHOICE' — defaulting to OpenAI."
|
||||||
|
CLEANUP_CHOICE="1"
|
||||||
|
CLEANUP_LABEL="OpenAI gpt-4o-mini"
|
||||||
|
if [[ -n "${OPENAI_API_KEY:-}" ]]; then
|
||||||
|
info "OPENAI_API_KEY already set — reusing."
|
||||||
|
else
|
||||||
|
prompt_hidden "Enter your OpenAI API key (from https://platform.openai.com/api-keys)" OPENAI_KEY_INPUT
|
||||||
|
store_api_key "OPENAI_API_KEY" "$OPENAI_KEY_INPUT"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# [7/8] First launch
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
step "7/8" "First launch"
|
||||||
|
|
||||||
|
cat <<'LAUNCH_INFO'
|
||||||
|
|
||||||
|
OpenWhispr will open now for first-run setup.
|
||||||
|
|
||||||
|
- It will download speech models (~75-500 MB depending on choice).
|
||||||
|
- Set your hotkey in Settings (default: backtick `).
|
||||||
|
- The app manages its own autostart.
|
||||||
|
|
||||||
|
LAUNCH_INFO
|
||||||
|
|
||||||
|
LAUNCHED=false
|
||||||
|
if command_exists openwhispr; then
|
||||||
|
openwhispr &>/dev/null &
|
||||||
|
LAUNCHED=true
|
||||||
|
elif command_exists open-whispr; then
|
||||||
|
open-whispr &>/dev/null &
|
||||||
|
LAUNCHED=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$LAUNCHED" == true ]]; then
|
||||||
|
info "OpenWhispr launched in the background."
|
||||||
|
else
|
||||||
|
warn "Could not find openwhispr in PATH."
|
||||||
|
warn "Try launching manually:"
|
||||||
|
warn " openwhispr"
|
||||||
|
warn " open-whispr"
|
||||||
|
warn " /opt/openwhispr/openwhispr"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
# [8/8] Summary
|
||||||
|
# ══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
step "8/8" "Done!"
|
||||||
|
|
||||||
|
printf "\n"
|
||||||
|
divider
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
printf "${BOLD} OpenWhispr is ready${RESET}\n"
|
||||||
|
divider
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
Hotkey: backtick (\`) — change in Settings
|
||||||
|
STT: ${STT_LABEL}
|
||||||
|
AI cleanup: ${CLEANUP_LABEL}
|
||||||
|
|
||||||
|
API keys stored in: ${BASHRC}
|
||||||
|
Apply now: source ${BASHRC}
|
||||||
|
|
||||||
|
Useful commands:
|
||||||
|
openwhispr launch the app
|
||||||
|
openwhispr --help show options
|
||||||
|
|
||||||
|
Settings → Hotkey change your hotkey
|
||||||
|
Settings → Models download better speech models
|
||||||
|
Settings → Processing change STT or AI provider
|
||||||
|
|
||||||
|
Troubleshoot: https://github.com/OpenWhispr/openwhispr/blob/main/TROUBLESHOOTING.md
|
||||||
|
This installer: https://github.com/YOUR_USERNAME/openwhispr-easy-setup
|
||||||
|
|
||||||
|
EOF
|
||||||
|
divider
|
||||||
|
printf "\n"
|
||||||
Reference in New Issue
Block a user