Skip to content
Development
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
5.7k32 skills32 agents

How it fires

How this agent gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.

Context preview

The summary Claude sees to decide when to auto-load this agent.

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.

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
Ships withemdash

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

Get the whole plugin
Stats
5,742
Stars
588
Forks
Active
Maintenance
TypeScript
Language
Apache-2.0
License
56m ago
Last commit
1y ago
Created

Repo: generalaction/emdash

Other agents on emdash.