# How Magnitude Handles Client Imports and Package Dependencies Between Client and Daemon

> Understand how Magnitude manages client imports and package dependencies between client and daemon. Discover its strict layered architecture and RPC-based SDK for secure communication.

- Repository: [Magnitude/magnitude](https://github.com/magnitudedev/magnitude)
- Tags: internals
- Published: 2026-09-06

---

**Magnitude enforces a strict layered architecture where clients (CLI/web) only import from `@magnitudedev/client-common` and `@magnitudedev/sdk`, while all daemon internals remain accessible only via RPC through the SDK.**

This article explains how the Magnitude monorepo isolates client-side code from daemon-side processes using import rules, package boundaries, and a single RPC bridge. Understanding this architecture is essential for contributing to the codebase or extending Magnitude with custom clients.

## Package Layering Architecture

Magnitude's dependency flow follows a unidirectional hierarchy documented in **[AGENTS.md](https://github.com/magnitudedev/magnitude/blob/main/AGENTS.md)**:

```

clients (cli/web) → client-common → sdk → acn (daemon)

```

This design guarantees that **client code cannot accidentally depend on daemon implementation details**. The client remains lightweight, portable, and independently testable.

### Allowed Client Dependencies

Clients may only import from two packages:

- **`@magnitudedev/client-common`** — shared UI state, React hooks, and display synchronization
- **`@magnitudedev/sdk`** — the portable Effect-TS RPC client that communicates with the daemon

### Prohibited Client Dependencies

The following packages are **never imported** directly by client code:

- `acn`
- `agent`
- `acn-protocol`
- `ai`
- `providers`

Attempting to import these triggers linting errors and violates the architectural contract.

## Dependency Flow by Layer

| Layer | Responsibility | Visible To |
|-------|---------------|------------|
| **client-common** | Maintains shared UI state; defines queries/mutations over the SDK | Clients, SDK |
| **sdk** | Implements Effect-TS-native RPC client; handles endpoint admission/recovery; optionally starts services | client-common, Clients |
| **acn** | Hosts agent runtime, session handling, file operations, display streams; implements ACN protocol RPCs | SDK (via RPC only) |
| **acn-protocol** | Pure wire contracts: RPC signatures, schemas; shared by SDK and ACN but **never imported by clients** | SDK, ACN |
| **providers / agent / internals** | Concrete provider implementations, worker projections, tools, storage | Internal daemon only |

The **SDK is the sole bridge** across the client-daemon boundary. All RPCs are declared once in `packages/acn-protocol/src/boundary/` and consumed through the SDK's generated methods.

## Enforcing Import Boundaries

Magnitude employs multiple mechanisms to prevent architectural violations:

### Static Analysis

Linting rules flag prohibited imports during development. Importing from `@magnitudedev/acn` or `@magnitudedev/providers` in client code fails the build.

### Runtime Validation

The SDK verifies RPC version compatibility before establishing daemon connections, preventing mismatched client-daemon deployments.

### Design Documentation

The cross-boundary ownership model is detailed in **[design/cross-boundary/client-acn-icn-ownership.md](https://github.com/magnitudedev/magnitude/blob/main/design/cross-boundary/client-acn-icn-ownership.md)**, explaining why only the SDK should handle cross-process communication.

## Code Examples: Correct and Incorrect Import Patterns

**✅ Correct: Client code using allowed packages**

```typescript
// Client-side code (CLI or web)
import { useDisplayView } from '@magnitudedev/client-common';
import { AgentClient } from '@magnitudedev/sdk';

export const SessionManager = () => {
  const display = useDisplayView();  // From client-common
  const listSessions = async () => {
    const client = await AgentClient.make();  // From sdk
    return client.session.list();
  };
  // ...
};

```

**❌ Incorrect: Client code attempting daemon imports**

```typescript
// These imports would trigger lint errors and architectural violations:
// import { ACNService } from '@magnitudedev/acn';
// import { ProviderRegistry } from '@magnitudedev/providers';
// import { AgentRuntime } from '@magnitudedev/agent';

```

The SDK abstracts all RPC details. The client calls methods; the SDK handles serialization, transport, and error recovery.

## RPC Declaration and Consumption

RPC contracts live in `packages/acn-protocol/src/boundary/` and provide **single source of truth** for remote operations:

```typescript
// packages/acn-protocol/src/boundary/session.ts (conceptual)
export interface SessionBoundary {
  list: Rpc<[], Session[]>;
  create: Rpc<[CreateSessionInput], Session>;
  // ...
}

```

The SDK consumes these contracts to generate typed client methods, while `packages/acn/` implements the handlers.

## Key Files and Their Roles

| Path | Purpose |
|------|---------|
| [`AGENTS.md`](https://github.com/magnitudedev/magnitude/blob/main/AGENTS.md) | High-level package layering and import rules |
| [`design/cross-boundary/client-acn-icn-ownership.md`](https://github.com/magnitudedev/magnitude/blob/main/design/cross-boundary/client-acn-icn-ownership.md) | Ownership model rationale |
| `packages/client-common/src/operations/*` | Client-side query/mutation wrappers around SDK |
| `packages/sdk/src/*` | Effect-TS RPC client implementation |
| `packages/acn-protocol/src/boundary/*` | Wire contracts (RPC signatures, schemas) |
| `packages/acn/*` | Daemon RPC handler implementation |

## Summary

- **Layered architecture** (`clients → client-common → sdk → acn`) enforces unidirectional dependencies
- **Two-package rule**: clients import only from `@magnitudedev/client-common` and `@magnitudedev/sdk`
- **SDK-only bridge**: all client-daemon communication routes through the SDK's RPC layer
- **Static and runtime enforcement**: lint rules and version checks prevent boundary violations
- **Single source of truth**: RPC contracts in `acn-protocol` are shared between SDK and daemon, never directly imported by clients

## Frequently Asked Questions

### What happens if client code imports from `@magnitudedev/acn` directly?

The build fails due to linting rules that prohibit cross-boundary imports. Even if bypassed, runtime errors would occur because the client lacks the daemon's execution context and environment dependencies.

### Why does the SDK use Effect-TS for its RPC implementation?

Effect-TS provides structured concurrency, built-in error handling, and type-safe composition that Magnitude leverages for reliable client-daemon communication, admission control, and automatic recovery from connection failures.

### Can third-party clients interact with the Magnitude daemon?

Yes—any client importing `@magnitudedev/sdk` can communicate with a running daemon, as the SDK encapsulates all protocol details. The daemon's RPC surface in `acn-protocol` serves as the stable public API.

### How does this architecture support testing?

Clients unit-test with mocked SDK calls without daemon dependencies. The SDK itself tests against stubbed ACN protocols. Integration tests exercise the full stack, but each layer remains independently verifiable.