Chalk Labs
Need help deploying dependency-injection?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/nitrictech-dependency-injection
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/dependency-injection
Tools it pre-approves 5
From allowed-tools in SKILL.md: the agent may use these without asking you each time.
Read,Edit,Grep,Glob,Bash
What's inside
- Skill name
dependency-injection- Description
- Refactor code to use dependency injection. Extract interfaces for dependencies, move construction to factories, and make components testable by accepting dependencies as parameters.
- License
- MIT
- Allowed tools
- Read,, Edit,, Grep,, Glob,, Bash
- Instructions
- 340 lines in SKILL.md · view on GitHub
Before installing
- Pre-approves any shell command
Files (1)
- SKILL.md
SKILL.md (first lines)
# Dependency Injection
When invoked, review the specified code for tightly coupled dependencies -- classes that directly instantiate their collaborators, call static methods on external services, or hard-code configuration. Refactor to inject dependencies through constructors or method parameters, enabling configurability, testability, and clean separation of concerns.
If the user has not specified a scope (file or directory), ask them which file or directory to focus on before proceeding.
## Core Rules
1. **Pass dependencies in instead of creating them internally.** If a class uses another class, that other class should be passed in (injected), not constructed inside. The class should declare what it needs, and the caller fulfills those needs.
2. **Create interfaces for dependencies that may vary.** Define an interface when:
- The dependency could have multiple implementations (different storage backends, different payment gateways).
- You want to test the caller independently from the dependency.
- The dependency is an external service (file system, network, database, third-party API).
The interface describes *what* the dependency can do, not *how*.
3. **Each implementation gets its own specific configuration.** If `S3Storage` needs an AWS key and `SftpStorage` needs a host and private key, each constructor demands exactly what it needs. No optional parameters that vary by implementation. No "fill out these fields depending on mode" pattern.
4. **Use factories to centralize the decision of which implementation to create.** The factory takes configuration and returns the interface type. This separates "which implementation" from "using the implementation." The consumer of the interface never knows or cares which concrete class it received.
5. **The architecture should be configurable from one location** -- the composition root (main function, startup file, request handler initialization). Changing an implementation should require changes in one place, not scattered throughout the codebase.
6. **Dependencies can be injected at different times:**
- **At startup** -- most common. The application wires everything together once at initialization.
- **Per request** -- when the implementation depends on request-specific context (which user, which tenant, which configuration). Factories or request-scoped containers handle this.
7. **Easy testing is a natural side effect.** Each interface boundary is a point where you can slice the system for testing. Inject fakes or mocks to isolate the component under test. If testing requires hacks (reflection, monkey-patching, setting internal state), the code probably needs better dependency injection.
8. **Do not over-inject.** Not every collaborator needs an interface. Pure utility functions (math, string formatting), language built-ins, and value objects do not need injection. Inject at the boundaries where behavior varies or where external systems are accessed.
## Procedure
1. **Identify tightly coupled dependencies.** Look for:
- `new ConcreteClass()` inside business logic (not in factories or composition roots).
- Static method calls to external services (`SmtpClient.send()`, `S3.upload()`).
- Direct file system, network, or database access inside business logic.
- Configuration values read directly from environment variables or config files deep in the code.
2. **For each dependency, determine if an interface is warranted.** Ask:
- Is this an external service? → Yes, inject it.
- Could there be multiple implementations? → Yes, create an interface.
- Do I want to test the caller without this dependency? → Yes, create an interface.
- Is this a pure utility with no side effects? → Probably no interface needed.
3. **Extract the interface.** It should contain only the methods the caller actually uses (Interface Segregation Principle). If the caller only calls `upload()`, the interface should only declare `upload()` even if the concrete class has 20 other methods.
4. **Modify the class to accept the interface** through its constructor (for startup-time dependencies) or as a method parameter (for request-time dependencies).
5. **Create a factory** if there are multiple implementations. The factory takes configuration and returns the correct implementation.
6. **Move all construction/wiring to the composition root.** Main, startup, or request initialization should be the only place that knows about concrete implementations.
7. **Verify testability.** Each class should be instantiable in a test with fake/mock dependencies, without needing the real external services.
## Adapt to the User's Language
In dynamically typed languages (Python, JavaScript), interfaces can be implicit (duck typing) or explicit (Python `Protocol`, TypeScript `interface`). In statically typed languages (Java, C#, Go), use the language's interface or trait mechanism. In functional languages, inject dependencies as function parameters or use higher-order functions.
---
## Examples
### Example A: Basic Dependency Extraction
A report generator that directly creates its collaborators:
**Before:**
```python
class ReportGenerator:
def generate(self, data: dict) -> None:
# Directly creates a PDF renderer -- can't swap to HTML or test without rendering
renderer = PdfRenderer(font_size=12, margin=20)
content = renderer.render(data)
# Directly creates SMTP client -- can't test without sending real emails
email_client = SmtpClient("smtp.company.com", 587, "reports@company.com")
email_client.send(
to=data["recipient"],
subject=f"Report for {data['period']}",
attachment=content,
)
# Directly accesses the database -- can't test without a live DB
db = DatabaseConnection("postgres://prod-server/reports")
db.execute(
"INSERT INTO report_log (period, recipient, generated_at) VALUES (?, ?, ?)",
data["period"], data["recipient"], datetime.now(),
)
```
This class is impossible to test without rendering a real PDF, sending a real email, and connecting to a real database. Changing the email provider or storage format requires editing this class.
**After:**
```python
from typing import Protocol
class Renderer(Protocol):
def render(self, data: dict) -> bytes: ...
class EmailService(Protocol):
def send(self, to: str, subject: str, attachment: bytes) -> None: ...
class ReportLog(Protocol):
def record(self, period: str, recipient: str, generated_at: datetime) -> None: ...
class ReportGenerator:
def __init__(self, renderer: Renderer, email: EmailService, log: ReportLog):
self.renderer = renderer
self.email = email
self.log = log
def generate(self, data: dict) -> None:
content = self.renderer.render(data)From nitrictech/skills, MIT.
More from nitrictech/skills
- 0.494score
flatten
nitrictech
Find and fix deeply nested code using extraction (pull logic into functions) and inversion (guard clauses, early returns).
SkillCFreshness: C★ 1Claude Code +9 - 0.494score
self-document
nitrictech
Improve readability by fixing names and eliminating unnecessary comments.
SkillCFreshness: C★ 1Claude Code +9 - 0.492score
implement
nitrictech
Implement a code change, typically a PR, as specified by the user.
SkillCFreshness: C★ 1Claude Code +9 - 0.492score
review-security
nitrictech
Audit an entire source tree for security vulnerabilities, validating findings against framework and library documentation to avoid false positives.
SkillCFreshness: C★ 1Claude Code - 0.492score
senior-review
nitrictech
Review a code changes, PR, etc.
SkillCFreshness: C★ 1Claude Code +9 - 0.429score
simplify-abstractions
nitrictech
Evaluate abstractions and inheritance for over-coupling.
SkillDFreshness: D★ 1Claude Code +9 - 0.429score
functional-patterns
nitrictech
Refactor imperative loops into functional data pipelines using map, filter, reduce, sort, and slice.
SkillDFreshness: D★ 1Claude Code +9
Signals
- Stars
- 1
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Apr 13, 2026 (6 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/nitrictech/skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from nitrictech
- 0.494score
flatten
nitrictech
Find and fix deeply nested code using extraction (pull logic into functions) and inversion (guard clauses, early returns).
SkillCFreshness: C★ 1Claude Code +9 - 0.494score
self-document
nitrictech
Improve readability by fixing names and eliminating unnecessary comments.
SkillCFreshness: C★ 1Claude Code +9 - 0.492score
implement
nitrictech
Implement a code change, typically a PR, as specified by the user.
SkillCFreshness: C★ 1Claude Code +9 - 0.492score
review-security
nitrictech
Audit an entire source tree for security vulnerabilities, validating findings against framework and library documentation to avoid false positives.
SkillCFreshness: C★ 1Claude Code - 0.492score
senior-review
nitrictech
Review a code changes, PR, etc.
SkillCFreshness: C★ 1Claude Code +9 - 0.429score
simplify-abstractions
nitrictech
Evaluate abstractions and inheritance for over-coupling.
SkillDFreshness: D★ 1Claude Code +9
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get dependency-injection running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
dependency-injection skill. Agent Mart. https://agentmart.dev/skills/nitrictech-dependency-injection (last updated 2026-10-24)