Skip to main content

Configuration

altgo reads a TOML configuration file. Every field has a default, so you only need to change what applies to you. Use Settings for day-to-day changes. The file is for fields the interface does not expose, or for changing many values at once.

Location​

~/.config/altgo/altgo.toml

Transcription​

[transcriber] backend selects the transcription engine. The default is local, which runs on this machine. Set it to online to use a cloud ASR service.

[transcriber]
backend = "local" # "local" (default) or "online"
language = "zh" # empty string means automatic detection, limited by the chosen model
threads = 0 # local engine threads, 0 = use all CPU parallelism

Local engine​

[transcriber]
model = "sense-voice" # filled in after a download in Settings, or a model directory path

Available models:

ModelDescriptionDownload size
sense-voiceSenseVoice, automatic detection of Chinese, English, Japanese, Korean and Cantonese, fastabout 230 MB
sense-voice-yueSenseVoice Cantonese-enhanced, more accurate on Cantoneseabout 237 MB
fire-red-asr2-ctcFireRedASR2 CTC, stronger on mixed Chinese and English speechabout 740 MB

The local engine embeds sherpa-onnx. The model loads once when the pipeline starts and stays in memory. A missing model file or a load failure is reported at startup. Recordings longer than 60 seconds are split at speech boundaries detected by silero-vad and transcribed segment by segment, with a target segment length of 25 seconds, so there is no practical length limit. Shorter recordings are transcribed in one pass. The silero-vad model ships with the app, and splitting falls back to silence detection if it cannot be loaded.

Online engine​

[transcriber]
backend = "online"

[transcriber.online]
protocol = "mimo_chat" # mimo_chat, chat_input_audio or transcriptions
api_key = "sk-your-key"
api_base_url = "https://token-plan-cn.xiaomimimo.com/v1"
model = "mimo-v2.5-asr"
timeout = 60 # request timeout in seconds

Differences between the three protocols:

ProtocolRequest shapeServices
mimo_chatchat/completions with the WAV as base64 in a single input_audio block and asr_optionsXiaomi MiMo gateway, the default
chat_input_audioSame chat shape without asr_options, with the language as a top-level field when setOpenAI-shaped input_audio endpoints
transcriptionsOpenAI /audio/transcriptions multipartwhisper, Zhipu glm-asr, the hosted SiliconFlow SenseVoiceSmall and others

An online transcription failure is reported directly and does not fall back to the local engine. The key can also be set with the ALTGO_TRANSCRIBER_API_KEY environment variable.

Polishing​

Polishing is optional. With level none altgo skips it and calls no model. With any other level, [polisher] backend selects a remote API or a local model.

Engine selection​

[polisher]
backend = "remote" # "remote" (default) or "local"
local_model = "qwen3-0.6b" # local: "qwen3-0.6b", "qwen3-1.7b" or a custom GGUF path

The local runtime and models are downloaded on demand from the polishing section in Settings and are not bundled with the installer. The runtime is llama.cpp's llama-server: the Windows x64 archive is about 19.5 MB and expands to about 47 MiB. Qwen3-0.6B is about 397 MB and Qwen3-1.7B about 1.1 GB. You can point local_model at your own GGUF file, in which case altgo downloads no weights and installs only the runtime.

Local settings are fixed at values measured in practice: temperature 0, output capped at 192 tokens and threads set to the number of physical cores, up to 16. The local engine has a single level. The level choice acts as a switch: none turns it off and any other level turns it on. Output also passes a fidelity check. Numbers, URLs or paths changed, the text reduced to a summary, content added, or formatting markers introduced all count as failures and fall back to the raw transcript.

Local latency: the first call waits for the runtime to start and the model to load, measured at about 1.3 to 2.7 seconds on a local machine. Later calls take about 0.15 to 0.3 seconds. The runtime exits after ten idle minutes to release memory and starts again on the next use.

Polishing level​

LevelEffectRemote API key required
noneNo polishing, the transcript is used as isNo
lightFix punctuation and typosYes
mediumFix grammar and improve word orderYes
heavyStructured rewrite for formal documentsYes

Remote configuration​

[polisher]
level = "medium"
protocol = "openai" # "openai" or "anthropic"
api_key = "sk-your-key"
api_base_url = "https://api.deepseek.com"
model = "deepseek-v4-flash"
max_tokens = 1024
timeout = 60
temperature = 0.3

With level = "none", no key, URL or model name is needed. With any other level, all three are required.

api_base_url accepts three forms. altgo builds the request URL for you:

  • Without a version path, such as https://api.deepseek.com or https://api.anthropic.com: altgo appends /v1/chat/completions or /v1/messages.
  • With a version path, such as https://api.moonshot.cn/v1, https://open.bigmodel.cn/api/paas/v4 or https://dashscope.aliyuncs.com/compatible-mode/v1: altgo appends only /chat/completions or /messages.
  • A full endpoint ending in /chat/completions or /messages: used unchanged.

The polishing section in Settings has a Test connection button. After choosing a provider preset and entering a key, click it to send one minimal request and get a readable result (invalid key, wrong URL, timeout and so on), without saving or recording anything.

Glossary​

The glossary fixes domain terms that speech recognition writes with homophone characters. Add terms one at a time in Settings, or set glossary in [polisher]:

[polisher]
glossary = [
"地月空间",
"平动点",
"深空",
"航天器",
"月球",
"近月空间",
"月面",
"探测器",
"地月转移轨道",
"拉格朗日点",
]

The list applies only to remote polishing at medium and heavy. When it is non-empty, altgo appends it to the system prompt and sends temperature 0 regardless of the configured value. The glossary is sent to the provider along with the transcript, so only list terms you are comfortable sending there. Keep it to 10 to 50 terms, with at most 32 characters per term. none, light and local polishing ignore the list. The model may normalize synonyms or replace a correct phrase with a glossary term. altgo checks the output and retries once without the glossary when it inserts a term that has no homophone source in the input. This phonetic check only covers Chinese terms. English terms can still be added to the list, but altgo does not run the check on them.

Common providers​

The table lists configuration values for common services. All combinations go in the [polisher] section.

Providerprotocolapi_base_urlExample model
OpenAIopenaihttps://api.openai.comgpt-3.5-turbo
DeepSeekopenaihttps://api.deepseek.comdeepseek-v4-flash
Anthropicanthropichttps://api.anthropic.comclaude-sonnet-4-20250514
Volcengine Ark (Doubao)openaihttps://ark.cn-beijing.volces.com/api/v3doubao-seed-1.6-flash-250828
Baidu Qianfanopenaihttps://qianfan.baidubce.com/v2ernie-4.5-turbo-128k
MiniMaxopenaihttps://api.minimaxi.com/v1MiniMax-M3
OpenRouteropenaihttps://openrouter.ai/api/v1deepseek/deepseek-v4-flash
Google Gemini (OpenAI-compatible endpoint)openaihttps://generativelanguage.googleapis.com/v1beta/openaigemini-2.5-flash-lite
Local Ollamaopenaihttp://localhost:11434qwen2.5:7b

The api_key for a local Ollama server can be any non-empty value, for example ollama.

Settings includes presets for about a hundred providers (13 native, plus 86 migrated from cc-switch). Selecting one fills in the URL and protocol, so you only add the key. Entries suffixed with (Anthropic) or (OpenAI) are different protocol endpoints of the same provider.

Thinking level (off by default)​

Voice polishing is a light text task. A reasoning model thinks before answering, which adds seconds of latency and token cost. The default is thinking_level = "off", and altgo adds the disable parameter automatically for providers that support it:

ProviderParameter added automatically
Dashscope (Qwen), SiliconFlow (.cn and .com)enable_thinking: false
Zhipu (bigmodel.cn and z.ai), Volcengine Ark, MiniMax, DeepSeek, Moonshot, Kimi, Xiaomi MiMothinking: {"type": "disabled"}
OpenRouterreasoning: {"enabled": false}
Providers that think by default behind the Anthropic protocol (DeepSeek, Xiaomi MiMo and others)thinking: {"type": "disabled"}

Set thinking_level to "low", "medium" or "high" when you want thinking. Settings has a dropdown with the same values. Requests enable thinking in each provider's own dialect:

ProviderParameter added when a level is set
Dashscope, SiliconFlowenable_thinking: true (a switch only, no levels)
Zhipu, Volcengine Ark, MiniMax, DeepSeek, Moonshot, Kimi, Xiaomi MiMothinking: {"type": "enabled"} (a switch only, no levels)
OpenRouterreasoning: {"effort": "low"}, "medium" or "high"
Other providers, including OpenAIreasoning_effort: "low", "medium" or "high"
Anthropic protocolthinking: {"type": "enabled", "budget_tokens": 1024}, 4096 or 16384, with a higher max_tokens and no temperature

Relay endpoints not listed above have any <think> reasoning traces stripped from the response. The Anthropic protocol takes the first text block. Anthropic itself and unknown endpoints receive no disable parameter, because official thinking is opt-in and newer models return HTTP 400 for disabled.

For providers whose thinking is on by default, when the disable parameter is not sent, thinking and the answer share max_tokens. If thinking uses the whole budget, the visible text is empty and polishing appears to fail. Some models force thinking (such as Zhipu GLM-5.3) and reject the disable parameter. Choosing the model recommended by the preset avoids this. If a model does not support the chosen level, the provider returns an error.

Environment variable override:

export ALTGO_POLISHER_API_KEY="sk-your-key"

Key configuration​

The default trigger key is right Alt. Using Press to set in Settings writes linux_evdev_code on Linux and windows_vk_code on Windows.

[key_listener]
key_name = "Alt_R" # trigger key, right Alt here; use Alt_L for left Alt
long_press_threshold = 200 # long press threshold in milliseconds
double_click_interval = 300 # double press interval in milliseconds
min_press_duration = 100 # minimum press duration, filters IME chatter

Recording​

[recorder]
sample_rate = 16000 # transcription uses 16 kHz mono input; other values are rejected

Output​

[output]
prefer_polished = true # clipboard and injection prefer polished text when it succeeded and is non-empty
inject_text = false # type the result into the focused window, Windows only

Linux needs xclip, xsel or wl-copy available, otherwise the automatic clipboard write fails. You can still copy from the overlay, or use the copy button in the history list on the home page.

Interface​

[gui]
language = "" # "zh", "en" or an empty string to follow the system language
overlay_position = "bottom_center" # "bottom_center" or "top_center"
auto_check_update = true # check for updates at startup

Logging​

Log levels are not part of the configuration file. Use an environment variable:

RUST_LOG=altgo=debug altgo

Precedence​

Environment variables > configuration file > code defaults

Environment variableOverrides
ALTGO_POLISHER_API_KEYpolisher.api_key
ALTGO_TRANSCRIBER_API_KEYtranscriber.online.api_key
ALTGO_MODEL_BASE_URLtranscription model download mirror (not a configuration field)
ALTGO_POLISH_MODEL_BASE_URLpolishing model download mirror (not a configuration field)