# apiari-common
Minimal shared library for the [Apiari](https://github.com/ApiariTools) toolchain. Used by `swarm` (TUI agent multiplexer) and `hive` (orchestration daemon) to share IPC and state persistence primitives.
## Modules
### `ipc` — JSONL read/write with cursor-based polling
Generic reader and writer for line-delimited JSON files.
- **`JsonlReader<T>`** — Tracks a byte offset so each call to `poll()` returns only newly appended records. Supports `skip_to_end()` and `with_offset()` for resuming from persisted cursors. Malformed lines are silently skipped.
- **`JsonlWriter<T>`** — Appends serialized records as JSON lines. Creates parent directories and the file automatically.
```rust
use apiari_common::ipc::{JsonlWriter, JsonlReader};
let writer = JsonlWriter::<MyMessage>::new(".swarm/inbox.jsonl");
writer.append(&msg)?;
let mut reader = JsonlReader::<MyMessage>::new(".swarm/inbox.jsonl");
let new_messages = reader.poll()?;
```
### `state` — Atomic JSON state persistence
Two functions for loading and saving arbitrary state to JSON files:
- **`load_state<T>(path)`** — Reads and deserializes a JSON file. Returns `T::default()` if the file doesn't exist.
- **`save_state<T>(path, state)`** — Writes atomically (write to `.tmp`, then rename) so a crash mid-write never corrupts the on-disk file. Creates parent directories automatically.
```rust
use apiari_common::state::{load_state, save_state};
let state: MyState = load_state(path)?; // returns Default if missing
save_state(path, &state)?; // atomic write
```
## Dependencies
Intentionally minimal — only `serde` and `serde_json`. This keeps compile times low and avoids pulling transitive dependencies into downstream crates.
## Usage
```toml
[dependencies]
apiari-common.workspace = true
```
## License
MIT