# Crate Map: Dependency Direction & Ownership Rules

> RMUX is a Cargo workspace of 12 crates arranged in strict layers. Foundation layer (no OS/network deps): `rmux-types` (TerminalSize newtype), `rmux-proto` (request/response frame contracts, codec, identity newtypes), `rmux-core` (pure in-memory domain model — sessions, windows, panes, layout, grid, scrollback). OS integration layer: `rmux-os` (host, signals, process, terminal helpers), `rmux-ipc` (socket/pipe endpoint naming and byte transport only — deliberately carries no protocol), `rmux-pty` (PTY allocation and child-process management across Linux/macOS/Windows ConPTY). Runtime layer: `rmux-server` (Tokio async daemon, owns pane I/O and all handlers), `rmux-client` (blocking RPC client, auto-start logic, attach mode). Public surface layer: `rmux-sdk` (async facade, must NOT depend on rmux-client/rmux-core/rmux-server/rmux-pty), `rmux-render-core` (pure-data snapshot projection, wasm32-compatible), `ratatui-rmux` (PaneDriver + PaneState + PaneWidget, depends only on rmux-sdk). Root binary `rmux` links rmux-server and Tokio directly only to host the hidden daemon re-exec path.

- Repository: Helvesec/rmux
- GitHub: https://github.com/Helvesec/rmux
- Human wiki: https://grok-wiki.com/public/wiki/helvesec-rmux-ea7220d1f181
- Complete Markdown: https://grok-wiki.com/public/wiki/helvesec-rmux-ea7220d1f181/llms-full.txt

## Source Files

- `Cargo.toml`
- `crates/rmux-types/src/lib.rs`
- `crates/rmux-proto/src/lib.rs`
- `crates/rmux-sdk/src/lib.rs`
- `crates/rmux-render-core/src/lib.rs`
- `crates/ratatui-rmux/src/lib.rs`

---

<details>
<summary>Relevant source files</summary>
The following files were used as context for generating this wiki page:

- [Cargo.toml](Cargo.toml)
- [crates/rmux-types/Cargo.toml](crates/rmux-types/Cargo.toml)
- [crates/rmux-types/src/lib.rs](crates/rmux-types/src/lib.rs)
- [crates/rmux-proto/Cargo.toml](crates/rmux-proto/Cargo.toml)
- [crates/rmux-proto/src/lib.rs](crates/rmux-proto/src/lib.rs)
- [crates/rmux-core/Cargo.toml](crates/rmux-core/Cargo.toml)
- [crates/rmux-core/src/lib.rs](crates/rmux-core/src/lib.rs)
- [crates/rmux-os/Cargo.toml](crates/rmux-os/Cargo.toml)
- [crates/rmux-ipc/Cargo.toml](crates/rmux-ipc/Cargo.toml)
- [crates/rmux-pty/Cargo.toml](crates/rmux-pty/Cargo.toml)
- [crates/rmux-server/Cargo.toml](crates/rmux-server/Cargo.toml)
- [crates/rmux-client/Cargo.toml](crates/rmux-client/Cargo.toml)
- [crates/rmux-sdk/Cargo.toml](crates/rmux-sdk/Cargo.toml)
- [crates/rmux-sdk/src/lib.rs](crates/rmux-sdk/src/lib.rs)
- [crates/rmux-render-core/Cargo.toml](crates/rmux-render-core/Cargo.toml)
- [crates/rmux-render-core/src/lib.rs](crates/rmux-render-core/src/lib.rs)
- [crates/ratatui-rmux/Cargo.toml](crates/ratatui-rmux/Cargo.toml)
- [crates/ratatui-rmux/src/lib.rs](crates/ratatui-rmux/src/lib.rs)
- [crates/ratatui-rmux/tests/budget.rs](crates/ratatui-rmux/tests/budget.rs)
</details>

# Crate Map: Dependency Direction & Ownership Rules

RMUX is a Cargo workspace of twelve crates arranged in four strict dependency layers. The layers form a directed acyclic graph: every edge points downward, toward more stable, more portable code. No cycle between layers is permitted, and several crates enforce their own budget with a machine-checked test (`crates/ratatui-rmux/tests/budget.rs`) to prevent scope creep.

Understanding the layer structure is essential before touching any crate. Adding a dependency that crosses a layer boundary — for example, giving `rmux-sdk` a reference to `rmux-core` — would collapse the portability and testability guarantees that the whole design rests on. The rules are not informal conventions; they are documented, tested, and encoded in `[dependencies]` tables.

---

## Layer Overview

```text
┌──────────────────────────────────────────────────────────────────────┐
│  PUBLIC SURFACE LAYER                                                │
│  rmux-sdk  ·  rmux-render-core  ·  ratatui-rmux                     │
└──────────────────────┬───────────────────────────────────────────────┘
                       │ depends on ↓
┌──────────────────────▼───────────────────────────────────────────────┐
│  RUNTIME LAYER                                                       │
│  rmux-server  ·  rmux-client                                         │
└──────────────────────┬───────────────────────────────────────────────┘
                       │ depends on ↓
┌──────────────────────▼───────────────────────────────────────────────┐
│  OS INTEGRATION LAYER                                                │
│  rmux-os  ·  rmux-ipc  ·  rmux-pty                                  │
└──────────────────────┬───────────────────────────────────────────────┘
                       │ depends on ↓
┌──────────────────────▼───────────────────────────────────────────────┐
│  FOUNDATION LAYER  (no OS/network/async deps)                        │
│  rmux-types  ·  rmux-proto  ·  rmux-core                            │
└──────────────────────────────────────────────────────────────────────┘

Binary: rmux  ←── links rmux-server + rmux-client + rmux-core + rmux-os + rmux-proto + Tokio
```

---

## Foundation Layer

The foundation layer has no OS, network, process, or async runtime dependencies. It may be compiled as a library, tested in a pure-logic harness, or published independently without carrying platform baggage.

### `rmux-types`

**Owns:** `TerminalSize` — a `(cols: u16, rows: u16)` newtype shared across non-adjacent crates without pulling in heavier shared modules.

**Dependencies:** only `serde` (optional feature gate). No other workspace crate.

```rust
// crates/rmux-types/src/lib.rs:9-14
pub struct TerminalSize {
    pub cols: u16,
    pub rows: u16,
}
```

`rmux-types` is the leaf crate every other crate can depend on without taking on any weight.

Sources: [crates/rmux-types/src/lib.rs:1-23](), [crates/rmux-types/Cargo.toml:12-17]()

---

### `rmux-proto`

**Owns:** the wire protocol. Concretely: request/response DTOs, the frame codec (`encode_frame`/`decode_frame`), handshake capability negotiation, identity newtypes (`PaneId`, `SessionId`, `SessionName`, `WindowId`), attach-stream message types, control-mode formatting helpers, and the canonical error type (`RmuxError`).

**Dependencies:** `rmux-types` (with `serde` feature) + `bincode` + `serde` + `thiserror`. Nothing higher.

The identity newtypes are intentionally anchored here, not in `rmux-core`, so that `rmux-sdk` (which must not depend on `rmux-core`) can still re-export them to SDK users.

```toml
# crates/rmux-proto/Cargo.toml:13-15
[dependencies]
bincode = "1.3.3"
rmux-types = { path = "../rmux-types", version = "0.2.0", features = ["serde"] }
```

Sources: [crates/rmux-proto/Cargo.toml:12-17](), [crates/rmux-proto/src/lib.rs:1-57]()

---

### `rmux-core`

**Owns:** the pure in-memory domain model — sessions, windows, panes, layout geometry, grid/screen state, scrollback buffers, VT parser, key bindings, hook store, option store, format strings, and target resolution. No OS calls, no network, no async.

**Dependencies:** `rmux-proto` + `chrono` (wall-clock for timestamps, no I/O) + `regex` + `unicode-width`.

`rmux-core` uses `PaneId`, `SessionId`, and `WindowId` from `rmux-proto` rather than defining its own — both layers share one identity vocabulary. The rich domain model (sessions, panes, windows, layout) lives here and is consumed by `rmux-server`.

Sources: [crates/rmux-core/Cargo.toml:12-16](), [crates/rmux-core/src/lib.rs:1-99]()

---

## OS Integration Layer

These crates introduce platform syscalls, async I/O, or process management. They are below the runtime layer and above the foundation layer. They must not depend on `rmux-server`, `rmux-client`, or `rmux-sdk`.

### `rmux-os`

**Owns:** host-detection helpers, signal primitives, terminal-size query, and platform path conventions.

**Dependencies:** `rmux-types` + conditional `libc`/`rustix` on Unix + `windows-sys` on Windows. No other workspace crate.

Sources: [crates/rmux-os/Cargo.toml:12-31]()

---

### `rmux-ipc`

**Owns:** local-socket endpoint naming and byte-level transport. Deliberately carries no protocol knowledge — it knows nothing about frames or DTOs. Protocol framing is assembled by callers (`rmux-server`, `rmux-client`, `rmux-sdk`) on top of the raw byte stream `rmux-ipc` provides.

**Dependencies:** `rmux-os` + `tokio` (`io-util`, `net`, `rt`, `sync`, `time`) + `tracing`. The async runtime enters the workspace at this boundary.

```toml
# crates/rmux-ipc/Cargo.toml:12-14
[dependencies]
rmux-os = { path = "../rmux-os", version = "0.2.0" }
tokio = { version = "1.48.0", features = ["io-util", "net", "rt", "sync", "time"] }
```

Sources: [crates/rmux-ipc/Cargo.toml:12-22]()

---

### `rmux-pty`

**Owns:** PTY allocation, resize, and child-process lifecycle across Linux, macOS, and Windows ConPTY.

**Dependencies:** `rmux-types` + `tracing` + conditional `rmux-os`/`libc`/`rustix` on Unix + `windows-sys` on Windows. No Tokio at the production-dependency level (Tokio appears only in `dev-dependencies` for Windows tests).

Sources: [crates/rmux-pty/Cargo.toml:12-33]()

---

## Runtime Layer

The runtime layer assembles foundation + OS integration into the two execution contexts: the async daemon and the blocking CLI client.

### `rmux-server`

**Owns:** the Tokio async daemon. It is the integration point for every foundation and OS crate. It accepts IPC connections, dispatches request frames to handlers, owns pane I/O loops, manages session/window/pane lifecycle through `rmux-core`, and writes PTY data through `rmux-pty`.

**Dependencies:** `rmux-core`, `rmux-ipc`, `rmux-os`, `rmux-proto`, `rmux-pty` + full Tokio feature set + `tracing`. On Unix: `signal-hook`.

```toml
# crates/rmux-server/Cargo.toml:17-22
rmux-core = { path = "../rmux-core", version = "0.2.0" }
rmux-ipc  = { path = "../rmux-ipc",  version = "0.2.0" }
rmux-os   = { path = "../rmux-os",   version = "0.2.0" }
rmux-proto = { path = "../rmux-proto", version = "0.2.0" }
rmux-pty  = { path = "../rmux-pty",  version = "0.2.0" }
```

Sources: [crates/rmux-server/Cargo.toml:12-27]()

---

### `rmux-client`

**Owns:** the blocking RPC client (tmux-style CLI dispatch), auto-start logic (spawn daemon if not running), and attach mode (raw terminal passthrough).

**Dependencies:** `rmux-core`, `rmux-ipc`, `rmux-os`, `rmux-proto` as common deps; `rmux-sdk` + Tokio + `signal-hook`/`libc`/`rustix` on both Unix and Windows platform targets.

Note: `rmux-client` depends on `rmux-sdk` (via platform-conditional deps) because the attach flow uses the SDK's event model. This is the only upward edge in the whole graph, and it is a compile-time guarded inversion limited to the client's attach path — `rmux-sdk` itself does not depend on `rmux-client`.

Sources: [crates/rmux-client/Cargo.toml:12-28]()

---

## Public Surface Layer

These three crates form the stable, published integration boundary. None of them may depend on `rmux-core`, `rmux-server`, or `rmux-pty` (the internal implementation). `rmux-sdk` is the single gateway.

### `rmux-sdk`

**Owns:** the async facade (`Rmux`, `Session`, `Window`, `Pane` handles), session ensure/lease builders, snapshot types (`PaneSnapshot`, `PaneCell`, `PaneColor`), event streams (`PaneOutputStream`, `PaneRenderStream`), wait helpers, locator API, and key input abstraction.

**Must NOT depend on:** `rmux-client`, `rmux-core`, `rmux-server`, `rmux-pty` — enforced by documented policy in the crate's module-level doc comment.

**Dependencies:** `rmux-ipc` + `rmux-os` + `rmux-proto` + `serde`/`serde_json` + Tokio + optional `crossterm`/`regex`. It reaches the daemon through the same IPC transport as the CLI, but speaks frames directly, bypassing `rmux-client`.

```rust
// crates/rmux-sdk/src/lib.rs:12-17
// `rmux-sdk` is a public integration peer of `rmux-client` and must not
// depend on `rmux-client`, `rmux-core`, `rmux-server`, or `rmux-pty` as
// normal dependencies. The authoritative identity newtypes
// ([`SessionName`], [`SessionId`], [`WindowId`], [`PaneId`]) live in
// `rmux-proto` and are re-exported here so SDK users import them through
// `rmux_sdk` without ever depending on those internal crates.
```

Sources: [crates/rmux-sdk/Cargo.toml:12-46](), [crates/rmux-sdk/src/lib.rs:1-136]()

---

### `rmux-render-core`

**Owns:** the pure-data snapshot projection layer — `PaneSnapshot`, `PaneCell`, `PaneColor`, `PaneCursor`, `PaneGlyph`, `PaneState`, and a deterministic ratatui `PaneWidget`. No daemon, IPC, process, filesystem, network, Tokio, or terminal-driver integration.

**Wasm32 compatibility:** the crate is explicitly designed to compile to `wasm32-unknown-unknown`. Its description even lists `wasm` as a category.

**Dependencies:** `ratatui` (aliased as `ratatui-core`, pinned to `=0.29.0`, `default-features = false`) + `serde`. No workspace crate at all.

```rust
// crates/rmux-render-core/src/lib.rs:8-11
// This crate owns no daemon, IPC, process, filesystem, network, Tokio, or
// terminal-driver integration. It contains only captured pane snapshot data and
// deterministic ratatui projection code that can compile for
// `wasm32-unknown-unknown`.
```

Sources: [crates/rmux-render-core/Cargo.toml:12-13](), [crates/rmux-render-core/src/lib.rs:1-25]()

---

### `ratatui-rmux`

**Owns:** three thin building blocks: `PaneDriver` (async I/O and state mutation owner), `PaneState` (sync folded snapshot), and `PaneWidget` (sync ratatui render). All RMUX behavior passes through `rmux-sdk`; this crate never touches `rmux-client`, `rmux-core`, `rmux-server`, or `rmux-pty`.

**Dependency budget enforced by test:** `crates/ratatui-rmux/tests/budget.rs` asserts exactly two direct production dependencies (`rmux-sdk` + one `ratatui*`), a maximum of five source files, a maximum of 1500 non-blank source lines, and the absence of the four forbidden crates. The test will fail a build that violates these rules.

```rust
// crates/ratatui-rmux/tests/budget.rs:11-12
const REQUIRED_DEPS: &[&str] = &["rmux-sdk"];
const FORBIDDEN_DEPS: &[&str] = &["rmux-client", "rmux-core", "rmux-server", "rmux-pty"];
```

The async/sync split inside the crate is also machine-verified: `widget.rs`, `state.rs`, and `theme.rs` must not contain `async fn`, `.await`, `tokio::`, `spawn(`, `subscribe(`, or any socket/time primitive. `driver.rs` is the sole async surface.

Sources: [crates/ratatui-rmux/Cargo.toml:12-17](), [crates/ratatui-rmux/src/lib.rs:1-75](), [crates/ratatui-rmux/tests/budget.rs:1-217]()

---

## Root Binary (`rmux`)

The root crate at the workspace root is the compiled `rmux` binary. Its Cargo.toml carries a comment that explains the unusual linkage:

```toml
# Cargo.toml:58-60
# The root binary owns the hidden internal daemon mode, so it links the server
# and Tokio runtime directly for that top-level re-exec path.
rmux-server = { path = "crates/rmux-server", version = "0.2.0" }
tokio = { version = "1.48.0", features = ["net", "rt", "rt-multi-thread", "time"] }
```

In normal invocations the binary dispatches through `rmux-client`. For the hidden `--internal-daemon` re-exec path, it invokes the server inline to host the daemon process. This is why the binary is not just a thin wrapper around `rmux-client`.

**Direct dependencies of the root binary:** `rmux-client`, `rmux-core`, `rmux-os`, `rmux-proto`, `rmux-server`, `clap`, `libc`, Tokio.

Sources: [Cargo.toml:51-61]()

---

## Verified Dependency Edge Table

| Crate | Layer | Depends on (workspace crates only) |
|---|---|---|
| `rmux-types` | Foundation | *(none)* |
| `rmux-proto` | Foundation | `rmux-types` |
| `rmux-core` | Foundation | `rmux-proto` |
| `rmux-os` | OS Integration | `rmux-types` |
| `rmux-ipc` | OS Integration | `rmux-os` |
| `rmux-pty` | OS Integration | `rmux-types`; `rmux-os` (Unix only) |
| `rmux-server` | Runtime | `rmux-core`, `rmux-ipc`, `rmux-os`, `rmux-proto`, `rmux-pty` |
| `rmux-client` | Runtime | `rmux-core`, `rmux-ipc`, `rmux-os`, `rmux-proto`; `rmux-sdk` (platform dep) |
| `rmux-sdk` | Public Surface | `rmux-ipc`, `rmux-os`, `rmux-proto` |
| `rmux-render-core` | Public Surface | *(no workspace crate)* |
| `ratatui-rmux` | Public Surface | `rmux-sdk` |
| `rmux` (binary) | Binary | `rmux-client`, `rmux-core`, `rmux-os`, `rmux-proto`, `rmux-server` |

---

## Dependency Direction Diagram

```mermaid
flowchart TD
    subgraph Binary
        BIN["rmux (bin)"]
    end

    subgraph Public["Public Surface Layer"]
        SDK["rmux-sdk"]
        RC["rmux-render-core"]
        RAT["ratatui-rmux"]
    end

    subgraph Runtime["Runtime Layer"]
        SRV["rmux-server"]
        CLI["rmux-client"]
    end

    subgraph OS["OS Integration Layer"]
        IPC["rmux-ipc"]
        PTY["rmux-pty"]
        OSL["rmux-os"]
    end

    subgraph Foundation["Foundation Layer"]
        CORE["rmux-core"]
        PROTO["rmux-proto"]
        TYPES["rmux-types"]
    end

    BIN --> SRV
    BIN --> CLI
    BIN --> CORE
    BIN --> OSL
    BIN --> PROTO

    RAT --> SDK
    SDK --> IPC
    SDK --> OSL
    SDK --> PROTO

    RC -.->|no workspace dep| RC

    SRV --> CORE
    SRV --> IPC
    SRV --> OSL
    SRV --> PROTO
    SRV --> PTY

    CLI --> CORE
    CLI --> IPC
    CLI --> OSL
    CLI --> PROTO
    CLI -->|platform dep| SDK

    IPC --> OSL
    PTY --> TYPES
    PTY -->|unix only| OSL
    OSL --> TYPES

    CORE --> PROTO
    PROTO --> TYPES
```

---

## Key Ownership Rules

**Identity newtypes live in `rmux-proto`, not `rmux-core`.** This is a deliberate placement: `rmux-sdk` cannot depend on `rmux-core`, but it needs `PaneId`, `SessionId`, `WindowId`, and `SessionName`. By anchoring them in `rmux-proto`, both layers can share the same identity vocabulary without coupling.

**`rmux-ipc` carries no protocol.** It provides a raw byte transport only. Framing (`encode_frame`, `decode_frame`) is in `rmux-proto`. This separation means protocol changes require no IPC transport changes, and IPC transport changes (e.g., switching from Unix domain sockets to named pipes) require no protocol changes.

**`rmux-sdk` is the only legal entry point for external code.** The `ratatui-rmux` budget test enforces this mechanically: any `rmux-core`, `rmux-server`, `rmux-pty`, or `rmux-client` dependency in `ratatui-rmux/Cargo.toml` causes a test failure. The same prohibition is documented in the `rmux-sdk` module doc.

**`rmux-render-core` is wasm32-safe.** It has no workspace dependencies at all — only `ratatui` and `serde`. It can be compiled for browser targets or embedded environments. Code that only needs to render a captured snapshot should depend on this crate, not on `rmux-sdk`.

**The root binary is the only entity that links both `rmux-server` and `rmux-client`.** This is the only place in the workspace where the daemon re-exec path (`--internal-daemon`) and the normal CLI dispatch path coexist. All other crates see at most one side of that boundary.

Sources: [Cargo.toml:51-61](), [crates/rmux-sdk/src/lib.rs:12-17](), [crates/ratatui-rmux/tests/budget.rs:11-12](), [crates/rmux-render-core/src/lib.rs:8-11]()
