Synth CLI
The Synth CLI is a small remote client for people and automation that need deterministic, revision-bound Project evidence. It does not generate answers, invoke an LLM, or mutate remote Projects.
Five-minute quickstart
The CLI supports Python 3.11 through 3.14 on macOS, Linux, and Windows. For platform-specific prerequisites, pipx and uv setup, upgrades, uninstall, and shell troubleshooting, see Install the Synth CLI.
Install it with pipx:
pipx install synthkb-cli
Or install it with uv:
uv tool install synthkb-cli
Confirm which executable your shell will use:
synth --version
synth --help
If synth is not found after installation, run pipx ensurepath or
uv tool update-shell, open a new terminal, and retry. Do not install the Synth
server package on a customer workstation.
Create an API key with the knowledge:read scope in Global Settings → API
Keys or Settings → Connect, then connect securely:
synth login https://synth.example.com
synth projects
synth use docs
synth search "authentication refresh"
synth page PAGE_ID
synth status
Interactive login prompts for the key without echoing it. The CLI stores it in the operating-system keychain when available and reports when it uses a private file fallback.
Disconnect locally when finished:
synth logout
Logout deletes the local credential; revoke the key in Synth settings when the server-side credential must also stop working.
Local configuration and credentials
The CLI keeps one active connection per configuration directory. Override the
directory with SYNTH_CONFIG_DIR for isolated CI jobs or separate accounts.
Otherwise it uses the native Linux/XDG, macOS Application Support, or Windows
AppData location documented in the automation guide.
remote-cli.json contains only the endpoint, selected Project identity, and a
credential reference. The token lives in the OS keychain or the separate
mode-private remote-cli-credentials.json fallback. Never copy either file
into a repository, image, support ticket, or build artifact.
Login is transactional. A new profile is committed only after verification; if persistence fails during a replacement login, the prior working credential is restored. Logout similarly restores the active profile if credential deletion fails rather than reporting a false success.
Commands
| Command | Purpose |
|---|---|
synth login SERVER | Verify a server and API key, then save the connection. |
synth logout | Delete the saved connection and local credential. |
synth connection | Show the active server, Project, and credential backend without secrets. |
synth projects | List Projects visible to the current key. |
synth use PROJECT | Select a Project by exact name or stable ID. |
synth search QUERY | Search the active Project for ranked page evidence. |
synth page PAGE_ID | Read exact page content. |
synth status | Inspect snapshot and index readiness. |
synth doctor | Diagnose installation, connection, access, compatibility, and Project readiness. |
synth mcp config | Print copy-ready configuration for an AI tool. |
Run synth COMMAND --help for the complete option set.
Global --debug and -H/--header options must appear before the command. For
example, synth --debug search "authentication" writes safe request metadata
to stderr and leaves successful data on stdout.
Exact and consistent reads
Search returns page identity, revision, excerpts, and the active Project snapshot. For a consequential workflow, pass those identities into the exact read:
synth search --json "authentication refresh"
synth page pg_auth --snapshot snap_123 --revision rev_456 --json
Snapshot and revision options are compare-before-read guards. They do not select historical content. If evidence changed, the command exits with code 5; search again and inspect the current page.
Automation and CI
Avoid passing API keys directly on the command line because process arguments may be visible to other users. Use a mounted secret file:
synth login https://synth.example.com \
--api-key-file /run/secrets/synth-api-key \
--project prj_docs \
--credential-store file \
--non-interactive \
--json
Or pipe a secret through stdin:
printf '%s' "$SYNTH_API_KEY" | synth login https://synth.example.com \
--api-key-stdin \
--non-interactive \
--json
All customer data commands support --json. Successful JSON uses a stable
envelope:
{"schema_version": 1, "ok": true, "data": {}}
Errors go to stderr. Their envelope contains a stable code and safe message, and may include a request ID for support.
Example shell handling:
synth status --json >status.json 2>status-error.json
code=$?
if [ "$code" -ne 0 ]; then
jq . status-error.json >&2
exit "$code"
fi
jq -e '.ok == true and .data.project.id != null' status.json
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Server, compatibility, or operation failure |
| 2 | Invalid command usage |
| 3 | Missing or rejected credential |
| 4 | Project/page unavailable, unauthorized, ambiguous, or not selected |
| 5 | Snapshot or revision changed |
| 6 | DNS, proxy, TLS, connection, or timeout failure |
| 130 | User cancellation |
Enterprise networks
The CLI honors the standard HTTPX environment variables:
HTTP_PROXY
HTTPS_PROXY
NO_PROXY
SSL_CERT_FILE
SSL_CERT_DIR
Remote servers require HTTPS. Plain HTTP is accepted only for loopback
development addresses. Use --timeout on network commands when a proxy or
remote deployment requires more time.
Connect through an access gateway with custom headers
Some Synth deployments require gateway credentials in addition to the Synth
API key. For example, a deployment protected by Cloudflare Access needs
CF-Access-Client-Id and CF-Access-Client-Secret on every request.
For a copy-ready walkthrough covering Bash, PowerShell, CI, secret handling, and troubleshooting, see CLI Access Gateways.
Load the gateway values from your secret manager, then create the JSON header map for the current shell:
export CF_ACCESS_CLIENT_ID='replace-with-client-id'
export CF_ACCESS_CLIENT_SECRET='replace-with-client-secret'
export SYNTH_HTTP_HEADERS="{\"CF-Access-Client-Id\":\"${CF_ACCESS_CLIENT_ID}\",\"CF-Access-Client-Secret\":\"${CF_ACCESS_CLIENT_SECRET}\"}"
unset CF_ACCESS_CLIENT_ID CF_ACCESS_CLIENT_SECRET
Log in with the public Synth URL:
synth login https://synth.example.com/
At the hidden API key prompt, paste the raw Synth API key, such as a
synth_sk_... or synth_mcp_... value. Do not add the Bearer prefix. The CLI
normalizes the public URL to the /api/mcp/ endpoint and sends the Synth key as
Authorization: Bearer ... separately from the gateway headers.
Verify the connection and select a Project:
synth doctor
synth projects
synth use PROJECT_NAME_OR_ID
synth status
synth search "test query"
The Synth API key is saved in the OS keychain or private credential file, but
custom headers are deliberately not saved. Recreate SYNTH_HTTP_HEADERS from
your secret manager in every new shell or CI job. Do not put an
Authorization entry in SYNTH_HTTP_HEADERS; headers owned by the CLI cannot
be overridden.
For a one-off request, repeat -H/--header before the command instead:
synth -H "CF-Access-Client-Id:$CF_ACCESS_CLIENT_ID" -H "CF-Access-Client-Secret:$CF_ACCESS_CLIENT_SECRET" login https://synth.example.com/
The -H/--header form is request-scoped. Prefer SYNTH_HTTP_HEADERS when
header values are secrets because command-line arguments may be visible in
shell history or process inspection. Additional headers are sent to readiness
and MCP requests and are redacted from debug output.
Run a redacted diagnostic:
synth doctor
synth doctor --json
synth --debug doctor
Debug output may contain request IDs and endpoint names, but never API keys or authorization headers or additional header values.
Troubleshooting
| Symptom | What to do |
|---|---|
Not connected | Run synth login SERVER, then synth connection. |
| Authentication failure | Create or reauthorize a knowledge:read key and log in again. |
| No visible Projects | Ask a Synth administrator to grant the key owner Project access. |
| Ambiguous Project name | Run synth projects and use the stable prj_... ID. |
| Revision conflict | Search again and pass the new snapshot and revision to synth page. |
| TLS or proxy failure | Check HTTPS_PROXY, NO_PROXY, and the SSL_CERT_* variables, then run synth --debug doctor. |
| Incompatible server | Follow the version range printed by doctor; upgrade the CLI or server deliberately. |
| Keychain unavailable | Log in with --credential-store file, especially in CI or headless Linux. |
synth doctor --json keeps every completed diagnostic stage when a later stage
fails. Send that redacted JSON and any request ID to support; never send the API
key or the credential file.
Configure an AI tool
Generate configuration for Claude-style clients, OpenCode, or OpenAI:
synth mcp config --client claude
synth mcp config --client opencode
synth mcp config --client openai
synth mcp config --client claude --api-key-file /run/secrets/synth-api-key
The generated configuration permits exactly:
synth_list_projectssynth_statussynth_searchsynth_get_page
It prints a placeholder token unless a key is supplied through
--api-key-file, --api-key-stdin, or the process-visible --api-key option.
Saved ambient credentials are never embedded.
Upgrade and uninstall
For pipx:
pipx upgrade synthkb-cli
pipx uninstall synthkb-cli
For uv:
uv tool upgrade synthkb-cli
uv tool uninstall synthkb-cli
Uninstalling the package does not silently delete user configuration or saved
credentials. Run synth logout before uninstalling when local credentials
should be removed.
Server operators
Local Project creation, ingestion, repair, OKF operations, licensing, support bundles, and provider administration belong to the licensed Synth server image. They are intentionally excluded from the standalone customer package.
For Docker Compose, operators can define an image-local helper:
synth-admin() {
docker compose --env-file values.env exec -T synth python -m synth.cli.main "$@"
}
For Kubernetes:
synth-admin() {
kubectl -n synth exec deploy/synth -- python -m synth.cli.main "$@"
}
Do not grant customers shell access to the server container merely to retrieve knowledge. Use the standalone CLI, REST API, Explore, or MCP instead.