How to Use the Cordis API: A Complete Guide to Context and Services

To use the Cordis API, instantiate a Context via the create() function, initialize it with await ctx.start(), and access built-in or custom services directly as properties on the context object.

The Cordis API provides a modular architecture centered around dependency injection and service-oriented design. In the cordiverse/cordis repository, all functionality flows through a central Context object that maintains a registry of Service classes. Understanding this relationship is essential for leveraging the full capabilities of the Cordis framework.

Core Architecture of the Cordis API

The Cordis API is built on three foundational components that manage application state and service lifecycle.

The Context Object

At the heart of the system lies the Context class defined in packages/core/src/context.ts. This object serves as an execution sandbox and service registry, storing all available services and providing the attachment points for plugins. Every Cordis application begins with a single root context that propagates to all child services and plugins.

Service Base Classes

Services in Cordis extend the base Service class located in packages/core/src/service.ts. When a service is registered, it becomes accessible as a property on the context using its designated name. For example, the HTTP service attaches as ctx.http, the timer service as ctx.timer, and the logger as ctx.logger. This convention ensures consistent access patterns across the entire API surface.

Application Creation

The entry point for any Cordis application is the create() function exported from packages/create/src/index.ts. This factory function constructs a new Context instance, registers all core services (logging, loader, HMR, timer), and returns an application object ready for startup. For CLI-based workflows, packages/create/src/bin.ts provides a command-line wrapper around this same initialization logic.

Implementing the Cordis API in Three Steps

Accessing and utilizing the Cordis API follows a deterministic pattern: create, start, and invoke.

Step 1: Instantiate the Application

Import the create function from @cordis/create and invoke it with optional configuration parameters. This returns a Context instance that represents your application.

import { create } from '@cordis/create'

const app = create({
  // Optional configuration passed to core services
})

const ctx = app // The app itself is the Context

Step 2: Initialize Services

Before accessing any APIs, you must start the context. The await ctx.start() method (also available as app.start()) initializes all registered services and loads configured plugins. This step is mandatory as it triggers the dependency injection container and sets up the service registry.

await app.start()

Step 3: Access Service Methods

Once started, every service becomes available as a property on the context object. Invoke methods directly using the ctx.<serviceName>.<method>() pattern.

// HTTP client request
const response = await ctx.http.get('https://api.example.com/data')

// Schedule delayed execution
ctx.timer.setTimeout(() => console.log('Task complete'), 2000)

// Structured logging
ctx.logger.info('Application initialized successfully')

Working with Built-in Services

The Cordis API ships with several core services that provide essential infrastructure functionality.

HTTP Client Service

The ctx.http service handles outbound network requests. It supports standard HTTP methods and integrates with the context lifecycle for automatic cleanup.

const data = await ctx.http.get('https://api.example.com/users')

Timer and Scheduling

The ctx.timer service provides setTimeout and setInterval implementations that are scoped to the context lifecycle. When the context stops, pending timers automatically clean up to prevent memory leaks.

ctx.timer.setInterval(() => {
  ctx.logger.debug('Periodic health check')
}, 5000)

Structured Logging

Access the logger via ctx.logger to emit categorized log messages. The logging service supports multiple levels (debug, info, warn, error) and integrates with the loader system for plugin-specific log scoping.

ctx.logger.info('Server listening on port 3000')

Extending the Cordis API with Custom Plugins

You can extend the Cordis API by creating custom plugins that inject new methods into the context. The definePlugin utility from @cordis/create provides type-safe plugin registration.

import { definePlugin } from '@cordis/create'

const helloPlugin = definePlugin('hello', ctx => ({
  greet(name: string) {
    ctx.logger.info(`Greeting generated for ${name}`)
    return `Hello, ${name}!`
  },
}))

// Register the plugin
app.plugin(helloPlugin)

// Use the new API
console.log(ctx.greet('World')) // Output: Hello, World!

The packages/loader/src/index.ts module handles the dynamic injection of these plugin-provided symbols. Once loaded, new methods appear on the context automatically without requiring additional imports in consuming code.

Summary

  • Create a Cordis application using the create() function from packages/create/src/index.ts to obtain a root Context instance.
  • Start the application with await ctx.start() to initialize the service registry and load plugins, as defined in packages/core/src/context.ts.
  • Access all functionality through the context object, where services like ctx.http, ctx.timer, and ctx.logger become available as properties.
  • Extend the API by creating custom plugins with definePlugin() that inject new methods directly onto the context.
  • Understand that packages/core/src/service.ts defines how all services attach to the context, while packages/loader/src/index.ts manages runtime plugin loading and hot-module replacement.

Frequently Asked Questions

How do I create a Cordis application instance?

Import the create function from @cordis/create and call it to instantiate a new Context. This function, located in packages/create/src/index.ts, constructs the execution sandbox and registers all core services including logging, loading, and HMR capabilities.

What is the difference between a Context and a Service in Cordis?

The Context (defined in packages/core/src/context.ts) is the central registry and execution environment, while Service classes (from packages/core/src/service.ts) are the functional units attached to that context. Services are accessible as properties on the context instance, such as ctx.http or ctx.logger, following the naming convention defined in their service implementation.

Do I need to call start() before using Cordis services?

Yes, you must await ctx.start() before accessing any service methods. This invocation triggers the initialization sequence in packages/loader/src/index.ts, which loads plugins, resolves dependencies, and activates all registered services. Attempting to use services before starting the context will result in undefined behavior or missing methods.

How can I add custom functionality to the Cordis API?

Use the definePlugin() utility to create a plugin that returns an object with your custom methods. When registered via app.plugin(), the loader injects these methods onto the context object, making them available as ctx.yourMethodName(). This mechanism allows seamless extension of the Cordis API without modifying core source files.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →