DeepSeek Harness Remote
DeepSeek Harness Remote: DeepSeek Harness 실행 PC와 모바일·PC를 안전하게 연결해 어디서나 작업 이어받기
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기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.