How Dependencies Are Managed Across Magnitude's Package Layers
Magnitude enforces strict vertical dependency management through workspace-level packages that form a four-layer stack, where each layer only imports from layers directly below it using workspace:* references in package.json files.
Magnitude is organized as a monorepo of workspace-level packages that maintain a strict vertical hierarchy. This architecture prevents circular imports and minimizes the public API surface by ensuring that higher-level layers like the CLI and web clients never depend on implementation details from lower-level daemon or protocol layers.
The Four-Layer Architecture
Magnitude's dependency management relies on a strict vertical stack of four distinct layers. Each layer only depends on the layers directly below it, preventing circular imports and keeping the public API surface minimal.
| Layer | Purpose | Allowed imports (dependencies) |
|---|---|---|
| clients (CLI / web) | UI entry points | @magnitudedev/client-common, @magnitudedev/sdk only |
| client-common | Shared UI state, hooks, display sync | Depends on @magnitudedev/sdk and utility libs |
| sdk | Typed RPC client, daemon lifecycle, provider helpers | Depends on low-level protocol & core libraries (acn-protocol, ai, providers, …) |
| acn (daemon) | Server-side agent runtime, file ops, display streams | Depends on acn-protocol, agent, storage, roles, … |
The layering rules are documented in the project's central guide in AGENTS.md (lines 6-16). According to this documentation, higher layers cannot reach into lower-level implementation details, ensuring clear separation of concerns across the codebase.
Workspace References and Layer Enforcement
Each package in the monorepo uses workspace references ("workspace:*") to declare dependencies on other internal packages. This approach allows package managers like Bun, PNPM, or Yarn to resolve them to the exact local version, guaranteeing that the layer hierarchy stays consistent across the whole codebase.
In packages/sdk/package.json (lines 29-40), the SDK declares its runtime dependencies on the core Effect ecosystem and lower-level packages it needs to expose RPC types:
@magnitudedev/acn-protocol@magnitudedev/ai@magnitudedev/providers
Similarly, packages/client-common/package.json (lines 25-33) reflects its constrained import scope, only listing @magnitudedev/sdk and UI-related libraries. The protocol layer at packages/acn-protocol/package.json (lines 21-28) sits just below the SDK, bringing in Effect platform and @magnitudedev/icn-protocol without any dependencies on sdk or client-common.
The daemon layer at packages/acn/package.json (lines 14-30) depends on acn-protocol plus domain-specific packages like agent, storage, and roles, but strictly excludes any dependencies on the SDK or client layers above it.
Adding Dependencies Across Package Layers
When extending Magnitude's functionality, developers must follow the dependency management workflow to maintain architectural integrity:
- Create a new shared library under
packages/(e.g.,utils). - Export it in its
package.jsonwith proper entry points. - Reference it from any higher layer by adding a
"workspace:*"entry to that layer'spackage.json. - Run the workspace installer (
bun installorpnpm install) to rewrite the import graph.
Because each layer only lists lower-layer packages in its dependencies, the package manager enforces the architecture automatically. Attempting to import from a higher layer will result in a resolution error.
Practical Implementation Examples
Creating a New Utility Package
To add a new utility to the SDK layer, first initialize the package:
mkdir -p packages/my-utils && cd packages/my-utils
pnpm init -y
Configure the package.json with workspace-compatible exports:
{
"name": "@magnitudedev/my-utils",
"version": "0.0.1",
"private": true,
"type": "module",
"main": "src/index.ts",
"exports": { ".": "./src/index.ts" },
"scripts": { "typecheck": "tsc --noEmit" },
"dependencies": {
"effect": "^3.21.2"
}
}
Then add the workspace reference to the SDK layer:
cd ../sdk
pnpm add @magnitudedev/my-utils@workspace:*
The resulting entry in packages/sdk/package.json shows:
{
"dependencies": {
"@magnitudedev/my-utils": "workspace:*"
}
}
Now the SDK can import utilities while client-common and clients layers remain unchanged until explicitly updated.
Consuming Lower-Layer Services in the Daemon
The acn daemon demonstrates strict adherence to layer ordering by only importing from lower-level packages:
// packages/acn/src/main.ts
import { Agent } from "@magnitudedev/agent"
import { Storage } from "@magnitudedev/storage"
import { AcnRpc } from "@magnitudedev/acn-protocol"
export const runDaemon = Effect.gen(function* (_) {
const storage = yield* _(Storage)
const rpc = yield* _(AcnRpc)
const agent = new Agent({ storage, rpc })
return agent.start()
})
All imports follow the hierarchy: acn → acn-protocol → agent/storage, never the reverse direction.
Key Source Files and Configuration
| File | Role | Location |
|---|---|---|
AGENTS.md |
Defines the high-level layering policy (lines 6-16) | AGENTS.md |
packages/sdk/package.json |
Shows SDK dependencies on lower layers (lines 29-40) | packages/sdk/package.json |
packages/client-common/package.json |
Demonstrates client-common's limited imports (lines 25-33) | packages/client-common/package.json |
packages/acn-protocol/package.json |
Illustrates the protocol layer's low-level deps (lines 21-28) | packages/acn-protocol/package.json |
packages/acn/package.json |
Shows daemon layer's dependencies (lines 14-30) | packages/acn/package.json |
These configuration files together reveal the strict, top-down dependency model that keeps Magnitude modular, testable, and easy to evolve.
Summary
- Strict vertical stack: Magnitude uses four distinct layers (clients, client-common, sdk, acn) where each layer only depends on layers directly below it.
- Workspace references: All internal dependencies use
"workspace:*"syntax to ensure deterministic builds and eliminate version drift. - Architectural enforcement: The
package.jsonconfigurations in each layer physically prevent imports from higher layers, eliminating circular dependencies. - Clear upgrade paths: When lower-level packages change their public API, only the immediately-above layer requires updates, preserving stability for all other layers.
- Documented constraints: The
AGENTS.mdfile explicitly defines the layering rules that govern how dependencies are managed across Magnitude's package layers.
Frequently Asked Questions
How does Magnitude prevent circular dependencies between packages?
Magnitude prevents circular dependencies through its strict vertical layer architecture enforced by workspace package.json configurations. Each layer explicitly lists only lower-layer packages in its dependencies, and the package manager resolves workspace:* references locally. If a developer attempts to import from a higher layer (e.g., acn importing from sdk), the module resolution fails immediately because the higher-layer package is not listed in the lower layer's dependencies.
What package managers support Magnitude's workspace dependency management?
Magnitude supports Bun, PNPM, and Yarn for workspace dependency resolution. All three package managers correctly interpret the "workspace:*" protocol used throughout the monorepo, rewriting these imports to point to the exact local package versions during installation. This ensures consistent builds regardless of which tool a developer chooses.
How do I add a new shared utility that multiple layers can use?
Create a new package under packages/ (e.g., packages/shared-utils), configure its package.json with the name @magnitudedev/shared-utils, and add it to the lowest layer that needs it. If only the SDK and above require it, add "@magnitudedev/shared-utils": "workspace:*" to packages/sdk/package.json. The utility will then be available to the SDK layer and can propagate upward to client-common and clients, but it will remain inaccessible to lower layers like acn-protocol or acn unless explicitly added to their dependencies.
Why can't the client layer import directly from acn-protocol?
The clients layer (CLI and web interfaces) is restricted to importing only from @magnitudedev/client-common and @magnitudedev/sdk to maintain architectural boundaries. This restriction prevents UI entry points from becoming coupled to low-level protocol implementation details or daemon-specific logic. By forcing all communication through the SDK layer, Magnitude ensures that protocol changes only require updates in the SDK and below, leaving the client interfaces stable and reducing the public API surface area.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →