sco-core SDK documentation
Public SDK contracts generated from a compiler-validated catalogue. Engineering guides are selected by an explicit public-input allowlist.
Releases
Section titled “Releases”sdk-v2.3.0
- SDK
- 2.3.0
- Game pack
- 0.6.0
- Plugin ABI
- 1.1
- Archives
- 5 profiles
Immutable approved assets. Release notes
This documentation build
- Source
- e616ed69d8f9f77b0f4827881c86d91e4a7d1689
- SDK
- 2.3.0
- Game pack
- 0.6.0
Not an approved release. Pages describe this source commit.
Libraries
Section titled “Libraries”-
Start & SDK profiles
Choose an SDK archive, build and check a first plugin, and learn how plugins are found and loaded.
-
Language SDKs & cookbooks
The C++ and C# SDK layers, worked examples and the per-language status of every contract.
-
Native & service reference
Service tables, callable contracts, game services and the engine-native index.
-
Host integration & AI agents
MCP discovery for agents and IDEs, the host-source kit, release notes and provenance.
Choose an archive
Section titled “Choose an archive”Archives published in sdk-v2.3.0. Profiles and versions come from its release-scope declaration.
-
core
sco-sdk-core-2.3.0.zipThe game-neutral plugin SDK: the sco_api ABI, the host services, the C, C++, C# and Lua layers, examples and tools.
-
game-sc
sco-sdk-game-sc-0.6.0.zipThe optional Star Citizen extension: the game pack's service tables and events, DataCore, their C++ and C# wrappers, game examples and docs.
-
legacy
sco-sdk-2.3.0.zipEverything in one zip, as sdk-v1.1.0 shipped.
-
core-source
sco-sdk-core-source-2.3.0.zipKernel source-development archive: host/runtime, native and Lua loaders, required vendored code, CMake, tools and synthetic tests.
-
host-source-sc
sco-sdk-host-source-sc-2.3.0.zipStandalone Star Citizen host source kit in repository layout: neutral kernel plus complete game implementation, DataCore, vendored build dependencies, headers and synthetic tests.
Verify a download
Section titled “Verify a download”Each archive’s SHA-256 digest is listed in the release’s SHA256SUMS. Download it and the archive into one folder, then check that archive’s line: OK means the bytes match the published list. This checks integrity against the release’s own list; it is not a signature check. On Linux, use sha256sum in place of shasum -a 256.
Verify core
Section titled “Verify core”curl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/SHA256SUMScurl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/sco-sdk-core-2.3.0.zipawk '$2 == "sco-sdk-core-2.3.0.zip"' SHA256SUMS | shasum -a 256 -c -Verify game-sc
Section titled “Verify game-sc”curl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/SHA256SUMScurl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/sco-sdk-game-sc-0.6.0.zipawk '$2 == "sco-sdk-game-sc-0.6.0.zip"' SHA256SUMS | shasum -a 256 -c -Verify legacy
Section titled “Verify legacy”curl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/SHA256SUMScurl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/sco-sdk-2.3.0.zipawk '$2 == "sco-sdk-2.3.0.zip"' SHA256SUMS | shasum -a 256 -c -Verify core-source
Section titled “Verify core-source”curl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/SHA256SUMScurl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/sco-sdk-core-source-2.3.0.zipawk '$2 == "sco-sdk-core-source-2.3.0.zip"' SHA256SUMS | shasum -a 256 -c -Verify host-source-sc
Section titled “Verify host-source-sc”curl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/SHA256SUMScurl -fLO https://github.com/scubamount/sco-core/releases/download/sdk-v2.3.0/sco-sdk-host-source-sc-2.3.0.zipawk '$2 == "sco-sdk-host-source-sc-2.3.0.zip"' SHA256SUMS | shasum -a 256 -c -Verify with Python
Section titled “Verify with Python”For any platform, including Windows (download with curl.exe). Set archive to the file you downloaded.
import hashlibfrom pathlib import Path
archive = "sco-sdk-core-2.3.0.zip"sums = dict(line.split()[::-1] for line in Path("SHA256SUMS").read_text().splitlines() if line.strip())actual = hashlib.sha256(Path(archive).read_bytes()).hexdigest()print(archive + (": OK" if actual == sums[archive] else ": FAILED"))raise SystemExit(actual != sums[archive])Reading rules
Section titled “Reading rules”- Result names without the prefix mean the corresponding
SCO_*value. Normal success isSCO_OKunless the row describes a Boolean, ID, count, string or void result. Listed failures are known cases, not an exhaustive proof of every fault; unspecified cases and precedence between simultaneous errors remain unspecified. - The size / since cell gives the minimum x64 table byte extent that includes
the whole function pointer, not just its first byte. Check
size >= offsetof(Table, method) + sizeof(table->method)before reading that pointer, then check it is non-NULL. A version match alone does not justify reading an uncovered tail. The historical examples usingsize > offsetof(...)presume a well-formed complete provider table; current consumers must use the full extent and non-null method check, not that historical shorthand. - For service discovery,
query_servicerequires equal version majors and a provider minor at least the requested minor. Missing service:SCO_NOT_FOUND; incompatible/older version:SCO_UNAVAILABLE; output table NULL except on success. No missing pointer or service should be called. Tables may grow only by appending fields; unknown tails are not to be inspected. Host/game-owned tables outlive all plugins and are withdrawn after plugin unload. Third-party tables have the provider’s lifetime, not that of the querying plugin. - Caller size-prefixed inputs/outputs use
sizeofas built by the caller. An oversized buffer/struct is not a promise that an unknown tail is initialized: tail initialization and preservation are unspecified unless noted. Command argument-definition stride isarg_def_size;sco_argis frozen at 16 bytes,sco_sql_valueat 16 bytes andsc_vehicle_seatat 96 bytes. Padding/reserved input fields are zero. Enums are 4 bytes; do not pass_FORCE32sentinels. - Byte handshake:
*inout_sizeis capacity on entry, bytes written on success, bytes needed withSCO_TOO_MANY; NULL output with zero capacity asks the size. Text is NUL-terminated and the terminator counts. This is not the same asget_peers’ element-count handshake or the truncating fixed-capacity name calls. Required size may change between calls: retry if needed, not an atomic snapshot. - Caller buffers stay caller-owned. No returned service pointer, string, mapping, command descriptor, frame or game ID is an allocation the plugin may free. “No allocation transfer” does not mean “no internal allocation” or “real-time safe.” Internal allocation bounds/latency are unspecified unless recorded.
- Unless a row says inputs are copied, their retention is unspecified beyond the synchronous call. Keep borrowed callback code and ctx alive for its registration or queued lifetime; ctx is not automatically freed. Callback payload pointers are valid during the callback only; copy retained data.
- Any-thread permission is not a recursive-reentrancy guarantee. Rows explicitly mark known callback-safe operations and otherwise say reentrancy unspecified. Game-thread permission does not permit calls from a game hook or arbitrary worker.
- “No cancellation entrypoint” records API surface, not guaranteed completion, rollback or an interruptible call. Unload/crash cleanup and callback quiescence are stated separately. Synchronous calls have no cancel token. Cancellation of an operation already in progress is unspecified unless stated.
last_erroris a diagnostic, not a return-value replacement: scope varies by service and another call may overwrite it. Complete diagnostics for every failure and error-text retention after success are unspecified unless documented.
Remaining gaps
Section titled “Remaining gaps”This is an inventory-complete catalogue, not a claim that the API has a complete behavioral specification. In particular:
- Recursive reentrancy/depth, lock-acquisition latency, internal allocation bounds and worker-vs-unload quiescence are unspecified for most methods. Any-thread support alone does not establish them.
- There is no general cancel-token API or promise to interrupt running calls. Queue drop, registration withdrawal, rollback, deferred despawn and a game action’s actual completion are different events; do not conflate them.
- No universal failure-output, tail-zeroing or diagnostic-isolation rule exists. Some methods zero outputs, some leave them unchanged, some change required sizes and some can fail after producing a game side effect. Buffer-specific conditions above take precedence over broad header prose.
- DataCore’s allocation-exception translation, concurrent commits/discards on the same patch and ordering of competing saved-file commits are unspecified.
- spawn.entities failure-reason lifetime is unspecified; copy it during the call’s immediate use and do not free it. Tracking failure may follow a successful spawn.
- game.vehicles / game.creative do not establish uniform released-self rejection or error-isolation guarantees; their last_error implementations need not enforce handle/service-start checks. Other game diagnostics also have no stopped-service refusal guarantee. Do not use stale handles merely because a table is still mapped.
- Direct IPC view synchronization with peers/close/unload is unspecified by this service table; a borrowed mapping does not grant safe concurrent unmapping.
- Watch/query-radius/state reserved behavior remains gated off; event vehicle-seat payload, actor health maximum and camera field of view are not filled from a verified live-game contract. Event payloads are not additional method rows; game services documents delivery and absent capability.
For additions, append a record under sdk/contracts/ and update the corresponding
method row and inventory here. Run tools/sdk_catalogue.py check to compare both
with compiled header declarations and member extents. A comment, signature or
sibling service’s behavior is not evidence for an unstated guarantee on a new method.