Skip to content
context-engine

Server communication

Every request Context Engine sends to the control plane, including license validation and telemetry fields.

No source code leaves your machine. Context Engine does not send file contents, code excerpts, file paths, repository names, symbols, search queries, prompts, tool arguments, tool results, diagnostics, or language-server messages to the Context Engine control plane.

This page covers outbound communication from the context-engine CLI binary to the Context Engine-operated control plane. MCP communication with your coding client and LSP communication with language servers remain local and are not control-plane telemetry.

At a glance

The current binary makes one kind of control-plane request:

DestinationMethodPurpose
https://api.context-engine.app/v1/license/verifyPOST with JSONVerify an API key and receive a signed license lease.

The request has a five-second timeout. There is no periodic heartbeat, session-end request, background telemetry upload, or source upload. A running serve process does not start a license-renewal timer.

CONTEXT_ENGINE_CONTROL_PLANE_URL can override the control-plane base URL. The production default uses HTTPS.

How often the API key is validated

Context Engine validates the signed lease locally every time serve or license-check starts. It contacts the control plane only when an online check is required.

The default server policy is:

  • attempt online renewal after 24 hours;
  • expire the lease after 72 hours.

These intervals are server-configurable. The exact next_check_after and valid_until timestamps returned in the signed lease are authoritative.

Startup behavior

  1. No cached lease: Context Engine sends one online verification request. An API key is required.
  2. Before next_check_after: Context Engine verifies the cached lease's signature and claims locally. It sends no request.
  3. After next_check_after, but before valid_until:
    • If an API key is available, Context Engine attempts one online renewal during startup.
    • A successful renewal starts a new reporting interval.
    • A transient network or server failure does not block startup while the signed lease remains valid.
    • An explicit denial, such as a revoked or expired key, blocks startup.
    • If no API key is available, the still-valid signed lease permits startup without a request.
  4. After valid_until: A successful online verification is required. A missing key, denial, network failure, or server failure blocks startup.

Under normal successful operation, the first process start after the 24-hour renewal point performs the next online check. Repeated starts before that point remain offline. If renewal fails transiently, later process starts can attempt it again while the 72-hour lease is still valid.

context-engine license-check --force-online always performs one online request and ignores an otherwise valid cached lease. The client allows 60 seconds of clock-skew leeway when checking signed timestamps.

Exact request body

The binary sends this JSON shape:

{
  "api_key": "<raw API key>",
  "machine_id": "<UUID>",
  "cli_version": "<semantic version>",
  "os": "<operating system>",
  "os_version": null,
  "telemetry": {
    "tool_calls": {},
    "tokens_saved_estimate": 0,
    "languages_used": []
  }
}

The control plane limits this request body to 16 KiB.

FieldMeaning
api_keyThe raw API key supplied through --api-key or CONTEXT_ENGINE_API_KEY. It is transmitted to the configured control-plane URL so the server can verify it.
machine_idA stable random UUID generated locally and stored beside the license cache. If that UUID cannot be persisted, Context Engine derives a deterministic UUID from the operating-system name and home-directory path; only the resulting UUID is sent.
cli_versionThe Context Engine package version compiled into the binary.
osThe operating-system identifier. macOS is reported as darwin; other platforms use Rust's operating-system name.
os_versionReserved for an operating-system version. The current binary always sends null.
telemetryAggregate usage counters for the license-verification interval. The current binary sends the empty values shown above.

The request does not contain a workspace identifier or any data derived from source text.

Full telemetry schema

The control plane accepts this telemetry schema inside the license-verification request:

{
  "tool_calls": {
    "outline": 0,
    "jump": 0,
    "extract": 0,
    "show_usage": 0,
    "grep_definition": 0,
    "line_context": 0,
    "hover": 0,
    "smart_read": 0,
    "initialize_workspace": 0,
    "shutdown_workspace": 0,
    "restart_workspace": 0,
    "reload_config": 0,
    "index_workspace": 0
  },
  "tokens_saved_estimate": 0,
  "languages_used": []
}

All tool counters are unsigned 32-bit integers. A missing counter is treated as zero.

FieldMeaning
tool_calls.outlineNumber of outline calls.
tool_calls.jumpNumber of jump calls.
tool_calls.extractNumber of extract calls.
tool_calls.show_usageNumber of show_usage calls.
tool_calls.grep_definitionNumber of grep_definition calls.
tool_calls.line_contextNumber of line_context calls.
tool_calls.hoverNumber of hover calls.
tool_calls.smart_readNumber of smart_read calls.
tool_calls.initialize_workspaceNumber of initialize_workspace calls.
tool_calls.shutdown_workspaceNumber of shutdown_workspace calls.
tool_calls.restart_workspaceNumber of restart_workspace calls.
tool_calls.reload_configNumber of reload_config calls.
tool_calls.index_workspaceNumber of index_workspace calls.
tokens_saved_estimateAggregate estimate of tokens avoided by returning focused context instead of the corresponding full-file reads.
languages_usedLSP language identifiers reported during the reporting interval, such as rust or typescript.

The server stores only nonzero tool counters, caps languages_used at 32 entries, and truncates each language identifier to 64 UTF-8 bytes. It caps an out-of-range token estimate at the largest signed 64-bit integer before database storage.

What the current binary actually sends

The schema above defines every supported telemetry field, but the current binary does not populate usage telemetry. Every license-verification request currently contains:

{
  "tool_calls": {},
  "tokens_saved_estimate": 0,
  "languages_used": []
}

There is no separate process that later sends tool counts, token estimates, languages, or session activity.

Server-side handling

When the control plane receives a verification request:

  1. It hashes the raw API key with SHA-256.
  2. It looks up the API-key record by that hash. The raw key is not written to the license-verification event.
  3. It checks the key's status, expiration, tier, and the minimum supported CLI version.
  4. It updates the API key's last_used_at and last_verified_at timestamps after successful verification.
  5. It records a license-verification event containing:
    • the server-resolved API-key ID, or null for an invalid key;
    • machine_id;
    • cli_version;
    • os_name;
    • os_version;
    • the result, such as active or denied;
    • a denial reason when applicable;
    • the sanitized aggregate telemetry object.
  6. It returns a signed lease.

Like any HTTPS service, the hosting stack can observe normal network metadata. When the control plane is configured to trust its proxy, it reads the first X-Forwarded-For address, hashes that address, and uses the hash for rate limiting. That value is not included in the license-verification event described above.

Successful response

A successful verification returns:

{
  "status": "active",
  "lease": {
    "version": 1,
    "alg": "Ed25519",
    "kid": "preview-2026-01",
    "payload": "<base64url-encoded signed payload>",
    "signature": "<base64url Ed25519 signature>"
  },
  "valid_until": "<RFC 3339 timestamp>",
  "next_check_after": "<RFC 3339 timestamp>",
  "tier": "preview",
  "features": {
    "context_engine_enabled": true,
    "telemetry_enabled": true
  },
  "minimum_cli_version": "<optional semantic version>"
}

tier can be preview, individual, team, or oem. minimum_cli_version is omitted when the server does not require one.

The signed lease.payload decodes to:

{
  "token_version": 1,
  "issuer": "context-engine-control-plane",
  "subject_user_id": "<UUID>",
  "api_key_id": "<UUID>",
  "tier": "preview",
  "features": {
    "context_engine_enabled": true,
    "telemetry_enabled": true
  },
  "issued_at": "<RFC 3339 timestamp>",
  "valid_until": "<RFC 3339 timestamp>",
  "next_check_after": "<RFC 3339 timestamp>",
  "minimum_cli_version": "<optional semantic version>"
}

The binary verifies the Ed25519 signature, envelope version, algorithm, signing-key ID, issuer, timestamps, minimum version, and context_engine_enabled feature locally before accepting the lease.

Error response

Denied or failed requests use this JSON shape:

{
  "error": "<machine-readable code>",
  "message": "<human-readable explanation>",
  "action": "<optional recovery action>"
}

Possible error codes include invalid_api_key, api_key_revoked, api_key_expired, subscription_required, update_required, rate_limited, and internal_error.

What never leaves the machine

Not a single line of source code is sent to the Context Engine control plane.

The request and telemetry schemas have no fields for:

  • file contents or code excerpts;
  • file names, paths, or directory structure;
  • repository names, remotes, or commit identifiers;
  • symbol names, definitions, references, or type information;
  • tool parameters, search queries, or tool responses;
  • prompts, chat messages, or generated output;
  • diagnostics or language-server protocol messages;
  • dependency names or source.

Semantic analysis, parsing, caching, filesystem watching, and language-server communication happen locally.