This section is for contributors and maintainers.
README.md: short overview, install, quick start, and links to guides.- docs/README.md: documentation index and entry points.
- docs/features.md: feature flags and how to enable them.
- docs/getting-started.md: onboarding example and minimal workflow.
- docs/configuration.md: SDK binaries, networking, and TLS setup.
- docs/tls.md: TLS backend selection and troubleshooting.
- docs/release.md: release automation and publishing flow.
- docs/dev.md: contributor-only guidance.
- Add or update the feature flag in crates/teamtalk/Cargo.toml.
- Update docs/features.md with the new flag and a one-line description.
- Update
README.mdonly if the feature affects onboarding or default usage. - Update the Architecture Overview below if it changes core behavior or modules.
- Add or update examples under crates/teamtalk/examples.
- Update docs/README.md if you add or remove guides.
- API reference:
cargo doc --no-deps --all-features --open - Scripts:
scripts/build-docs.ps1,scripts/build-docs.sh
- Install lefthook using the official guide for your OS (includes manual installs): https://lefthook.dev/installation/
- Enable hooks:
lefthook install - Default hooks run formatting, linting, type checks, and doc-link checks.
- On Windows, if you don't have a bash-compatible shell for
scripts/check-doc-links.sh, copylefthook-local.example.ymltolefthook-local.ymland override the doc-link command:- Example file: lefthook-local.example.yml
pre-commit:
commands:
doc-links:
run: pwsh -File scripts/check-doc-links.ps1- Release flow is automated by
.github/workflows/release-plz.yml. - On push to
main, release-plz creates or updates a release PR with version bump and changelog updates. - The release PR also syncs README, getting-started.md, and features.md to the new crate version.
- After the release PR is merged, release-plz creates the tag/release and publishes to crates.io.
- Keep commit messages in Conventional Commits format so release-plz can infer semver bumps and changelog sections for the release PR.
- docs.rs builds automatically after publish and uses
all-features = true.
- CI runs formatting, linting, checks, tests, docs build, and link validation.
- CI also verifies docs version references are in sync with crates/teamtalk/Cargo.toml.
- Release and publish are handled by the release-plz workflow.
Run the full test suite with all features enabled:
cargo test --workspace --all-targets --all-featuresPreferred day-to-day runner:
cargo nextest run --workspace --all-featuresUse cargo test for the canonical compatibility gate and cargo-nextest for
faster local and CI execution. Local runs use the strict default profile; CI-style
runs use the softer ci profile from .config/nextest.toml.
Quick checks used in CI:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo check --workspace --all-targetsRecommended test stack:
cargo-nextestfor the primary test runner in CI and local fast loops.rstestfor parameterized cases and fixtures in repetitive scenario tests.proptestfor property-based invariants and roundtrip behavior.cargo-llvm-covfor logic coverage summaries.
Backend testing notes:
Client::with_backend(...)and themockfeature exist to support crate-level testing and mock-driven integration tests.TeamTalkBackendis sealed and should be treated as an internal-facing test/runtime abstraction, not as a stable downstream extension point.- Future backend evolution may continue in major releases without preserving external backend implementations.
Run the TeamTalk header coverage audit with:
python scripts/audit_teamtalk_coverage.py --root .
python scripts/audit_teamtalk_coverage.py --root . --format md,txt
python scripts/audit_teamtalk_coverage.py --root . --format md txtThe script generates:
target/teamtalk-coverage-audit.jsontarget/teamtalk-coverage-audit.mdtarget/teamtalk-coverage-audit.txt
Use the report to distinguish:
wrapped_symbols: runtime candidates with a directTT_*hit in the high-level source treedirect_test_hits_for_wrapped_symbols: wrapped runtime candidates with a directTT_*hit in the integration test treefully_covered_symbols: wrapped runtime candidates with directTT_*hits in source, tests, and docs- missing bindings
- missing high-level wrappers
- missing tests
- missing docs
- intentional omissions
The missing_tests count is intentionally strict. It reports missing direct symbol hits in tests, not proof that runtime behavior is broken.
Wrapper policy:
- The scanner treats non-macro, non-platform-specific
TT_*symbols as runtime API candidates. - Macro/constant detection comes from
TeamTalk.hdeclarations, not from a fixed symbol prefix list. - Triage those candidates manually before adding wrappers.
- Add a high-level wrapper when the symbol is a user-facing runtime API with safe semantics and clear downstream value.
- Leave constants/macros, unsupported platform-specific APIs, and specialized low-level utilities as intentional omissions unless a concrete use case appears.
The repository includes a justfile with shortcuts for checks,
docs, and dependency updates.
On Windows, the justfile uses PowerShell as windows-shell, so just does
not require a separate sh installation for normal recipes.
Install tools:
cargo install just cargo-edit cargo-outdated cargo-llvm-cov cargo-nextestDaily profile:
just quick
just quick-nextest
just test-feature async
just test-nextest-feature async
just release-statusWeekly maintenance:
just deps-outdated
just deps-safe-cycle
just runs-failPre-release:
just qa-full
just qa-nextest
just release-dry
just release-watchRelease day (explicit publish):
just release-run
just release-watchCommon commands:
just dod
just ci
just ci-nextest
just test
just test-nextest
just doc
just search tokio
just info release-plzDependency update flows:
# patch/minor only
just deps-refresh-compatible
# include majors
just deps-refresh-majorSafety model for release commands:
release-status,release-watch,pr-*, andruns-*are read/inspect only.release-drytriggers manual release workflow withdry_run=true.release-runtriggers manual release workflow withdry_run=false(publish path).
Execution policy:
- Prefer a
justrecipe first. - If
justis unavailable, use equivalent manual commands. - If a recipe exists but optional tooling is missing (
gh,cargo-outdated,miri), either install tools or skip only that optional step and report it clearly.
Daily flow:
just env-check
just quick
just quick-nextest
just test-feature async
just release-statusWeekly flow:
just deps-outdated
just deps-safe-cycle
just runs-failPre-release flow:
just qa-full
just release-dry
just release-watchRelease-day flow:
just release-status
just release-run
just release-watchCritical fallback commands:
# quick
cargo fmt --all -- --check
cargo check --workspace --all-targets
cargo test --workspace --all-targets
# qa-full / ci
cargo fmt --all -- --check
cargo check --workspace --all-targets --all-features
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-targets --all-features
cargo doc --no-deps --all-features
bash ./scripts/check-doc-links.sh
bash ./scripts/check-version-refs.sh
# deps-refresh-compatible
cargo upgrade --manifest-path crates/teamtalk/Cargo.toml
cargo upgrade --manifest-path crates/teamtalk-sys/Cargo.toml
cargo update
# deps-refresh-major
cargo upgrade --manifest-path crates/teamtalk/Cargo.toml --incompatible allow --pinned allow
cargo upgrade --manifest-path crates/teamtalk-sys/Cargo.toml --incompatible allow --pinned allow
cargo update
# release commands
gh workflow run release-plz.yml -f dry_run=true
gh workflow run release-plz.yml -f dry_run=false
gh run watch $(gh run list --workflow "Release-plz" --limit 1 --json databaseId --jq '.[0].databaseId')Required tooling by command family:
- Cargo-only checks: Rust toolchain only.
deps-outdated*: requirescargo-outdated.miri-test: requires nightly +miricomponent.- Release/GitHub recipes: requires authenticated
ghCLI and repo permissions.
Failure policy:
- Do not silently skip failed steps.
- Report the exact failing recipe and short error summary.
- Optional checks can be skipped with explicit note and reason.
- Required quality/release checks must be fixed before commit/push.
About set positional-arguments in justfile:
- It allows plain positional args in recipes (for example
just test-feature async) instead of requiring named assignments. - It is used by commands like
check-feature,clippy-feature,test-feature,test-one,test-filter,search, andinfo.
Doc link checks used in CI:
scripts/check-doc-links.shCoverage (logic-only; excludes thin FFI wrappers):
scripts/coverage.sh
scripts/coverage.ps1
just coverageThe coverage scripts exclude thin FFI wrapper modules and the teamtalk-sys
crate so the reported percentage reflects logic we can validate without the
SDK or a live server.
Use the mock feature for deterministic event-driven tests without a running
TeamTalk server.
Backend abstractions are intentionally limited to logic-heavy areas that need mocking (recording, scripting, channels). Thin FFI wrappers stay direct to avoid unnecessary indirection. If you add a new mockable logic layer, route it through the backend; if you add a thin wrapper, keep it direct.
The SDK wraps the TeamTalk C API with a polling client and typed structures. The design emphasizes:
- Event-driven flow via
Client::poll(). - Recovery watchdogs are poll-driven as well; there is no background reconnect timer outside the normal event loop.
- Strongly typed IDs (
UserId,ChannelId) to avoid mixing values. - Explicit conversion between Rust structs and TeamTalk FFI types.
Clientis thread-safe (Send+Sync) and uses internal locking.- For concurrent usage, prefer
Client::split()and keep polling on one thread while sending commands from another.
client: main client and per-domain operations (users, channels, audio).client/core/watchdog.rs: stalled connect/login/join supervision for built-in auto recovery.types: strongly typed data structures and conversion helpers.events: event and error types emitted by polling.utils: string and math helpers for working with TeamTalk types.
- Keep user-facing docs focused on usage and configuration.
- Keep developer details in this file.
- Avoid internal implementation details in user guides.
For applications that depend on this SDK, you can use a release profile like:
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true
panic = "abort"Avoid putting these settings into the SDK itself; keep them in your app crate.
For development, the default dev profile is typically fine:
[profile.dev]
opt-level = 0
debug = true