mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
* feat(voice): configure OpenAI STT and TTS endpoints separately
Replace providers.openai.voice (a single apiKey/baseUrl shared by
speech-to-text and text-to-speech) with independent providers.openai.stt
and providers.openai.tts, each carrying its own apiKey/baseUrl. STT and
TTS now resolve fully independently, so they can point at different
OpenAI-compatible endpoints. The env equivalents OPENAI_VOICE_API_KEY /
OPENAI_VOICE_BASE_URL split into OPENAI_STT_* and OPENAI_TTS_*.
No backcompat: the voice key is removed and no longer read. Each feature
still falls back to providers.openai.apiKey/baseUrl, then OPENAI_API_KEY/
OPENAI_BASE_URL. Composer dictation resolves from the STT endpoint.
* fix(voice): keep daemon bootable and respect global OpenAI key
Two issues from review of the STT/TTS endpoint split:
- A config from an older release that still sets providers.openai.voice
crashed daemon startup, because the strict schema rejects the now-unknown
key. Strip it before parsing (alongside the existing local.autoDownload
strip) so the daemon boots; the value is discarded, not migrated.
- An empty endpoint env var (e.g. a copied .env.example leaving
OPENAI_STT_API_KEY= blank) shadowed the OPENAI_API_KEY fallback, so
speech was reported as missing credentials despite a configured global
key. firstDefined now skips empty/whitespace strings.
* fix(voice): isolate STT and TTS option parsing per endpoint
An STT-only OpenAI setup could be broken by a stale or invalid TTS env
var (e.g. a leftover TTS_VOICE/TTS_MODEL), because the single resolution
schema validated both endpoints' option groups before the per-endpoint
gate. Split into endpoint-key, STT-option, and TTS-option schemas and
parse each option group only when that endpoint has credentials, so an
unused endpoint's bad env can no longer take down the configured one.
* fix(voice): tag voice-config shim and update direct-daemon test callers
- Mark the providers.openai.voice strip with a COMPAT(openaiVoiceConfig)
comment + removal date so it shows up in the back-compat cleanup
inventory, per repo convention.
- Update the tests that build the daemon directly with a resolved OpenAI
config (bootstrap smoke + the real-API voice/daemon e2e suites) to the
new { stt, tts } shape; the old top-level { apiKey } is no longer read,
and these files are excluded from typecheck so the break was silent.
* fix(voice): update voice-roundtrip debug script to new OpenAI config shape
Last direct daemon caller still passing the removed top-level
openai: { apiKey }; the debug script lives outside tsconfig.scripts.json
so the stale shape wasn't caught by typecheck. Use { stt, tts }.
224 lines
7.3 KiB
Markdown
224 lines
7.3 KiB
Markdown
---
|
|
title: Configuration
|
|
description: Configure Paseo via config.json, environment variables, and CLI overrides.
|
|
nav: Configuration
|
|
order: 40
|
|
category: Configuration
|
|
---
|
|
|
|
# Configuration
|
|
|
|
Paseo loads configuration from a single JSON file in your Paseo home directory, with optional environment variable and CLI overrides.
|
|
|
|
## Where config lives
|
|
|
|
By default, Paseo uses `~/.paseo` as its home directory. The configuration file is:
|
|
|
|
```bash
|
|
~/.paseo/config.json
|
|
```
|
|
|
|
You can change the home directory by setting `PASEO_HOME` or passing `--home` to `paseo daemon start`.
|
|
|
|
## Precedence
|
|
|
|
Paseo merges configuration in this order:
|
|
|
|
1. Defaults
|
|
2. `config.json`
|
|
3. Environment variables
|
|
4. CLI flags
|
|
|
|
Lists append across sources (for example, `hostnames` and `cors.allowedOrigins`).
|
|
|
|
## Example
|
|
|
|
Minimal example that configures listening address, hostnames, and MCP:
|
|
|
|
```json
|
|
{
|
|
"$schema": "https://paseo.sh/schemas/paseo.config.v1.json",
|
|
"version": 1,
|
|
"daemon": {
|
|
"listen": "127.0.0.1:6767",
|
|
"hostnames": ["localhost", ".localhost"],
|
|
"mcp": { "enabled": true }
|
|
}
|
|
}
|
|
```
|
|
|
|
`daemon.hostnames` is the primary field. The old `daemon.allowedHosts` name still works as a deprecated alias for backward compatibility.
|
|
|
|
## Agent providers
|
|
|
|
Agent providers, both the first-class ones Paseo ships with and custom entries you add under `agents.providers`, are documented on their own page.
|
|
|
|
See [Providers](/docs/providers) for the mental model and [Supported providers](/docs/supported-providers) for the full list of agents Paseo can launch. For pointing Claude at Anthropic-compatible endpoints (Z.AI, Alibaba/Qwen), multiple profiles, custom binaries, ACP agents, and the `additionalModels` merge behavior, see [Custom providers](/docs/custom-providers). The full field reference lives on GitHub at [docs/custom-providers.md](https://github.com/getpaseo/paseo/blob/main/docs/custom-providers.md).
|
|
|
|
## Worktrees
|
|
|
|
New worktrees are created under `$PASEO_HOME/worktrees` by default. To place new worktrees somewhere else, set `worktrees.root`:
|
|
|
|
```json
|
|
{
|
|
"worktrees": {
|
|
"root": "/mnt/fast/paseo-worktrees"
|
|
}
|
|
}
|
|
```
|
|
|
|
Relative paths are resolved against `PASEO_HOME`. Existing worktrees remain where they are; changing this setting only changes where Paseo creates and discovers Paseo-managed worktrees going forward.
|
|
|
|
## Voice
|
|
|
|
Voice is configured through `features.dictation` and `features.voiceMode`, with provider credentials under `providers`.
|
|
|
|
For voice philosophy, architecture, and complete local/OpenAI setup examples, see [Voice docs](/docs/voice).
|
|
|
|
## Bundled web UI
|
|
|
|
The daemon can serve the browser web client from the same HTTP server. This is enabled in the official Docker image and disabled by default for normal CLI and desktop-managed daemons.
|
|
|
|
Enable it from the CLI:
|
|
|
|
```bash
|
|
paseo daemon start --web-ui
|
|
```
|
|
|
|
Or set the environment variable:
|
|
|
|
```bash
|
|
PASEO_WEB_UI_ENABLED=true paseo daemon start
|
|
```
|
|
|
|
Or persist it in `config.json`:
|
|
|
|
```json
|
|
{
|
|
"features": {
|
|
"webUi": {
|
|
"enabled": true
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
When enabled, open the daemon HTTP origin, for example `http://localhost:6767/`, to load the web app. Static UI files load without daemon auth; API and WebSocket requests still require the configured password.
|
|
|
|
## Logging
|
|
|
|
Daemon logging uses separate console and file sinks by default:
|
|
|
|
- Console: `info` and above
|
|
- File (`$PASEO_HOME/daemon.log`): `trace` and above
|
|
- File rotation: `10m` max file size, `2` retained files total (active + 1 rotated)
|
|
|
|
```json
|
|
{
|
|
"log": {
|
|
"console": {
|
|
"level": "info",
|
|
"format": "pretty"
|
|
},
|
|
"file": {
|
|
"level": "trace",
|
|
"path": "daemon.log",
|
|
"rotate": {
|
|
"maxSize": "10m",
|
|
"maxFiles": 2
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Legacy fields `log.level` and `log.format` are still supported and map to the new destination settings.
|
|
|
|
## Password authentication
|
|
|
|
You can require a password to connect to the daemon. When set, all HTTP and WebSocket clients must authenticate. Only the `/api/health` liveness endpoint is exempt, so that process supervisors and load balancers can probe without credentials.
|
|
|
|
The easiest way to set a password is with the CLI:
|
|
|
|
```bash
|
|
paseo daemon set-password
|
|
```
|
|
|
|
This prompts for a password, writes the bcrypt hash to `config.json`, and tells you to restart the daemon.
|
|
|
|
Alternatively, set the `PASEO_PASSWORD` environment variable (plaintext, hashed automatically at startup):
|
|
|
|
```bash
|
|
PASEO_PASSWORD=my-secret paseo daemon start
|
|
```
|
|
|
|
Or write the hash directly in `config.json`:
|
|
|
|
```json
|
|
{
|
|
"daemon": {
|
|
"auth": {
|
|
"password": "$2b$12$..."
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
After setting a password, restart the daemon for the change to take effect.
|
|
|
|
### Connecting with a password
|
|
|
|
The CLI picks up a password from, in order:
|
|
|
|
1. The `password` query parameter on a `tcp://` host URI:
|
|
|
|
```bash
|
|
paseo --host "tcp://192.168.1.10:6767?password=my-secret" ls
|
|
```
|
|
|
|
2. The `PASEO_PASSWORD` environment variable, used as a fallback when the host carries no embedded password (works for `localhost:6767`, bare `host:port`, or `tcp://` hosts without a `password=` query):
|
|
|
|
```bash
|
|
PASEO_PASSWORD=my-secret paseo ls
|
|
PASEO_PASSWORD=my-secret paseo --host 192.168.1.10:6767 ls
|
|
```
|
|
|
|
A `password=` in the URI always wins over the env var, so you can keep `PASEO_PASSWORD` set globally and still target a different daemon by spelling its password into the URI.
|
|
|
|
In the mobile app, enter the password in the direct connection setup screen.
|
|
|
|
## Common env vars
|
|
|
|
- `PASEO_HOME`, set Paseo home directory
|
|
- `PASEO_PASSWORD`, on the daemon, the password to require (plaintext, hashed at startup); on the CLI, the password used to connect when the host URI doesn't include one
|
|
- `PASEO_LISTEN`, override `daemon.listen`
|
|
- `PASEO_HOSTNAMES`, override/extend `daemon.hostnames`
|
|
- `PASEO_ALLOWED_HOSTS`, deprecated alias for `PASEO_HOSTNAMES`
|
|
- `PASEO_WEB_UI_ENABLED`, enable or disable the daemon-served web UI
|
|
- `PASEO_WEB_UI_DIST_DIR`, override the daemon web UI build directory
|
|
- `PASEO_TRUSTED_PROXIES`, configure trusted reverse proxy ranges for `X-Forwarded-*` headers
|
|
- `PASEO_LOG_CONSOLE_LEVEL`, override `log.console.level`
|
|
- `PASEO_LOG_FILE_LEVEL`, override `log.file.level`
|
|
- `PASEO_LOG_FILE_PATH`, override `log.file.path`
|
|
- `PASEO_LOG_FILE_ROTATE_SIZE`, override `log.file.rotate.maxSize`
|
|
- `PASEO_LOG_FILE_ROTATE_COUNT`, override `log.file.rotate.maxFiles`
|
|
- `PASEO_LOG`, `PASEO_LOG_FORMAT`, legacy log overrides (still supported)
|
|
- `OPENAI_API_KEY`, override OpenAI provider key
|
|
- `OPENAI_STT_API_KEY`, `OPENAI_STT_BASE_URL`, OpenAI speech-to-text endpoint (dictation + voice mode STT)
|
|
- `OPENAI_TTS_API_KEY`, `OPENAI_TTS_BASE_URL`, OpenAI text-to-speech endpoint (voice mode TTS)
|
|
- `PASEO_VOICE_LLM_PROVIDER`, override voice LLM provider (`claude`, `codex`, `opencode`)
|
|
- `PASEO_DICTATION_STT_PROVIDER`, `PASEO_VOICE_STT_PROVIDER`, `PASEO_VOICE_TTS_PROVIDER`, override voice provider selection (`local` or `openai`)
|
|
- `PASEO_LOCAL_MODELS_DIR`, control local model directory
|
|
- `PASEO_DICTATION_LOCAL_STT_MODEL`, override local dictation STT model
|
|
- `PASEO_VOICE_LOCAL_STT_MODEL`, `PASEO_VOICE_LOCAL_TTS_MODEL`, override local voice STT/TTS models
|
|
- `PASEO_DICTATION_LANGUAGE`, `PASEO_VOICE_LANGUAGE`, override dictation and voice STT language
|
|
- `PASEO_VOICE_LOCAL_TTS_SPEAKER_ID`, `PASEO_VOICE_LOCAL_TTS_SPEED`, optional local voice TTS tuning
|
|
|
|
## Schema
|
|
|
|
For editor autocomplete/validation, set `$schema` to:
|
|
|
|
```
|
|
https://paseo.sh/schemas/paseo.config.v1.json
|
|
```
|