skills/injeca/SKILL.md
Guide for using injeca — a pure functional dependency injection library with application lifecycle management, inspired by go.uber.org/dig and go.uber.org/fig. Use this skill whenever the user imports from 'injeca', mentions injeca, needs dependency injection in TypeScript/JavaScript without classes, wants to wire up services with lifecycle hooks (start/stop), needs to manage application startup/shutdown order, or discusses functional DI patterns. Also use when the user asks about alternatives to tsyringe, inversify, or awilix that avoid class-based decorators.
npx skillsauth add moeru-ai/injeca injecaInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Pure functional dependency injection with application lifecycle management.
build runs once, the result is cachedonStart / onStop for ordered startup and graceful shutdownThe simplest way — injeca is a pre-created global container:
import { injeca, lifecycle } from 'injeca'
// Register a provider (returns a typed key for dependency declaration)
const config = injeca.provide('config', () => ({ port: 3000 }))
// Provider with dependencies and lifecycle
const server = injeca.provide({
dependsOn: { config, lifecycle },
async build({ dependsOn }) {
const { config, lifecycle } = dependsOn
const app = createServer()
lifecycle.appHooks.onStart(() => app.listen(config.port))
lifecycle.appHooks.onStop(() => app.close())
return app
},
})
// Invoke — runs after all providers are resolved
injeca.invoke({
dependsOn: { server },
async callback({ server }) {
console.log('Server ready:', server.address())
},
})
// Start the application (resolves deps → runs onStart hooks → runs invocations)
await injeca.start()
// Graceful shutdown (runs onStop hooks in reverse topological order)
process.once('SIGINT', () => injeca.stop())
import { createContainer, invoke, lifecycle, provide, start, stop } from 'injeca'
const container = createContainer()
const token = provide(container, 'token', () => crypto.randomUUID())
invoke(container, {
dependsOn: { token },
callback: ({ token }) => console.log('token', token),
})
await start(container)
await stop(container)
const config = injeca.provide('config', () => ({ port: 3000 }))
// or with scoped container:
const config = provide(container, 'config', () => ({ port: 3000 }))
const db = injeca.provide({
dependsOn: { config },
build: ({ dependsOn }) => createDatabase(dependsOn.config.connectionString),
})
const server = injeca.provide({
dependsOn: { config, lifecycle },
async build({ dependsOn }) {
const { config, lifecycle } = dependsOn
const app = createServer()
lifecycle.appHooks.onStart(() => app.listen(config.port))
lifecycle.appHooks.onStop(() => app.close())
return app
},
})
If build returns a function, that function itself is cached (not its return value). Useful for factory patterns:
const createWindow = injeca.provide('createWindow', {
dependsOn: { config },
build: ({ dependsOn }) => {
const getWindow = setupReusableWindow(dependsOn.config)
return async () => await getWindow() // callable many times, same window
},
})
Import lifecycle from injeca to declare start/stop hooks inside providers:
import { lifecycle } from 'injeca'
const service = injeca.provide({
dependsOn: { lifecycle },
build({ dependsOn }) {
dependsOn.lifecycle.appHooks.onStart(() => { /* runs on start */ })
dependsOn.lifecycle.appHooks.onStop(() => { /* runs on stop */ })
return myService
},
})
onStart hooks run in topological order (dependencies first)onStop hooks run in reverse topological order (dependents first)import { resolve } from 'injeca'
const resolved = await resolve(container, { config, db })
// resolved.config and resolved.db are ready to use
import { createContainer } from 'injeca'
// Disable logging
const container = createContainer({ enabled: false })
// Custom logger
import { createLoggLogger } from 'injeca'
const container = createContainer({ logger: createLoggLogger() })
build only runs once — the return value is cached. If you return a function, the function is cached, not its result.dependsOn with typed keys from provide() for full type safety.lifecycle from injeca and declare it in dependsOn to get onStart/onStop hooks.start(container) or injeca.start() after all providers and invocations are registered.any: Provider types are fully inferred from build return type and dependsOn declarations.For the latest API reference, use context7 to query injeca documentation.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.