Summary
openclaw currently hardcodes an auto-sync of external CLI credentials (MiniMax CLI, Codex CLI) into the per-agent auth-profile store. For users who have those CLIs installed locally but don't route them through openclaw, this produces noisy info logs on every command, with no config-level way to opt out. Requesting a first-class opt-out surface (config key, env var, or log downgrade).
Problem to solve
External CLI credential sync is unconditionally enabled at the API layer and is not reachable from user-facing configuration:
- Every command that loads the auth store prints an
info-level "synced … credentials from external cli" message, even when the credential is not used by any agent's model selection.
- The message fires twice per command because
loadAuthProfileStoreForAgent is invoked more than once per command lifecycle (init + model resolve).
- The synced credential is only written to in-memory
runtimeStore — it never lands in auth-profiles.json, so the TTL-based "no-op if already synced" fast path can never engage across processes.
- The only way to skip the behavior today is to pass
options.syncExternalCli = false at the JS API call site. There is no openclaw.json field, no environment variable, and no CLI flag exposed.
Effect: users who keep the upstream CLI installed but configure openclaw with their own <provider>:<scope> profiles see persistent log noise they cannot silence without patching node_modules.
Proposed solution
Any one of the following (listed by preference):
- Config opt-out in
openclaw.json — add an auth.externalCliSync field:
Read at the three call sites in loadAuthProfileStore, loadAuthProfileStoreForAgent, and the runtime-store clone path (around dist lines 878 / 914 / 948 / 1025).
- Environment variable — e.g.
OPENCLAW_DISABLE_EXTERNAL_CLI_SYNC=1, or per-provider OPENCLAW_EXTERNAL_CLI_SYNC_PROVIDERS=minimax-cli.
- Log downgrade — demote the "synced … credentials from external cli" message to
debug level when the synced credential is bit-for-bit identical to the previous sync within the TTL window (currently EXTERNAL_CLI_SYNC_TTL_MS = 15 min). This is the smallest change, but it does not help users who want to fully disable the behavior.
Alternatives considered
- Delete
~/.codex/auth.json — not viable: the user actively uses Codex CLI outside openclaw, so removing the file breaks their upstream tool.
- Set
options.syncExternalCli = false at every call site locally — requires patching node_modules/openclaw/dist/store-*.js, which is lost on every upgrade.
- Ignore the noise — acceptable short-term, but the message is in the
info channel (not debug), so it leaks into user-facing CLI output regardless of log-level tuning at the user end.
- Overlay an empty
externalAuthProfiles override — (overlayExternalAuthProfiles appears in the same file) — the sync step runs before the overlay, so it cannot suppress the log.
Impact
- User-visible — removes two lines of unsolicited
info output from every command, improving CLI signal-to-noise.
- Performance — avoids repeated reads of
~/.codex/auth.json + optional keychain lookups for users who have opted out (minor, but non-zero on cold start).
- Backward compatibility — default-on preserves today's behavior; opt-out is purely additive.
- Surface area — small. The existing
shouldSyncExternalCliCredentials(options) helper already centralizes the gate; the change is to feed it from config/env in addition to the current options.syncExternalCli API arg.
Evidence/examples
Environment:
- openclaw
2026.4.14
- Windows 11, Node
v24.9.0
- Codex CLI installed and active at
~/.codex/ (auth.json present)
agents/<id>/agent/auth-profiles.json contains only user-declared profiles (e.g. deepseek:default, minimax:cn) — no openai-codex:default entry, confirming the sync never persists to disk
Reproduction:
$ openclaw models list --agent main
[agents/auth-profiles] synced openai-codex credentials from external cli
[agents/auth-profiles] synced openai-codex credentials from external cli
Model Input Ctx Local Auth Tags
minimax/MiniMax-M2.7 text 200k no yes default,configured,alias:chat-primary
deepseek/deepseek-chat text 128k no yes fallback#1,configured,alias:chat-fallback
Relevant code references (in dist/store-*.js, identifiers stable across recent releases):
EXTERNAL_CLI_SYNC_PROVIDERS (hardcoded list of minimax-cli, codex-cli)
syncExternalCliCredentialsForProvider — emits log.info("synced ${provider} credentials from external cli", …) on every non-no-op path
shouldSyncExternalCliCredentials(options) — current gate, reads only options.syncExternalCli
loadAuthProfileStoreForAgent — invokes the sync on each call, and is itself invoked multiple times per command
Additional information
- Happy to contribute a PR if a direction is confirmed — the change surface is small and localized.
- If a maintainer prefers option 3 (log downgrade) as a near-term partial fix while option 1 is designed, I can send that as a standalone PR first.
- The same reasoning applies symmetrically to the MiniMax CLI sync path; an opt-out should cover both providers uniformly.
Summary
openclaw currently hardcodes an auto-sync of external CLI credentials (MiniMax CLI, Codex CLI) into the per-agent auth-profile store. For users who have those CLIs installed locally but don't route them through openclaw, this produces noisy
infologs on every command, with no config-level way to opt out. Requesting a first-class opt-out surface (config key, env var, or log downgrade).Problem to solve
External CLI credential sync is unconditionally enabled at the API layer and is not reachable from user-facing configuration:
info-level "synced … credentials from external cli" message, even when the credential is not used by any agent's model selection.loadAuthProfileStoreForAgentis invoked more than once per command lifecycle (init + model resolve).runtimeStore— it never lands inauth-profiles.json, so the TTL-based "no-op if already synced" fast path can never engage across processes.options.syncExternalCli = falseat the JS API call site. There is noopenclaw.jsonfield, no environment variable, and no CLI flag exposed.Effect: users who keep the upstream CLI installed but configure openclaw with their own
<provider>:<scope>profiles see persistent log noise they cannot silence without patchingnode_modules.Proposed solution
Any one of the following (listed by preference):
openclaw.json— add anauth.externalCliSyncfield:{ "auth": { "externalCliSync": false // or object form for per-provider control: // "externalCliSync": { "providers": ["minimax-cli"] } // only sync these // "externalCliSync": { "exclude": ["codex-cli"] } // sync all except these } }loadAuthProfileStore,loadAuthProfileStoreForAgent, and the runtime-store clone path (around dist lines 878 / 914 / 948 / 1025).OPENCLAW_DISABLE_EXTERNAL_CLI_SYNC=1, or per-providerOPENCLAW_EXTERNAL_CLI_SYNC_PROVIDERS=minimax-cli.debuglevel when the synced credential is bit-for-bit identical to the previous sync within the TTL window (currentlyEXTERNAL_CLI_SYNC_TTL_MS = 15 min). This is the smallest change, but it does not help users who want to fully disable the behavior.Alternatives considered
~/.codex/auth.json— not viable: the user actively uses Codex CLI outside openclaw, so removing the file breaks their upstream tool.options.syncExternalCli = falseat every call site locally — requires patchingnode_modules/openclaw/dist/store-*.js, which is lost on every upgrade.infochannel (notdebug), so it leaks into user-facing CLI output regardless of log-level tuning at the user end.externalAuthProfilesoverride — (overlayExternalAuthProfilesappears in the same file) — the sync step runs before the overlay, so it cannot suppress the log.Impact
infooutput from every command, improving CLI signal-to-noise.~/.codex/auth.json+ optional keychain lookups for users who have opted out (minor, but non-zero on cold start).shouldSyncExternalCliCredentials(options)helper already centralizes the gate; the change is to feed it from config/env in addition to the currentoptions.syncExternalCliAPI arg.Evidence/examples
Environment:
2026.4.14v24.9.0~/.codex/(auth.json present)agents/<id>/agent/auth-profiles.jsoncontains only user-declared profiles (e.g.deepseek:default,minimax:cn) — noopenai-codex:defaultentry, confirming the sync never persists to diskReproduction:
Relevant code references (in
dist/store-*.js, identifiers stable across recent releases):EXTERNAL_CLI_SYNC_PROVIDERS(hardcoded list ofminimax-cli,codex-cli)syncExternalCliCredentialsForProvider— emitslog.info("synced ${provider} credentials from external cli", …)on every non-no-op pathshouldSyncExternalCliCredentials(options)— current gate, reads onlyoptions.syncExternalCliloadAuthProfileStoreForAgent— invokes the sync on each call, and is itself invoked multiple times per commandAdditional information