Skip to main content

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

CommandPurpose
synth login SERVERVerify a server and API key, then save the connection.
synth logoutDelete the saved connection and local credential.
synth connectionShow the active server, Project, and credential backend without secrets.
synth projectsList Projects visible to the current key.
synth use PROJECTSelect a Project by exact name or stable ID.
synth search QUERYSearch the active Project for ranked page evidence.
synth page PAGE_IDRead exact page content.
synth statusInspect snapshot and index readiness.
synth doctorDiagnose installation, connection, access, compatibility, and Project readiness.
synth mcp configPrint 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

CodeMeaning
0Success
1Server, compatibility, or operation failure
2Invalid command usage
3Missing or rejected credential
4Project/page unavailable, unauthorized, ambiguous, or not selected
5Snapshot or revision changed
6DNS, proxy, TLS, connection, or timeout failure
130User 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

SymptomWhat to do
Not connectedRun synth login SERVER, then synth connection.
Authentication failureCreate or reauthorize a knowledge:read key and log in again.
No visible ProjectsAsk a Synth administrator to grant the key owner Project access.
Ambiguous Project nameRun synth projects and use the stable prj_... ID.
Revision conflictSearch again and pass the new snapshot and revision to synth page.
TLS or proxy failureCheck HTTPS_PROXY, NO_PROXY, and the SSL_CERT_* variables, then run synth --debug doctor.
Incompatible serverFollow the version range printed by doctor; upgrade the CLI or server deliberately.
Keychain unavailableLog 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_projects
  • synth_status
  • synth_search
  • synth_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.