Summary
Two small things that cost me a while to work out, both around credentials on --provider openai-compatible:
JCODE_API_KEY is ignored on this path. The credential is resolved by env-var name (OPENAI_COMPAT_API_KEY, or the profile's api_key_env / env file), so the generic-looking JCODE_API_KEY — which does work on the OpenRouter path — silently does nothing here.
- When no key is found and the endpoint is local, jcode sends no credential at all rather than reporting that the key it was looking for is missing. It prints
auth: local endpoint (no auth), which reads like a deliberate configuration rather than a fallback.
crates/jcode-provider-openrouter-runtime/src/lib.rs:699-710 (at 02439b4) is the branch:
let auth = if let Some(key) = load_api_key_from_env_or_config(&resolved.api_key_env, &resolved.env_file) {
ProviderAuth::AuthorizationBearer { token: key, label: resolved.api_key_env.clone() }
} else if !resolved.requires_api_key {
ProviderAuth::None { label: "local endpoint (no auth)".to_string() }
} else { ... }
Reproduction
# A: key set under the generic name -> no credential is sent
JCODE_OPENAI_COMPAT_API_BASE=http://127.0.0.1:8099/v1 JCODE_API_KEY=secret-123 \
jcode run --provider openai-compatible -m <model> --json 'hi'
# prints: auth: local endpoint (no auth)
# B: same endpoint, correct name -> credential is sent
JCODE_OPENAI_COMPAT_API_BASE=http://127.0.0.1:8099/v1 OPENAI_COMPAT_API_KEY=secret-123 \
jcode run --provider openai-compatible -m <model> --json 'hi'
# prints: auth: OPENAI_COMPAT_API_KEY
(Point a local server at it that logs the Authorization header to see the difference directly.)
Why it matters
Local endpoints are not automatically unauthenticated: vLLM's --api-key, a LiteLLM proxy, or anything sitting behind a local gateway all expect a key on 127.0.0.1. In my case the key doubles as a session identifier for a recording proxy, so "no credential sent" was not an auth failure — it silently merged traffic from separate runs that should have stayed distinct, and I first misdiagnosed it as jcode special-casing loopback (it does not; the name was simply wrong).
Suggestion
Either is enough, and neither needs to change the local-endpoint default:
- Accept
JCODE_API_KEY as a fallback on this path too, or say plainly in the docs that it is OpenRouter-only.
- When a key was configured-but-not-found, say which env var was checked before falling back — e.g.
auth: local endpoint (no auth; OPENAI_COMPAT_API_KEY not set). The existing error on non-local endpoints already names the variable, which is what eventually told me the right name.
Environment: jcode 0.68.0, Linux x86_64.
Summary
Two small things that cost me a while to work out, both around credentials on
--provider openai-compatible:JCODE_API_KEYis ignored on this path. The credential is resolved by env-var name (OPENAI_COMPAT_API_KEY, or the profile'sapi_key_env/ env file), so the generic-lookingJCODE_API_KEY— which does work on the OpenRouter path — silently does nothing here.auth: local endpoint (no auth), which reads like a deliberate configuration rather than a fallback.crates/jcode-provider-openrouter-runtime/src/lib.rs:699-710(at 02439b4) is the branch:Reproduction
(Point a local server at it that logs the
Authorizationheader to see the difference directly.)Why it matters
Local endpoints are not automatically unauthenticated: vLLM's
--api-key, a LiteLLM proxy, or anything sitting behind a local gateway all expect a key on 127.0.0.1. In my case the key doubles as a session identifier for a recording proxy, so "no credential sent" was not an auth failure — it silently merged traffic from separate runs that should have stayed distinct, and I first misdiagnosed it as jcode special-casing loopback (it does not; the name was simply wrong).Suggestion
Either is enough, and neither needs to change the local-endpoint default:
JCODE_API_KEYas a fallback on this path too, or say plainly in the docs that it is OpenRouter-only.auth: local endpoint (no auth; OPENAI_COMPAT_API_KEY not set). The existing error on non-local endpoints already names the variable, which is what eventually told me the right name.Environment: jcode 0.68.0, Linux x86_64.