# StreamZet Linux SDK — integration preview

Documentation revision: 2026-09-23

https://streamzet.com/docs?lang=en

## Linux quickstart

Test the Go API or C ABI in a Linux host app. Ubuntu 24.04 ARM64/AMD64 binaries and source are provided.

### Downloads and public test settings

- [First visit: try screen sharing without coding](https://streamzet.com/docs/try?lang=en)

Download the files below directly. The downloads guide provides the public test key and configuration; pair the device code in your own account for testing.

- [Linux SDK · AMD64](https://api.streamzet.com/storage/v1/object/public/downloads/sdk/public/2026-09-23-key/streamzet-linux-sdk-preview-20260923-key-amd64.zip?download=streamzet-linux-sdk-preview-20260923-key-amd64.zip) — Ubuntu 24.04 / x86_64, preview / linux 0.3.3. C library and header, runnable C/Go examples, source and test configuration for Intel/AMD 64-bit.
- [Linux SDK · ARM64](https://api.streamzet.com/storage/v1/object/public/downloads/sdk/public/2026-09-23-key/streamzet-linux-sdk-preview-20260923-key-arm64.zip?download=streamzet-linux-sdk-preview-20260923-key-arm64.zip) — Ubuntu 24.04 / aarch64, preview / linux 0.3.3. C library and header, runnable C/Go examples, source and test configuration for ARM 64-bit. Not for xSpan ARMv5.

- [Public test key, configuration and run steps](https://streamzet.com/docs/downloads?lang=en#public-test-key)

### Prerequisites and scope

Run as a normal user, not root. Terminal requires /bin/bash and a PTY. For desktop mode, deploy the matching capture helper and desktop dependencies; headless systems remain terminal-only. Fleet is disabled unless explicitly enabled. This library is not compatible with legacy ARMv5 xSpan.

Backend HTTPS and signaling WSS origins, DNS, correct time and outbound ICE/TURN connectivity are required. relay_only=true requires usable TURN credentials/connectivity. There is no inbound public listener installed by the SDK.

### Run the C test application

```json
{
  "config": {
    "api_key": "sz_test_public",
    "device_name": "Store Linux",
    "mode": "terminal"
  },
  "state_dir": "/home/operator/.local/state/streamzet-sdk-test",
  "fleet": false
}
```

```sh
chmod 600 config.json
./embedded-example config.json
```

The C example prints initial status and changes detected every 500 ms, then stops on Enter or stdin closure. running=true does not mean enrolled or connected. Pair in the dashboard after device_code appears.

- [Step-by-step example guide](https://streamzet.com/docs/linux/test-apps?lang=en)

### Embed in Go

```go
support, err := sdk.Start(ctx, sdk.Options{
    Config: sdk.Config{
        APIKey: "sz_test_public",
        DeviceName: "Store Linux", Mode: "terminal",
    },
    StateDir: "/home/operator/.local/state/streamzet-sdk",
    Fleet: false,
})
if err != nil { return err }
// The host decides when support is enabled and when to stop.
// Poll support.Identity() for public registration information.
// Later, from a worker during host shutdown:
support.Stop()
return support.Wait()
```

Import github.com/plitsoft/streamzet/linux-agent/sdk. Use a local module replace to the delivered source until a tagged module release exists. Start enables support availability; it does not show a local consent dialog. The product must expose its own support policy and controls.

### Build and lifetime

```sh
make sdk
# Outputs: dist/sdk/native/libstreamzet.so, libstreamzet.h, embedded-example
```

Build on the target Linux ABI with Go 1.26 and a C compiler. Use the generated header; keep libstreamzet.so beside the example. Do not dlclose the Go library during the host lifetime. Start once per process; stop and wait before host shutdown. Preserve state across updates and never share it with the standalone agent. Embedded mode does not run the standalone updater or replace the host executable.

## Integrate into a Linux app

Build and configure the C ABI or Go SDK, with runnable examples of ownership and shutdown.

### Downloads and public test settings

- [First visit: try screen sharing without coding](https://streamzet.com/docs/try?lang=en)

This page is for developers who can edit and build the host app. To try the features first, use the no-code walkthrough or test-app guide above.

Download the files below directly. The downloads guide provides the public test key and configuration; pair the device code in your own account for testing.

- [Linux SDK · AMD64](https://api.streamzet.com/storage/v1/object/public/downloads/sdk/public/2026-09-23-key/streamzet-linux-sdk-preview-20260923-key-amd64.zip?download=streamzet-linux-sdk-preview-20260923-key-amd64.zip) — Ubuntu 24.04 / x86_64, preview / linux 0.3.3. C library and header, runnable C/Go examples, source and test configuration for Intel/AMD 64-bit.
- [Linux SDK · ARM64](https://api.streamzet.com/storage/v1/object/public/downloads/sdk/public/2026-09-23-key/streamzet-linux-sdk-preview-20260923-key-arm64.zip?download=streamzet-linux-sdk-preview-20260923-key-arm64.zip) — Ubuntu 24.04 / aarch64, preview / linux 0.3.3. C library and header, runnable C/Go examples, source and test configuration for ARM 64-bit. Not for xSpan ARMv5.

- [Public test key, configuration and run steps](https://streamzet.com/docs/downloads?lang=en#public-test-key)

### 1. Target and prerequisites

The Linux SDK is an integration preview, based on normal-user execution on Ubuntu 24.04. It is separate from the legacy ARMv5/Linux 2.6 xSpan product SDK. Build arm64/amd64 for each target ABI; a library built for macOS cannot be copied to Linux.

Install Go 1.26.x, a C compiler, make, Bash and a CA trust store. Record the target architecture and glibc version. Install ca-certificates and any required enterprise CA; do not disable TLS verification.

```sh
uname -m
getconf GNU_LIBC_VERSION
go version
sudo apt-get update
sudo apt-get install --no-install-recommends build-essential ca-certificates bash
# Run application builds and support as your normal user:
cd source
make sdk
```

### 2. Configuration and identity directory

```json
{
  "config": {
    "api_key": "sz_test_public",
    "device_name": "SDK integration test",
    "mode": "terminal"
  },
  "state_dir": "/home/operator/.local/state/streamzet-sdk-test",
  "fleet": false
}
```

The JSON below includes public test connection settings. Replace state_dir with a private absolute path for this user/installation, or run python3 configure-linux-test.py from the ZIP. JSON does not expand ~ or $HOME. The directory uses 0700 and identity.json 0600; do not share them with another SDK/agent or clone them into machine images.

```sh
chmod 600 config.json
mkdir -p /home/operator/.local/state/streamzet-sdk-test
chmod 700 /home/operator/.local/state/streamzet-sdk-test
./dist/sdk/native/embedded-example config.json
# Press Enter for a graceful stop.
```

> Start enables remote support. The Linux SDK has no built-in consent UI; the host must implement disclosure and start/stop policy. Fleet command execution defaults to false and must be explicitly enabled by products that require it.

### 3. Use from C/C++

Use libstreamzet.h and libstreamzet.so from the same build. From the SDK source directory, the command below sets rpath to load the adjacent library. This ABI is not a Windows DLL or xSpan static library.

```sh
cc -Wall -Wextra -Werror -I dist/sdk/native examples/embedded.c \
  -L dist/sdk/native -lstreamzet -Wl,-rpath,'$ORIGIN' \
  -o dist/sdk/native/embedded-example
ldd dist/sdk/native/embedded-example
./dist/sdk/native/embedded-example config.json
```

```c
#include "libstreamzet.h"
#include <stdio.h>

/* Call from a worker thread; config_json is NUL-terminated UTF-8. */
int run_support(char *config_json) {
    int rc = StreamzetStart(config_json);
    char *status = StreamzetStatus();
    puts(status);
    StreamzetFree(status); /* Exactly once, including error paths. */
    if (rc != 0) return rc;
    /* The real host continues its work here until support should end. */
    getchar();
    StreamzetStop(); /* Waits for peers/background work; not a UI callback. */
    return 0;
}
```

Start returns 0=started, 1=invalid configuration/start failure, 2=already started. Input JSON is copied during the call and remains caller-owned. Each Status string is caller-owned and must be released once with StreamzetFree. Stop is synchronous and idempotent; do not dlclose the Go library during process lifetime.

### 4. Integrate a Go host

Do not assume a published version tag. Put the delivered source at vendor/streamzet-linux and add a local replace in the host module. Never import the SDK’s internal packages directly.

```sh
# Run inside your existing host Go module:
go mod edit -require=github.com/plitsoft/streamzet/linux-agent@v0.0.0
go mod edit -replace=github.com/plitsoft/streamzet/linux-agent=./vendor/streamzet-linux
# After adding the SDK import to your host:
go mod tidy
# Or run the complete example shipped in the source package:
cd vendor/streamzet-linux
go run ./examples/go /absolute/path/config.json
```

```go
import (
    "context"
    "github.com/plitsoft/streamzet/linux-agent/sdk"
)

func startSupport(ctx context.Context, options sdk.Options) (*sdk.Support, error) {
    support, err := sdk.Start(ctx, options)
    if err != nil { return nil, err }
    // support.Identity() returns only device ID/code; enrollment is asynchronous.
    // Keep support while the host performs its normal work.
    return support, nil
}

func stopSupport(support *sdk.Support) error {
    support.Stop() // Requests cancellation; nonblocking.
    return support.Wait() // Join before host shutdown, off the UI thread.
}
```

The complete runnable host is examples/go/main.go. Context cancellation/Stop requests shutdown; Done/Wait confirms completion. Only one instance per process is allowed. The SDK does not replace host signal handlers, call os.Exit or install the standalone updater.

### 5. Add desktop capture

First verify connection and shutdown with mode=terminal. For GUI support, run mode=auto inside the logged-in user’s graphical session. Do not substitute another user’s DISPLAY, WAYLAND_DISPLAY, XDG_RUNTIME_DIR or DBUS_SESSION_BUS_ADDRESS.

```sh
sudo apt-get install --no-install-recommends pkg-config libgstreamer1.0-dev \
  libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base \
  gstreamer1.0-plugins-good gstreamer1.0-pipewire wl-clipboard
mkdir -p dist/sdk/native
cc -O2 -Wall -Wextra -Werror native/capture.c \
  -o dist/sdk/native/streamzet-capture \
  $(pkg-config --cflags --libs gstreamer-app-1.0)
# Set config.capture_helper to the ABSOLUTE path of streamzet-capture.
# Set config.mode to "auto".
```

Wayland requires PipeWire and the desktop’s xdg-desktop-portal backend, plus user sharing/control approval. Denial grants no desktop input; terminal access may remain available independently. X11 also requires display access and GStreamer plugins. File transfer is not supported by this SDK.

### 6. Delivery and operation

Ship the target-ABI library, generated header, required capture helper, licenses and public configuration procedure with the host. Preserve the identity directory across updates and restrict backups. Dashboard online/connected states are distinct from the SDK’s running flag.

- [Verify behavior with the Linux examples](https://streamzet.com/docs/linux/test-apps?lang=en)

## Linux API reference

Go fields, C JSON names, return codes and memory ownership. Configuration validation runs before any worker is started.

### Downloads and public test settings

Download the files below directly. The downloads guide provides the public test key and configuration; pair the device code in your own account for testing.

- [Linux SDK · AMD64](https://api.streamzet.com/storage/v1/object/public/downloads/sdk/public/2026-09-23-key/streamzet-linux-sdk-preview-20260923-key-amd64.zip?download=streamzet-linux-sdk-preview-20260923-key-amd64.zip) — Ubuntu 24.04 / x86_64, preview / linux 0.3.3. C library and header, runnable C/Go examples, source and test configuration for Intel/AMD 64-bit.
- [Linux SDK · ARM64](https://api.streamzet.com/storage/v1/object/public/downloads/sdk/public/2026-09-23-key/streamzet-linux-sdk-preview-20260923-key-arm64.zip?download=streamzet-linux-sdk-preview-20260923-key-arm64.zip) — Ubuntu 24.04 / aarch64, preview / linux 0.3.3. C library and header, runnable C/Go examples, source and test configuration for ARM 64-bit. Not for xSpan ARMv5.

- [Public test key, configuration and run steps](https://streamzet.com/docs/downloads?lang=en#public-test-key)

### sdk.Options / top-level JSON

| Field / API | Type / default | Contract |
| --- | --- | --- |
| Config / config | sdk.Config · required | Endpoint and feature configuration below. Start validates and defaults a copy. |
| StateDir / state_dir | string · required | Absolute owned directory, 0700, not a symlink. Created if absent. Exclusive file lock prevents simultaneous identity use. Keep it across updates; never clone to another device. |
| Fleet / fleet | bool · false | Opt in to remote batch commands as the host OS user while support runs. |

### sdk.Config / config

| Field / API | Type / default | Contract |
| --- | --- | --- |
| APIKey / api_key | string · required | StreamZet key: sz_test_public for evaluation, or an issued sz_live_ key for tenant enrollment. The SDK manages service endpoints and its public transport key. |
| DeviceName / device_name | string · hostname | Empty uses os.Hostname(); resulting name must be nonblank and at most 128 UTF-8 bytes. |
| CaptureHelper / capture_helper | string · /usr/lib/streamzet/streamzet-capture | Absolute helper path; required even when terminal mode ignores capture. Existence is checked when desktop capture starts, not during Start. |
| Mode / mode | string · auto | Empty becomes auto. auto detects the current user’s desktop; terminal forces terminal-only. Other values rejected. |
| RelayOnly / relay_only | bool · false | true limits WebRTC to relay candidates; requires TURN. false permits direct and relay paths. |

> sz_test_public selects public evaluation. It grants no account or tenant access and does not create an isolated sandbox. Sign in with your own account and pair the device code. Values in distributed apps can be extracted; never embed administrator secrets.

### Go lifecycle

| Field / API | Type / default | Contract |
| --- | --- | --- |
| Start(ctx, options) | (*Support, error) | ctx: non-nil, not canceled context.Context. options: sdk.Options. Rejects root, invalid config/path, occupied process/state, filesystem/identity failures. ErrRunning means another SDK worker in this process. Success starts async enrollment; no services or signal handlers installed. |
| Support.Stop() | void | Idempotent, nonblocking cancellation. Does not confirm shutdown completion. |
| Support.Wait() | error | Blocks until worker ends; nil on normal stop, terminal worker error otherwise. Do not call on a GUI thread. |
| Support.Done() | <-chan struct{} | Read-only channel closed when all worker cleanup completes. |
| Support.Identity() | Identity | Thread-safe public snapshot; no secret. DeviceCode fills after enrollment; DeviceID may exist before registration. Not a presence signal. |

### C ABI

| Field / API | Type / default | Contract |
| --- | --- | --- |
| StreamzetStart(char *json) | int | NUL-terminated UTF-8 JSON copied before return; caller owns input. Rejects unknown fields and trailing JSON. 0: started; 1: invalid/start error; 2: handle already started (Stop before reuse, even if worker ended). |
| StreamzetStatus() | char * · owned JSON | Snapshot fields below. Call StreamzetFree exactly once on the returned pointer. Calls serialize with Start/Stop; Status can block during Stop. |
| StreamzetStop() | void | Serialized, idempotent and blocking; requests stop, waits, clears handle. Call from a worker. Does not delete identity. |
| StreamzetFree(char *value) | void | Only a Status-owned pointer or NULL. Do not free twice or pass caller-owned/Go pointers. |

### Identity and C status fields

| Field / API | Type / default | Contract |
| --- | --- | --- |
| running | boolean · false | Worker is alive. It does not mean online, enrolled or viewer-connected. |
| error | string · "" | Last synchronous Start failure or error collected by Stop. Empty means no recorded error, not network success. |
| identity | object · omitted | Present while the C handle exists; omitted before Start/after Stop. No secret or instance_id is exposed. |
| Identity.DeviceID / identity.device_id | string | Persistent public UUID, created before enrollment. |
| Identity.DeviceCode / identity.device_code | string · "" | Pairing code after enrollment; empty while unregistered. |

## Linux example guide

Use the C and Go examples to verify enrollment, web terminal, desktop sharing and shutdown.

### Downloads and public test settings

- [First visit: try screen sharing without coding](https://streamzet.com/docs/try?lang=en)

Download the files below directly. The downloads guide provides the public test key and configuration; pair the device code in your own account for testing.

- [Linux SDK · AMD64](https://api.streamzet.com/storage/v1/object/public/downloads/sdk/public/2026-09-23-key/streamzet-linux-sdk-preview-20260923-key-amd64.zip?download=streamzet-linux-sdk-preview-20260923-key-amd64.zip) — Ubuntu 24.04 / x86_64, preview / linux 0.3.3. C library and header, runnable C/Go examples, source and test configuration for Intel/AMD 64-bit.
- [Linux SDK · ARM64](https://api.streamzet.com/storage/v1/object/public/downloads/sdk/public/2026-09-23-key/streamzet-linux-sdk-preview-20260923-key-arm64.zip?download=streamzet-linux-sdk-preview-20260923-key-arm64.zip) — Ubuntu 24.04 / aarch64, preview / linux 0.3.3. C library and header, runnable C/Go examples, source and test configuration for ARM 64-bit. Not for xSpan ARMv5.

- [Public test key, configuration and run steps](https://streamzet.com/docs/downloads?lang=en#public-test-key)

### 1. Prepare the test

This walkthrough runs prebuilt examples on Ubuntu 24.04. No C/Go compiler or make is needed for the first trial. You need a terminal, Python 3 and internet access.

1. Open a terminal on Linux and check the Ubuntu version and CPU below. Download AMD64 for x86_64 or ARM64 for aarch64.
2. Extract the ZIP into a new folder. In the file manager, open the folder containing configure-linux-test.py and bin, then use Open in Terminal from its context menu. Run the commands there.
3. Run as your normal user; do not prefix example commands with sudo. Also open StreamZet Devices on a PC using your own account.

```sh
cat /etc/os-release
uname -m
python3 --version
```

> If VERSION_ID is not 24.04 or the CPU is neither target above, compatibility is not assured. Ask a developer to build for that environment or contact support. Ask your system administrator to install Python 3 if it is missing.

### 2. Generate settings and run the C executable

Run each line below from the extracted folder. The helper writes the public test key and a private state path under your home into config.json. No manual key or path editing is needed.

```sh
ls configure-linux-test.py bin/embedded-example
python3 configure-linux-test.py
chmod u+x bin/embedded-example bin/go-example
./bin/embedded-example config.json
```

After Created …/config.json, output shows running=true and identity. Once registration finishes, identity.device_code contains an eight-character code to register on the PC. Keep this window open: it shows the running example rather than accepting shell commands.

```sh
{"running":true,"error":"","identity":{"device_code":""}}
# After registration, read the device_code from your own output.
```

> running=true only means the program started, not that a PC viewer connected. Pressing Enter or closing this terminal stops the example.

### 3. Verify the web terminal

1. On the PC, register the printed code from Devices, then start that Linux device’s session in control mode and open Terminal. View-only mode does not allow terminal input.
2. Run the printf and whoami commands below in the web terminal. Verify the normal host user and round-trip English/Korean output. Do not use production-changing commands or sensitive files.
3. Resize the browser and check that stty size changes. Close the shell with exit and reopen it with New terminal.

- [PC registration dialog example](https://streamzet.com/docs/try?lang=en#pair)

```sh
printf 'SDK_%s_OK\n' LINUX
printf '한글 UTF-8 확인\n'
whoami
stty size
```

![Actual SDK_LINUX_OK response in the web terminal](https://streamzet.com/docs-assets/linux/images/web-terminal.png)

Actual SDK_LINUX_OK output from printf in the PC web terminal, connected to the public ARM64 Go example in an Ubuntu container. Only the terminal area is captured.

### 4. Go example and identity persistence

1. Press Enter in the C console and confirm running=false and clean exit. The web End connection button ends that peer session; it is separate from starting/stopping the SDK worker.
2. Run the Go example with the same config.json/state_dir. Confirm the same device_id/device_code, then reconnect from the dashboard.
3. Press Enter to stop the Go example. For later runs, reuse config.json; you do not need to run the configuration helper again.

```sh
./bin/go-example config.json
# Press Enter to stop.
```

### 5. Verify X11 / Wayland desktop

After installing the capture helper and graphical runtime, set config.mode=auto and an absolute capture_helper path. Run as the logged-in desktop user. A headless machine is terminal-only; a black video is not evidence of desktop support.

1. X11: open a test editor and verify changing video, pointer, click, drag, scroll and text. Do not force access to an unauthorized display.
2. Wayland: approve the target screen and remote interaction in the system portal. Test uppercase, symbols and Korean. Text transport may use the device clipboard.
3. Test Wayland denial separately: it must grant no screen/input. A terminal allowed by host policy may continue, and the host must let the user stop the SDK to end terminal availability too.

![GNOME Wayland screen and remote-interaction consent](https://streamzet.com/docs-assets/linux/images/wayland-consent.png)

Actual GNOME portal. Enable Allow Remote Interaction before Share when remote input is needed.

### Troubleshooting

| Symptom | Check and action |
| --- | --- |
| config.json already exists | The helper does not overwrite settings. Restart from that folder with ./bin/embedded-example config.json. |
| root remote shells are not supported | Run as a normal user without sudo. |
| state directory must be absolute/private | Use a real absolute path; check ownership, 0700 permissions and symlinks. |
| another agent owns this identity / already running | Stop the other instance cleanly and retry. Never delete live lock/identity files. |
| libstreamzet.so not found | Place the matching-ABI library beside the executable and use the supplied rpath command; inspect ldd. |
| running=true, no device code | Enrollment is asynchronous. Check DNS, HTTPS, CA store, public key and firewall. Do not disable TLS verification. |
| Example exits immediately | Closed stdin stops the example. Run in a terminal or retain container -i/-t. A service host must manage SDK lifetime itself. |
| Wayland screen unavailable | Check login session, portal backend, PipeWire, consent and capture_helper. Terminal success is separate from desktop success. |

### Acceptance record and support

Record SDK build/ZIP SHA-256, distro/kernel/CPU/glibc, X11/Wayland session, host user, network path, expected/actual result and reproduction steps. End all viewers and confirm SDK Stop/Wait or C Stop completion. Do not attach private enrollment keys or identity.json externally.

### Developers: building from source

Use the integration guide for tool setup, configuration and lifecycle when building for another environment or embedding into a host. These paths are relative to the SDK source folder and differ from the prebuilt bin paths above.

```sh
cd source
make sdk
./dist/sdk/native/embedded-example ../config.json
# Press Enter, then:
./dist/sdk/native/go-example ../config.json
```

- [Linux SDK developer integration guide](https://streamzet.com/docs/linux/integration?lang=en)
