# Synapse cFS SDK
[](https://github.com/sjbeskur/synapse/actions/workflows/ci.yml)
[](https://github.com/sjbeskur/synapse/releases/latest)
[](https://crates.io/crates/cfs-synapse)
[](https://docs.rs/cfs-synapse)
[](https://sjbeskur.github.io/synapse/coverage/)
[](LICENSE)
Synapse is a small interface definition language and code generator for NASA cFS-friendly data types. A `.syn` file can describe plain ABI-compatible structs, cFS Software Bus commands and telemetry packets, and cFS Table Services payloads; the `synapse` CLI turns those definitions into C headers or Rust `#[repr(C)]` bindings.
## Quick Start
Install `synapse` with the path that best fits your environment.
For C developers and CI jobs without Rust installed, download a prebuilt binary from GitHub Releases:
```bash
curl -L https://github.com/sjbeskur/synapse/releases/latest/download/synapse-linux-x86_64.tar.gz | tar -xz
./synapse --help
```
For Rust users, install the `cfs-synapse` package from crates.io. The installed executable is still named `synapse`:
```bash
cargo install cfs-synapse
synapse --help
```
Generate C and Rust bindings from a `.syn` file:
```bash
synapse --lang c -o generated synapse-integration-tests/syn/geometry_msgs.syn
synapse --lang rust -o generated synapse-integration-tests/syn/geometry_msgs.syn
```
The output file is named after the input file. For example, the commands above write `generated/geometry_msgs.h` and `generated/geometry_msgs.rs`.
## Install
### Prebuilt Binaries
Tagged releases attach a Linux archive:
- `synapse-linux-x86_64.tar.gz`
Download the archive from the latest GitHub Release, extract it, and place the `synapse` executable somewhere on your `PATH`. For other platforms, install from crates.io with Cargo.
### Cargo
```bash
cargo install cfs-synapse
```
The crates.io package is named `cfs-synapse`; the installed command is `synapse`.
### From Source
Use the source workflow when contributing to Synapse itself:
```bash
cargo test -p cfs-synapse-parser -p cfs-synapse-codegen-cfs -p cfs-synapse -p synapse-integration-tests
cargo run -p cfs-synapse -- --lang c -o generated synapse-integration-tests/syn/geometry_msgs.syn
```
If you have `just` installed, the common contributor workflow is:
```bash
just test
just gen-geometry
```
The default test workflow skips the `cfs-sys` crate because it needs a local cFS tree and generated cFS build headers. To include it, bootstrap cFS first:
```bash
just cfs-bootstrap
just test-cfs
```
By default cFS is expected at `/tmp/cFS`. Override it with:
```bash
CFS_ROOT=/path/to/cFS just test-cfs
```
## CLI
```bash
synapse check <file.syn> [more-roots.syn ...]
synapse doc [-o <out-dir>] <file.syn> [more-roots.syn ...]
synapse registry [--format <json|csv>] [-o <file>] <file.syn> [more-roots.syn ...]
```
- `check` validates input roots, their import graphs, and cFS codegen support without writing generated output. Multiple roots are checked together for mission-wide telemetry MID and command MID/CC conflicts.
- `doc` generates static HTML documentation for input roots, their import graphs, packet IDs, command codes, fields, types, and doc comments. Without `-o`, HTML is written to stdout; with `-o`, Synapse writes `index.html`.
- `registry` emits a validated packet registry for input roots as JSON or CSV. Without `-o`, registry output is written to stdout.
- `--lang c` generates a cFS C header (`.h`) that includes `cfe.h`.
- `--lang rust` generates Rust `#[repr(C)]` bindings (`.rs`) that reference `cfs_sys` header types by default.
- Without `-o`, generated code is written to stdout.
- With `-o <out-dir>`, Synapse writes the root file and its transitive imports in dependency order.
- Add `--single-file` with `-o` to write only the requested root file.
## Build Scripts
Rust projects can use Synapse from `build.rs` without requiring the `synapse` executable to be installed on `PATH`.
```toml
[build-dependencies]
cfs-synapse = "0.1"
```
```rust
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("cargo:rerun-if-changed=syn/my_msgs.syn");
let out_dir = std::env::var("OUT_DIR")?;
cfs_synapse::generate_c_file("syn/my_msgs.syn", out_dir)?;
Ok(())
}
```
The library facade also exposes `check_path`, `check_str`, `generate_rust_file`, `generate_file`, `generate_files`, `generate_path`, and `generate_str` for custom build flows. Path-based generation validates the import graph rooted at the input file. Use `generate_files` when a build should emit the root file plus its transitive imports.
## Mental Model
Use `struct` for plain data layout:
```syn
struct Point {
x: f64
y: f64
}
```
Plain structs do not include a cFS message header. They are useful as nested payload types and other reusable C-compatible data.
Use represented `enum`s for small named integer domains:
```syn
enum u8 CameraMode {
Standby = 0
Preview = 1
}
```
Represented enums generate fixed-width C/Rust aliases and named constants. The explicit representation is what makes them safe to use in generated cFS packet and table fields.
Use `command` for Software Bus packets sent to an app:
```syn
@mid(0x1880)
@cc(1)
command SetMode {
mode: CameraMode
}
```
Generated commands place `CFE_MSG_CommandHeader_t` first and emit both `_MID` and `_CC` constants. Commands may share a command MID when their literal command codes differ.
Use `telemetry` for Software Bus packets published by an app:
```syn
@mid(0x0801)
telemetry NavState {
position: geometry_msgs::Point
}
```
Generated telemetry packets place `CFE_MSG_TelemetryHeader_t` first.
Use `table` for cFS Table Services payload data:
```syn
table NavConfig {
max_speed: f64
enabled: bool
frame_id: string[<=32]
}
```
Generated tables do not include a Software Bus header. They are plain table data. The legacy `message` keyword still parses for older files, but cFS codegen rejects it. Use explicit `command` or `telemetry` packets.
## Language Surface
The cFS generator currently emits:
- `namespace` prefixes for generated C type names, such as `geometry_msgs_Point_t`.
- `import` declarations as C `#include` lines or Rust `use crate::...` lines.
- `const` declarations as C `#define`s or Rust `pub const`s.
- Represented enums such as `enum u8 CameraMode` as fixed-width type aliases and constants.
- `struct` and `table` definitions as plain data structs.
- `command` and `telemetry` definitions as Software Bus packet structs with cFS headers.
- Required `@mid(...)` attributes as message ID constants.
- Required command `@cc(...)` attributes as command-code constants.
- Fixed arrays, bounded strings, and namespaced type references.
Enums need an explicit integer representation when used in generated cFS fields, for example `enum u8 CameraMode`. Unrepresented enums, unbounded strings, optional field markers, field defaults, dynamic arrays, and non-string bounded arrays are parsed but rejected by cFS codegen until concrete ABI and initializer semantics exist. Prefer represented enums, fixed arrays, and bounded strings for generated packet payloads.
See `docs/language.md` for the current language status and `0.1.x` review checklist.
See `docs/types.md` for the supported type forms and generated C/Rust mappings.
See `docs/one-pager.md` for a short explanation of why Synapse is relevant.
See `docs/mission.md` for the mission-wide validation and registry concept.
See `docs/registry.md` for the JSON and CSV packet registry schema.
See `docs/roadmap-0.2.md` for the `0.2.x` language, validation, and output status.
## Documentation Comments
Use `///` for comments that should attach to the next declaration or field and feed generated code comments and HTML documentation:
```syn
/// Stable identifier for one physical or logical camera.
struct CameraId {
/// Mission-defined camera name.
name: string[<=32]
}
```
Use `//` comments for ordinary notes that should not become API documentation.
## UDP and Tables
When communicating with cFS through UDP apps such as `CI_LAB` or `TO_LAB`, UDP is only the transport. The bytes entering or leaving the Software Bus are still cFS packets, so generated `command` and `telemetry` types need the cFS header.
Table Services are different: the table data itself is normally a plain struct without a Software Bus header. Commands that load, validate, or activate tables are Software Bus command messages, but the table buffer/file is just table data.
## Examples
Sample `.syn` files live in `synapse-integration-tests/syn`.
- `geometry_msgs.syn`: ROS-like geometry telemetry packets.
- `cfs_patterns.syn`: minimal command, telemetry, and table examples.
- `camera_msgs.syn`: camera control syntax coverage, including a represented camera mode enum, commands to set mode/exposure, a command to send updated intrinsics, telemetry for camera status, and a `CameraCalibration` table containing persistent calibration data. It also exercises doc-comment support.
See `examples/README.md` for runnable canary projects and the mission demo.
See `docs/examples.md` for links to all sample `.syn` files and checked-in generated output.
## Workspace
- `cfs-synapse-parser`: Pest grammar and AST builder for `.syn`
- `cfs-synapse-codegen-cfs`: C and Rust cFS code generation
- `cfs-synapse`: public library facade and `synapse` CLI binary
- `cfs-sys`: bindgen wrapper for selected cFS types
- `synapse-integration-tests`: sample `.syn` files and generated-code checks
- `generated`: checked-in generated geometry examples
## Release Model
CI runs the core test suite on pull requests and pushes to `main`. Pushing a tag like `v0.1.0` runs the release workflow, builds release binaries, and attaches platform archives to the GitHub Release.
Crates.io publishing is gated behind the repository variable `PUBLISH_CRATE=true` and the `CARGO_REGISTRY_TOKEN` secret. When enabled, the release workflow publishes `cfs-synapse-parser`, `cfs-synapse-codegen-cfs`, and then `cfs-synapse`.
See `docs/release-checklist.md` for the step-by-step release checklist.
See `docs/publishing.md` for publishing workflow details and first-publish notes.
## Editor Support
A local VS Code syntax-highlighting extension lives in `vscode-synapse`.
```bash
just vscode-syntax
```
This launches VS Code with the extension development path pointed at the local Synapse grammar.