Skip to content

Commit cf6bc19

Browse files
AGENTS.md
1 parent 5555e0b commit cf6bc19

1 file changed

Lines changed: 158 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# AGENTS.md — LiveKit C++ Client SDK
2+
3+
## Project Overview
4+
5+
This is **client-sdk-cpp**, the official LiveKit C++ client SDK. It wraps a Rust core (`client-sdk-rust/`) via a protobuf-based FFI bridge. All WebRTC, networking, and media logic lives in Rust; the C++ layer provides an ergonomic API for C++ consumers.
6+
7+
## Architecture
8+
9+
### Core Principle
10+
Rust owns as much of the business logic as possible. If a feature may be used by another SDK it should be implemented in Rust. Since this is an SDK,
11+
ensure backwards compatibility is maintained when possible.
12+
13+
14+
### Platform Support
15+
The SDK must be supported on the following platforms:
16+
1. windows x64
17+
2. linux x86_64
18+
3. linux arm64
19+
3. macOS x86_64
20+
4. macOS arm64
21+
22+
23+
SDK features follow pattern:
24+
25+
1. Serialize a protobuf `FfiRequest` message.
26+
2. Send it to Rust via `FfiClient::instance().sendRequest(req)`.
27+
3. Receive a synchronous `FfiResponse` or an asynchronous `FfiEvent` callback.
28+
4. Expose the result through the C++ API.
29+
30+
When making larger scale changes, check with the developer before committing to architecture changes involving changes to the `client-sdk-rust/` submodule.
31+
32+
### Directory Layout
33+
34+
| Path | Description |
35+
|------|-------------|
36+
| `include/livekit/` | Public API headers (what SDK consumers include) |
37+
| `src/` | Implementation files and internal-only headers (`ffi_client.h`, `lk_log.h`, etc.) |
38+
| `src/tests/` | Google Test integration and stress tests |
39+
| `examples/` | In-tree example applications |
40+
| `bridge/` | **Deprecated** C-style bridge layer — do not add new functionality |
41+
| `client-sdk-rust/` | Git submodule holding the Rust core of the SDK|
42+
| `client-sdk-rust/livekit-ffi/protocol/*.proto` | FFI contract (protobuf definitions, read-only reference) |
43+
| `cmake/` | Build helpers (`protobuf.cmake`, `spdlog.cmake`, `LiveKitConfig.cmake.in`) |
44+
| `docker/` | Dockerfile for CI and SDK distribution images |
45+
| `.github/workflows/` | GitHub Actions CI workflows |
46+
47+
### Key Types
48+
49+
- **`FfiClient`** — Singleton that sends FFI requests to Rust and dispatches event callbacks. Defined in `src/ffi_client.h` (internal).
50+
- **`FfiHandle`** — RAII wrapper for Rust-owned resource handles; drop releases the FFI resource.
51+
- **`Room`** — Central object for connecting to a LiveKit server room.
52+
- **`RoomDelegate`** — Virtual callback interface for room lifecycle events.
53+
- **`SubscriptionThreadDispatcher`** — Owns callback registrations and per-subscription reader threads for audio, video, and data tracks. `Room` delegates callback management here.
54+
- **`LocalParticipant` / `RemoteParticipant`** — Participant objects for publishing and receiving tracks.
55+
56+
## Build
57+
for building, use the build.sh script for Linux and macOS, and the build.cmd script for Windows. Do not invoke CMake directly.
58+
59+
```
60+
./build.sh debug # Debug build
61+
./build.sh debug-tests # Debug build with tests
62+
./build.sh debug-examples # Debug build with examples
63+
./build.sh release # Release build
64+
./build.sh release-tests # Release build with tests
65+
./build.sh release-examples # Release build with examples
66+
./build.sh build-all # All of the above
67+
./build.sh clean # Clean build artifacts
68+
./build.sh clean-all # Full clean (C++ + Rust targets)
69+
```
70+
71+
**Requirements:** CMake 3.20+, C++17, Rust toolchain (cargo), protoc. On macOS: `brew install cmake ninja protobuf abseil spdlog`. On Linux: see the CI workflow for apt packages.
72+
73+
### SDK Packaging
74+
75+
```
76+
./build.sh release --bundle --prefix /path/to/install
77+
```
78+
79+
This installs headers, libraries, and CMake config files so downstream projects can use `find_package(LiveKit CONFIG)`.
80+
81+
## Coding Conventions
82+
83+
### Copyright Header
84+
85+
All source files must have the LiveKit Apache 2.0 copyright header. Use the current year for new files. Do not copyright externally pulled/cloned files.
86+
87+
### Logging
88+
89+
- Use `LK_LOG_*` macros from `src/lk_log.h` (internal header, **not** public API).
90+
- `LK_LOG_ERROR` — when something is broken.
91+
- `LK_LOG_WARN` — when something is unexpected but recoverable.
92+
- `LK_LOG_INFO` — initialization, critical state changes.
93+
- `LK_LOG_DEBUG` — potentially useful diagnostic info.
94+
- Do not spam logs. Keep it concise.
95+
- In production/internal SDK code, do not use `std::cout`, `std::cerr`, `printf`, or raw spdlog calls; use the logging APIs instead. Tests may use standard streams sparingly for ad hoc diagnostics when appropriate.
96+
- The public logging API is `include/livekit/logging.h` (`setLogLevel`, `setLogCallback`). spdlog is a **private** dependency — it must never leak into public headers.
97+
98+
### Public API Surface
99+
100+
- Keep public APIs small. Minimize what goes into `include/livekit/`.
101+
- Never introduce backwards compatibility breaking changes to the public API.
102+
- `lk_log.h` lives under `src/` (internal). The public-facing logging API is `include/livekit/logging.h`.
103+
- spdlog must not appear in any public header or installed header.
104+
105+
### Error Handling
106+
107+
- Throw exceptions for broken/unrecoverable states.
108+
- Use `LK_LOG_WARN` for non-fatal unexpected conditions.
109+
- Use `Result<T, E>` for operations that can fail with typed errors (e.g., data track publish/subscribe).
110+
111+
### Git Practices
112+
113+
- Use `git mv` when moving or renaming files.
114+
115+
### CMake
116+
117+
- spdlog is linked **PRIVATE** to the `livekit` target. It must not appear in exported/installed dependencies.
118+
- protobuf is vendored via FetchContent on non-Windows platforms; Windows uses vcpkg.
119+
- The CMake install produces a `find_package(LiveKit CONFIG)`-compatible package with `LiveKitConfig.cmake`, `LiveKitTargets.cmake`, and `LiveKitConfigVersion.cmake`.
120+
121+
### Readability and Performance
122+
Code should be easy to read and understand. If a sacrifice is made for performance or readability, it should be documented.
123+
## Dependencies
124+
125+
| Dependency | Scope | Notes |
126+
|------------|-------|-------|
127+
| protobuf | Private (built-in) | Vendored via FetchContent (Unix) or vcpkg (Windows) |
128+
| spdlog | **Private** | FetchContent or system package; must NOT leak into public API |
129+
| client-sdk-rust | Build-time | Git submodule, built via cargo during CMake build |
130+
| Google Test | Test only | FetchContent in `src/tests/CMakeLists.txt` |
131+
132+
## Testing
133+
134+
Tests are under `src/tests/` using Google Test:
135+
136+
```
137+
./build.sh debug-tests
138+
cd build-debug && ctest
139+
```
140+
141+
Integration tests (`src/tests/integration/`) cover: room connections, callbacks, data tracks, RPC, logging, audio processing, and the subscription thread dispatcher.
142+
143+
When adding new client facing functionality, add a new test case to the existing test suite.
144+
When adding new client facing functionality, add benchmarking to understand the limitations of the new functionality.
145+
146+
## Formatting
147+
Adhere to the formatting rules if TODO: @alan
148+
149+
## Deprecated / Out of Scope
150+
151+
- **`bridge/`** (`livekit_bridge`) is deprecated. Do not add new functionality to it.
152+
153+
## Common Pitfalls
154+
155+
- A `Room` with `auto_subscribe = false` will never receive remote audio/video frames — this is almost never what you want.
156+
- A single participant cannot subscribe to its own tracks as "remote." Testing sender/receiver requires two separate room connections with distinct identities.
157+
- macOS dylibs require `install_name_tool` fixups for `@rpath` — the CMakeLists.txt handles this automatically. Do not manually adjust RPATH unless you understand the implications.
158+
- When consuming the installed SDK, use `-DLIVEKIT_LOCAL_SDK_DIR=/path/to/sdk` to point cmake at a local install instead of downloading a release tarball.

0 commit comments

Comments
 (0)