Domain-Driven Design (DDD) Skill
This skill provides guidelines for organizing the @silverassist/agents-toolkit
codebase following Domain-Driven Design principles. The project is a Node.js ESM CLI
with TypeScript compiled to dist/ via unbuild — adapt all examples accordingly.
Core Principles
- Group by Responsibility, Not by Type — Organize files by what they do, not what kind of file they are
- Clear Boundaries — Each domain module has well-defined inputs, outputs, and responsibilities
- Self-Documenting Structure — Folder and file names communicate intent without needing comments
- Colocation — Tests (
src/cli.test.js) live next to the code they test
Project Layout
agents-toolkit/
├── src/
│ ├── cli.ts # Entry point — shebang + main() dispatcher (~40 lines)
│ ├── index.ts # Public API — metadata exports only (VERSION, PROMPTS, …)
│ ├── types.ts # Shared interfaces (Lockfile, InstallOptions, …)
│ ├── constants.ts # TEMPLATES_DIR (import.meta.url based)
│ ├── logger.ts # ColorKey union + log helpers
│ ├── paths.ts # Install-path helpers
│ ├── filter/ # FILE_CATEGORIES + shouldIncludeFile
│ ├── config/ # AgentToolkitConfig loading + resolveFilters
│ ├── lockfile/ # computeSkillHash + readLockfile + writeLockfile
│ ├── transforms/ # Copilot→Claude frontmatter transforms
│ ├── copy/ # copyDir + linkSkill + installSkillsStandard
│ ├── installers/ # hooks, instructions, agents, git-based orchestrator
│ ├── commands/ # install, restore, status, list, help
│ └── cli.test.js # Spawn-based tests (node:test + spawnSync against dist/)
├── dist/ # Compiled output (gitignored; built by unbuild)
├── templates/
│ ├── shared/ # Canonical source of truth for distributed content
│ └── agents/ # Root agent files (AGENTS.md, CLAUDE.md, …)
├── .agents/skills/ # Canonical dev skills store (single source of truth)
├── .github/
│ ├── prompts/ # Dev workflow prompts for Copilot/Codex (real files)
│ ├── skills/ # Symlinks → .agents/skills/
│ └── instructions/ # Path-scoped Copilot review rules
└── .claude/
├── commands/ # Dev workflow commands for Claude Code (real files)
└── skills/ # Symlinks → .agents/skills/
Responsibility Boundaries
src/cli.ts — Entry Point
Thin dispatcher only — imports commands, parses args, calls the right function. ~40 lines.
Rule: No install logic in src/cli.ts. If you're adding behavior, it belongs in a domain module.
src/commands/ — Top-Level Commands
One file per command verb: install.ts, restore.ts, status.ts, help.ts. Each imports
from domain modules and orchestrates them into user-facing behavior.
Rule: Commands are thin orchestrators. Business logic lives in domain modules.
src/installers/ — Install Orchestration
git-based.ts is the main orchestrator for Copilot/Codex installs. hooks.ts, instructions.ts,
agents.ts each handle one install concern.
src/filter/ src/config/ src/lockfile/ src/transforms/ src/copy/ — Domain Modules
Pure-ish modules: each owns one domain, exports through index.ts barrel only.
Rule: Import from a domain's index.ts, never from an internal file.
src/index.ts — Public Metadata
Only exports package metadata. No logic:
export const VERSION = '2.4.0';
export const PROMPTS = { workflow: [...], utility: [...] };
export const SKILLS = [...];
// ...
Rule: Every array must stay alphabetically sorted and in sync with the corresponding
templates/shared/ directory. See .github/instructions/index-exports.instructions.md.
templates/shared/ — Distributed Content
The single source of truth for what gets installed into end-user projects.
Rule: Never reference project-specific paths (src/, dist/) inside templates.
Templates must be generic enough to work in any project matching the target stack/tracker.
src/cli.test.js — Tests
Tests spawn dist/cli.mjs as a child process against a temp directory and assert on
the filesystem and stdout/stderr. pretest builds dist/ automatically.
Rule: Use spawnSync against temp dirs. Never mock internal functions. See the
testing-patterns skill for patterns.
Organizing New Features
Adding a new CLI flag
- Add the flag to
parseArgs()insrc/commands/help.tsand toInstallOptionsinsrc/types.ts - Thread the value through the relevant install functions
- Honor the flag in all install paths (
install,installClaude,installCodex) - Add to the
showHelp()output insrc/commands/help.ts - Add a test:
help shows --flag-name option
Adding a new template file
- Create the file under the correct
templates/shared/subdirectory - Add the name (without extension) to the appropriate
FILE_CATEGORIESarray insrc/filter/index.ts - Add to the matching export array in
src/index.ts - Add
shouldIncludeFile()logic if the file is stack- or tracker-specific - Add/update a test asserting the file appears (or doesn't) under the right
--stack/--tracker
Adding a new skill to .agents/skills/
- Create
.agents/skills/<name>/SKILL.md - Create symlinks:
.github/skills/<name>→../../.agents/skills/<name>and.claude/skills/<name>→../../.agents/skills/<name> - The skill description must reflect this repo (Node.js ESM CLI, TypeScript,
node:test)
Avoiding Common Mistakes
❌ Don't put logic in src/cli.ts
// ❌ BAD: logic in the entry point
export function main() {
// ...200 lines of install logic...
}
// ✅ GOOD: delegate to a command module
export function main() {
const { command, options } = parseArgs();
if (command === 'install') install(options);
}
❌ Don't put logic in src/index.ts
// ❌ BAD
export function install(target: string) { ... } // logic belongs in src/commands/
// ✅ GOOD
export const SKILLS = ['domain-driven-design', 'testing-patterns']; // metadata only
❌ Don't import from a domain's internal files
// ❌ BAD
import { readLockfile } from '../lockfile/lockfile.js';
// ✅ GOOD
import { readLockfile } from '../lockfile/index.js';
❌ Don't add project-specific content to templates
# ❌ BAD: template references this repo's layout
templates/shared/prompts/review-code.prompt.md mentions src/commands/install.ts
# ✅ GOOD: template is generic
templates/shared/prompts/review-code.prompt.md describes general code review steps
Checklist
Before adding new code:
- Is this logic (→ a domain module in
src/) or metadata (→src/index.ts)? - If it's a new template, is it in the right
templates/shared/subdirectory? - Is
FILE_CATEGORIESupdated insrc/filter/index.ts? - Is
src/index.tsexport updated and alphabetically sorted? - Is there a test for the new behavior?
- Does the template avoid project-specific references?