Skip to main content

Command-Line Interface (CLI)

Knowii Voice AI gives you two command-line tools, and they do very different jobs:

  • transcribe is the real CLI. It runs fully headless, turns audio and video files into subtitles or text, and manages your transcription models. No window, no clicking, no waiting.
  • knowii-voice-ai is the desktop app itself. Its flags let you drive a running app from a script or a keybinding, and change how it starts up.

The first one is what most readers want, so it goes first.

New to the CLI?

The Transcribe CLI Tutorial walks you through your first file, start to finish, in about ten minutes. This page is the reference you come back to afterwards.

The transcribe CLI​

transcribe turns the audio that never passes through your microphone (meeting recordings, interviews, podcasts, old videos) into subtitles or text. Point it at files, get text back.

It decodes media in-process (mp4, mkv, mov, m4a, mp3, wav, ogg, opus, flac, and more), so there is no ffmpeg to install. It runs the same transcription engines as the desktop app, on your machine, offline. And because it is a normal command-line program, it composes with everything else you already use: shell loops, cron jobs, Makefiles, scripts.

It works alongside the running app

transcribe never launches or interferes with a running Knowii Voice AI window. It does its work and exits, so it is safe to use while the desktop app is open. Models downloaded with transcribe models download show up in the app, and models downloaded in the app are available to the CLI.

Where to find it​

transcribe is installed with Knowii Voice AI, in the same folder as the main executable:

PlatformLocation
Windows%LOCALAPPDATA%\Programs\knowii-voice-ai\transcribe.exe
macOS/Applications/Knowii Voice AI.app/Contents/MacOS/transcribe
Linux (deb / RPM)/usr/bin/transcribe, already on your PATH
Linux (AppImage)Run it through the AppImage (see below)
Using the AppImage?

The AppImage packs everything, transcribe included, into a single file, so the CLI is not on your PATH. Put transcribe right after the AppImage and you get the CLI, with no window:

./Knowii-Voice-AI.AppImage transcribe --version
./Knowii-Voice-AI.AppImage transcribe file talk.mp4 --model parakeet-tdt-0.6b-v3

Everything after transcribe goes to the CLI unchanged, and so do piped input, output, the exit code and Ctrl+C. It is exactly the transcribe described on this page, and safe to run while the app is open.

To type plain transcribe from anywhere, save this small script as ~/.local/bin/transcribe (or any folder on your PATH), with the real path of your AppImage, and make it executable with chmod +x ~/.local/bin/transcribe:

#!/bin/sh
exec "$HOME/Applications/Knowii-Voice-AI.AppImage" transcribe "$@"

Other tools, Knowii Video AI included, can then call transcribe like any other program. Do not copy the transcribe file out of the AppImage: it needs the libraries packed next to it, and fails to start on its own.

Windows

On Windows, call transcribe.exe directly (see the table above). Starting the app with transcribe first is not supported there.

Check that it works:

transcribe --help

If your shell cannot find the command, that folder is not on your PATH. Either call it by its full path, or add the folder to your PATH so you can type transcribe from anywhere. On macOS, an alias does the job too:

alias transcribe="/Applications/Knowii\ Voice\ AI.app/Contents/MacOS/transcribe"

Your first transcription​

Two commands. Download a model, then use it:

transcribe models download whisper-large-v3
transcribe file talk.mp4 --model whisper-large-v3

That writes talk.srt next to talk.mp4. Open the video in any player and your subtitles are there.

Already downloaded a model inside the app? Skip the first command. The CLI and the app share the same models.

Transcribe files​

transcribe file <FILE>... --model <NAME_OR_PATH> [OPTIONS]
OptionDescriptionDefault
<FILE>...One or more audio/video files. Use - to read one stream from stdin.(required)
-m, --modelA model id (e.g. whisper-large-v3) or a path to a model file/directory(required)
--engineEngine for raw paths: parakeet, omnilingual (folders), transcribe-cppby file type
-l, --languageLanguage code (e.g. en, fr) or auto to detect (see below)auto
-f, --formatOutput format: srt, vtt, txt, json, or mdsrt
-o, --outputOutput directory, a single output file, or - for stdoutnext to each input
--translateTranslate to English (multilingual Whisper models only)off
--initial-prompt <TEXT>Bias vocabulary/style (Whisper models only)(none)
--use-app-dictionaryAlso use your app dictionary, as dictation does (see below)off
--settings <PATH>With --use-app-dictionary: read another settings filethe app's own
--int8Trade a little accuracy for more speed and lower memory, where supportedoff
--no-preprocessSkip preprocessing (peak-normalize; silence-trim for txt)off
--timestamp-granularityTiming detail: auto, token, word, or segment (see below)auto
--models-dir <DIR>Where to look up models by idapp data directory

When --model is an id, it is resolved against your downloaded models. When it is a raw path, a .gguf file (Whisper, Parakeet, Moonshine) is loaded on the transcribe-cpp engine automatically; a model folder defaults to parakeet, so pass --engine omnilingual for an Omnilingual folder.

Long files. Whisper reads a file of any length in one pass. The other families (Parakeet, Moonshine, Omnilingual) work on short stretches of audio, so the CLI splits longer files for them the way the app does: in pieces of about 30 seconds, cut at pauses in the speech so words are never split in half, then stitched back together. Timestamps in every output format stay on the file's own timeline, so a subtitle file or a JSON transcript reads the same whether the file was split or not. Files shorter than a piece are transcribed in one go, as before.

Examples:

# Subtitle a video - writes "talk.srt" next to it
transcribe file talk.mp4 --model whisper-large-v3

# Several files at once, into a folder, as WebVTT
transcribe file *.mp4 --model whisper-medium --format vtt --output ./subs/

# Force English and print plain text to the terminal
transcribe file interview.m4a --model whisper-large-v3 --language en --format txt --output -

# Translate a French recording into English subtitles
transcribe file entretien.mp3 --model whisper-large-v3 --translate

# Feed a jargon-heavy recording some vocabulary up front
transcribe file standup.m4a --model whisper-large-v3 --initial-prompt "Kubernetes, Grafana, Prometheus, OTEL"

# Use the custom words and initial prompt you set up in the app
transcribe file standup.m4a --model whisper-large-v3 --use-app-dictionary

# Pipe audio in from stdin
cat note.ogg | transcribe file - --model whisper-medium --format txt

# A faster model, in its lower-memory mode
transcribe file clip.mkv --model parakeet-tdt-0.6b-v3 --int8

Choosing the language. --language fr is used as is by the models that can be told a language (Whisper, for the languages it knows). A model that does not know that language, or cannot be told one at all, says so on the terminal (for example "this model doesn't support 'fr'; the language was detected automatically instead") and carries on. The transcript is still written; with -f json, its language field says which language was actually used.

Reading from stdin. With -, the audio is copied to a temporary file of its own, so several transcribe file - runs can work side by side. The copy is deleted when the run ends: when it succeeds, when it fails, and when you stop it with Ctrl+C or it is asked to stop (exit code 130 for Ctrl+C, 143 for a termination request).

Quote your paths

File names often contain spaces. Always quote them: transcribe file "My Recording.mp4" --model whisper-large-v3.

Output formats​

FormatWhat you getUse it for
srtNumbered subtitle blocks with timestampsVideo players, YouTube, editing software
vttWebVTT subtitlesWeb video, HTML5 players
txtPlain text, no timestampsNotes, search, feeding text into another tool
jsonStructured segments with timingsScripts and further processing
mdA Markdown note: # <file name>, then the transcript as paragraphs, no timestampsObsidian and other note apps — a new paragraph wherever the speaker paused for 1.5 s or more

Word-level timings and the JSON contract​

--timestamp-granularity decides how fine the timings are. auto (the default) keeps each model family's usual behaviour, so scripts written before this option existed keep working unchanged. word gives one entry per word — and with -f json it also fills the words list — while segment gives sentence-sized blocks. The parakeet and transcribe-cpp engines honour all of them; the other engines keep their native segments and print a note.

transcribe file talk.mp4 -m parakeet-tdt-0.6b-v3 -f json --timestamp-granularity word -o -

The JSON is versioned so a tool built on it can check what it is reading:

{
"contract_version": 3,
"language": "en",
"text": "And so, my fellow Americans, ask not…",
"segments": [
{
"start": 0.24,
"end": 10.88,
"start_ms": 240,
"end_ms": 10880,
"text": "And so, my fellow Americans, ask not…"
}
],
"words": [
{ "index": 0, "start_ms": 240, "end_ms": 560, "segment": 0, "text": "And" },
{ "index": 1, "start_ms": 560, "end_ms": 1040, "segment": 0, "text": "so," }
]
}
  • contract_version is 3. It changes whenever the shape changes in a way that could break a consumer.
  • language is the language the transcript was made in: the one you asked for with --language when the model used it, otherwise the one the model detected, or null when the model does not report one: Parakeet and Moonshine with --language auto, and the Parakeet folder models and Omnilingual always. With --translate, it is the language that was spoken, not English. When a long file is split into pieces and they report different languages, the language with the most text overall wins, and a tie goes to the earliest piece.
  • Coming from version 2? Version 3 only adds language; every other field is exactly as before. A tool that reads version 2 only needs to accept 3 as well.
  • Times are in whole milliseconds (start_ms / end_ms); the older float start / end seconds on segments stay for compatibility.
  • Each word has a stable index within the transcript and the segment it belongs to.
  • words is null — not an empty list — when you did not ask for word granularity or the model cannot time words. Null means "not available"; an empty list [] means the model could time words and nobody spoke (a silent file).
  • Pauses and silent stretches never cost you the word timings: a long file split into pieces keeps its words even when one piece was silent, and the index numbers run on without a gap.
  • Long files transcribed in pieces (see Long files above) come back as one transcript: segment and word times are already shifted to the file's timeline and each word's segment points into the merged list, so nothing has to be re-aligned on your side.

Your app dictionary​

The words you taught the app in Settings > Transcription (custom words, word replacements, phonetic replacements, the correction threshold and your initial prompt) are your dictionary. The CLI can read it, and it only ever reads it: it never changes your settings file, even when that file looks damaged. The running app stays in charge of it.

Use it in a file transcription. Add --use-app-dictionary and the model gets the same hint dictation gives it: your initial prompt, then your custom words. If you also pass --initial-prompt, your text comes first and the dictionary follows, separated by a space.

transcribe file standup.m4a --model whisper-large-v3 --use-app-dictionary
transcribe file standup.m4a --model whisper-large-v3 --initial-prompt "Weekly standup." --use-app-dictionary
  • Only Whisper models take this hint, just as in the app. With another model the option is accepted, and the CLI prints a note that the dictionary was not used.
  • The dictionary does not rewrite the output. Word replacements and fuzzy corrections are not applied to the subtitles, text or JSON, so every word and its timing stay exactly as the model heard them. A tool that wants those fixes applies them itself, word by word, from transcribe dictionary --json.

See it, or hand it to another tool:

transcribe dictionary # a readable listing
transcribe dictionary --json # for scripts and other apps
{
"contract_version": 1,
"custom_words": ["Knowii", "Obsidian"],
"word_replacements": [{ "from": "no we", "to": "Knowii" }],
"phonetic_replacements": [{ "from": "эн восемь эн", "to": "N8N" }],
"threshold": 0.18,
"initial_prompt": "Technical dictation."
}
  • contract_version is 1. It changes whenever the shape changes in a way that could break a consumer.
  • Entries keep the order they have in the app; values are exactly as saved.
  • threshold is the custom-word correction threshold (the app's default is 0.18).

Which settings file. By default, the app's own, in its data folder: ~/.local/share/knowii-voice-ai/settings.json on Linux, %APPDATA%\knowii-voice-ai\settings.json on Windows, ~/Library/Application Support/knowii-voice-ai/settings.json on macOS. Pass --settings <PATH> to read another one, such as a copy.

When one setting is damaged. If a single dictionary setting cannot be read (say, a word replacement with no replacement text), the CLI does what the app does: it uses the default for that one setting, keeps all the others, and prints a note naming it. That is not an error: the exit code stays 0.

Exit codes.

CodeMeaning
0The dictionary was read, even if a single setting was reset to its default (see above). Also when there is no settings file yet: the dictionary is simply empty.
3The settings file could not be used at all: it cannot be read, is not valid JSON, does not have the expected shape, is a broken link or not a regular file, or is larger than 64 MiB. The dictionary is treated as empty and a warning names the file and the problem. With file, the transcription still runs, without the dictionary.
1Any other error, as for every transcribe command.

Model families​

Models come in four families. Whisper and Moonshine are single .gguf files; Parakeet and Omnilingual are folders unless you use the GPU Parakeet .gguf. --engine only matters when you point --model at a raw folder:

FamilyWhat it gives you
whisperTimestamped segments and the widest language support. Best for subtitles.
parakeetMuch faster than Whisper. Supports --int8 for more speed and less memory.
moonshineFastest of all. English plus several other languages. Longer files are split at pauses.
omnilingualWidest language coverage (1,600+). Supports --int8.

When --model is a known model id (e.g. whisper-large-v3), the family is detected automatically, so you rarely need this flag.

Manage models​

transcribe models lists, downloads, and removes transcription models from the terminal, using the same catalog and the same folder as the app. Changes are shared in both directions.

List what is available:

transcribe models list
Models directory: /home/you/.local/share/knowii-voice-ai/models
ID ENGINE SIZE DL NAME
parakeet-tdt-0.6b-v3 Parakeet 785M - Parakeet V3
whisper-tiny Whisper 74M - Whisper - Tiny
whisper-large-v3 Whisper 2952M ✓ Whisper - Large V3
...

The DL column shows ✓ for models you already have. Add --downloaded to list only those, --json for machine-readable output, or --models-dir <DIR> to inspect another location.

Download a model:

transcribe models download whisper-large-v3

The download streams to disk with a progress indicator and is written atomically, so it is safe to run while the app is open. If the model is already there, nothing happens.

Remove a model:

transcribe models remove whisper-large-v3
Model ids

Use the ID column from transcribe models list. Whisper ids also accept a short form: large-v3 resolves to whisper-large-v3.

Shell completions​

Tab completion for subcommands, flags, and model ids:

transcribe completions bash
transcribe completions zsh > ~/.zsh/completions/_transcribe
transcribe completions fish > ~/.config/fish/completions/transcribe.fish

Controlling the desktop app​

The knowii-voice-ai executable takes flags of its own. These have nothing to do with file transcription. They exist so you can drive the app from somewhere other than its keyboard shortcut, and change how it starts.

AI-powered voice transcription application

Usage: knowii-voice-ai [OPTIONS]

Options:
--log-level <LEVEL> Set the log level (trace, debug, info, warn, error, off) [default: info]
--toggle-transcription Start or stop a transcription in the running instance
--toggle-capture Start or stop an Obsidian capture in the running instance
--preset <KEY> With --toggle-capture: the preset to capture with, by key (default: the active preset)
--cancel Abort the running instance's current recording or transcription
--start-hidden Start with the main window hidden (tray only)
--no-tray Start without creating a system tray icon
-h, --help Print help

One more: knowii-voice-ai transcribe … runs the transcribe CLI instead of the app, with everything after transcribe passed on unchanged. It is how the AppImage gives you the CLI (see Where to find it). It is not in the list above because it is not a flag of the app: it never opens a window or talks to a running app. Linux and macOS only.

Control a running app​

Knowii Voice AI only ever runs once. Launch it again while it is already open and the new command hands its instructions to the running app, then exits. That is what makes these flags work:

FlagWhat it does
--toggle-transcriptionStarts recording. Run it again to stop recording, transcribe, and paste, just like the shortcut.
--toggle-captureStarts an Obsidian capture. Run it again to stop, transcribe, and save the note, like the capture shortcut. Works even when no capture shortcut is set. Add --preset <key> to capture with a given preset: --toggle-capture --preset task. (Coming in the next release.)
--cancelThrows away whatever is in progress and returns to idle. Does nothing if nothing is running.

This gives you a second way to trigger dictation, alongside your keyboard shortcut. It is handy for a panel or status-bar button (Waybar, Polybar, a dock, a stream deck), a desktop keybinding set in your window manager, or a script that dictates as part of a longer sequence.

# Start recording (or stop it and transcribe, if already recording)
knowii-voice-ai --toggle-transcription

# Discard the current recording or transcription
knowii-voice-ai --cancel

Hyprland keybindings (~/.config/hypr/hyprland.conf):

bind = SUPER, D, exec, knowii-voice-ai --toggle-transcription
bind = SUPER SHIFT, D, exec, knowii-voice-ai --cancel

A Waybar button (~/.config/waybar/config):

"custom/dictate": {
"format": "🎙",
"tooltip": "Dictate with Knowii Voice AI",
"on-click": "knowii-voice-ai --toggle-transcription",
"on-click-right": "knowii-voice-ai --cancel"
}
These commands never steal your window

Running the app with --toggle-transcription or --cancel will not pop the Knowii Voice AI window in front of what you are doing. Otherwise every press of your panel button would interrupt you. Launching it with no flags at all still brings the window forward, as before.

Press once to start, once to stop

--toggle-transcription always works as a toggle, even with Push-to-talk enabled in the settings. A command has no key to hold down, so there is nothing to release. Your keyboard shortcut keeps behaving exactly as you configured it.

If Knowii Voice AI is not running yet, these flags simply start the app normally, without recording. Recording during startup would only capture the few seconds the app needs to load its model, so your first words would be lost. Start the app, then trigger it again.

Change how the app starts​

These flags apply to the launch itself. They have no effect if the app is already running (you will see a note about it in the logs).

FlagWhat it does
--start-hiddenStarts with the main window hidden, straight to the tray. Same as Start hidden, but only for this launch.
--no-trayStarts without a system tray icon, for desktops where you would rather not have one.
# Start quietly in the tray, e.g. from a session autostart script
knowii-voice-ai --start-hidden

# Start with no tray icon at all
knowii-voice-ai --no-tray
With --no-tray, closing the window minimizes it

Without a tray icon there would be no way to bring the window back, so closing it minimizes the window instead of hiding it. You can always find it again in your task switcher. For the same reason, combining --no-tray with a hidden start is not possible: the window is shown, so the app never becomes unreachable.

Logging​

--log-level controls how much detail the app writes to its logs. Use it when something misbehaves and you want to see why.

knowii-voice-ai --log-level debug
LevelWhat it gives youWhen to use it
traceInternal state dumps, every audio buffer, full timingDeep debugging. Creates huge files.
debugDetailed diagnostics, state transitions, shortcut eventsTroubleshooting and bug reports
infoStartup, model loading, recording, transcriptionNormal operation (default)
warnWarnings onlyQuiet monitoring
errorErrors onlyMinimal logging
offNothingNot recommended

When reporting a problem, start the app with --log-level debug, reproduce the issue, then attach the log files. You can also read the most recent logs without leaving the app, under Settings → Advanced.

Where the log files live, and which ones to send, is covered in Application Data and on the Support page.

Need Help?​