From coding-agent
Centralized config and lightweight dependency injection — single config module, validated at startup, factory/constructor injection for wiring, composition root pattern. No heavy DI frameworks unless the app actually needs them.
How this skill is triggered — by the user, by Claude, or both
Slash command
/coding-agent:config-managementThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Two related concerns: where config comes from, and how dependencies are wired. Both follow the same principle — **centralize and inject, don't scatter and import**.
Two related concerns: where config comes from, and how dependencies are wired. Both follow the same principle — centralize and inject, don't scatter and import.
process.env / os.environ / System.getenv is accessed in exactly ONE file — the config module. Everything else receives config via injection.
.env gitignored, .env.example committedconfig.database.url, config.auth.jwtSecretconfig.isProduction not process.env.NODE_ENV === 'production'For framework-specific config patterns, see rules/patterns-by-framework.md.
1. Define interfaces/protocols for dependencies
2. Accept them via constructor/factory parameters
3. Wire everything in ONE place (composition root)
4. For tests, pass fakes directly — no framework needed
5. Config is just another dependency
| Complexity | Pattern | Example |
|---|---|---|
| Simple (< 15 services) | Factory functions + constructor injection | Most apps start here |
| Medium (15-50 services) | Composition root with grouped factory functions | Growing apps |
| Complex (50+ services, multiple entry points) | Lightweight container (awilix, Wire, Dagger) | Large apps, monorepos |
| Framework provides it | Use the framework's DI (FastAPI Depends, Spring, SwiftUI Environment) | When it's idiomatic |
Default: start with factory functions. Add a container only when the composition root becomes painful.
One file/function that wires all dependencies. The ONLY place that knows about concrete implementations.
src/
├── composition-root.ts ← wires everything, knows all concrete classes
├── config.ts ← reads env vars, exports typed config
├── services/
│ ├── user-service.ts ← accepts interfaces, knows nothing about DB/config
│ └── order-service.ts
├── repositories/
│ ├── user-repo.ts ← implements interface, accepts db connection
│ └── order-repo.ts
└── index.ts ← calls composition root, starts server
For language-specific composition root patterns, see rules/dependency-injection.md.
WITHOUT DI:
Service imports DB directly → can't test without real DB
Service imports config directly → can't test with different config
Must mock imports → fragile, tied to file paths
WITH DI:
Service accepts interfaces → pass fakes in tests
No mocking library needed for most tests
Tests are fast, isolated, don't need infrastructure
shared / instance / module-level vars. Makes testing painful.Container.resolve(Thing) inside business logic hides dependencies.@Autowired lateinit var repo hides what a class needs.import { db } from '../db' hardwires the dependency.Wave 1 (foundation) should set up:
.env.example — every var with description and safe defaultProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
npx claudepluginhub devjarus/coding-agent --plugin coding-agent