From 0fd58a41c384c08097f95303ff7a9f58ff552be4 Mon Sep 17 00:00:00 2001 From: Menglei Li <57990306+Lumos-789@users.noreply.github.com> Date: Sun, 1 Nov 2026 13:12:36 +0800 Subject: [PATCH 1/5] feat: add voicetranser plugin (local push-to-talk voice input for macOS) Skill-based installer/troubleshooter for the open-source VoiceTranser tool. Source: https://github.com/Lumos-789/VoiceTranser --- assets/voicetranser/icon.png | Bin 0 -> 6120 bytes .../voicetranser/.zcode-plugin/plugin.json | 27 ++++++ external_plugins/voicetranser/README.md | 36 ++++++++ external_plugins/voicetranser/README_CN.md | 36 ++++++++ .../voicetranser/skills/voicetranser/SKILL.md | 66 +++++++++++++ marketplace.json | 87 +++++++++++++++--- 6 files changed, 239 insertions(+), 13 deletions(-) create mode 100644 assets/voicetranser/icon.png create mode 100644 external_plugins/voicetranser/.zcode-plugin/plugin.json create mode 100644 external_plugins/voicetranser/README.md create mode 100644 external_plugins/voicetranser/README_CN.md create mode 100644 external_plugins/voicetranser/skills/voicetranser/SKILL.md diff --git a/assets/voicetranser/icon.png b/assets/voicetranser/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d5bed0b3a9cdbbde9700ff4c87fcdea59821f882 GIT binary patch literal 6120 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 /dev/null" }], + "to_after_key_up": [{ "shell_command": "curl -s localhost:9877/stop > /dev/null" }] } + ] + } + ``` + No Karabiner? Raycast/Hammerspoon hitting `/toggle` works too. +6. **Accessibility permission** (paste step needs it, grant once): System Settings → Privacy & Security → Accessibility → enable the terminal app. Then `uv run python tests/diagnose.py` — all 8 checks must pass. + +## Troubleshoot (in order of likelihood) + +- **Nothing pastes** → accessibility permission missing (step 6); re-run diagnose. +- **Hotkey does nothing** → `curl -s localhost:9877/status`; if refused, `launchctl kickstart -k gui/$(id -u)/com.voicetranser-sense` and check `~/Library/Logs/VoiceTranser-sense.log`. +- **Slow first transcription after boot** → model preload still running (cold load can take ~75 s); it is one-time per service start. +- **Bad quality on specific words** → append a mapping to `corrections.json` (whole-word replace, applied post-transcription), restart service. +- **GPU/memory concerns** → engine already caps MLX buffer cache at 1 GB; to fully avoid GPU use switch: `STT_ENGINE=sensevoice` (edit plist/`.env`, restart). +- **Generic health** → `uv run python tests/diagnose.py` (8 checks: deps, models, mic, clipboard, service, logs…). Fix whatever it flags before guessing. + +## Switch engines + +Edit `STT_ENGINE` in `~/Library/LaunchAgents/com.voicetranser-sense.plist` (overrides `.env`), then `launchctl bootout gui/$(id -u)/com.voicetranser-sense && launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.voicetranser-sense.plist`. + +## Hard rules + +- Never send audio or transcripts anywhere — the whole point is local-only operation. +- Don't install brew packages or modify Karabiner config without asking first. +- After any config change, verify with `diagnose.py` + one real `curl /status` before declaring done. diff --git a/marketplace.json b/marketplace.json index c7f09a06..910754ad 100644 --- a/marketplace.json +++ b/marketplace.json @@ -10,7 +10,10 @@ "url": "https://z.ai" }, "unlistedPlugins": [ - { "name": "openpencil", "source": "./external_plugins/openpencil" } + { + "name": "openpencil", + "source": "./external_plugins/openpencil" + } ], "plugins": [ { @@ -827,7 +830,9 @@ }, { "name": "excalidraw", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "Excalidraw", "displayName_i18n": { "en": "Excalidraw", @@ -850,7 +855,9 @@ "name": "photocraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/photocraft/icon.png", "source": "./external_plugins/photocraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "PhotoCraft", "displayName_i18n": { "en": "PhotoCraft", @@ -877,7 +884,9 @@ "name": "vectorcraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/vectorcraft/icon.png", "source": "./external_plugins/vectorcraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "VectorCraft", "displayName_i18n": { "en": "VectorCraft", @@ -904,7 +913,9 @@ "name": "pdfcraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/pdfcraft/icon.png", "source": "./external_plugins/pdfcraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "PdfCraft", "displayName_i18n": { "en": "PdfCraft", @@ -931,7 +942,9 @@ "name": "designcraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/designcraft/icon.png", "source": "./external_plugins/designcraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "DesignCraft", "displayName_i18n": { "en": "DesignCraft", @@ -958,7 +971,9 @@ "name": "wordcraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/wordcraft/icon.png", "source": "./external_plugins/wordcraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "WordCraft", "displayName_i18n": { "en": "WordCraft", @@ -985,7 +1000,9 @@ "name": "gridcraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/gridcraft/icon.png", "source": "./external_plugins/gridcraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "GridCraft", "displayName_i18n": { "en": "GridCraft", @@ -1012,7 +1029,9 @@ "name": "deckcraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/deckcraft/icon.png", "source": "./external_plugins/deckcraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "DeckCraft", "displayName_i18n": { "en": "DeckCraft", @@ -1039,7 +1058,9 @@ "name": "cadcraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/cadcraft/icon.png", "source": "./external_plugins/cadcraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "CADCraft", "displayName_i18n": { "en": "CADCraft", @@ -1066,7 +1087,9 @@ "name": "soundcraft", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/soundcraft/icon.png", "source": "./external_plugins/soundcraft", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "SoundCraft", "displayName_i18n": { "en": "SoundCraft", @@ -1149,7 +1172,9 @@ }, "category": "developer-tools", "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/kicad/icon.png", - "componentTypes": ["ui"], + "componentTypes": [ + "ui" + ], "displayName": "KiCad", "displayName_i18n": { "en": "KiCad", @@ -1443,6 +1468,42 @@ "mcp", "verification" ] + }, + { + "name": "voicetranser", + "source": "./external_plugins/voicetranser", + "icon": "assets/voicetranser/icon.png", + "description": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", + "description_i18n": { + "en": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", + "zh-CN": "macOS 本地按住说话语音输入:按住全局热键说话、松开即转写粘贴到光标处。纯本地 STT(Qwen3-ASR MLX / SenseVoice / mlx-whisper),零外部 API。内置技能引导 agent 完成安装、热键接线、launchd 常驻与排障。" + }, + "version": "1.0.0", + "author": { + "name": "Lumos-789", + "url": "https://github.com/Lumos-789" + }, + "category": "productivity", + "keywords": [ + "voice-input", + "speech-to-text", + "dictation", + "macos", + "push-to-talk", + "local-first", + "qwen3-asr", + "sensevoice" + ], + "examplePrompts": [ + "Install VoiceTranser and wire my right Option key for push-to-talk", + "语音输入装一下,右 Option 按住说话" + ], + "examplePrompts_i18n": { + "zh-CN": [ + "语音输入装一下,右 Option 按住说话", + "转写没粘贴出来,帮我排查 VoiceTranser" + ] + } } ] -} \ No newline at end of file +} From 379aadccd1886766cbcb1aa8582b2f65f4583c04 Mon Sep 17 00:00:00 2001 From: Menglei Li <57990306+Lumos-789@users.noreply.github.com> Date: Mon, 2 Nov 2026 22:44:51 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix(voicetranser):=20ship=20v1.0.1=20?= =?UTF-8?q?=E2=80=94=20generate=20launchd=20plist=20from=20the=20current?= =?UTF-8?q?=20checkout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop copying the author's hardcoded plist. install_launchd.py builds the plist from the user's own checkout path; diagnose aligns with the active engine and service label; three-engine docs refreshed. --- external_plugins/voicetranser/.zcode-plugin/plugin.json | 2 +- external_plugins/voicetranser/README.md | 2 ++ external_plugins/voicetranser/README_CN.md | 2 ++ external_plugins/voicetranser/skills/voicetranser/SKILL.md | 7 +++++-- marketplace.json | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/external_plugins/voicetranser/.zcode-plugin/plugin.json b/external_plugins/voicetranser/.zcode-plugin/plugin.json index 7bea2797..748f669a 100644 --- a/external_plugins/voicetranser/.zcode-plugin/plugin.json +++ b/external_plugins/voicetranser/.zcode-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "voicetranser", - "version": "1.0.0", + "version": "1.0.1", "description": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", "description_i18n": { "en": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", diff --git a/external_plugins/voicetranser/README.md b/external_plugins/voicetranser/README.md index bf2312cb..a58b746f 100644 --- a/external_plugins/voicetranser/README.md +++ b/external_plugins/voicetranser/README.md @@ -4,6 +4,8 @@ Local push-to-talk voice input for macOS: hold a global hotkey, speak, release This plugin ships an **agent skill** — it does not bundle the tool itself. Once installed, you can say *"install VoiceTranser for me"* and the agent walks the whole chain: prerequisites, clone, deps, model download, launchd service, Karabiner hotkey wiring, accessibility permission, then verifies with the built-in 8-point diagnose script. It also handles ongoing troubleshooting and engine switching. +The runtime is pulled from the upstream repository, so installation needs network access and the tools listed below. The launchd step generates a plist from the current checkout path with `install_launchd.py`; the repository's own plist is an author-local example and is not copied to users' machines. + ## What you get - 🎙️ **Push-to-talk** — Karabiner `right_option` hold-to-talk (or Raycast/Hammerspoon hitting `/toggle`) diff --git a/external_plugins/voicetranser/README_CN.md b/external_plugins/voicetranser/README_CN.md index 11f0ef8b..1191bd0f 100644 --- a/external_plugins/voicetranser/README_CN.md +++ b/external_plugins/voicetranser/README_CN.md @@ -4,6 +4,8 @@ macOS 本地按住说话语音输入:按住全局热键说话、松开即转 本插件提供的是 **agent 技能**,不内嵌工具本体。安装后对 agent 说「帮我装 VoiceTranser」,它就会走完整条链:前置检查、clone、依赖、模型下载、launchd 常驻服务、Karabiner 热键接线、辅助功能权限,最后用内置 8 项自检脚本验证收工。日常排障与引擎切换也由它接管。 +工具本体从上游仓库拉取,因此安装需要网络和下面列出的依赖。launchd 步骤会用 `install_launchd.py` 按当前 checkout 路径生成 plist;仓库里那份 plist 是作者本机示例,不会直接复制到用户机器。 + ## 你会得到什么 - 🎙️ **按住说话** — Karabiner `right_option` 按住录音松开出稿(也可用 Raycast/Hammerspoon 触发 `/toggle`) diff --git a/external_plugins/voicetranser/skills/voicetranser/SKILL.md b/external_plugins/voicetranser/skills/voicetranser/SKILL.md index 7b421f89..954e3d6c 100644 --- a/external_plugins/voicetranser/skills/voicetranser/SKILL.md +++ b/external_plugins/voicetranser/skills/voicetranser/SKILL.md @@ -28,10 +28,13 @@ Fully local (zero external APIs). Repo: https://github.com/Lumos-789/VoiceTranse 3. **First-run check**: `uv run python -m voicetranser --config` must print config without error. 4. **Service (recommended)**: ``` - cp com.voicetranser-sense.plist ~/Library/LaunchAgents/ - launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.voicetranser-sense.plist + uv run python install_launchd.py curl -s localhost:9877/status # expect {"status": "idle"}; model preloads in background ``` + `install_launchd.py` writes a per-user plist whose `ProgramArguments` and + `WorkingDirectory` point at this checkout, then loads it. Do not copy the + repository's `com.voicetranser-sense.plist`: that file contains the author's + local paths. Use `--port`, `--engine`, or `--no-load` when needed. 5. **Hotkey — Karabiner-Elements** complex modification (user must have Karabiner installed; add to `~/.config/karabiner/karabiner.json` → `profiles[].complex_modifications.rules`, then enable in the Karabiner UI): ```json { diff --git a/marketplace.json b/marketplace.json index 910754ad..4fe772ab 100644 --- a/marketplace.json +++ b/marketplace.json @@ -1478,7 +1478,7 @@ "en": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", "zh-CN": "macOS 本地按住说话语音输入:按住全局热键说话、松开即转写粘贴到光标处。纯本地 STT(Qwen3-ASR MLX / SenseVoice / mlx-whisper),零外部 API。内置技能引导 agent 完成安装、热键接线、launchd 常驻与排障。" }, - "version": "1.0.0", + "version": "1.0.1", "author": { "name": "Lumos-789", "url": "https://github.com/Lumos-789" From 1d55ab28467cf621c0eff7568075637bbb700588 Mon Sep 17 00:00:00 2001 From: Menglei Li <57990306+Lumos-789@users.noreply.github.com> Date: Thu, 5 Nov 2026 02:20:41 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix(voicetranser):=20ship=201.0.2=20?= =?UTF-8?q?=E2=80=94=20diagnose=20cannot=20hang=20or=20prompt=20for=20the?= =?UTF-8?q?=20mic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The diagnostic probes the microphone through a non-prompting authorization check and a 3s child-process timeout, so it always returns a verdict; the port has one source of truth (9877) and diagnose resolves it from the installed launchd plist, warning when it disagrees with the default. --- .../voicetranser/.zcode-plugin/plugin.json | 6 ++++-- external_plugins/voicetranser/README.md | 2 +- external_plugins/voicetranser/README_CN.md | 4 ++-- .../voicetranser/skills/voicetranser/SKILL.md | 13 +++++++------ marketplace.json | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/external_plugins/voicetranser/.zcode-plugin/plugin.json b/external_plugins/voicetranser/.zcode-plugin/plugin.json index 748f669a..64ab7849 100644 --- a/external_plugins/voicetranser/.zcode-plugin/plugin.json +++ b/external_plugins/voicetranser/.zcode-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "voicetranser", - "version": "1.0.1", + "version": "1.0.2", "description": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", "description_i18n": { "en": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", @@ -23,5 +23,7 @@ "qwen3-asr", "sensevoice" ], - "skills": ["skills/voicetranser"] + "skills": [ + "skills/voicetranser" + ] } diff --git a/external_plugins/voicetranser/README.md b/external_plugins/voicetranser/README.md index a58b746f..08a44d1c 100644 --- a/external_plugins/voicetranser/README.md +++ b/external_plugins/voicetranser/README.md @@ -4,7 +4,7 @@ Local push-to-talk voice input for macOS: hold a global hotkey, speak, release This plugin ships an **agent skill** — it does not bundle the tool itself. Once installed, you can say *"install VoiceTranser for me"* and the agent walks the whole chain: prerequisites, clone, deps, model download, launchd service, Karabiner hotkey wiring, accessibility permission, then verifies with the built-in 8-point diagnose script. It also handles ongoing troubleshooting and engine switching. -The runtime is pulled from the upstream repository, so installation needs network access and the tools listed below. The launchd step generates a plist from the current checkout path with `install_launchd.py`; the repository's own plist is an author-local example and is not copied to users' machines. +The runtime is pulled from the upstream repository, so installation needs network access and the tools listed below. The launchd step generates a plist from the current checkout path with `install_launchd.py`; the repository ships no plist snapshot to copy, so the generated one is the only source. ## What you get diff --git a/external_plugins/voicetranser/README_CN.md b/external_plugins/voicetranser/README_CN.md index 1191bd0f..3f762d57 100644 --- a/external_plugins/voicetranser/README_CN.md +++ b/external_plugins/voicetranser/README_CN.md @@ -2,9 +2,9 @@ macOS 本地按住说话语音输入:按住全局热键说话、松开即转写粘贴到光标处。为「跟编程助手对话」以及一切打字场景而生。完全本地运行,零外部 API。 -本插件提供的是 **agent 技能**,不内嵌工具本体。安装后对 agent 说「帮我装 VoiceTranser」,它就会走完整条链:前置检查、clone、依赖、模型下载、launchd 常驻服务、Karabiner 热键接线、辅助功能权限,最后用内置 8 项自检脚本验证收工。日常排障与引擎切换也由它接管。 +本插件提供的是 **agent 技能**,不内嵌工具本体。安装后对 agent 说「帮我装 VoiceTranser」,它就会走完整条链:前置检查、clone、依赖、模型下载、launchd 常驻服务、Karabiner 热键接线、辅助功能权限,最后用内置 8 项自检脚本验证收工(音频项有 3 秒硬超时、不会弹麦克风授权;无权限时明确报「未授权」并计为未完整通过,可用 `--skip-audio` 跳过)。日常排障与引擎切换也由它接管。 -工具本体从上游仓库拉取,因此安装需要网络和下面列出的依赖。launchd 步骤会用 `install_launchd.py` 按当前 checkout 路径生成 plist;仓库里那份 plist 是作者本机示例,不会直接复制到用户机器。 +工具本体从上游仓库拉取,因此安装需要网络和下面列出的依赖。launchd 步骤会用 `install_launchd.py` 按当前 checkout 路径生成 plist;仓库不再保存 plist 快照,生成出来的那份就是唯一来源。 ## 你会得到什么 diff --git a/external_plugins/voicetranser/skills/voicetranser/SKILL.md b/external_plugins/voicetranser/skills/voicetranser/SKILL.md index 954e3d6c..e7108969 100644 --- a/external_plugins/voicetranser/skills/voicetranser/SKILL.md +++ b/external_plugins/voicetranser/skills/voicetranser/SKILL.md @@ -13,7 +13,7 @@ Fully local (zero external APIs). Repo: https://github.com/Lumos-789/VoiceTranse - Target: macOS **Apple Silicon** (the default engine needs MLX/Metal; Intel Macs fall back to the CPU engine). - Stack: Python 3.11+ managed by **uv**; HTTP server (stdlib); launchd service; Karabiner-Elements hotkey. - Engines (`STT_ENGINE`): `qwen3-mlx` (default, Qwen3-ASR 0.6B 4bit via mlx-audio, RTF≈0.015, best zh quality, punctuated) → `sensevoice` (CPU fallback, RTF≈0.03) → `mlx-whisper` (en/exotic languages). -- Ports: default 9876; the documented launchd instance uses **9877**. +- Port: **9877** is the single default (`config.DEFAULT_SERVER_PORT`; `server.py`, `install_launchd.py` and diagnose all derive from it). `SERVER_PORT` and the installed launchd plist override it. Diagnose resolves `--port` > env > launchd plist > `.env` > default and prints a WARNING when the plist disagrees with the default. If the mic is off-limits, use `--skip-audio`. - Model files: SenseVoice 228 MB via `download_model.py` (hf-mirror); Qwen3-ASR ~500 MB auto-fetched on first run (respects `HF_ENDPOINT`). ## Install flow (do these in order, verify each step) @@ -32,9 +32,9 @@ Fully local (zero external APIs). Repo: https://github.com/Lumos-789/VoiceTranse curl -s localhost:9877/status # expect {"status": "idle"}; model preloads in background ``` `install_launchd.py` writes a per-user plist whose `ProgramArguments` and - `WorkingDirectory` point at this checkout, then loads it. Do not copy the - repository's `com.voicetranser-sense.plist`: that file contains the author's - local paths. Use `--port`, `--engine`, or `--no-load` when needed. + `WorkingDirectory` point at this checkout, then loads it — the repo ships no + plist snapshot, so there is nothing to copy. Use `--port`, `--engine`, or + `--no-load` when needed. 5. **Hotkey — Karabiner-Elements** complex modification (user must have Karabiner installed; add to `~/.config/karabiner/karabiner.json` → `profiles[].complex_modifications.rules`, then enable in the Karabiner UI): ```json { @@ -47,7 +47,7 @@ Fully local (zero external APIs). Repo: https://github.com/Lumos-789/VoiceTranse } ``` No Karabiner? Raycast/Hammerspoon hitting `/toggle` works too. -6. **Accessibility permission** (paste step needs it, grant once): System Settings → Privacy & Security → Accessibility → enable the terminal app. Then `uv run python tests/diagnose.py` — all 8 checks must pass. +6. **Accessibility permission** (paste step needs it, grant once): System Settings → Privacy & Security → Accessibility → enable the terminal app. Then `.venv/bin/python tests/diagnose.py` — it must return a verdict within seconds: all 8 checks pass. The audio probe is bounded (3 s) and never prompts for the microphone; without permission it reports `microphone permission not granted`. A skipped check (e.g. `--skip-audio`) counts as *not fully verified* and keeps the exit code non-zero, so it can never masquerade as green. ## Troubleshoot (in order of likelihood) @@ -56,7 +56,8 @@ Fully local (zero external APIs). Repo: https://github.com/Lumos-789/VoiceTranse - **Slow first transcription after boot** → model preload still running (cold load can take ~75 s); it is one-time per service start. - **Bad quality on specific words** → append a mapping to `corrections.json` (whole-word replace, applied post-transcription), restart service. - **GPU/memory concerns** → engine already caps MLX buffer cache at 1 GB; to fully avoid GPU use switch: `STT_ENGINE=sensevoice` (edit plist/`.env`, restart). -- **Generic health** → `uv run python tests/diagnose.py` (8 checks: deps, models, mic, clipboard, service, logs…). Fix whatever it flags before guessing. +- **Generic health** → `.venv/bin/python tests/diagnose.py` (8 checks: deps, models, mic, clipboard, service, logs…). Fix whatever it flags before guessing. +- **Microphone off-limits / permission prompt risk** → never let a diagnostic wait on a TCC dialog: run `.venv/bin/python tests/diagnose.py --skip-audio`. The audio check only opens a stream after a non-prompting TCC status read reports *authorized*, and the probe itself is killed after 3 s. ## Switch engines diff --git a/marketplace.json b/marketplace.json index 4fe772ab..e65bda14 100644 --- a/marketplace.json +++ b/marketplace.json @@ -1478,7 +1478,7 @@ "en": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", "zh-CN": "macOS 本地按住说话语音输入:按住全局热键说话、松开即转写粘贴到光标处。纯本地 STT(Qwen3-ASR MLX / SenseVoice / mlx-whisper),零外部 API。内置技能引导 agent 完成安装、热键接线、launchd 常驻与排障。" }, - "version": "1.0.1", + "version": "1.0.2", "author": { "name": "Lumos-789", "url": "https://github.com/Lumos-789" From faa982740545f08ae3ef37c653d178446fa6f218 Mon Sep 17 00:00:00 2001 From: Menglei Li <57990306+Lumos-789@users.noreply.github.com> Date: Thu, 5 Nov 2026 14:46:47 +0800 Subject: [PATCH 4/5] fix(voicetranser): ship 1.0.2 with a resolvable icon and a template body The marketplace entry named a relative icon path while every icon-bearing entry in the catalogue uses the absolute CDN URL of assets//icon.png; the file is now uploaded with the branch so the entry cannot dangle. --- marketplace.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marketplace.json b/marketplace.json index e65bda14..843f9b69 100644 --- a/marketplace.json +++ b/marketplace.json @@ -1472,7 +1472,7 @@ { "name": "voicetranser", "source": "./external_plugins/voicetranser", - "icon": "assets/voicetranser/icon.png", + "icon": "https://cdn-zcode.z.ai/zcode/official-plugin/assets/voicetranser/icon.png", "description": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", "description_i18n": { "en": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", From 72efa5cf0702635c1ff55d8d3a08dd06a1d782a4 Mon Sep 17 00:00:00 2001 From: Menglei Li <57990306+Lumos-789@users.noreply.github.com> Date: Mon, 9 Nov 2026 02:04:13 +0800 Subject: [PATCH 5/5] fix(voicetranser): ship 1.0.3 with a resolvable icon and a template body The marketplace entry named a relative icon path while every icon-bearing entry in the catalogue uses the absolute CDN URL of assets//icon.png; the file is now uploaded with the branch so the entry cannot dangle. --- external_plugins/voicetranser/.zcode-plugin/plugin.json | 2 +- marketplace.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/external_plugins/voicetranser/.zcode-plugin/plugin.json b/external_plugins/voicetranser/.zcode-plugin/plugin.json index 64ab7849..88805c3e 100644 --- a/external_plugins/voicetranser/.zcode-plugin/plugin.json +++ b/external_plugins/voicetranser/.zcode-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "voicetranser", - "version": "1.0.2", + "version": "1.0.3", "description": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", "description_i18n": { "en": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", diff --git a/marketplace.json b/marketplace.json index 843f9b69..d8ab9cc0 100644 --- a/marketplace.json +++ b/marketplace.json @@ -1478,7 +1478,7 @@ "en": "Local push-to-talk voice input for macOS: hold a global hotkey, speak, release — transcription is pasted at your cursor. Fully local STT (Qwen3-ASR MLX, SenseVoice, mlx-whisper), zero external APIs. The bundled skill guides your agent through install, hotkey wiring, launchd setup and troubleshooting.", "zh-CN": "macOS 本地按住说话语音输入:按住全局热键说话、松开即转写粘贴到光标处。纯本地 STT(Qwen3-ASR MLX / SenseVoice / mlx-whisper),零外部 API。内置技能引导 agent 完成安装、热键接线、launchd 常驻与排障。" }, - "version": "1.0.2", + "version": "1.0.3", "author": { "name": "Lumos-789", "url": "https://github.com/Lumos-789"