Harness configuration through Praxis¶
Use all-in-one user setup or
remote client setup for normal use. This reference
explains the installed praxis-harness launcher and file-based alternatives.
It configures the selected CLI; Praxis is the server handling inference.
Unified native configuration¶
For the two unified all-in-one listeners, follow user setup.
Run praxis-harness-config as the ordinary user, then claude-code or
opencode. The refresh helper reads the gateway's configured
catalogs; no alternate config home or per-launch provider URL is needed.
Its source is scripts/common/harness_config.py, installed as
/usr/local/bin/praxis-harness-config by the account helper.
The reference below covers per-provider routes without unified mode, including remote clients. Those paths no longer exist after enabling unified models.
Native files or the launcher¶
For ongoing use, configure the CLI's files and launch the CLI directly. The
praxis-harness helper is optional: it supplies per-launch provider settings,
known Qwen limits, environment cleanup and bounded smoke-test options without
rewriting your usual configuration. Its source is scripts/common/harness.py,
installed as /usr/local/bin/praxis-harness by scripts/common/harness-user.
| CLI menu | Where the list comes from | Switching limits |
|---|---|---|
OpenCode /models |
Configured provider.NAME.models entries |
Multiple configured provider/model pairs can coexist in one session |
Claude Code /model |
Configured picker entries; optional native gateway discovery | One Messages base per launch; discovery filters out IDs without claude/anthropic, so configure Qwen explicitly |
A model menu does not install weights, enforce a gateway allowlist, prove account access, or combine gateway catalogs. Give each harness the exact served IDs and appropriate context limits. The helper currently supplies one selected local model; persistent files are the better choice for a maintained multi-model menu.
| Provider | OpenCode | Claude Code |
|---|---|---|
| vLLM | Chat Completions, :8080/vllm/v1 |
Messages, :8081/vllm base |
| OpenAI | Chat Completions, :8080/v1 |
Not configured |
| Anthropic | Messages, :8081/v1 |
Messages, :8081 base |
These are loopback origins on an all-in-one host. Claude appends /v1/messages
to its base. Remote mode replaces the origin with the HTTPS gateway for every
API, retaining the provider path. The launcher does not enable API translation.
Local clients use local-placeholder; remote clients use a caller JWT. Upstream
provider keys stay with Praxis.
The examples below target 27B after the server is updated to 32,768 tokens.
For 8B, use qwen3-8b, context 16,384 and output 4,096.
Thinking consumes output tokens. See preset limits.
Merge file settings deliberately with existing configuration. Native files do not
inherit future launcher fixes; verify menu selection and a tool query after editing.
OpenCode¶
Expand: environment JSON, config-file alternative and model menu
The launcher supplies `OPENCODE_CONFIG_CONTENT` with a `praxis` provider, one selected model and its limits. Qwen uses the OpenAI-compatible Chat SDK, with reasoning enabled and interleaved reasoning preserved for tool continuation. Anthropic instead uses `@ai-sdk/anthropic` and the Messages listener. For a file alternative, save the following as a dedicated user-owned file, for example `~/.config/praxis/opencode-qwen38.json`:{
"$schema": "https://opencode.ai/config.json",
"model": "praxis/qwen3.8-27b-int4",
"provider": {
"praxis": {
"npm": "@ai-sdk/openai-compatible",
"name": "Praxis",
"options": {
"baseURL": "http://127.0.0.1:8080/vllm/v1",
"apiKey": "local-placeholder",
"headers": {"Authorization": "Bearer local-placeholder"}
},
"models": {
"qwen3.8-27b-int4": {
"name": "qwen3.8-27b-int4",
"limit": {"context": 32768, "output": 8192},
"reasoning": true,
"interleaved": {"field": "reasoning"}
}
}
}
}
}
Claude Code¶
Expand: environment and flags, settings-file alternative and model menu
The launcher sets the Messages base and local authentication, maps the Opus, Sonnet and Haiku aliases to Qwen, and passes the selected model explicitly. For local Qwen it selects `--permission-mode default` (Manual) so tool execution uses user approval rather than the unavailable auto-mode classifier. For 27B it selects `--effort medium`; thinking remains enabled. It supplies a 32,768-token context and 8,192-token output limit and disables 1M context variants so a menu alias cannot override the served limit. Compaction follows Claude's client logic; this is not a separately configured 24,576-token trigger. Local Qwen also uses `CLAUDE_CODE_SIMPLE=1`: a reduced system prompt and basic file/shell tools, with automatic `CLAUDE.md`, skill, plugin, hook and subagent discovery disabled. This affects repository workflows; it is not full Claude Code feature qualification. Nonessential traffic and experimental betas are disabled. The native Anthropic route does not apply these Qwen-specific settings. A dedicated file such as `~/.config/praxis/claude-qwen38.json` can hold the model and environment settings:{
"model": "qwen3.8-27b-int4",
"env": {
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8081/vllm",
"ANTHROPIC_API_KEY": "local-placeholder",
"ANTHROPIC_AUTH_TOKEN": "local-placeholder",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "qwen3.8-27b-int4",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "qwen3.8-27b-int4",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "qwen3.8-27b-int4",
"ANTHROPIC_CUSTOM_MODEL_OPTION": "qwen3.8-27b-int4",
"ANTHROPIC_CUSTOM_MODEL_OPTION_NAME": "qwen3.8-27b-int4",
"ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION": "Local Qwen through Praxis",
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "0",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "1",
"CLAUDE_CODE_DISABLE_1M_CONTEXT": "1",
"CLAUDE_CODE_MAX_CONTEXT_TOKENS": "32768",
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "8192"
}
}
Additional compatible providers¶
Enable the provider on the server,
then configure its route in the native CLI files above. For provider team:
| Client | Local base URL |
|---|---|
| OpenCode OpenAI-compatible | http://127.0.0.1:8080/providers/team/v1 |
| Claude Code | http://127.0.0.1:8081/providers/team |
| OpenCode Anthropic | http://127.0.0.1:8081/providers/team/v1 |
For a quick single-model launch without file edits:
praxis-harness opencode --provider openai --route-prefix /providers/team --model MODEL_ID
praxis-harness claude-code --provider anthropic --route-prefix /providers/team --model MODEL_ID
Here --provider selects the API dialect; --route-prefix selects the upstream
provider configured in Praxis. A hosted Qwen model can need model-specific context,
reasoning and permission settings; do not assume the local-vLLM preset matches it.
To maintain several OpenCode providers, add separately named entries under
provider, each with its URL and models map. Use distinct custom IDs such as praxis-local,
praxis-openai and praxis-team (built-in IDs can merge extra catalog entries); /models can then switch among their entries.
For Claude, add non-Claude models explicitly to its settings file:
Its built-in aliases can still appear. Configure only models supported by the
selected Messages endpoint. CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 is
optional and does not discover arbitrary Qwen IDs. A second Messages endpoint
needs a separate settings file and launch, not another model-picker label.
Remote and automated use¶
For HTTPS, the launcher requires --token-file with a caller JWT and accepts
--ca-file for the gateway CA. It passes CA trust through SSL_CERT_FILE and
NODE_EXTRA_CA_CERTS. A file-based setup needs the same origin, provider path,
caller authentication and CA trust. Keep tokens in private user storage or
environment references supported by the client, never in committed project
files. No TLS verification bypass is needed.
The launcher removes inherited OPENAI_*, ANTHROPIC_* and PRAXIS_*
environment values and Claude's CLAUDE_CODE_USE_* cloud selectors before adding
its own settings, keeping Claude on the Messages gateway route. Launching a CLI directly does not
provide that cleanup; check for conflicting provider/authentication settings.
--print-config prints the command and generated environment with the caller
credential replaced by [caller]; it starts no CLI. It is an inspection aid,
not a complete runnable configuration export.
--prompt changes execution mode: OpenCode uses JSON run with bounded build
steps and tool permissions, and Claude uses
streamed JSON print mode with a turn limit and restricted tools. These smoke
settings are distinct from normal interactive approvals. See
manual acceptance.