DeepSeek Harness Remote
DeepSeek Harness Remote 可將手機或另一台電腦與你運行 DeepSeek Harness 的電腦安全連接,隨時隨地繼續你的工作,方便隨時查看進度並繼續工作。
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證JarvisVoice:自動語音輸入與操作(macOS 選單列小程式)。開著就自動收音,講的話寫進你正在用的 app;可從選單打開 AI 整理(OpenAI/DeepSeek/Claude,像 Typeless)、自動找輸入框、語音指令操作 app
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗English | 繁體中文
Website: jarvis-voice.com
A macOS menu bar app. While it's running it listens on its own, and what you say goes straight into the app you're using: Claude, ChatGPT, your browser, LINE, Notes, anything.
It works in three layers. All three are on by default, each one builds on the one before, and you can turn layers 2 and 3 off from the menu:
| Layer | When it writes | What it writes | Where it writes |
|---|---|---|---|
| 1. Voice typing | After each sentence (a pause of about 0.85 s) | The raw transcript | The text field your cursor is in; if the cursor isn't in a text field, nothing is written |
| 2. AI cleanup (like Typeless) | After each passage (a pause of about 2 s) | Text cleaned up by AI: filler words removed, self-corrections resolved, lists formatted, tone matched to the app, your own terms spelled right. The AI looks at the text around the cursor, the text visible on screen, the app, the window and the URL. Choose OpenAI, DeepSeek or Claude | Same as layer 1 |
| 3. Auto-focus and voice commands | Same as layer 2 | Same as layer 2 | If the cursor isn't in a text field, it picks the right field in the window and writes there. If what you said is a command such as "open the TSMC stock page", it doesn't type anything; it operates the frontmost app for you. Decisions are made by Jev (or by your AI if you don't have Jev) |
Architecture and measured numbers (in Chinese): docs/ARCHITECTURE.md.
Step 1: install and open the app
You need macOS, Node.js 22 or later, and ffmpeg (brew install node ffmpeg).
git clone https://github.com/urusaqqrun/jarvis-voice.git ~/jarvis-voice
cd ~/jarvis-voice
./install.sh openai # OpenAI transcription (most accurate); use ./install.sh local to pay nothing
The JarvisVoice icon (a circular arrow around three sound bars) appears in the menu bar. The first time, macOS asks for two permissions, once each:
Pick one of three ways to power transcription and AI cleanup; you can switch any time from the menu:
./install.sh local)."apiKeyFile": "<file with your key>" under openai in ~/.voice-dictation/config.json.Step 2: ask your AI to set it up
Everyone has their own product names, acronyms and in-house jargon, and those are the words speech recognition gets wrong most. AI cleanup, auto-focus and voice commands also need an AI provider and a key (you can paste the key yourself under "Set up your own key…" in the menu, without the AI). Open an AI that can read files and run commands on your Mac (Claude Code, Codex and the like; ChatGPT on the web can't) and paste this (or edit the config file yourself, see "Config file" below):
Please follow ~/jarvis-voice/AI_SETUP.md to set up JarvisVoice for me: fill in my vocabulary and run the tests, and ask me whether I want AI cleanup, auto-focus and voice commands; if I do, set them up and check that they work.
The AI will:
~/.voice-dictation/vocabulary.txt, and run a test comparing accuracy with and without them. In our test of 4 mixed Chinese–English developer sentences, 1/4 came out fully correct without the vocabulary and 4/4 with it.node ~/jarvis-voice/bin/ai-check.mjs to confirm the AI and the decision maker both work.On by default (it only runs when you have an AI key; without one you get layer 1). Switch providers under "AI cleanup" in the menu, or choose "Off" to go back to sentence-by-sentence pasting. While it's on:
ai.styles.~/.voice-dictation/history.jsonl, only on your Mac.| Provider | Default model | Speed (measured median) | Cost |
|---|---|---|---|
| DeepSeek | deepseek-flash | 0.75 s | About US$0.00004 per passage (doubled during DeepSeek's peak hours) |
| Claude | claude-haiku-5-5 | 0.85 s | About US$0.00004 per passage |
| OpenAI | gpt-6-luna | 1.1 s | About US$0.00003 per passage |
Dictating an hour a day, AI cleanup costs less than US$1 a month.
jev), Jev decides, about 0.2 s per decision.| Engine | Accuracy | Cost | Where your audio goes |
|---|---|---|---|
openai (gpt-transcribe, default) | Most accurate, uses your vocabulary | US$0.0045 a minute; an hour a day is about US$7.4 a month | OpenAI |
openai (gpt-live-transcribe) | Slightly worse | US$0.017 a minute | OpenAI |
local (SenseVoice-Small) | Good Chinese, weaker English, ignores vocabulary | Free | Never leaves your Mac |
cubelv (Sign in with CubeLV) | Same as gpt-live-transcribe | Uses your CubeLV account's credits | CubeLV, then OpenAI |
parallelsandbox | Same as gpt-live-transcribe | Depends on your ParallelSandbox plan | ParallelSandbox, then OpenAI |
Only segments recognized as speech are sent; nothing is sent while it's quiet. Costs include the ~1.25 s of padding around each sentence. To switch engines pick one under "Transcription" in the menu, run ./install.sh <engine>, or edit the config file; changes apply within a few seconds of saving.
No config file to edit and no Terminal needed:
ai-check.mjs. If it works, the key is saved and you're told you're all set; if not, you're told why (wrong key, out of balance, can't connect) and nothing is saved.apiKey / ai.keys, apiKeyFile / ai.keyFiles, ai.keyCommands and environment variables. All of those still work as before; remove the menu key and the one in your config file is used again.node ~/jarvis-voice/bin/set-key.mjs set deepseek (the key isn't shown as you paste; set openai --engine also switches transcription to OpenAI).If you'd rather not get and look after your own keys, you can use a CubeLV account:
node ~/jarvis-voice/bin/cubelv-login.mjs in Terminal). Transcription and AI cleanup then switch to CubeLV; to use it for only one of them, switch the other back to on-device or your own key from the "Transcription" or "AI cleanup" submenu.~/.voice-dictation/config.json; anything you leave out uses the default:
{
"engine": "openai",
"output": "traditional",
"replacements": { "部屬": "部署" },
"openai": {
"apiKeyFile": "~/secrets/openai.env",
"model": "gpt-transcribe",
"languages": ["zh-tw", "en"],
"prompt": "A Taiwanese engineer dictating in Chinese mixed with English about software development and operations."
}
}
| Field | Meaning |
|---|---|
engine | openai, local, cubelv, parallelsandbox |
apps | Only listen in these apps (bundle ids); default ["*"], all apps |
excludeApps | Don't listen while these apps are frontmost; defaults to meeting and calling apps |
output | traditional (Taiwan Traditional Chinese), simplified, original |
replacements | Fixed replacements for spellings that are still wrong after testing |
openai.model | gpt-transcribe (default, whole sentence at once) or gpt-live-transcribe (real-time) |
openai.apiKey / openai.apiKeyFile | The key itself, or a file containing it (just the key, or a .env with OPENAI_API_KEY=); otherwise the OPENAI_API_KEY environment variable. A key saved under "Set up your own key…" (Keychain) comes before all of these |
openai.languages | Expected languages, e.g. ["zh-tw", "en"] |
openai.prompt | A sentence or two describing the setting; don't put your vocabulary here |
openai.vocabularyFile | Vocabulary file, default ~/.voice-dictation/vocabulary.txt, one term per line |
local.language | auto, or zh, en, yue, ja, ko |
ai.enabled / ai.provider | AI cleanup on/off (default on); deepseek, openai, claude, cubelv (Sign in with CubeLV). If unset, whichever provider you already have a key for. Also switchable from the menu |
ai.keys / ai.keyFiles / ai.keyCommands | Each provider's key, a file with the key, or a command that prints it (e.g. aws ssm get-parameter ..., so the key never touches disk). Otherwise the / environment variables; OpenAI reuses the key. A key saved under "Set up your own key…" (Keychain) comes before all of these |
~/Applications/JarvisVoice.app. On macOS 26, check System Settings → Menu Bar to make sure it's allowed.node ~/jarvis-voice/bin/ai-check.mjs; it tells you what's missing.~/.voice-dictation/listen.log.git pull && ./install.sh. If the app shell (app/main.js) and packaging haven't changed, it isn't rebuilt and you keep your permissions. If your keychain has an Apple developer certificate (Developer ID Application or Apple Development), the app is signed with it and keeps its permissions across rebuilds; otherwise it's signed ad hoc, macOS asks for the microphone again after a rebuild, and under Accessibility you need to select "JarvisVoice", remove it with "−", then reopen JarvisVoice and turn it on (just toggling it off and on doesn't work: the switch looks on but still points at the old build).app/main.js: the menu bar app shell, packaged into JarvisVoice.app with macOS's built-in osacompile (no Xcode). Microphone and Accessibility permissions belong to it.app/ui.js: the menu bar UI and the code that starts the background process. The shell loads it at launch, so changing it doesn't require rebuilding the app or re-granting permissions; quit from the menu and reopen to apply.bin/listen.mjs: the background process. It watches which app is frontmost, records with ffmpeg, splits sentences locally and hands them to the transcription engine; with AI cleanup on, it groups them into passages for the AI, then writes into the text field or runs the command.bin/engines/: batch.mjs (OpenAI transcription), realtime.mjs (real-time transcription via OpenAI, CubeLV or ParallelSandbox), local.mjs (SenseVoice via sherpa-onnx).bin/own-keys.mjs, bin/set-key.mjs: "Set up your own key…" in the menu (test before saving, keys kept in the Keychain, switching transcription and AI cleanup).bin/cubelv.mjs, bin/cubelv-login.mjs: Sign in with CubeLV (browser authorization, tokens kept in the Keychain and refreshed automatically, CubeLV transcription and AI cleanup).bin/ax-agent.js: the long-running Accessibility helper (JXA). Reads context and on-screen text, finds and focuses text fields, pastes (save clipboard → Cmd+V → restore, only to the frontmost app), selects what it just pasted to replace it, and lists and operates on-screen controls.core/: the shared core, one copy used by this app, CubeLV and ParallelSandbox (see docs/ARCHITECTURE.md); other projects mount this repo as a git submodule and import core/index.mjs directly (never copy it).bin/editor.mjs: AI cleanup. bin/ai-check.mjs: checks that AI cleanup and the decision maker are set up. bin/decide.mjs: layer 3 decisions (Jev). bin/agent-screen.mjs: voice commands (reads the frontmost app's screen for the shared agent and carries out its steps). bin/targeter.mjs: rules for picking a text field. bin/learn.mjs: learning from your corrections. bin/vocab-auto.mjs: automatic vocabulary updates and the cap.bin/vocab-test.mjs: vocabulary test (see AI_SETUP.md).npm install
npm test # never sends keystrokes or takes focus
VOICE_DICTATION_FOCUS_TESTS=1 npm test # also checks real pasting and reverting with the test window frontmost (takes focus for ~2 s)
TYPESAFE_API_KEY=... npm test # also lets the real Jev drive the stock-app test window
VOICE_DICTATION_REAL_AI=1 npm test # also runs AI cleanup against all three real providers (greetings, one-word replies and swearing kept; filler and self-corrections still cleaned), using the keys in your config
VOICE_DICTATION_E2E=1 npm test # also runs real speech end to end: say speaks sentences -> transcription -> AI cleanup -> pasted into the test window, then reads the window back (calls the cloud, takes focus; waits for 3 s of no keyboard or mouse before each sentence)
./uninstall.sh
Your config, vocabulary and models stay in ~/.voice-dictation; delete it yourself if you don't need them.
The code is MIT licensed. The local model is downloaded by install.sh from k2-fsa/sherpa-onnx and isn't part of this repo; see the FunASR model license.
DEEPSEEK_API_KEYANTHROPIC_API_KEYopenaiai.models | Use a different model, e.g. { "openai": "gpt-4.1-mini" } |
ai.segmentPauseMs | How long a pause ends a passage, default 1800 (only waited out in full when early cleanup is off) |
speed.earlyTranscribeMs | Send the sentence for transcription after this much silence, default 400 (discarded if you keep talking); 0 turns it off |
speed.pasteAfterMs | Start cleanup as soon as the text is back, and paste if you've been quiet this long when it's ready, default 1200; 0 waits for ai.segmentPauseMs |
speed.hedge | How many copies of each transcription and cleanup request to send at once, using whichever answers first, default 2 (cost scales with it) |
speed.bubble / speed.preview | The bubble next to the cursor, and the live preview while you talk (on-device SenseVoice, shown but never pasted); both on by default |
ai.styles | Tone per app (bundle id) or website (domain), e.g. { "com.tinyspeck.slackmacgap": "casual and short" } |
ai.screenChars | How many characters of on-screen text go to the AI, default 1500 |
ai.history / ai.learn | Local history, learning from your corrections; both on by default |
ai.autoVocabulary | Automatic vocabulary updates: { "enabled": true, "max": 250, "maxAuto": 80, "minSightings": 3 } |
autoFocus | Find a text field when the cursor isn't in one (default on) |
commands | Voice commands (default on) |
jev.apiKey / jev.apiKeyFile / jev.apiKeyCommand | Your TypeSafe key (or the TYPESAFE_API_KEY environment variable); a key saved under "Set up your own key…" comes first |
cubelv.apiUrl | Which CubeLV to sign in to, default https://app-api.cubelv.com; the sign-in itself lives in the Keychain, not in the config file |
site/: the jarvis-voice.com website, published to GitHub Pages by GitHub Actions on every push to main.