@lousy-agents/cli 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/api/copilot-with-fastify/biome.json +1 -1
  2. package/cli/copilot-with-citty/.devcontainer/devcontainer.json +76 -0
  3. package/cli/copilot-with-citty/.editorconfig +16 -0
  4. package/cli/copilot-with-citty/.github/ISSUE_TEMPLATE/feature-to-spec.yml +54 -0
  5. package/cli/copilot-with-citty/.github/copilot-instructions.md +228 -0
  6. package/cli/copilot-with-citty/.github/instructions/pipeline.instructions.md +92 -0
  7. package/cli/copilot-with-citty/.github/instructions/software-architecture.instructions.md +166 -0
  8. package/cli/copilot-with-citty/.github/instructions/spec.instructions.md +127 -0
  9. package/cli/copilot-with-citty/.github/instructions/test.instructions.md +157 -0
  10. package/cli/copilot-with-citty/.github/specs/README.md +84 -0
  11. package/cli/copilot-with-citty/.github/workflows/assign-copilot.yml +59 -0
  12. package/cli/copilot-with-citty/.github/workflows/ci.yml +67 -0
  13. package/cli/copilot-with-citty/.nvmrc +1 -0
  14. package/cli/copilot-with-citty/.vscode/extensions.json +13 -0
  15. package/cli/copilot-with-citty/.vscode/launch.json +25 -0
  16. package/cli/copilot-with-citty/.vscode/mcp.json +19 -0
  17. package/cli/copilot-with-citty/.yamllint +18 -0
  18. package/cli/copilot-with-citty/biome.json +31 -0
  19. package/cli/copilot-with-citty/package.json +29 -0
  20. package/cli/copilot-with-citty/tsconfig.json +28 -0
  21. package/cli/copilot-with-citty/vitest.config.ts +15 -0
  22. package/cli/copilot-with-citty/vitest.setup.ts +2 -0
  23. package/dist/index.js +205 -55
  24. package/dist/index.js.map +1 -1
  25. package/dist/mcp-server.js +3 -0
  26. package/dist/mcp-server.js.map +1 -1
  27. package/package.json +3 -2
  28. package/ui/copilot-with-react/biome.json +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "root": false,
3
- "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
3
+ "$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
4
4
  "vcs": {
5
5
  "enabled": true,
6
6
  "clientKind": "git",
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "<%= it.projectName %>",
3
+ "image": "mcr.microsoft.com/devcontainers/javascript-node:24-bookworm",
4
+ "features": {
5
+ "ghcr.io/devcontainers/features/github-cli:1": {
6
+ "version": "2.83.2"
7
+ },
8
+ "ghcr.io/rocker-org/devcontainer-features/apt-packages:1": {
9
+ "packages": "yamllint, shellcheck",
10
+ "upgradePackages": true
11
+ },
12
+ "ghcr.io/devcontainers-extra/features/actionlint:1": {
13
+ "version": "1.7.9"
14
+ }
15
+ },
16
+ "forwardPorts": [],
17
+ "postCreateCommand": "npm cache add @upstash/context7-mcp @modelcontextprotocol/server-sequential-thinking",
18
+ "waitFor": "postCreateCommand",
19
+ "remoteUser": "node",
20
+ "customizations": {
21
+ "vscode": {
22
+ "extensions": [
23
+ "biomejs.biome",
24
+ "editorconfig.editorconfig",
25
+ "vitest.explorer",
26
+ "ms-vscode-remote.remote-containers",
27
+ "GitHub.codespaces",
28
+ "GitHub.Copilot",
29
+ "GitHub.Copilot-Chat",
30
+ "GitHub.github-vscode-theme",
31
+ "redhat.vscode-yaml"
32
+ ],
33
+ "settings": {
34
+ "editor.formatOnSave": true,
35
+ "editor.defaultFormatter": "biomejs.biome",
36
+ "[json]": {
37
+ "editor.defaultFormatter": "biomejs.biome"
38
+ },
39
+ "[javascript]": {
40
+ "editor.defaultFormatter": "biomejs.biome"
41
+ },
42
+ "[typescript]": {
43
+ "editor.defaultFormatter": "biomejs.biome"
44
+ },
45
+ "[yaml]": {
46
+ "editor.defaultFormatter": "redhat.vscode-yaml",
47
+ "editor.tabSize": 2
48
+ },
49
+ "vitest.enable": true,
50
+ "vitest.commandLine": "vitest",
51
+ "github.copilot.chat.agent.model": "claude-sonnet-4.5",
52
+ "github.copilot.chat.ask.model": "claude-sonnet-4.5",
53
+ "yaml.schemas": {
54
+ "https://json.schemastore.org/github-workflow.json": ".github/workflows/*.yml"
55
+ },
56
+ "github.copilot.chat.mcp.enabled": true
57
+ },
58
+ "mcp": {
59
+ "servers": {
60
+ "context7": {
61
+ "type": "stdio",
62
+ "command": "npx",
63
+ "args": ["-y", "@upstash/context7-mcp"]
64
+ },
65
+ "sequential-thinking": {
66
+ "command": "npx",
67
+ "args": [
68
+ "-y",
69
+ "@modelcontextprotocol/server-sequential-thinking"
70
+ ]
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,16 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_size = 4
7
+ indent_style = space
8
+ insert_final_newline = true
9
+ max_line_length = off
10
+ trim_trailing_whitespace = true
11
+
12
+ [{*.json}]
13
+ indent_size = 4
14
+
15
+ [{*.yaml,*.yml}]
16
+ indent_size = 2
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: Copilot Feature To Spec
3
+ description: Create a spec for the Copilot coding agent.
4
+ title: "[Spec]: "
5
+ labels: ["copilot-ready", "enhancement"]
6
+ body:
7
+ - type: markdown
8
+ attributes:
9
+ value: |
10
+ ## Copilot Specification
11
+ Please fill out the details below.
12
+ This structure is parsed by the Copilot Agent.
13
+
14
+ - type: textarea
15
+ id: context
16
+ attributes:
17
+ label: Context & Goal
18
+ description: What is the goal? What part of the codebase?
19
+ placeholder: |
20
+ We need to add a new command to the CLI
21
+ tool...
22
+ validations:
23
+ required: true
24
+
25
+ - type: textarea
26
+ id: acceptance-criteria
27
+ attributes:
28
+ label: Acceptance Criteria
29
+ description: How will we verify this is done?
30
+ placeholder: |
31
+ I run `npm run dev -- my-command`.
32
+ I see the expected output.
33
+ validations:
34
+ required: true
35
+
36
+ # ---------------------------------------------------------
37
+ # This section triggers the GitHub Script integration
38
+ # ---------------------------------------------------------
39
+ - type: textarea
40
+ id: extra-instructions
41
+ attributes:
42
+ label: Extra Instructions
43
+ description: Specific prompt engineering for the agent. This will be posted as a comment to guide the bot.
44
+ value: |
45
+ 1. Review .github/instructions/spec.instructions.md for more details and use this as your guide for the feature specification.
46
+ 2. Ensure you review all other repository instructions before starting work to understand engineering requirements.
47
+ 3. Create your final spec output in the .github/specs directory and ensure requirements are captured in the EARS format.
48
+ 4. Create a data flow diagram and sequence diagram to illustrate the feature's operation.
49
+ 5. Break down the feature into manageable tasks with clear descriptions.
50
+ 6. As you complete each task in the spec, mark the checkboxes as complete in the spec file using [x] notation.
51
+ 7. If you need to make assumptions, ask questions on the issue.
52
+ 8. Use the diagrams to inform your implementation plan.
53
+ validations:
54
+ required: false
@@ -0,0 +1,228 @@
1
+ ---
2
+ applyTo: "**"
3
+ ---
4
+
5
+ # CLI Application
6
+
7
+ A TypeScript CLI application using citty for command handling and consola for terminal output, following Test-Driven Development, Clean Architecture, and strict validation workflows.
8
+
9
+ ## Commands
10
+
11
+ Run `nvm use` before any npm command. During development, use file-scoped commands for faster feedback, and run the full validation suite (`npx biome check && npm test && npm run build`) before commits.
12
+
13
+ ```bash
14
+ # ALWAYS run first
15
+ nvm use
16
+
17
+ # Core commands
18
+ npm install # Install deps (updates package-lock.json)
19
+ npm test # Run tests (vitest)
20
+ npm run build # Production build
21
+ npm run dev # Start development with hot reload
22
+ npx biome check # Lint check
23
+ npx biome check --write # Auto-fix lint/format
24
+
25
+ # File-scoped (faster feedback)
26
+ npx biome check path/to/file.ts
27
+ npm test path/to/file.test.ts
28
+
29
+ # Validation suite (run before commits)
30
+ npx biome check && npm test && npm run build
31
+
32
+ # Other
33
+ npm audit # Security check
34
+ npm run lint:workflows # Validate GitHub Actions (actionlint)
35
+ npm run lint:yaml # Validate YAML (yamllint)
36
+ ```
37
+
38
+ ## Workflow: TDD Required
39
+
40
+ Follow this exact sequence for ALL code changes. Work in small increments — make one change at a time and validate before proceeding.
41
+
42
+ 1. **Research**: Search codebase for existing patterns, commands, utilities. Use Context7 MCP tools for library/API documentation.
43
+ 2. **Write failing test**: Create test describing desired behavior
44
+ 3. **Verify failure**: Run `npm test` — confirm clear failure message
45
+ 4. **Implement minimal code**: Write just enough to pass
46
+ 5. **Verify pass**: Run `npm test` — confirm pass
47
+ 6. **Refactor**: Clean up, remove duplication, keep tests green
48
+ 7. **Validate**: `npx biome check && npm test && npm run build`
49
+
50
+ Task is NOT complete until all validation passes.
51
+
52
+ ## Tech Stack
53
+
54
+ - **Framework**: citty — lightweight CLI framework with command definitions and argument parsing
55
+ - **Language**: TypeScript (strict mode)
56
+ - **Terminal Output**: consola — elegant console logging with levels and formatting
57
+ - **Validation**: Zod for runtime validation of external data
58
+ - **Testing**: Vitest (never Jest), Chance.js for test fixtures
59
+ - **Linting**: Biome (never ESLint/Prettier separately)
60
+ - **HTTP**: fetch API only (for external service calls)
61
+ - **Architecture**: Clean Architecture principles
62
+
63
+ ## Project Structure
64
+
65
+ ```
66
+ .github/ GitHub Actions workflows
67
+ src/ Application source code
68
+ entities/ Layer 1: Business domain entities
69
+ use-cases/ Layer 2: Application business rules
70
+ gateways/ Layer 3: External system adapters
71
+ commands/ Layer 3: CLI command handlers
72
+ lib/ Utilities and helpers
73
+ index.ts Application entry point
74
+ tests/ Test files (mirror src/ structure)
75
+ .nvmrc Node.js version (latest LTS)
76
+ ```
77
+
78
+ ## Code Style
79
+
80
+ ```typescript
81
+ import { defineCommand } from 'citty';
82
+ import { consola } from 'consola';
83
+ import { z } from 'zod';
84
+
85
+ // Define schema for runtime validation
86
+ const ConfigSchema = z.object({
87
+ name: z.string(),
88
+ version: z.string(),
89
+ });
90
+
91
+ type Config = z.infer<typeof ConfigSchema>;
92
+
93
+ // ✅ Good - small, typed, single purpose, descriptive names, runtime validation
94
+ async function loadConfig(filePath: string): Promise<Config> {
95
+ if (!filePath) {
96
+ throw new Error('File path required');
97
+ }
98
+
99
+ const content = await readFile(filePath, 'utf-8');
100
+ const data: unknown = JSON.parse(content);
101
+ return ConfigSchema.parse(data);
102
+ }
103
+
104
+ // ❌ Bad - untyped, no validation, multiple responsibilities
105
+ async function doStuff(x) {
106
+ console.log('loading');
107
+ const data = JSON.parse(await readFile(x));
108
+ return data as Config;
109
+ }
110
+ ```
111
+
112
+ **Rules:**
113
+ - Always use TypeScript type hints
114
+ - Use descriptive names for variables, functions, and modules
115
+ - Functions must be small and have single responsibility
116
+ - Avoid god functions and classes — break into smaller, focused units
117
+ - Avoid repetitive code — extract reusable functions
118
+ - Extract functions when there are multiple code paths
119
+ - Favor immutability and pure functions
120
+ - Avoid temporal coupling
121
+ - Keep cyclomatic complexity low
122
+ - Remove all unused imports and variables
123
+ - Validate external data at runtime with Zod — never use type assertions (`as Type`) on API responses
124
+ - Run lint and tests after EVERY change
125
+
126
+ ## Testing Standards
127
+
128
+ Tests are executable documentation. Use Arrange-Act-Assert pattern. Generate test fixtures with Chance.js.
129
+
130
+ ```typescript
131
+ import Chance from 'chance';
132
+ import { describe, it, expect, vi } from 'vitest';
133
+ import { createConfigLoader } from './config-loader';
134
+
135
+ const chance = new Chance();
136
+
137
+ // ✅ Good - describes behavior, uses generated fixtures, mocks dependencies
138
+ describe('Config Loader', () => {
139
+ describe('given a valid config file path', () => {
140
+ it('loads and validates the configuration', async () => {
141
+ // Arrange
142
+ const configPath = chance.word() + '.json';
143
+ const expectedConfig = {
144
+ name: chance.word(),
145
+ version: chance.semver(),
146
+ };
147
+ const mockReader = vi.fn().mockResolvedValue(JSON.stringify(expectedConfig));
148
+ const loader = createConfigLoader(mockReader);
149
+
150
+ // Act
151
+ const result = await loader.load(configPath);
152
+
153
+ // Assert
154
+ expect(result).toEqual(expectedConfig);
155
+ expect(mockReader).toHaveBeenCalledWith(configPath);
156
+ });
157
+ });
158
+
159
+ describe('given an empty file path', () => {
160
+ it('throws a validation error', async () => {
161
+ // Arrange
162
+ const mockReader = vi.fn();
163
+ const loader = createConfigLoader(mockReader);
164
+
165
+ // Act & Assert
166
+ await expect(loader.load('')).rejects.toThrow('File path required');
167
+ });
168
+ });
169
+ });
170
+ ```
171
+
172
+ **Rules:**
173
+ - Tests are executable documentation — describe behavior, not implementation
174
+ - Name `describe` blocks for features/scenarios, not function names
175
+ - Name `it` blocks as specifications that read as complete sentences
176
+ - Use nested `describe` blocks for "given/when" context
177
+ - Use Chance.js to generate test fixtures — avoid hardcoded test data
178
+ - Extract test data to constants — never duplicate values across arrange/act/assert
179
+ - Use Vitest (never Jest)
180
+ - Follow Arrange-Act-Assert pattern
181
+ - Tests must be deterministic — same result every run
182
+ - Avoid conditional logic in tests unless absolutely necessary
183
+ - Ensure all code paths have corresponding tests
184
+ - Test happy paths, unhappy paths, and edge cases
185
+ - Never modify tests to pass without understanding root cause
186
+
187
+ ## Dependencies
188
+
189
+ - Use latest LTS Node.js — check with `nvm ls-remote --lts`, update `.nvmrc`
190
+ - Pin ALL dependencies to exact versions (no ^ or ~)
191
+ - Use explicit version numbers when adding new dependencies
192
+ - Search npm for latest stable version before adding
193
+ - Run `npm audit` after any dependency change
194
+ - Ensure `package-lock.json` is updated correctly
195
+ - Use Dependabot to keep dependencies current
196
+
197
+ ## GitHub Actions
198
+
199
+ - Validation must be automated via GitHub Actions and runnable locally the same way
200
+ - Validate all workflows using actionlint
201
+ - Validate all YAML files using yamllint
202
+ - Pin all 3rd party Actions to specific version or commit SHA
203
+ - Keep all 3rd party Actions updated to latest version
204
+
205
+ ## Boundaries
206
+
207
+ **✅ Always do:**
208
+ - Run `nvm use` before any npm command
209
+ - Write tests before implementation (TDD)
210
+ - Run lint and tests after every change
211
+ - Run full validation before commits
212
+ - Use existing patterns from codebase
213
+ - Work in small increments
214
+ - Validate all external data with Zod
215
+ - Use Context7 MCP tools for code generation and documentation
216
+
217
+ **⚠️ Ask first:**
218
+ - Adding new dependencies
219
+ - Changing project structure
220
+ - Modifying GitHub Actions workflows
221
+
222
+ **🚫 Never do:**
223
+ - Skip the TDD workflow
224
+ - Store secrets in code (use environment variables)
225
+ - Use Jest (use Vitest)
226
+ - Modify tests to pass without fixing root cause
227
+ - Add dependencies without explicit version numbers
228
+ - Use type assertions (`as Type`) on external/API data
@@ -0,0 +1,92 @@
1
+ ---
2
+ applyTo: ".github/workflows/*.{yml,yaml}"
3
+ ---
4
+
5
+ # Pipeline Instructions for CLI
6
+
7
+ ## MANDATORY: After Modifying Workflows
8
+
9
+ Run these validation commands in order:
10
+
11
+ ```bash
12
+ npm run lint:workflows # Validate GitHub Actions workflows with actionlint
13
+ npm run lint:yaml # Validate YAML syntax with yamllint
14
+ ```
15
+
16
+ ## Workflow Structure Requirements
17
+
18
+ 1. Every workflow MUST include test and lint jobs.
19
+ 2. Reference Node.js version from `.nvmrc` using `actions/setup-node` with `node-version-file` input.
20
+ 3. Use official setup actions: `actions/checkout`, `actions/setup-node`, `actions/cache`.
21
+
22
+ ## Action Pinning Format
23
+
24
+ Pin ALL third-party actions to exact commit SHA with version comment:
25
+
26
+ ```yaml
27
+ # CORRECT format:
28
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
29
+
30
+ # INCORRECT formats (do NOT use):
31
+ uses: actions/checkout@v4 # ❌ version tag only
32
+ uses: actions/checkout@v4.1.1 # ❌ version tag only
33
+ uses: actions/checkout@main # ❌ branch reference
34
+ ```
35
+
36
+ Before adding any action:
37
+ 1. Check GitHub for the LATEST stable version
38
+ 2. Find the full commit SHA for that version
39
+ 3. Add both SHA and version comment
40
+
41
+ ## Runner Requirements
42
+
43
+ | Workflow | Runner |
44
+ |----------|--------|
45
+ | Default (all workflows) | `ubuntu-latest` |
46
+
47
+ ## Example CI Workflow
48
+
49
+ ```yaml
50
+ name: CI
51
+
52
+ on:
53
+ push:
54
+ branches: [main]
55
+ pull_request:
56
+ branches: [main]
57
+
58
+ jobs:
59
+ lint:
60
+ runs-on: ubuntu-latest
61
+ steps:
62
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
63
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
64
+ with:
65
+ node-version-file: '.nvmrc'
66
+ cache: 'npm'
67
+ - run: npm ci
68
+ - run: npx biome check
69
+
70
+ test:
71
+ runs-on: ubuntu-latest
72
+ steps:
73
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
74
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
75
+ with:
76
+ node-version-file: '.nvmrc'
77
+ cache: 'npm'
78
+ - run: npm ci
79
+ - run: npm test
80
+
81
+ build:
82
+ runs-on: ubuntu-latest
83
+ needs: [lint, test]
84
+ steps:
85
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
86
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
87
+ with:
88
+ node-version-file: '.nvmrc'
89
+ cache: 'npm'
90
+ - run: npm ci
91
+ - run: npm run build
92
+ ```
@@ -0,0 +1,166 @@
1
+ ---
2
+ applyTo: "src/**/*.ts"
3
+ ---
4
+
5
+ # Clean Architecture Instructions for CLI
6
+
7
+ ## The Dependency Rule
8
+
9
+ Dependencies point inward only. Outer layers depend on inner layers, never the reverse.
10
+
11
+ **Layers (innermost to outermost):**
12
+ 1. Entities — Enterprise business rules
13
+ 2. Use Cases — Application business rules
14
+ 3. Adapters — Interface converters (commands, gateways)
15
+ 4. Infrastructure — Frameworks, drivers, composition root
16
+
17
+ ## Directory Structure
18
+
19
+ ```
20
+ src/
21
+ ├── entities/ # Layer 1: Business domain entities
22
+ ├── use-cases/ # Layer 2: Application business rules
23
+ ├── gateways/ # Layer 3: External system adapters (file system, APIs)
24
+ ├── commands/ # Layer 3: CLI command handlers
25
+ ├── lib/ # Layer 3: Configuration and utilities
26
+ └── index.ts # Layer 4: Composition root
27
+ ```
28
+
29
+ ## Layer 1: Entities
30
+
31
+ **Location:** `src/entities/`
32
+
33
+ - MUST NOT import from any other layer
34
+ - MUST NOT depend on frameworks or infrastructure
35
+ - MUST NOT use non-deterministic or side-effect-producing global APIs (e.g., `crypto.randomUUID()`, `Date.now()`)
36
+ - MUST be plain TypeScript objects/classes with business logic
37
+ - MAY contain validation and business rules
38
+
39
+ ```typescript
40
+ // src/entities/project.ts
41
+ export interface Project {
42
+ readonly name: string;
43
+ readonly version: string;
44
+ readonly type: ProjectType;
45
+ }
46
+
47
+ export type ProjectType = 'cli' | 'webapp' | 'api';
48
+
49
+ export function isValidProjectName(name: string): boolean {
50
+ return /^[a-z][a-z0-9._-]*$/.test(name) && name.length <= 214;
51
+ }
52
+ ```
53
+
54
+ ## Layer 2: Use Cases
55
+
56
+ **Location:** `src/use-cases/`
57
+
58
+ - MUST only import from entities and ports (interfaces)
59
+ - MUST define input/output DTOs
60
+ - MUST define ports for external dependencies
61
+ - MUST NOT import concrete implementations
62
+
63
+ ```typescript
64
+ // src/use-cases/initialize-project.ts
65
+ import type { Project } from '../entities/project';
66
+
67
+ export interface InitializeProjectInput {
68
+ name: string;
69
+ type: string;
70
+ }
71
+
72
+ export interface ProjectGateway {
73
+ createStructure(project: Project): Promise<void>;
74
+ }
75
+
76
+ export class InitializeProjectUseCase {
77
+ constructor(private readonly gateway: ProjectGateway) {}
78
+
79
+ async execute(input: InitializeProjectInput): Promise<void> {
80
+ if (!input.name) {
81
+ throw new Error('Project name is required');
82
+ }
83
+ await this.gateway.createStructure({
84
+ name: input.name,
85
+ version: '0.1.0',
86
+ type: input.type as any,
87
+ });
88
+ }
89
+ }
90
+ ```
91
+
92
+ ## Layer 3: Adapters
93
+
94
+ **Location:** `src/commands/`, `src/gateways/`, and `src/lib/`
95
+
96
+ - MUST implement ports defined by use cases
97
+ - MAY import from entities and use cases
98
+ - MAY use framework-specific code
99
+ - MUST NOT contain business logic
100
+
101
+ ```typescript
102
+ // src/commands/init.ts
103
+ import { defineCommand } from 'citty';
104
+ import { consola } from 'consola';
105
+
106
+ export const initCommand = defineCommand({
107
+ meta: {
108
+ name: 'init',
109
+ description: 'Initialize a new project',
110
+ },
111
+ args: {
112
+ name: { type: 'string', description: 'Project name' },
113
+ },
114
+ async run({ args }) {
115
+ consola.info(`Initializing project: ${args.name}`);
116
+ // Delegate to use case
117
+ },
118
+ });
119
+ ```
120
+
121
+ ## Layer 4: Infrastructure
122
+
123
+ **Location:** `src/index.ts` (composition root)
124
+
125
+ - Composition root wires dependencies
126
+ - MAY import from all layers
127
+
128
+ ```typescript
129
+ // src/index.ts
130
+ import { defineCommand, runMain } from 'citty';
131
+ import { initCommand } from './commands/init';
132
+
133
+ const main = defineCommand({
134
+ meta: { name: 'my-cli', description: 'My CLI tool' },
135
+ subCommands: { init: initCommand },
136
+ });
137
+
138
+ runMain(main);
139
+ ```
140
+
141
+ ## Import Rules Summary
142
+
143
+ | From | Entities | Use Cases | Commands/Gateways/Lib | Index (Root) |
144
+ |------|----------|-----------|----------------------|--------------|
145
+ | Entities | ✓ | ✗ | ✗ | ✗ |
146
+ | Use Cases | ✓ | ✓ | ✗ | ✗ |
147
+ | Commands/Gateways/Lib | ✓ | ✓ | ✓ | ✗ |
148
+ | Index (Root) | ✓ | ✓ | ✓ | ✓ |
149
+
150
+ ## Anti-Patterns
151
+
152
+ **Anemic Domain Model:** Entities as data-only containers with logic in services. Put business rules in entities.
153
+
154
+ **Leaky Abstractions:** Ports exposing framework types. Use domain concepts only.
155
+
156
+ **Business Logic in Adapters:** Validation rules or decisions in commands. Move to entities/use cases.
157
+
158
+ **Framework Coupling:** Use cases accepting CLI `args` objects. Use plain DTOs.
159
+
160
+ ## Code Review Checklist
161
+
162
+ - Entities have zero imports from other layers
163
+ - Use cases define ports for all external dependencies
164
+ - Adapters implement ports, contain no business logic
165
+ - Only composition root instantiates concrete implementations
166
+ - Use cases testable with simple mocks (no file system, no HTTP)