Singleton Runtime
Singleton Runtime
Use the default server/runtime singleton when your process is started through cnos run, or when you want the zero-config default entrypoint.
import cnos from '@kitsy/cnos';
await cnos.ready();
cnos('value.app.name');cnos.value('app.name');cnos.secret('app.token');Available methods
The runtime currently exposes:
cnos(key)as shorthand forcnos.read(key)cnos.read(key)cnos.require(key)cnos.readOr(key, fallback)cnos.value(path)cnos.secret(path)cnos.meta(path)cnos.inspect(key)cnos.toNamespace(namespace)cnos.toEnv()cnos.toPublicEnv()cnos.toServerProjection()cnos.format(message)cnos.log(message)cnos.loadProjection(path)cnos.registerRuntimeProvider(namespace, provider)cnos.registerSecretVaultProvider(factory)cnos.registerSecretVaultProviders(factories)cnos.refreshSecrets()cnos.refreshSecret(key)
Example:
import cnos from '@kitsy/cnos';
await cnos.ready();
const appName = cnos.value('app.name');const dbPassword = cnos.secret('db.password');const profile = cnos.meta('profile');const port = cnos.readOr('value.server.port', 3000);const flags = cnos.toNamespace('flags');const line = cnos.format('Starting server at ${value.server.port}');
cnos.log('Starting server at ${value.server.port}');cnos.format(...) and cnos.log(...) interpolate ${logical.key} placeholders through the active runtime. Missing keys are left unchanged.
For server packaging, the runtime can also bootstrap from a projection artifact:
import cnos from '@kitsy/cnos';
await cnos.loadProjection('./.cnos-server.json');await cnos.ready();Bootstrap sources are checked in order:
__CNOS_GRAPH____CNOS_PROJECTION__CNOS_SERVER_PROJECTION_PATH- auto-discovery of
.cnos-server.jsonfromprocess.cwd()and bounded ancestor.cnosrc.yml
For production servers, set CNOS_REQUIRE_SERVER_PROJECTION=1 to avoid falling back into full authoring-time resolution when no projection can be loaded.
Derived Values
Derived values resolve transparently through the same read APIs.
app: origin: $derive: "${value.app.protocol}://${value.app.host}:${value.app.port}"const origin = cnos.value('app.origin');Config-only derivations are cached for the active runtime. Runtime-dependent derivations stay live:
server: effective_port: $derive: expr: "coalesce(process.env.PORT, value.server.default_port, '3000')"const port = cnos.value('server.effective_port');Runtime Providers
Declare custom runtime namespaces in the manifest, then register a provider at runtime.
cnos.registerRuntimeProvider('request', (key) => { if (key === 'headers.host') { return currentRequest?.headers.host; }
return undefined;});That lets server-side derived values depend on live request, session, or app-framework context without adding a second config layer.
Secret Vault Providers
Vault selection is declared in .cnos/cnos.yml; runtime code only declares which provider implementations were compiled into the bundle.
import cnos from '@kitsy/cnos';import { createGcpSecretManagerVaultProvider } from '@kitsy/cnos-vault-gcp';
cnos.registerSecretVaultProvider(createGcpSecretManagerVaultProvider());await cnos.ready();Provider packages and batteries-included wrappers should register capabilities before ready(). CNOS does not dynamically load provider packages from manifest config.
Typed values
CNOS values are not limited to strings. If the underlying config stores numbers, booleans, arrays, or objects, runtime reads return those values as-is.
const enabled = cnos.value<boolean>('flags.upi_enabled');const params = cnos.read<string[]>('value.api.default_query_params');What does not exist
The current v1 runtime does not expose helper methods such as:
readAsString()readAsNumber()readAsBoolean()
Use read<T>(), require<T>(), or the namespace helpers instead.