Skip to content
Loading local search…

Try a task like “spawn a ship” or “read inventory”, or an exact API name.

Choose one category, or search all.

Stability

What a plugin or product can rely on across SDK 2.x releases. Three questions are kept apart on purpose:

  • Stability: will code written against this table keep compiling and working in later SDK 2.x releases? That is this page.
  • Availability: is the service published, and is its capability on, in a given host and game session? See game services and game status.
  • Evidence: how far has it been checked (signature rows, synthetic tests, a run in a game session)? See the evidence levels in game status.

A Stable table is not a promise that its capability is on or that it works in the game. Nothing on this page has been run in game.

Plugin ABI 1.x (sco_api.h, currently 1.1; its released layout is pinned by the ABI freeze) only grows. New functions and fields go at the end of their struct, SCO_API_MINOR goes up, and nothing released is removed, renamed, retyped or reordered. The rules are in Plugin API v1: Compatibility, and the ABI freeze checks them in CI on every change.

Every host service table under the reserved owner sco, declared in an include/sco_*.h header, is Stable:

Service Version Header
sco.content 1.0 sco_content.h
sco.datacore 1.1 sco_datacore.h
sco.diagnostics.publisher 1.0 sco_diagnostics_publisher.h
sco.ipc 1.0 sco_ipc.h
sco.net 1.0 sco_net.h
sco.settings 1.0 sco_settings.h
sco.storage 1.1 sco_storage.h
sco.ui 1.0 sco_ui.h
sco.ui.surfaces 1.0 sco_ui_surfaces.h
sco.widgets 1.2 sco_widgets.h

A host service is still optional: a host or game build that does not offer one does not publish it, and query_service answers SCO_NOT_FOUND (Host-owned services).

Every published service table, Stable or Experimental, follows the same rule within its major version:

  • It grows only at its tail. New members go after the last one, behind a new minor version macro in its header. For example, sco.widgets 1.2 (SCO_WIDGETS_VERSION_1_2) appended the node-tag members to the 1.1 table.
  • Existing members are never removed, renamed, retyped or reordered, and the layout of a released table never changes.
  • A caller checks that the table is non-null, that its size covers the whole member it is about to call, and that the member is non-null (reading the rows). A newer table answers an older minor; an older table is shorter, and the size check catches it.

A change that cannot be made at the tail needs a replacement table: a new service under a distinct name (for example game.loadout2), with its own header and version macros, published next to the unchanged old name. Plugins move by querying the new name. The kernel publishes one table per name: provide_service refuses a name that is already published, and query_service answers SCO_UNAVAILABLE when the major differs (services). Two major versions therefore never share a name. Publishing them under one name would need a kernel change with its own design and ABI review; the current host does not support it.

Stable: the table is never removed or changed incompatibly within SDK 2.x. It only grows at its tail as above. Once a released SDK has carried the Stable label for a table, the table stays Stable for the rest of SDK 2.x, whatever its later evidence.

Experimental: the table grows the same way, but a later SDK 2.x minor release may replace it with a new table under a distinct name, as above. When that happens, the old name stays published and is marked deprecated in the changelog and in its documentation for at least one further SDK minor release. If SDK 2.N ships the replacement, 2.N and 2.(N+1) both still publish the old name; 2.(N+2) is the earliest release that may drop it.

Either way, stability is independent of availability and of evidence. A Stable table’s capability can be OFF by default, can answer SCO_UNAVAILABLE when the game is not ready or a row did not resolve, and can have no in-game run at all. Evidence levels are recorded separately, per capability, in game status.

Game-pack tables come from the optional Star Citizen game pack and are declared in include/sc_*.h: the game.* tables, plus teleport.spatial (sc_spatial.h) and spawn.entities (sc_spawn.h). Their engine side changes with the game. A new label follows one rule, set by the maintainer:

  • Stable if at least one of the table’s capabilities has evidence level sigcheck_resolved (its rows resolve in a sco-sigcheck report of a game build), off_pending_probe (its rows resolve and one in-game question is open) or in_game_verified (a dated run in a game session; no capability has this level yet).
  • Experimental otherwise: every capability is synthetic-only, blocked or undocumented.

The rule decides a label until an SDK release carries it. After that, Stable is a ratchet: if a later game patch takes away every qualifying evidence level, the table keeps its Stable label and its promise, and its capability answers unavailable until the game pack is updated. An Experimental table becomes Stable as soon as one capability qualifies.

The game.* event bus (sc_game_events.h) has no service table but carries a label by the same rule. For the bus, Stable means that event names are never removed or renamed and that payload structs grow only at their tail: every payload starts with uint32_t size, which a subscriber checks before reading a field past what it was built against.

The two signature-row groups in the status table (mining rows and CryPak adapter rows) carry no label. They are not service tables: they are read by host-internal code and the internal C++ API (version 0, below), and a game patch can stop them resolving.

The label is the stability field of each service and event-bus entry in sdk/status_registry.json, the same file that records the evidence. A Stable entry also records stable_since, the SDK release that first carries the label (sdk-v2.4.0 for every Stable entry today). tools/status_registry.py refuses an entry without a label, an unknown label, a label on a signature-row group, stable without stable_since, and experimental when a capability qualifies. Until the stable_since release is out (while sdk/VERSION still names it), it also refuses stable when no capability qualifies. After that it refuses demoting the entry. It renders the label in the Stability column of the service table, with - for a signature-row group.

In SDK 2.4.0 (release candidate 1) the registry labels 13 game-pack service tables Stable and 20 Experimental, and the game.* event bus Stable. The Stability column of the status table is the current list.

  • The internal host C++ API in include/sco/ (sco namespace) is version 0 and outside this promise.
  • The language layers: the C++ wrappers in include/scosdk/ (C++ SDK), the C# Sco.Sdk bindings (C# SDK) and the Lua API (Lua plugins). This page makes no promise about their source-level API. They call the C tables above, so the table’s promise holds for what they call.
  • Wire and shared-memory layouts with their own version constants: sc_ipc.h (SC_IPC_VERSION), sc_titanlink.h (TL_LAYOUT_VERSION), sc_voxel_bridge.h (VX_LAYOUT_VERSION) and the sc_net.h packet header (SC_NET_PROTOCOL_VERSION). Both sides must agree on that constant, and any layout change bumps it (bridge layouts, net wire).
  • The plugin.ini manifest and its keys (Plugins).
  • The ImGui draw context that sco.ui passes through. Using it is a third-party ABI coupling outside the frozen C ABI (UI).
  • Game behavior. A game patch can stop a Stable table’s rows from resolving. Its capability then answers unavailable until the game pack is updated. The table’s name and layout stay as promised, and so does its label once a released SDK has carried it.
  • In-game verification. A label is a compatibility promise, never a claim that anything was run in game.

The MCP discovery server (agent integration) returns stability per service from list_services and per record from get_capability_status: stable, experimental, or unknown. unknown means the server was started without a repository root, its status source was refused or predates the labels, or the source has no entry for that table. Host services and the plugin ABI are always stable. Signature-row groups are not catalogue tables and do not appear.