Skip to content

Environment variables reference

This page lists all FUTU_* environment variables supported by the daemon (futu-opend), CLI (futucli), and MCP (futu-mcp), with purpose, default values, and matching CLI flags.


Credentials

Env var Purpose Default Matching CLI flag
FUTU_ACCOUNT Login-account hint. futucli unlock-trade / futu-mcp can use it to select account-scoped trade-password keychain entries when --trade-pwd-account is not set; helper scripts also use it to start the daemon (as needed) Prefer daemon --login-account <ACCOUNT>
FUTU_PWD Login password (plaintext or 32-hex MD5, auto-detected) (required or use CLI flag) --login-pwd <PWD>
FUTU_TRADE_PWD Trade unlock password (futucli unlock / MCP unlock) (as needed) --trade-pwd <PWD>
FUTU_TRADE_PWD_ACCOUNT Account hint for account-scoped trade-password keychain lookup (as needed) --trade-pwd-account <ACCOUNT>
FUTU_API_KEY Bearer token used by futucli stock-note-labels, stock-notes, and set-stock-note with OpenD REST, and by tape-reading CLI commands with native binary WebSocket (as needed in secure KeyStore mode) futucli ... --api-key <KEY>
FUTU_MCP_API_KEY Process-wide default API key for futu-mcp --keys-file stdio scope mode; HTTP scope mode never uses it as a fallback and requires a valid Authorization: Bearer on every /mcp request (required for stdio scope mode; not used by HTTP) futu-mcp --api-key <KEY>
FUTU_MCP_OPEND_REST_URL OpenD REST base URL that futu-mcp guarded real-money write tools (group orders / algorithm orders / position actions) forward to when the daemon disables raw TCP in secure KeyStore mode; unset means those write tools refuse (as needed; secure deployments only) futu-mcp --opend-rest-url <URL>

Security tip: Prefer systemd EnvironmentFile=/etc/futu-opend.env (mode 0600) to avoid leaking plaintext to shell history / ps aux.


MCP protocol diagnostics

Env var Purpose Default Matching CLI flag
FUTU_MCP_PROTOCOL_DIAGNOSTICS Enable MCP protocol conformance diagnostic tools while retaining authentication; --keys-file mode requires qot:read. Precedence is CLI, environment, TOML protocol_diagnostics, then default; explicit false disables it false futu-mcp --protocol-diagnostics[=true\|false]

Connection addresses

Env var Purpose Default
FUTU_GATEWAY MCP / futucli daemon gRPC address 127.0.0.1:11111
FUTU_REST_URL futucli daemon REST URL http://127.0.0.1:11112
FUTU_WS_URL Native binary WebSocket URL (ws:// / wss://) for tape-reading CLI queries and subscriptions, equivalent to --ws-url; supply the caller key through --api-key / FUTU_API_KEY No default; must be supplied explicitly
FUTU_MCP_TAPE_WS_URL Native binary WebSocket URL for futu-mcp tape reads and stream subscriptions, equivalent to --tape-ws-url; preserves caller permissions and market restrictions and still requires a valid Bearer key No default; unset rejects corresponding reads or new streams
FUTU_ADDR Used by examples/live_test for daemon address 127.0.0.1:11111

Upstream CA and proxy

Env var Purpose Default
FUTU_UPSTREAM_CA_FILE Explicit trusted PEM certificates appended to Mozilla roots for ordinary upstream HTTP and WebTCP Unset; environment and system CA stores are not loaded
FUTU_UPSTREAM_PROXY HTTP proxy URL for ordinary upstream HTTPS, WebTCP and backend TCP; accepts http:// only and percent-encoded URI userinfo for authentication Unset; existing HTTP environment-proxy and direct TCP behavior remain

Settings freeze on first use; restart the daemon after changing them. Missing, empty or invalid certificate files and unsupported proxy settings fail closed. Certificate chains, validity periods and names remain verified.

An explicit proxy overrides inherited HTTP_PROXY, HTTPS_PROXY and NO_PROXY. HTTPS, WebTCP and backend TCP use CONNECT; denial or timeout never falls back to a direct connection. A custom http:// authentication origin retains HTTP forwarding. HTTPS CONNECT uses the domain, so a retry-IP override does not guarantee the proxy connects to that IP. A proxy that allows only port 443 may reject backend TCP ports.

Through an explicit proxy, WebTCP sends SNI matching its certificate verification name so an intercepting proxy can select the correct certificate. The CONNECT target still comes from the existing connection configuration. Direct WebTCP connections do not send SNI; both paths strictly verify certificates.

For platform login, write_completed (INFO) confirms only that the complete local frame was written and flushed; write_failed (WARN) reports failure of that operation. Correlate requests using serial_no, connection_generation and endpoint_fingerprint. frame_bytes is the frame length, never a partial byte count on failure. These logs omit bodies, accounts, raw endpoints and opaque error text. A subsequent timeout with received_bytes=0 requires proxy or backend records to establish forwarding and response progress; local completion does not prove backend receipt.

When a VM already provides a trusted CA file and HTTP proxy, select them explicitly:

export FUTU_UPSTREAM_CA_FILE="$SSL_CERT_FILE"
export FUTU_UPSTREAM_PROXY="$HTTPS_PROXY"
futu-opend --setup-only

Confirm these variables are nonempty, the trusted PEM is readable and the proxy URL uses http://. Supply credential-bearing settings through a protected environment file. Either setting can be used independently. Local REST/MCP TLS, update checks and native Bank transports use their existing configuration.


Browser entrypoints / Metrics security

Env var Purpose Default
FUTU_REST_ALLOWED_ORIGINS REST CORS Origin allowlist, comma-separated; * / any / all means development wildcard With REST keys configured: loopback only. Legacy unauth mode keeps wildcard compatibility
FUTU_WS_ALLOWED_ORIGINS WebSocket handshake Origin allowlist, comma-separated Loopback Origin only when unset; non-browser clients without Origin skip this check
FUTU_METRICS_PUBLIC=1 Revert /metrics to public access and plaintext key_id labels By default /metrics follows auth posture and redacts key_id labels

Production guidance:

  • Browser UI deployments should set exact origins such as https://app.example.com.
  • Use FUTU_METRICS_PUBLIC=1 only when the metrics port is protected by firewall / sidecar controls.

Long-running daemon hardening (v1.4.103+)

Compatibility env opt-in, default OFF. You can also enable the same behavior with futu-opend --client-sig-proactive-refresh / --client-sig-reactive-refresh, or TOML client_sig_proactive_refresh = true / client_sig_reactive_refresh = true. See long-running daemon deployment guide for details.

Env var Purpose Default Risk
FUTU_CLIENT_SIG_PROACTIVE_REFRESH=1 Proactively refresh client_sig 1h before expiry OFF Low — single refresh action; validate server acceptance on a non-critical account first
FUTU_CLIENT_SIG_REACTIVE_REFRESH=1 Reactive refresh after tcp_login persistent failures (≥3) OFF Medium — ret_type=15 semantics not exclusively "client_sig invalid" (includes rate limiting / risk control); in multi-account daemon, misfire may affect other accounts; safe for single-account
FUTU_QOT_RELOGIN_BACKOFF_MS QOT login-health self-heal ladder, four millisecond values: fail0,fail1,fail2,fail3+ 60000,120000,240000,600000 Medium — useful for real-machine verification / long-run diagnostics; avoid overly frequent production relogin
FUTU_WEBSIG_REFRESH Master switch for proactive WebSig refresh. Set only to 0 / false / no / off for emergency rollback, then restart the daemon ON High — when disabled, an expired WebSig can recover only through failure-driven reconnect / ticket replacement
FUTU_SESSION_KEY_REFRESH Control the C++-aligned periodic TCP session-key refresh actor; a refresh failure invalidates the connection and enters the unified reconnect path ON; disabled only by 0 / false / no / off Low — emergency opt-out; normal operation does not need this variable
FUTU_WEBTCP_SITE_CONFIG_REFRESH Enable the periodic WebTCP site-config refresh timer; the initial fetch and commconfig-target-change refresh still run when disabled OFF; enabled only by 1 / true / yes / on Low — last-good remains active

When to flip the two client-sig switches to default ON: after enough real deployments show that FUTU_CLIENT_SIG_PROACTIVE_REFRESH and FUTU_CLIENT_SIG_REACTIVE_REFRESH do not trigger extra rate limiting or risk-control behavior. These two switches remain experimental opt-in; this note does not apply to the WebSig and session-key refresh rows that are already default-on.


Client (CLI / SDK / MCP)

Env var Purpose Default
FUTU_CLI_AUTO_IDEM=1 futucli auto-derives idempotency_key (param hash) for place-order/modify/cancel OFF
FUTU_UPDATE_CHECK_URL Override URL for futucli version --check / futucli doctor version.json update checks unset uses https://futuapi.com/version.json; unavailable, non-2xx, or schema-incompatible manifests fail closed

Startup and local caches

Env var Purpose Default
FUTU_STOCK_LIST_STARTUP_WAIT_SECS Seconds to wait for the first stock-list sync before ready when the local list is empty; background sync continues after timeout 3; 0 disables the wait
FUTU_LANGUAGE_PACK_CACHE_DIR Root directory for the language-pack manifest and last-good cache futu-opend-rs/language-packs under the OS cache directory

Quote quota diagnostics

Env var Purpose Default
FUTU_HISTORY_KLINE_CLOUD_SYNC Whether to synchronize used historical K-line quota with official OpenD/App; accepts only true / false true; use --history-kline-cloud-sync false or history_kline_cloud_sync = false to enter local-only compatibility mode
FUTU_HISTORY_KL_QUOTA_MAX Override for the max unique stocks allowed in one local historical K-line quota period; unset follows the account's dynamic quota unset (cold-start fallback 100)
FUTU_HISTORY_KL_QUOTA_PERIOD_SECS Historical K-line quota period length, in seconds 604800 (7 days)

Note: the historical K-line total quota prefers the account quota returned after login by backend request, matching the value shown in official OpenD UI. FUTU_HISTORY_KL_QUOTA_MAX is only an explicit override for debugging or stress tests; before the dynamic quota arrives, Rust uses the C++ cold-start default 100 as a fail-closed fallback.


Trade diagnostics

FUTU_TRADE_PUSH_DIAGNOSTICS is off by default and freezes on first use. Set it to 1, true, yes, or on to enable it. Use INFO logging and daemon --json-log; a receiver using this Rust SDK must also enable the variable and initialize INFO-level JSON logs. Restart the corresponding process after changes.

Diagnostics correlate notification parsing, requery, cache decisions, subscription/permission filtering, native TCP/WS writing and receiver stages. Writing, frame receipt, integrity checks and local queue admission are separate facts; admission does not prove application consumption. REST WebSocket/gRPC records stop at adapter handoff, and other SDKs need matching receiver fields. The packaged scripts/trade_push_diagnostics.py reads local JSONL files and requires an explicit daemon/receiver run binding in a verified common connection observation window. Cross-run frame collisions remain ambiguous; unmatched receiver observations retain unknown server association. Share its allowlisted summary rather than ordinary raw logs, which may contain business data. No new trades are needed.

Env var Purpose Default
FUTU_HISTORY_ORDER_AUDIT=1 Enable history-orders backend-row filtering / projection audit logs for investigating Rust vs official C++ history-order count or field differences OFF
FUTU_TRADE_PUSH_DIAGNOSTICS Correlate trade notifications through native TCP/WS writers and this Rust SDK receiver using INFO JSON logs OFF

Account setting switches

Env var Purpose Default
FUTU_ACCOUNT_FUNDING_SETTINGS_WRITES Allow explicit changes to account financing, currency-exchange and automatic-exchange settings; independent of --extended-data-writes, with original account capabilities, caller permissions and result readback checks still required OFF; enabled only by 1 or case-insensitive true

Testing / Chaos engineering

Env var Purpose Default
FUTU_E2E_SIM_ACC E2E test sim account (test-only)
FUTU_E2E_SIM_PWD E2E test sim password (test-only)
FUTU_E2E_SIM_PLATFORM E2E test platform (futunn / moomoo) futunn
FUTU_CHAOS_ENABLE=1 chaos test fault-injection toggle OFF
FUTU_MULTI_VERSION_GUARD_STRICT=1 multi_version_smoke.sh strict mode (binary fingerprint diff → exit 1) (set by ship.sh A9)

Release tooling

Env var Purpose
FUTU_MULTI_VERSION_GUARD_STRICT=1 Forced by ship.sh A9; fingerprint diff blocks release
FUTU_MV_CACHE_DIR Cache directory for historical binaries downloaded by scripts/multi_version_smoke.sh

Build metadata

Env var Purpose Default
FUTU_OPEND_RS_GIT_SHA Override the git SHA compiled into device_alias / version diagnostics build script reads git rev-parse --short HEAD

Naming convention

FUTU_<SUBSYSTEM>_<FEATURE>_<ACTION>=<VALUE>:

  • FUTU_ prefix — shared namespace for daemon / CLI / SDK
  • subsystem: CLIENT_SIG / TRADE / CLI / E2E / CHAOS etc
  • feature/action: describes the functionality itself, no internal ticket numbers exposed (for example, use PROACTIVE_REFRESH instead of INTERNAL_123)
  • value: follow the matching row; accepted boolean values and default states vary by switch

Precedence vs CLI flags

The general order is CLI flag > env var > config file > built-in default; feature-specific compatibility rules are documented in their table rows. FUTU_HISTORY_KLINE_CLOUD_SYNC uses CLI > config file > env > default true.

Example: FUTU_PWD=foo futu-opend --login-pwd bar uses bar (CLI flag).