Skip to main content

ECMAScript Modules

Kosko supports ECMAScript modules (ESM). You can write components and environments in native ESM files.

Node.js v12 or above is required for ESM. However, Node.js v14.8.0 or above is recommended because top-level await is supported without flags in this version.


You don't have to modify any config in kosko.toml at all. To start using ESM, you can either set type in package.json as below.

"type": "module"

Or rename file extension as .mjs. See Node.js documentation for more information.


When @kosko/env is imported in ESM, it returns a Promise instead. This is because import() is asynchronous. You MUST add await when retrieving environment variables as below.

import env from "@kosko/env";

const globalParams = await;
const componentParams = await env.component("demo");

Programmatical Usage

You can use @kosko/env and @kosko/generate package directly. The following is a basic example.

import env from "@kosko/env";
import { generate, print, PrintFormat } from "@kosko/generate";
import { fileURLToPath } from "url";
import { join } from "path";

// Set environment
env.env = "dev";

// Set CWD (optional)
env.cwd = fileURLToPath(new URL("./", import.meta.url));

// Generate manifests
const result = await generate({
path: join(env.cwd, "components"),
components: ["*"]

// Print manifests to stdout
print(result, {
format: PrintFormat.YAML,
writer: process.stdout

There's no much difference between CommonJS and ESM when using Kosko programmatically. However, it could be troublesome if you are going to use both CommonJS and ESM at the same time. In Node.js, ESM has its own separate cache, which means there are two isolated instances of Environment in CommonJS and ESM and both must be initialized separately.

It's recommended to use only one module type. If you really need to use both, here's an example of how to initialize them.

function setupEnv(env) {
env.env = "dev";
env.cwd = __dirname;

(async () => {
// CommonJS

// ESM
setupEnv((await import("@kosko/env")).default);


Set compilerOptions.module to esnext to allow TypeScript compile your code into ESM instead of CommonJS.

"compilerOptions": {
"module": "esnext"

Currently Kosko can't set Node.js loader, and require option doesn't work with ESM. So you have to set ts-node/esm loader when running Kosko CLI.

NODE_OPTIONS='--loader=ts-node/esm' kosko generate