@drakulavich/kesha-voice-kit 1.18.1 → 1.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -10
- package/completions/kesha.bash +38 -0
- package/completions/kesha.fish +71 -0
- package/completions/kesha.zsh +125 -0
- package/docs/product-positioning.md +4 -0
- package/man/kesha.1 +174 -0
- package/package.json +10 -4
- package/src/cli/completions.ts +41 -0
- package/src/cli/dispatch.ts +29 -1
- package/src/cli/install.ts +15 -1
- package/src/cli/main.ts +76 -21
- package/src/cli/manpage.ts +12 -0
- package/src/cli/record.ts +71 -0
- package/src/cli/stats.ts +73 -2
- package/src/cli.ts +5 -0
- package/src/engine.ts +126 -26
- package/src/log.ts +4 -1
- package/src/process-tree.ts +133 -0
- package/src/progress.ts +91 -0
- package/src/shell-artifacts.ts +324 -0
- package/src/stats.ts +383 -1
- package/src/synth.ts +25 -5
- package/src/transcribe.ts +20 -5
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="assets/logo.png" alt="Kesha Voice Kit" width="200">
|
|
2
|
+
<img src="docs/assets/logo.png" alt="Kesha Voice Kit" width="200">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">Kesha Voice Kit</h1>
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
<a href="https://bun.sh"><img src="https://img.shields.io/badge/runtime-Bun-f9f1e1?logo=bun" alt="Bun"></a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
|
-
<p align="center"><b>
|
|
14
|
+
<p align="center"><b>Give your local tools and LLM agents a voice.</b><br>Fast speech-to-text, text-to-speech, voice-activity detection, and language detection in one local-first CLI: Apple Silicon CoreML first, ONNX fallback on supported Linux/Windows builds.</p>
|
|
15
15
|
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
16
|
+
- **Transcribe locally** — 25 languages, up to ~19x faster than Whisper on Apple Silicon, ~2.5x on CPU
|
|
17
|
+
- **Speak back** — Kokoro (EN), Vosk-TTS (RU), macOS system voices, and SSML preview
|
|
18
|
+
- **Plug into agents** — ship voice workflows as CLI commands or an <a href="https://github.com/openclaw/openclaw">OpenClaw</a> skill
|
|
19
|
+
- **Small Rust engine** — single ~20MB binary, no ffmpeg, no Python, no native Node addons
|
|
20
20
|
|
|
21
21
|
See [Product positioning](docs/product-positioning.md) for supported workflows, non-goals, maturity labels, and the platform matrix.
|
|
22
22
|
|
|
@@ -51,6 +51,32 @@ kesha audio.ogg # transcript to stdout
|
|
|
51
51
|
|
|
52
52
|
Air-gapped or behind a corporate mirror? See [docs/model-mirror.md](docs/model-mirror.md).
|
|
53
53
|
|
|
54
|
+
## Shell Completions and Manpage
|
|
55
|
+
|
|
56
|
+
The npm package includes bash, zsh, and fish completions plus `kesha(1)`.
|
|
57
|
+
The CLI can print the packaged files, so install paths do not depend on the
|
|
58
|
+
Bun global package layout:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# bash
|
|
62
|
+
mkdir -p ~/.local/share/bash-completion/completions
|
|
63
|
+
kesha completions bash > ~/.local/share/bash-completion/completions/kesha
|
|
64
|
+
|
|
65
|
+
# zsh
|
|
66
|
+
mkdir -p ~/.zsh/completions
|
|
67
|
+
kesha completions zsh > ~/.zsh/completions/_kesha
|
|
68
|
+
# add to ~/.zshrc once: fpath=(~/.zsh/completions $fpath); autoload -Uz compinit; compinit
|
|
69
|
+
|
|
70
|
+
# fish
|
|
71
|
+
mkdir -p ~/.config/fish/completions
|
|
72
|
+
kesha completions fish > ~/.config/fish/completions/kesha.fish
|
|
73
|
+
|
|
74
|
+
# manpage
|
|
75
|
+
mkdir -p ~/.local/share/man/man1
|
|
76
|
+
kesha manpage > ~/.local/share/man/man1/kesha.1
|
|
77
|
+
mandb ~/.local/share/man 2>/dev/null || true
|
|
78
|
+
```
|
|
79
|
+
|
|
54
80
|
## Homebrew Install
|
|
55
81
|
|
|
56
82
|
Homebrew installs the Bun-based CLI wrapper. Engine and model downloads remain
|
|
@@ -77,6 +103,39 @@ kesha support-bundle --output kesha-support.tar.gz
|
|
|
77
103
|
|
|
78
104
|
`support-bundle` creates a redacted `.tar.gz` archive for GitHub issues. It includes runtime, engine, cache, optional-component, Stats status, and known Kesha environment settings. It does not include audio, transcripts, model files, or the Stats database.
|
|
79
105
|
|
|
106
|
+
## Local Stats privacy and lifecycle
|
|
107
|
+
|
|
108
|
+
Kesha Stats is disabled by default. When you opt in with `kesha stats enable`,
|
|
109
|
+
Kesha writes a local SQLite database only on your machine:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
kesha stats status
|
|
113
|
+
kesha stats week
|
|
114
|
+
kesha stats errors
|
|
115
|
+
kesha stats export --format json # or csv
|
|
116
|
+
kesha stats retention 30 # default: 90 days
|
|
117
|
+
kesha stats retention off # keep until reset
|
|
118
|
+
kesha stats reset # delete recorded stats rows
|
|
119
|
+
kesha stats vacuum # compact the SQLite file
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The database stores content-free operational records only: command name
|
|
123
|
+
(`transcribe` or `say`), timestamps, success/failure status, app version, item
|
|
124
|
+
count, anonymous stage timings, input/output artifact kind, file extension,
|
|
125
|
+
size, optional duration/sample-rate/channel counts, and sanitized error
|
|
126
|
+
class/code/message.
|
|
127
|
+
|
|
128
|
+
Stats never stores audio bytes, transcripts, input text, generated speech text,
|
|
129
|
+
file names, full file paths, raw stdout/stderr, environment variables, model
|
|
130
|
+
files, API tokens, or cloud identifiers. `support-bundle` reports Stats status
|
|
131
|
+
only; it never includes the Stats SQLite database.
|
|
132
|
+
|
|
133
|
+
By default, Stats prunes rows older than 90 days before writing or exporting
|
|
134
|
+
data. Use `kesha stats retention <days>` to change the TTL or `kesha stats
|
|
135
|
+
retention off` to disable TTL pruning. `kesha stats reset` deletes recorded
|
|
136
|
+
runs, artifacts, timings, and errors while preserving settings such as enabled
|
|
137
|
+
state and retention.
|
|
138
|
+
|
|
80
139
|
## Nix Install
|
|
81
140
|
|
|
82
141
|
Alternative reproducible-build path on `aarch64-darwin` / `x86_64-linux`:
|
|
@@ -150,9 +209,9 @@ $ kesha freedom.ogg tahiti.ogg
|
|
|
150
209
|
Таити, Таити! Не были мы ни в какой Таити! Нас и тут неплохо кормят.
|
|
151
210
|
```
|
|
152
211
|
|
|
153
|
-
Stdout: transcript. Stderr: errors. Pipe-friendly.
|
|
212
|
+
Stdout: transcript. Stderr: errors. Pipe-friendly.
|
|
154
213
|
|
|
155
|
-
For long / silence-heavy audio,
|
|
214
|
+
For long / silence-heavy audio, install VAD (`kesha install --vad`) and run without `--no-vad`. Kesha auto-uses VAD past 120 s when installed; without VAD, very long audio falls back to fixed ASR chunks. Details: [docs/vad.md](docs/vad.md).
|
|
156
215
|
|
|
157
216
|
**Speaker diarization** (darwin-arm64, post-v1.12.0):
|
|
158
217
|
|
|
@@ -208,11 +267,11 @@ macOS system voices, SSML, voice listing, and the full voice catalogue: [docs/tt
|
|
|
208
267
|
|
|
209
268
|
## Performance
|
|
210
269
|
|
|
211
|
-
>
|
|
270
|
+
> **Up to ~19x faster than Whisper** on Apple Silicon (M2), **~2.5x faster** on CPU
|
|
212
271
|
|
|
213
272
|
Compared against Whisper `large-v3-turbo` — all engines auto-detect language.
|
|
214
273
|
|
|
215
|
-

|
|
274
|
+

|
|
216
275
|
|
|
217
276
|
See [BENCHMARK.md](BENCHMARK.md) for the full per-file breakdown (Russian + English).
|
|
218
277
|
|
|
@@ -238,6 +297,7 @@ Audio decoding via [symphonia](https://github.com/pdeljanov/Symphonia) — WAV,
|
|
|
238
297
|
## Integrations
|
|
239
298
|
|
|
240
299
|
- **OpenClaw** — give your LLM agent ears. Install & config: [docs/openclaw.md](docs/openclaw.md).
|
|
300
|
+
- **Hermes Agent** — local STT/TTS through Hermes command providers. Setup: [docs/hermes.md](docs/hermes.md).
|
|
241
301
|
- **Raycast** (macOS) — transcribe selected audio & speak clipboard from the launcher. Source + install: [`raycast/`](raycast/).
|
|
242
302
|
|
|
243
303
|
## Programmatic API
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# bash completion for kesha.
|
|
2
|
+
# Source this file or copy it into your bash-completion directory.
|
|
3
|
+
|
|
4
|
+
_kesha_completion() {
|
|
5
|
+
local cur command opts commands
|
|
6
|
+
COMPREPLY=()
|
|
7
|
+
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
8
|
+
command="${COMP_WORDS[1]}"
|
|
9
|
+
commands="completions doctor install manpage record say stats status support-bundle"
|
|
10
|
+
|
|
11
|
+
if [[ "$COMP_CWORD" -eq 1 ]]; then
|
|
12
|
+
if [[ "$cur" == -* ]]; then
|
|
13
|
+
COMPREPLY=( $(compgen -W "--help -h --version -v --json --toon --timestamps --speakers --include-errors --verbose --format --lang --debug --vad --no-vad" -- "$cur") )
|
|
14
|
+
else
|
|
15
|
+
COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
|
|
16
|
+
fi
|
|
17
|
+
return 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
case "$command" in
|
|
21
|
+
completions) opts="--help -h" ;;
|
|
22
|
+
doctor) opts="--help -h --json --redact" ;;
|
|
23
|
+
install) opts="--help -h --coreml --onnx --no-cache --plan --tts --vad --diarize" ;;
|
|
24
|
+
manpage) opts="--help -h" ;;
|
|
25
|
+
record) opts="--help -h --out --max-seconds --debug" ;;
|
|
26
|
+
say) opts="--help -h --voice --lang --out --rate --list-voices --ssml --format --bitrate --sample-rate --no-expand-abbrev --verbose --debug" ;;
|
|
27
|
+
stats) opts="--help -h --format" ;;
|
|
28
|
+
status) opts="--help -h --disk" ;;
|
|
29
|
+
support-bundle) opts="--help -h --output" ;;
|
|
30
|
+
*) opts="--help -h --version -v --json --toon --timestamps --speakers --include-errors --verbose --format --lang --debug --vad --no-vad" ;;
|
|
31
|
+
esac
|
|
32
|
+
|
|
33
|
+
if [[ "$cur" == -* ]]; then
|
|
34
|
+
COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
|
|
35
|
+
fi
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
complete -F _kesha_completion kesha
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# fish completion for kesha.
|
|
2
|
+
complete -c kesha -f
|
|
3
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'completions' -d 'Print shell completion script for bash, zsh, or fish'
|
|
4
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'doctor' -d 'Collect support diagnostics without changing local state'
|
|
5
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'install' -d 'Download inference engine and models'
|
|
6
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'manpage' -d 'Print the kesha(1) manpage'
|
|
7
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'record' -d 'Record microphone audio to a WAV file'
|
|
8
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'say' -d 'Synthesize speech from text (TTS). Writes audio to stdout (or --out file). Defaults to WAV; use --format ogg-opus for messenger-ready voice notes.'
|
|
9
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'stats' -d 'Manage local anonymous Kesha Stats'
|
|
10
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'status' -d 'Show backend installation status'
|
|
11
|
+
complete -c kesha -n '__fish_use_subcommand' -a 'support-bundle' -d 'Create a redacted diagnostics archive for support'
|
|
12
|
+
complete -c kesha -n '__fish_use_subcommand' -l help -d 'Show help'
|
|
13
|
+
complete -c kesha -n '__fish_use_subcommand' -s h -d 'Show help'
|
|
14
|
+
complete -c kesha -n '__fish_use_subcommand' -l version -d 'Show version'
|
|
15
|
+
complete -c kesha -n '__fish_use_subcommand' -s v -d 'Show version'
|
|
16
|
+
complete -c kesha -n '__fish_use_subcommand' -l json -d 'Output results as JSON'
|
|
17
|
+
complete -c kesha -n '__fish_use_subcommand' -l toon -d 'Output results as TOON (compact, LLM-friendly encoding of the same data as --json)'
|
|
18
|
+
complete -c kesha -n '__fish_use_subcommand' -l timestamps -d 'Include timestamped transcript segments in JSON/TOON output'
|
|
19
|
+
complete -c kesha -n '__fish_use_subcommand' -l speakers -d 'Include speaker labels in transcript segments. Requires --json / --toon / --format json. Implies --timestamps. Currently darwin-arm64 only (#199).'
|
|
20
|
+
complete -c kesha -n '__fish_use_subcommand' -l include-errors -d 'With --json, output { results, errors } so scripts can read per-file failures without parsing stderr'
|
|
21
|
+
complete -c kesha -n '__fish_use_subcommand' -l verbose -d 'Show language detection details'
|
|
22
|
+
complete -c kesha -n '__fish_use_subcommand' -l format -r -d 'Output format: transcript | json | toon (long-form alias for --json / --toon)'
|
|
23
|
+
complete -c kesha -n '__fish_use_subcommand' -l lang -r -d 'Expected language code (ISO 639-1), warn if mismatch'
|
|
24
|
+
complete -c kesha -n '__fish_use_subcommand' -l debug -d 'Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)'
|
|
25
|
+
complete -c kesha -n '__fish_use_subcommand' -l vad -d 'Force Silero VAD preprocessing (kesha install --vad first). Without this, VAD auto-engages on audio ≥ 120s.'
|
|
26
|
+
complete -c kesha -n '__fish_use_subcommand' -l no-vad -d 'Force full-file ASR for short/medium files; long audio fails early'
|
|
27
|
+
complete -c kesha -n '__fish_seen_subcommand_from completions' -l help -d 'Show help'
|
|
28
|
+
complete -c kesha -n '__fish_seen_subcommand_from completions' -s h -d 'Show help'
|
|
29
|
+
complete -c kesha -n '__fish_seen_subcommand_from doctor' -l help -d 'Show help'
|
|
30
|
+
complete -c kesha -n '__fish_seen_subcommand_from doctor' -s h -d 'Show help'
|
|
31
|
+
complete -c kesha -n '__fish_seen_subcommand_from doctor' -l json -d 'Output diagnostics as JSON'
|
|
32
|
+
complete -c kesha -n '__fish_seen_subcommand_from doctor' -l redact -d 'Redact secrets and user-home paths from diagnostic output'
|
|
33
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -l help -d 'Show help'
|
|
34
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -s h -d 'Show help'
|
|
35
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -l coreml -d 'Force CoreML backend (macOS arm64)'
|
|
36
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -l onnx -d 'Force ONNX backend'
|
|
37
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -l no-cache -d 'Re-download even if cached'
|
|
38
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -l plan -d 'Show download, disk, and warm-up plan without changing local state'
|
|
39
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -l tts -d 'Also install TTS models (Kokoro EN + Vosk-TTS RU, ~990MB)'
|
|
40
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -l vad -d 'Also install Silero VAD (~2.3MB) for long-audio preprocessing'
|
|
41
|
+
complete -c kesha -n '__fish_seen_subcommand_from install' -l diarize -d 'Also install the Sortformer streaming-diarization model (~245MB, darwin-arm64 only — #199)'
|
|
42
|
+
complete -c kesha -n '__fish_seen_subcommand_from manpage' -l help -d 'Show help'
|
|
43
|
+
complete -c kesha -n '__fish_seen_subcommand_from manpage' -s h -d 'Show help'
|
|
44
|
+
complete -c kesha -n '__fish_seen_subcommand_from record' -l help -d 'Show help'
|
|
45
|
+
complete -c kesha -n '__fish_seen_subcommand_from record' -s h -d 'Show help'
|
|
46
|
+
complete -c kesha -n '__fish_seen_subcommand_from record' -l out -r -d 'Write recorded WAV audio to this path'
|
|
47
|
+
complete -c kesha -n '__fish_seen_subcommand_from record' -l max-seconds -r -d 'Maximum recording duration in seconds'
|
|
48
|
+
complete -c kesha -n '__fish_seen_subcommand_from record' -l debug -d 'Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)'
|
|
49
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l help -d 'Show help'
|
|
50
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -s h -d 'Show help'
|
|
51
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l voice -r -d 'Voice id, e.g. en-am_michael'
|
|
52
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l lang -r -d 'BCP 47 language code (default en-us)'
|
|
53
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l out -r -d 'Write audio to file instead of stdout'
|
|
54
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l rate -r -d 'Speaking rate 0.5–2.0'
|
|
55
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l list-voices -d 'List installed voices and exit'
|
|
56
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l ssml -d 'Parse input as SSML (supports <speak>, <break>; strips unknown tags)'
|
|
57
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l format -r -d 'Output format: wav (default) or ogg-opus (Telegram-ready voice note). Inferred from --out extension when omitted.'
|
|
58
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l bitrate -r -d 'Opus bitrate in bits/sec (e.g. 32000). Only with --format ogg-opus.'
|
|
59
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l sample-rate -r -d 'Opus encoder sample rate (8000/12000/16000/24000/48000). Only with --format ogg-opus.'
|
|
60
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l no-expand-abbrev -d 'Disable Russian acronym auto-expansion (ВОЗ → \'вэ о зэ\') for ru-vosk-* voices. <say-as interpret-as=\'characters\'> still works. Applies to Russian (ru-vosk-*) and English (en-*) voices.'
|
|
61
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l verbose -d 'Log TTS synthesis time to stderr'
|
|
62
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l debug -d 'Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)'
|
|
63
|
+
complete -c kesha -n '__fish_seen_subcommand_from stats' -l help -d 'Show help'
|
|
64
|
+
complete -c kesha -n '__fish_seen_subcommand_from stats' -s h -d 'Show help'
|
|
65
|
+
complete -c kesha -n '__fish_seen_subcommand_from stats' -l format -r -d 'Export format: json | csv'
|
|
66
|
+
complete -c kesha -n '__fish_seen_subcommand_from status' -l help -d 'Show help'
|
|
67
|
+
complete -c kesha -n '__fish_seen_subcommand_from status' -s h -d 'Show help'
|
|
68
|
+
complete -c kesha -n '__fish_seen_subcommand_from status' -l disk -d 'Include recursive cache disk usage'
|
|
69
|
+
complete -c kesha -n '__fish_seen_subcommand_from support-bundle' -l help -d 'Show help'
|
|
70
|
+
complete -c kesha -n '__fish_seen_subcommand_from support-bundle' -s h -d 'Show help'
|
|
71
|
+
complete -c kesha -n '__fish_seen_subcommand_from support-bundle' -l output -r -d 'Write archive to this .tar.gz path'
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#compdef kesha
|
|
2
|
+
# zsh completion for kesha.
|
|
3
|
+
|
|
4
|
+
_kesha() {
|
|
5
|
+
local -a commands
|
|
6
|
+
commands=(
|
|
7
|
+
'completions:Print shell completion script for bash, zsh, or fish'
|
|
8
|
+
'doctor:Collect support diagnostics without changing local state'
|
|
9
|
+
'install:Download inference engine and models'
|
|
10
|
+
'manpage:Print the kesha(1) manpage'
|
|
11
|
+
'record:Record microphone audio to a WAV file'
|
|
12
|
+
'say:Synthesize speech from text (TTS). Writes audio to stdout (or --out file). Defaults to WAV; use --format ogg-opus for messenger-ready voice notes.'
|
|
13
|
+
'stats:Manage local anonymous Kesha Stats'
|
|
14
|
+
'status:Show backend installation status'
|
|
15
|
+
'support-bundle:Create a redacted diagnostics archive for support'
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
if (( CURRENT == 2 )); then
|
|
19
|
+
if [[ "$words[CURRENT]" == -* ]]; then
|
|
20
|
+
_arguments '--help[Show help]' \
|
|
21
|
+
'-h[Show help]' \
|
|
22
|
+
'--version[Show version]' \
|
|
23
|
+
'-v[Show version]' \
|
|
24
|
+
'--json[Output results as JSON]' \
|
|
25
|
+
'--toon[Output results as TOON (compact, LLM-friendly encoding of the same data as --json)]' \
|
|
26
|
+
'--timestamps[Include timestamped transcript segments in JSON/TOON output]' \
|
|
27
|
+
'--speakers[Include speaker labels in transcript segments. Requires --json / --toon / --format json. Implies --timestamps. Currently darwin-arm64 only (#199).]' \
|
|
28
|
+
'--include-errors[With --json, output { results, errors } so scripts can read per-file failures without parsing stderr]' \
|
|
29
|
+
'--verbose[Show language detection details]' \
|
|
30
|
+
'--format=[Output format: transcript | json | toon (long-form alias for --json / --toon)]:format:' \
|
|
31
|
+
'--lang=[Expected language code (ISO 639-1), warn if mismatch]:lang:' \
|
|
32
|
+
'--debug[Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)]' \
|
|
33
|
+
'--vad[Force Silero VAD preprocessing (kesha install --vad first). Without this, VAD auto-engages on audio ≥ 120s.]' \
|
|
34
|
+
'--no-vad[Force full-file ASR for short/medium files; long audio fails early]'
|
|
35
|
+
else
|
|
36
|
+
_describe -t commands 'kesha command' commands
|
|
37
|
+
fi
|
|
38
|
+
return
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
case "$words[2]" in
|
|
42
|
+
completions)
|
|
43
|
+
_arguments '--help[Show help]' \
|
|
44
|
+
'-h[Show help]'
|
|
45
|
+
;;
|
|
46
|
+
doctor)
|
|
47
|
+
_arguments '--help[Show help]' \
|
|
48
|
+
'-h[Show help]' \
|
|
49
|
+
'--json[Output diagnostics as JSON]' \
|
|
50
|
+
'--redact[Redact secrets and user-home paths from diagnostic output]'
|
|
51
|
+
;;
|
|
52
|
+
install)
|
|
53
|
+
_arguments '--help[Show help]' \
|
|
54
|
+
'-h[Show help]' \
|
|
55
|
+
'--coreml[Force CoreML backend (macOS arm64)]' \
|
|
56
|
+
'--onnx[Force ONNX backend]' \
|
|
57
|
+
'--no-cache[Re-download even if cached]' \
|
|
58
|
+
'--plan[Show download, disk, and warm-up plan without changing local state]' \
|
|
59
|
+
'--tts[Also install TTS models (Kokoro EN + Vosk-TTS RU, ~990MB)]' \
|
|
60
|
+
'--vad[Also install Silero VAD (~2.3MB) for long-audio preprocessing]' \
|
|
61
|
+
'--diarize[Also install the Sortformer streaming-diarization model (~245MB, darwin-arm64 only — #199)]'
|
|
62
|
+
;;
|
|
63
|
+
manpage)
|
|
64
|
+
_arguments '--help[Show help]' \
|
|
65
|
+
'-h[Show help]'
|
|
66
|
+
;;
|
|
67
|
+
record)
|
|
68
|
+
_arguments '--help[Show help]' \
|
|
69
|
+
'-h[Show help]' \
|
|
70
|
+
'--out=[Write recorded WAV audio to this path]:out:' \
|
|
71
|
+
'--max-seconds=[Maximum recording duration in seconds]:max seconds:' \
|
|
72
|
+
'--debug[Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)]'
|
|
73
|
+
;;
|
|
74
|
+
say)
|
|
75
|
+
_arguments '--help[Show help]' \
|
|
76
|
+
'-h[Show help]' \
|
|
77
|
+
'--voice=[Voice id, e.g. en-am_michael]:voice:' \
|
|
78
|
+
'--lang=[BCP 47 language code (default en-us)]:lang:' \
|
|
79
|
+
'--out=[Write audio to file instead of stdout]:out:' \
|
|
80
|
+
'--rate=[Speaking rate 0.5–2.0]:rate:' \
|
|
81
|
+
'--list-voices[List installed voices and exit]' \
|
|
82
|
+
'--ssml[Parse input as SSML (supports <speak>, <break>; strips unknown tags)]' \
|
|
83
|
+
'--format=[Output format: wav (default) or ogg-opus (Telegram-ready voice note). Inferred from --out extension when omitted.]:format:' \
|
|
84
|
+
'--bitrate=[Opus bitrate in bits/sec (e.g. 32000). Only with --format ogg-opus.]:bitrate:' \
|
|
85
|
+
'--sample-rate=[Opus encoder sample rate (8000/12000/16000/24000/48000). Only with --format ogg-opus.]:sample rate:' \
|
|
86
|
+
'--no-expand-abbrev[Disable Russian acronym auto-expansion (ВОЗ → '\''вэ о зэ'\'') for ru-vosk-* voices. <say-as interpret-as='\''characters'\''> still works. Applies to Russian (ru-vosk-*) and English (en-*) voices.]' \
|
|
87
|
+
'--verbose[Log TTS synthesis time to stderr]' \
|
|
88
|
+
'--debug[Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)]'
|
|
89
|
+
;;
|
|
90
|
+
stats)
|
|
91
|
+
_arguments '--help[Show help]' \
|
|
92
|
+
'-h[Show help]' \
|
|
93
|
+
'--format=[Export format: json | csv]:format:'
|
|
94
|
+
;;
|
|
95
|
+
status)
|
|
96
|
+
_arguments '--help[Show help]' \
|
|
97
|
+
'-h[Show help]' \
|
|
98
|
+
'--disk[Include recursive cache disk usage]'
|
|
99
|
+
;;
|
|
100
|
+
support-bundle)
|
|
101
|
+
_arguments '--help[Show help]' \
|
|
102
|
+
'-h[Show help]' \
|
|
103
|
+
'--output=[Write archive to this .tar.gz path]:output:'
|
|
104
|
+
;;
|
|
105
|
+
*)
|
|
106
|
+
_arguments '--help[Show help]' \
|
|
107
|
+
'-h[Show help]' \
|
|
108
|
+
'--version[Show version]' \
|
|
109
|
+
'-v[Show version]' \
|
|
110
|
+
'--json[Output results as JSON]' \
|
|
111
|
+
'--toon[Output results as TOON (compact, LLM-friendly encoding of the same data as --json)]' \
|
|
112
|
+
'--timestamps[Include timestamped transcript segments in JSON/TOON output]' \
|
|
113
|
+
'--speakers[Include speaker labels in transcript segments. Requires --json / --toon / --format json. Implies --timestamps. Currently darwin-arm64 only (#199).]' \
|
|
114
|
+
'--include-errors[With --json, output { results, errors } so scripts can read per-file failures without parsing stderr]' \
|
|
115
|
+
'--verbose[Show language detection details]' \
|
|
116
|
+
'--format=[Output format: transcript | json | toon (long-form alias for --json / --toon)]:format:' \
|
|
117
|
+
'--lang=[Expected language code (ISO 639-1), warn if mismatch]:lang:' \
|
|
118
|
+
'--debug[Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)]' \
|
|
119
|
+
'--vad[Force Silero VAD preprocessing (kesha install --vad first). Without this, VAD auto-engages on audio ≥ 120s.]' \
|
|
120
|
+
'--no-vad[Force full-file ASR for short/medium files; long audio fails early]'
|
|
121
|
+
;;
|
|
122
|
+
esac
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
_kesha "$@"
|
|
@@ -8,6 +8,7 @@ The product promise is not "one model for every audio problem." The promise is a
|
|
|
8
8
|
|
|
9
9
|
- Developers and agent builders who need local speech-to-text for voice messages, meetings, support clips, or batch audio files.
|
|
10
10
|
- OpenClaw users who want private, low-latency voice-message transcription through a CLI model route.
|
|
11
|
+
- Hermes Agent users who want command-provider STT/TTS without cloud audio uploads.
|
|
11
12
|
- macOS users who want the fastest path on Apple Silicon through CoreML, with a CPU/ONNX fallback on Linux and Windows.
|
|
12
13
|
- Automation-heavy users who prefer stdout/stderr contracts, JSON/TOON output, and shell-friendly commands over a hosted dashboard.
|
|
13
14
|
- Projects that can accept explicit model downloads and local cache management in exchange for no API keys and no cloud audio upload.
|
|
@@ -24,6 +25,7 @@ The product promise is not "one model for every audio problem." The promise is a
|
|
|
24
25
|
| Use macOS system voices without model downloads | Stable on macOS | `kesha say --voice macos-*` |
|
|
25
26
|
| Label speakers in meeting transcripts | Preview, darwin-arm64 only | `kesha --json --vad --speakers meeting.m4a` |
|
|
26
27
|
| Integrate with OpenClaw as a local voice model | Stable integration surface, user-configured route | `docs/openclaw.md` |
|
|
28
|
+
| Integrate with Hermes Agent as local STT/TTS commands | Stable CLI surface, user-configured route | `docs/hermes.md` |
|
|
27
29
|
| Use Raycast actions for selected-file transcription or clipboard speech | Beta, macOS only | `raycast/` extension |
|
|
28
30
|
| Install through Nix instead of Bun/npm | Beta, selected systems | `docs/nix-install.md` |
|
|
29
31
|
|
|
@@ -51,6 +53,7 @@ The product promise is not "one model for every audio problem." The promise is a
|
|
|
51
53
|
| Speaker diarization | Preview | darwin-arm64 only; cluster IDs are stable within one file only. |
|
|
52
54
|
| Raycast extension | Beta | Convenience UI over the CLI; macOS-only. |
|
|
53
55
|
| OpenClaw plugin | Stable integration surface | Discovery is packaged; actual audio route remains explicit user config. |
|
|
56
|
+
| Hermes Agent command provider | Stable CLI surface | Hermes owns the command-provider lifecycle; Kesha supplies the local STT/TTS commands. |
|
|
54
57
|
| Nix flake | Beta | Reproducible alternate install path for selected systems; Bun/npm remains canonical. |
|
|
55
58
|
|
|
56
59
|
## Platform matrix
|
|
@@ -66,6 +69,7 @@ The product promise is not "one model for every audio problem." The promise is a
|
|
|
66
69
|
| Speaker diarization | Preview, darwin-arm64 only | Not supported | Not supported | Not supported | Not wired into the Nix build yet |
|
|
67
70
|
| Raycast extension | Supported | Not shipped | Not applicable | Not applicable | Not applicable |
|
|
68
71
|
| OpenClaw integration | Supported through CLI route | Not shipped | Supported through CLI route | Supported through CLI route | Use the installed `kesha` command from the chosen path |
|
|
72
|
+
| Hermes Agent integration | Supported through command providers | Not shipped | Supported through command providers | Supported through command providers | Use the installed `kesha` command from the chosen path |
|
|
69
73
|
|
|
70
74
|
`macOS x64` means Intel Macs. Kesha does not currently publish a `darwin-x64` engine binary, so Intel Macs are intentionally marked as not shipped rather than implied to use the ONNX fallback.
|
|
71
75
|
|
package/man/kesha.1
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
.TH KESHA 1 "May 2026" "kesha 1.18.3" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
kesha \- open-source local voice toolkit
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B kesha
|
|
6
|
+
[OPTIONS] AUDIO_FILE...
|
|
7
|
+
.br
|
|
8
|
+
.B kesha
|
|
9
|
+
COMMAND [OPTIONS]
|
|
10
|
+
.SH DESCRIPTION
|
|
11
|
+
Kesha Voice Kit is a local speech-to-text and text-to-speech toolkit with a Bun TypeScript CLI and a Rust engine.
|
|
12
|
+
.SH COMMANDS
|
|
13
|
+
.TP
|
|
14
|
+
.B completions
|
|
15
|
+
Print shell completion script for bash, zsh, or fish
|
|
16
|
+
.TP
|
|
17
|
+
.B doctor
|
|
18
|
+
Collect support diagnostics without changing local state
|
|
19
|
+
.TP
|
|
20
|
+
.B install
|
|
21
|
+
Download inference engine and models
|
|
22
|
+
.TP
|
|
23
|
+
.B manpage
|
|
24
|
+
Print the kesha(1) manpage
|
|
25
|
+
.TP
|
|
26
|
+
.B record
|
|
27
|
+
Record microphone audio to a WAV file
|
|
28
|
+
.TP
|
|
29
|
+
.B say
|
|
30
|
+
Synthesize speech from text (TTS). Writes audio to stdout (or \-\-out file). Defaults to WAV; use \-\-format ogg\-opus for messenger\-ready voice notes.
|
|
31
|
+
.TP
|
|
32
|
+
.B stats
|
|
33
|
+
Manage local anonymous Kesha Stats
|
|
34
|
+
.TP
|
|
35
|
+
.B status
|
|
36
|
+
Show backend installation status
|
|
37
|
+
.TP
|
|
38
|
+
.B support-bundle
|
|
39
|
+
Create a redacted diagnostics archive for support
|
|
40
|
+
.SH OPTIONS
|
|
41
|
+
.TP
|
|
42
|
+
.B \-\-json
|
|
43
|
+
Output results as JSON
|
|
44
|
+
.TP
|
|
45
|
+
.B \-\-toon
|
|
46
|
+
Output results as TOON (compact, LLM\-friendly encoding of the same data as \-\-json)
|
|
47
|
+
.TP
|
|
48
|
+
.B \-\-timestamps
|
|
49
|
+
Include timestamped transcript segments in JSON/TOON output
|
|
50
|
+
.TP
|
|
51
|
+
.B \-\-speakers
|
|
52
|
+
Include speaker labels in transcript segments. Requires \-\-json / \-\-toon / \-\-format json. Implies \-\-timestamps. Currently darwin\-arm64 only (#199).
|
|
53
|
+
.TP
|
|
54
|
+
.B \-\-include\-errors
|
|
55
|
+
With \-\-json, output { results, errors } so scripts can read per\-file failures without parsing stderr
|
|
56
|
+
.TP
|
|
57
|
+
.B \-\-verbose
|
|
58
|
+
Show language detection details
|
|
59
|
+
.TP
|
|
60
|
+
.B \-\-format
|
|
61
|
+
Output format: transcript | json | toon (long\-form alias for \-\-json / \-\-toon)
|
|
62
|
+
.TP
|
|
63
|
+
.B \-\-lang
|
|
64
|
+
Expected language code (ISO 639\-1), warn if mismatch
|
|
65
|
+
.TP
|
|
66
|
+
.B \-\-debug
|
|
67
|
+
Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)
|
|
68
|
+
.TP
|
|
69
|
+
.B \-\-vad
|
|
70
|
+
Force Silero VAD preprocessing (kesha install \-\-vad first). Without this, VAD auto\-engages on audio ≥ 120s.
|
|
71
|
+
.TP
|
|
72
|
+
.B \-\-no\-vad
|
|
73
|
+
Force full\-file ASR for short/medium files; long audio fails early
|
|
74
|
+
.SH SUBCOMMAND OPTIONS
|
|
75
|
+
.SS doctor
|
|
76
|
+
.TP
|
|
77
|
+
.B \-\-json
|
|
78
|
+
Output diagnostics as JSON
|
|
79
|
+
.TP
|
|
80
|
+
.B \-\-redact
|
|
81
|
+
Redact secrets and user\-home paths from diagnostic output
|
|
82
|
+
.SS install
|
|
83
|
+
.TP
|
|
84
|
+
.B \-\-coreml
|
|
85
|
+
Force CoreML backend (macOS arm64)
|
|
86
|
+
.TP
|
|
87
|
+
.B \-\-onnx
|
|
88
|
+
Force ONNX backend
|
|
89
|
+
.TP
|
|
90
|
+
.B \-\-no\-cache
|
|
91
|
+
Re\-download even if cached
|
|
92
|
+
.TP
|
|
93
|
+
.B \-\-plan
|
|
94
|
+
Show download, disk, and warm\-up plan without changing local state
|
|
95
|
+
.TP
|
|
96
|
+
.B \-\-tts
|
|
97
|
+
Also install TTS models (Kokoro EN + Vosk\-TTS RU, ~990MB)
|
|
98
|
+
.TP
|
|
99
|
+
.B \-\-vad
|
|
100
|
+
Also install Silero VAD (~2.3MB) for long\-audio preprocessing
|
|
101
|
+
.TP
|
|
102
|
+
.B \-\-diarize
|
|
103
|
+
Also install the Sortformer streaming\-diarization model (~245MB, darwin\-arm64 only — #199)
|
|
104
|
+
.SS record
|
|
105
|
+
.TP
|
|
106
|
+
.B \-\-out
|
|
107
|
+
Write recorded WAV audio to this path
|
|
108
|
+
.TP
|
|
109
|
+
.B \-\-max\-seconds
|
|
110
|
+
Maximum recording duration in seconds
|
|
111
|
+
.TP
|
|
112
|
+
.B \-\-debug
|
|
113
|
+
Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)
|
|
114
|
+
.SS say
|
|
115
|
+
.TP
|
|
116
|
+
.B \-\-voice
|
|
117
|
+
Voice id, e.g. en\-am_michael
|
|
118
|
+
.TP
|
|
119
|
+
.B \-\-lang
|
|
120
|
+
BCP 47 language code (default en\-us)
|
|
121
|
+
.TP
|
|
122
|
+
.B \-\-out
|
|
123
|
+
Write audio to file instead of stdout
|
|
124
|
+
.TP
|
|
125
|
+
.B \-\-rate
|
|
126
|
+
Speaking rate 0.5–2.0
|
|
127
|
+
.TP
|
|
128
|
+
.B \-\-list\-voices
|
|
129
|
+
List installed voices and exit
|
|
130
|
+
.TP
|
|
131
|
+
.B \-\-ssml
|
|
132
|
+
Parse input as SSML (supports <speak>, <break>; strips unknown tags)
|
|
133
|
+
.TP
|
|
134
|
+
.B \-\-format
|
|
135
|
+
Output format: wav (default) or ogg\-opus (Telegram\-ready voice note). Inferred from \-\-out extension when omitted.
|
|
136
|
+
.TP
|
|
137
|
+
.B \-\-bitrate
|
|
138
|
+
Opus bitrate in bits/sec (e.g. 32000). Only with \-\-format ogg\-opus.
|
|
139
|
+
.TP
|
|
140
|
+
.B \-\-sample\-rate
|
|
141
|
+
Opus encoder sample rate (8000/12000/16000/24000/48000). Only with \-\-format ogg\-opus.
|
|
142
|
+
.TP
|
|
143
|
+
.B \-\-no\-expand\-abbrev
|
|
144
|
+
Disable Russian acronym auto\-expansion (ВОЗ → 'вэ о зэ') for ru\-vosk\-* voices. <say\-as interpret\-as='characters'> still works. Applies to Russian (ru\-vosk\-*) and English (en\-*) voices.
|
|
145
|
+
.TP
|
|
146
|
+
.B \-\-verbose
|
|
147
|
+
Log TTS synthesis time to stderr
|
|
148
|
+
.TP
|
|
149
|
+
.B \-\-debug
|
|
150
|
+
Trace engine subprocess calls on stderr (or KESHA_DEBUG=1)
|
|
151
|
+
.SS stats
|
|
152
|
+
.TP
|
|
153
|
+
.B \-\-format
|
|
154
|
+
Export format: json | csv
|
|
155
|
+
.SS status
|
|
156
|
+
.TP
|
|
157
|
+
.B \-\-disk
|
|
158
|
+
Include recursive cache disk usage
|
|
159
|
+
.SS support-bundle
|
|
160
|
+
.TP
|
|
161
|
+
.B \-\-output
|
|
162
|
+
Write archive to this .tar.gz path
|
|
163
|
+
.SH FILES
|
|
164
|
+
.TP
|
|
165
|
+
.B completions/kesha.bash
|
|
166
|
+
Bash completion script included in the npm package.
|
|
167
|
+
.TP
|
|
168
|
+
.B completions/kesha.zsh
|
|
169
|
+
Zsh completion script included in the npm package.
|
|
170
|
+
.TP
|
|
171
|
+
.B completions/kesha.fish
|
|
172
|
+
Fish completion script included in the npm package.
|
|
173
|
+
.SH SEE ALSO
|
|
174
|
+
.BR bun (1)
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drakulavich/kesha-voice-kit",
|
|
3
|
-
"version": "1.18.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.18.3",
|
|
4
|
+
"description": "Give your local tools a voice: fast STT in 25 languages (~19x faster than Whisper on Apple Silicon, ONNX CPU fallback), TTS via Kokoro/Vosk/macOS voices, VAD + 107-language detection. Rust engine, Bun CLI, OpenClaw skill.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"kesha": "bin/kesha.js"
|
|
8
|
-
"parakeet": "bin/kesha.js"
|
|
7
|
+
"kesha": "bin/kesha.js"
|
|
9
8
|
},
|
|
10
9
|
"exports": {
|
|
11
10
|
".": "./src/cli.ts",
|
|
@@ -13,6 +12,8 @@
|
|
|
13
12
|
},
|
|
14
13
|
"files": [
|
|
15
14
|
"bin/",
|
|
15
|
+
"completions/",
|
|
16
|
+
"man/",
|
|
16
17
|
"src/",
|
|
17
18
|
"package.json",
|
|
18
19
|
"tsconfig.json",
|
|
@@ -38,6 +39,11 @@
|
|
|
38
39
|
"test:unit": "bun test tests/unit/",
|
|
39
40
|
"test:cli-fast": "bun test tests/unit/ tests/integration/cli-contracts.test.ts tests/integration/e2e-cli.test.ts tests/integration/say.test.ts",
|
|
40
41
|
"test:integration": "bun test tests/integration/",
|
|
42
|
+
"coverage:ts": "bun run test:cli-fast --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage/ts",
|
|
43
|
+
"coverage:check:ts": "bun .github/scripts/check-coverage.ts --preset=ts --lcov=coverage/ts/lcov.info --summary=coverage/ts/summary.md",
|
|
44
|
+
"coverage:rust": "mkdir -p coverage/rust && cd rust && cargo llvm-cov nextest --features tts --lcov --output-path ../coverage/rust/lcov.info",
|
|
45
|
+
"coverage:check:rust": "bun .github/scripts/check-coverage.ts --preset=rust --lcov=coverage/rust/lcov.info --summary=coverage/rust/summary.md",
|
|
46
|
+
"generate:shell-artifacts": "bun scripts/generate-shell-artifacts.ts",
|
|
41
47
|
"lint": "bunx tsc --noEmit",
|
|
42
48
|
"lint:tsgo": "bunx tsgo --noEmit",
|
|
43
49
|
"check": "bun run lint && bun run check:versions && bun run test:cli-fast",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { log } from "../log";
|
|
3
|
+
|
|
4
|
+
const SHELL_FILES = {
|
|
5
|
+
bash: "kesha.bash",
|
|
6
|
+
zsh: "kesha.zsh",
|
|
7
|
+
fish: "kesha.fish",
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
type Shell = keyof typeof SHELL_FILES;
|
|
11
|
+
|
|
12
|
+
interface CompletionsCommandArgs {
|
|
13
|
+
shell?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isShell(value: string): value is Shell {
|
|
17
|
+
return value === "bash" || value === "zsh" || value === "fish";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const completionsCommand = defineCommand({
|
|
21
|
+
meta: {
|
|
22
|
+
name: "completions",
|
|
23
|
+
description: "Print shell completion script for bash, zsh, or fish",
|
|
24
|
+
},
|
|
25
|
+
args: {
|
|
26
|
+
shell: {
|
|
27
|
+
type: "positional",
|
|
28
|
+
required: true,
|
|
29
|
+
description: "Shell: bash | zsh | fish",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
async run({ args }: { args: CompletionsCommandArgs }) {
|
|
33
|
+
const shell = args.shell;
|
|
34
|
+
if (!shell || !isShell(shell)) {
|
|
35
|
+
log.error("usage: kesha completions <bash|zsh|fish>");
|
|
36
|
+
process.exit(2);
|
|
37
|
+
}
|
|
38
|
+
const file = new URL(`../../completions/${SHELL_FILES[shell]}`, import.meta.url);
|
|
39
|
+
process.stdout.write(await Bun.file(file).text());
|
|
40
|
+
},
|
|
41
|
+
});
|