- macOS 13+
- Xcode Command Line Tools (
xcode-select --install) - Swift 5.9+ (
swift --version) - Docker Desktop (for backend) OR local Postgres
- OpenAI API key (for transcription live test)
cd vibemic-native-macos
swift buildIf build succeeds, create .app bundle:
# Build release
swift build -c release
# Create .app bundle
mkdir -p VibeMic.app/Contents/MacOS
mkdir -p VibeMic.app/Contents/Resources
cp .build/release/VibeMic VibeMic.app/Contents/MacOS/
cp VibeMic/Resources/Info.plist VibeMic.app/Contents/
cp VibeMic/Resources/VibeMic.entitlements VibeMic.app/Contents/Resources/
# Run it
open VibeMic.app-
swift buildsucceeds with no errors -
swift build -c releasesucceeds - .app bundle launches without crash
- Menu bar icon appears (waveform icon)
- Status bar menu shows: Record, History, Settings, Paraphrase, Quit
cd vibemic-api
# Create .env
cp .env.example .env
# Edit .env: set a real OPENAI_API_KEY + JWT_SECRET
docker-compose up -d
alembic upgrade headcd vibemic-api
# Create DB
createdb vibemic
psql vibemic -c "CREATE USER vibemic WITH PASSWORD 'vibemic'; GRANT ALL ON DATABASE vibemic TO vibemic; GRANT ALL ON SCHEMA public TO vibemic;"
# Create .env
cat > .env << 'EOF'
DATABASE_URL=postgresql+asyncpg://vibemic:vibemic@localhost:5432/vibemic
OPENAI_API_KEY=sk-your-real-key-here
JWT_SECRET=your-random-secret-here
CORS_ORIGINS=*
EOF
# Install deps
pip3 install -r requirements.txt
# Run migration
alembic upgrade head
# Start server
uvicorn app.main:app --host 0.0.0.0 --port 8000-
curl http://localhost:8000/healthreturns{"status":"ok"} - Register:
curl -X POST http://localhost:8000/auth/register -H 'Content-Type: application/json' -d '{"email":"test@test.com","password":"testpass123"}'returns token - Login:
curl -X POST http://localhost:8000/auth/login -H 'Content-Type: application/json' -d '{"email":"test@test.com","password":"testpass123"}'returns token - Usage:
curl http://localhost:8000/api/usage -H 'Authorization: Bearer <token>'returns plan + usage
This tests the existing BYOK (bring your own key) flow.
- Launch VibeMic.app
- Open Settings (menu bar → Settings, or Dock → Settings)
- In User Settings, scroll to "About" section, Option-click "Developer Mode" text
- Developer Settings opens
- Enter your OpenAI API key
- Make sure "Use VibeMic Cloud" is unchecked
- Save
- Settings window opens
- Option-click Developer Mode text opens developer settings
- Can enter API key
- Save works (settings persist after reopen)
- Press Ctrl+Option+V → recording starts (red "STOP" in menu bar)
- Press Ctrl+Option+V again → transcription happens
- Text appears in clipboard / auto-pastes
- Notification shows preview of transcribed text
- History window shows the entry
- Recording overlay appears and disappears correctly
This tests the subscription flow.
- Make sure backend is running on
localhost:8000 - Launch VibeMic.app
- Open Settings (menu bar → Settings)
- User Settings should open by default
In Developer Settings (Option-click → Developer Mode):
- Check "Use VibeMic Cloud"
- Set Server URL to
http://localhost:8000 - Save
OR: temporarily change defaultProxyBaseURL in ConfigManager.swift to http://localhost:8000 before building.
- In User Settings → Account section
- Enter email + password
- Click "Create Account"
- Should show "Signed in as ..."
- Plan badge shows "Free"
- Usage bar shows "0 min / 10 min used"
- Press Ctrl+Option+V → record something
- Press Ctrl+Option+V → stop
- App should send audio to
localhost:8000/api/transcribe - Text should appear in clipboard / auto-paste
- In Developer Settings, enable Paraphrase
- Record + transcribe
- Should get error or skip paraphrase (free plan doesn't include it)
- After a transcription, reopen Settings
- Usage bar should show > 0 min used
curl http://localhost:8000/api/usage -H 'Authorization: Bearer <token>'should confirm
- User Settings opens by default (not developer settings)
- Create Account works → token saved
- Login works → "Signed in as ..." shows
- Plan badge shows "Free"
- Usage bar loads and shows 0/10 min
- Transcription via proxy works (text returned)
- Usage bar updates after transcription
- Paraphrase blocked on free tier (402 error)
- Upgrade button present (will fail without Stripe setup, that's OK)
- Logout → reopen → token persisted (still signed in)
- Record with no mic permission → shows notification asking for permission
- Record with no API key and no proxy login → shows error
- Record very short audio (< 1 second) → "No audio recorded" or "No speech detected"
- Backend down + proxy mode → shows network error
- Bad JWT token → 401, app shows "Session expired" or similar
- Global hotkey works in any app (not just VibeMic)
- History → copy button works
- History → delete button works
- History → clear all works (with confirmation dialog)
- Hotkey recorder in settings → capture new hotkey → works after save
- Quit from menu bar → app exits cleanly
If anything fails, check debug log:
cat /tmp/vibemic/debug.logBackend logs:
# If using uvicorn directly:
# logs are in terminal
# If using docker:
docker-compose logs apiIf you just want a fast sanity check:
swift build→ succeeds?- Run .app → menu bar icon appears?
- Ctrl+Option+V → overlay appears, "STOP" in menu bar?
- Ctrl+Option+V → notification with text?
- Settings → fields load?
If all 5 pass, the app is functional.