# How to Integrate Cordis with Other Tools: A Complete Guide to Service Wrapping and Plugin Architecture

> Discover how to integrate Cordis with other tools by wrapping services, using the Context, and loading plugins for hot-reload and runtime isolation. Unlock seamless external tool integration.

- Repository: [Cordiverse/cordis](https://github.com/cordiverse/cordis)
- Tags: how-to-guide
- Published: 2026-09-13

---

**Cordis integrates with external tools by wrapping them as injectable services that extend the `Service` base class, registering them on the shared `Context`, and loading dependent plugins through the `Loader` to enable hot-reload and runtime isolation.**

Cordis is a meta-framework designed for composing, isolating, and hot-reloading runtime modules. When you integrate Cordis with other tools, you transform external JavaScript or TypeScript libraries into first-class plugins that benefit from dependency injection and state isolation. This guide explains how to bridge any npm package or local utility into the cordiverse/cordis ecosystem using the core APIs found in [`packages/core/src/context.ts`](https://github.com/cordiverse/cordis/blob/main/packages/core/src/context.ts) and [`packages/core/src/service.ts`](https://github.com/cordiverse/cordis/blob/main/packages/core/src/service.ts).


## Understanding Cordis Core Concepts for Integration

Before bridging external tools, you must understand the three primitives that mediate all integrations: the **Context**, **Service**, and **Loader**.

### The Context Isolation Model

The `Context` class, defined in [`packages/core/src/context.ts`](https://github.com/cordiverse/cordis/blob/main/packages/core/src/context.ts), acts as the central object holding services, configuration, and isolation state. Every plugin receives a unique `Context` instance, ensuring that state conflicts are avoided through the internal isolation map (`ctx[Symbol.isolate]`). When you integrate an external tool, you register it on this context so other plugins can access it via `ctx.<serviceName>`.

### Services as Injectable Wrappers

Services are reusable components that extend the `Service` base class from [`packages/core/src/service.ts`](https://github.com/cordiverse/cordis/blob/main/packages/core/src/service.ts). To integrate an external library, you create a wrapper class that instantiates the tool inside its constructor and exposes typed methods. Registration occurs via `ctx.add('serviceName', new YourService(ctx))`, which inserts the service into the context’s dependency graph.

### Plugin Resolution and Loading

The `Loader`, implemented in [`packages/loader/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/loader/src/index.ts), resolves and instantiates plugins from local files, npm packages, or remote URLs. It builds a dependency tree ensuring each plugin receives its own isolated context while maintaining access to shared services. This is the entry point for loading third-party code that consumes your integrated tools.


## Step-by-Step Integration Workflow

Follow this sequence to safely integrate any external tool into Cordis:

1. **Scaffold the project** using the `create` package ([`packages/create/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/create/src/index.ts)) to establish the standard directory structure.

2. **Expose the target tool as a service** by extending the `Service` class, wrapping the library’s API, and registering it on the context with `ctx.add()`.

3. **Load dependent plugins** via the `loader`, passing file paths or package names. The loader automatically injects the registered services into each plugin’s context.

4. **Augment behavior with `include`** ([`packages/include/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/include/src/index.ts)) if you need to monkey-patch the external tool at runtime without modifying source code.

5. **Enable HMR** ([`packages/hmr/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/hmr/src/index.ts)) to watch the integrated tool’s files and hot-reload changes without restarting the entire application.


## Practical Implementation Examples

These runnable examples demonstrate integrating a Git client, consuming it in a plugin, patching a logger, and enabling hot-reload.

### Wrapping an External Library as a Service

Create a service file that wraps `simple-git` and exposes it through the context:

```typescript
// src/services/git.ts
import { Service } from 'cordis'
import simpleGit, { SimpleGit } from 'simple-git'

export class GitService extends Service {
  public git: SimpleGit

  constructor(ctx: any) {
    super(ctx, 'git')
    this.git = simpleGit()
  }

  async clone(repo: string, dir: string) {
    return this.git.clone(repo, dir)
  }
}

// Register in your main entry
import { Context } from 'cordis'
import { GitService } from './services/git'

export const ctx = new Context()
ctx.add('git', new GitService(ctx))

```

The `Service` constructor receives the context and a service name string (`'git'`), which becomes the property name other plugins use to access the instance.

### Loading a Third-Party Plugin That Consumes the Service

Plugins receive the context and can immediately access registered services:

```typescript
// plugins/auto-deploy.ts
export default (ctx) => {
  ctx.on('commit:pushed', async ({ repo, dir }) => {
    await ctx.git.clone(repo, dir)
    // deployment logic...
  })
}

// Boot script
import { loader } from 'cordis'
await loader(ctx, ['./plugins/auto-deploy.ts'])

```

The `loader` function in [`packages/loader/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/loader/src/index.ts) resolves the file path, creates an isolated context for the plugin, and executes the default export with full access to `ctx.git`.

### Runtime Patching with Include

Use `include` to modify existing services without altering their source files:

```typescript
import { include } from 'cordis'

include(ctx, {
  logger: {
    async warn(...args) {
      // prepend timestamp to all warnings
      this.info('[WARN]', ...args)
    },
  },
})

```

This lightweight patch system, defined in [`packages/include/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/include/src/index.ts), intercepts method calls on the context’s logger service and injects custom behavior at runtime.

### Enabling Hot Module Replacement for Rapid Development

Watch plugin files and hot-reload them while preserving context state:

```typescript
import { hmr } from 'cordis'

hmr(ctx, {
  files: ['./plugins/auto-deploy.ts'],
  debounce: 200,
})

```

The `hmr` function from [`packages/hmr/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/hmr/src/index.ts) monitors the specified glob patterns and swaps module implementations without destroying the context isolation map, ensuring that service state persists across reloads.


## Key Source Files for Integration Developers

When building integrations, reference these specific files in the cordiverse/cordis repository:

- **[`packages/core/src/context.ts`](https://github.com/cordiverse/cordis/blob/main/packages/core/src/context.ts)** – Central context manager handling service registration and event propagation (`ctx.emit`, `ctx.on`).

- **[`packages/core/src/service.ts`](https://github.com/cordiverse/cordis/blob/main/packages/core/src/service.ts)** – Base class constructor signature and lifecycle hooks for injectable services.

- **[`packages/loader/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/loader/src/index.ts)** – Plugin resolution logic and dependency tree construction.

- **[`packages/include/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/include/src/index.ts)** – Runtime augmentation and monkey-patching utilities.

- **[`packages/hmr/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/hmr/src/index.ts)** – File watcher and hot-swap implementation.

- **[`packages/create/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/create/src/index.ts)** – CLI scaffolding entry point for new projects.

- **[`packages/logger-console/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/logger-console/src/index.ts)** – Reference implementation of a service that wraps the Node.js console API.


## Summary

- **Wrap external tools** by extending `Service` from [`packages/core/src/service.ts`](https://github.com/cordiverse/cordis/blob/main/packages/core/src/service.ts) and registering instances via `ctx.add()`.

- **Maintain isolation** by allowing the `Loader` in [`packages/loader/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/loader/src/index.ts) to create separate contexts for each plugin while sharing services through the dependency graph.

- **Patch at runtime** using the `include` system in [`packages/include/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/include/src/index.ts) to modify third-party behavior without forking code.

- **Preserve state during development** by enabling HMR through [`packages/hmr/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/hmr/src/index.ts), which reloads modules without resetting the context’s isolation map.

- **Access integrated tools** within any plugin through the context object (`ctx.<serviceName>`) after registration.


## Frequently Asked Questions

### How do I expose an existing npm package as a Cordis service?

Create a class that extends `Service`, instantiate the npm package’s client in the constructor, and register it using `ctx.add('name', new YourService(ctx))` before loading plugins that depend on it. The service becomes accessible as `ctx.name` throughout the application lifecycle.

### Can I integrate CLI tools that spawn child processes?

Yes. Wrap the child process logic inside a service method. Because each plugin runs in an isolated context via the `Context` isolation map (`ctx[Symbol.isolate]`), spawning processes from within a service does not leak state or event listeners to other plugins.

### What is the difference between the Loader and Include when integrating tools?

The `Loader` in [`packages/loader/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/loader/src/index.ts) resolves and instantiates entire plugins from files or packages, building a fresh isolated context for each. The `Include` system in [`packages/include/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/include/src/index.ts) patches existing service methods at runtime without creating new plugin instances, useful for modifying behavior without reloading modules.

### How does hot module replacement affect integrated third-party libraries?

HMR watches the files you specify and reloads only those modules while preserving the `Context` state. If you wrap a third-party library in a service, updates to your wrapper file trigger a hot-reload, but the service instance remains attached to the context unless you explicitly dispose of it, ensuring continuous availability during development.