Skip to content
Agent Workspaces
Agent

core-modules

This page defines the target organization of `packages/core/src/`. Core is organized by module type so that shared domain APIs and their platform implementations can remain close without collapsing their dependency boundaries.

From plugin
emdash
6.2k33 skills33 agents

Agent definition

core-modules.md

Core Module Architecture

This page defines the target organization of `packages/core/src/`. Core is organized by module type so that shared domain APIs and their platform implementations can remain close without collapsing their dependency boundaries.

This is the active architecture. Runtime and service implementations live in `packages/core`; application hosts own worker entries and build manifests.

Why Core Owns Both APIs And Implementations

The desktop app and workspace-server deploy many of the same capabilities in different hosts. Keeping their contracts in one package and their implementations in another makes a single domain span distant trees, duplicates export and build configuration, and makes coordinated changes harder to review.

Core therefore owns both:

  • portable public APIs used across process and machine boundaries; and
  • platform implementations used by the hosts that serve those APIs.

Separate subpath exports preserve the important platform boundary. Colocation does not mean that browser code may import Node implementations.

Module Types

Every top-level Core module belongs to one of three types:

packages/core/src/
  runtimes/
  services/
  primitives/

Runtimes

A runtime is a host-scoped composition root for a larger product domain.

A runtime typically:

  • implements a public Wire contract;
  • owns domain state, resources, caches, and background work;
  • orchestrates multiple injected services and primitives;
  • is created once per host, workspace, or another explicit host boundary; and
  • exposes lifecycle through a caller-owned `Scope` or an equivalent explicit owner.

Examples include ACP, Git, Files, agent configuration, TUI agents, and workspaces.

Runtimes are peers. **A runtime must never depend on another runtime**, including another runtime's API surface. Shared vocabulary belongs in a primitive. Shared active behavior belongs in a service. Cross-runtime workflows are composed by the application host, not by either runtime.

Node runtime implementations that expose a Wire contract should also provide a `WireComponent` definition from their `node/` surface. The component is the deployment wrapper: it declares typed requirements, validates config at the creation/worker boundary, and creates the existing runtime and controller. It must not auto-locate other services or recursively construct dependencies.

Services

A service is a focused, injectable capability that can be reused by runtimes.

A service may:

  • own a bounded resource or lifecycle;
  • provide a swappable port with Node or browser implementations;
  • expose a Wire contract when it must run out of process; and
  • depend on primitives.

A service must not depend on a runtime or another service. Shared contracts, vocabulary, and portable ports that need to cross service boundaries belong in primitives. Concrete service implementations are composed by a runtime or host.

Examples include filesystem watching, PTY management, host dependency detection, and other cross-domain host capabilities.

Services that need to run in process or out of process use the same `WireComponent` convention as runtimes. The distinction between runtime and service remains architectural ownership, not a different hosting primitive.

Primitives

A primitive is reusable vocabulary or behavior that does not orchestrate a product domain.

A primitive should:

  • have no dependency on a runtime or service;
  • avoid independently managed background work;
  • be deterministic or narrowly effectful;
  • represent values, algorithms, policies, or small infrastructure abstractions; and
  • be reusable by multiple runtimes or services.

Examples include host-aware paths, resource identifiers, concurrency helpers, and pure validation or normalization utilities.

Primitives may depend on other primitives, but those dependencies must remain acyclic.

Shared Foundations

`@emdash/shared` owns package-level foundations that are below Core, Wire, desktop, workspace-server, and tests. Do not move these into Core primitives just because Core uses them:

  • `@emdash/shared/concurrency` owns `Scope`, `Run`, `LifecycleRegistry`, `Mailbox`,

`ResourceCache`, `SharedResource`, `AsyncCache`, bounded buffers, and disposable helpers.

  • `@emdash/shared/scheduling` owns `Clock`, `TimerHandle`, timeout helpers, retry schedules,

and `retry()`.

  • `@emdash/shared/testing` owns `ManualClock`, deferred promises, `waitFor()`, and stub logger

helpers.

  • `@emdash/shared/util` owns stable generic utilities such as `stableStringify()`.

Core primitives should hold Emdash domain vocabulary, portable contracts, and narrowly scoped domain behavior. Shared foundations should hold reusable lifecycle, concurrency, scheduling, testing, result, logging, and utility behavior that has no Core domain ownership.

Choose lifecycle primitives by ownership shape:

  • Use `Scope` for cleanup ordering, cancellation, child ownership, and tracked async work.
  • Use `LifecycleRegistry` for keyed local resources with explicit `start()`, `stop()`,

`register()`, queryable state, typed start/stop results, and state-change observers.

  • The `Machine` command/event/effect primitive is internal to the acp runtime

(`packages/core/src/runtimes/acp/node/machine/primitive/`), not a shared building block; it promotes back to `primitives/` only when a second runtime adopts it.

  • Use `ResourceCache` when resource lifetime is lease-driven through `acquire()` and `release()`,

optionally with an idle TTL. Use `SharedResource` for one unkeyed leased resource and `AsyncCache` for cached async values without finalizers.

  • Use `WireWorkerHost.create(component, ...)` or `spawn(component, ...)` when supervising a

process-hosted Wire component with a stable client, readiness, restart backoff, and process generations. The lower-level worker slot is internal to `@emdash/wire`.

  • Use Wire `LiveJobSource` when work must be visible over the Wire protocol as a cancellab
Read more
@generalaction
Ships withemdash

Emdash is the Open-Source Agentic Development Environment (🧡 YC W26). Run multiple coding agents in parallel. Use any provider.

Stars on GitHub

Momentum

stars in total
6.2k
Star history of generalaction/emdash on GitHub, a chart by star-history.com

Other agents on emdash.

acp-runtime

acp-runtime

Agent

The ACP runtime is the domain service that serves the ACP API contract. It owns the host-scoped dependencies needed to run…

git-runtime

git-runtime

Agent

Git is split into a transport contract and a host-scoped runtime. Renderer, desktop, and workspace-server code share the Wire…

main-process

main-process

Agent

The main process is organized into domain modules under `src/main/core/`. Each domain typically has a `controller.ts` (RPC…

path-system

path-system

Agent

`@emdash/core/primitives/path/api` is the source of truth for portable file identity and lexical path operations. The detailed…

More agents from other plugins.

api-builder

api-builder

Agent

Deprecated placeholder. Do not use; follow root AGENTS.md and package instructions instead.

happier2d2.2k
@happier-dev@happier-devInstall Agent

Questions about core-modules.

Which coding agents can use core-modules?
core-modules installs in Claude Code and Cursor: each loads subagents from .claude/agents, so copy the file there. Flowy's auto-invocation runs in Claude Code only.