Contributing
Contributions to DojOps are welcome. This guide covers development setup, coding standards, testing, and how to add new skills and agents.
Prerequisites
- Node.js >= 20
- pnpm >= 8
- TypeScript >= 5.4
Development Setup
# Clone the repository
git clone https://github.com/dojops/dojops.git
cd dojops
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Run linter
pnpm lintMonorepo Structure
packages/
cli/ CLI entry point + TUI (@clack/prompts)
api/ REST API (Express) + web dashboard
skill-registry/ Skill registry + custom skill system (built-in + custom skill discovery)
core/ LLM providers (7) + specialist agents (32) + CI debugger + infra diff + DevOps checker
planner/ Task graph decomposition + topological executor
executor/ SafeExecutor + policy engine + approval workflows + audit log
runtime/ 38 built-in DevOps skills as .dops files (DopsRuntime)
scanner/ 10 security scanners + remediation engine
session/ Chat session management + memory + context injection
context/ Context7 documentation augmentation for skills
sdk/ BaseSkill<T> abstract class + Zod re-export + verification types + file-reader utilitiesPackage scope: @dojops/*
Dependency flow: cli -> api -> skill-registry -> runtime -> core -> sdk
Build, Test, Lint
# Build all packages via Turbo
pnpm build
# Dev mode (no caching)
pnpm dev
# Run all tests (Vitest)
pnpm test
# Run tests for a specific package
pnpm --filter @dojops/core test
pnpm --filter @dojops/api test
# ESLint across all packages
pnpm lint
# Prettier write
pnpm format
# Prettier check (CI mode)
pnpm format:check
# Run CLI locally (no global install)
pnpm dojops -- "Create a Terraform config for S3"
pnpm dojops -- serve --port=8080Code Style
- TypeScript, ES2022, CommonJS modules
- ESLint, Enforced across all packages
- Prettier, Auto-formatting
- Husky + lint-staged, Pre-commit hooks run linting and formatting
Key conventions:
- Use Zod for all schema validation (inputs, outputs, API requests)
- Use
parseAndValidate()for LLM response parsing - Follow the existing barrel export pattern (
index.tsin each package) - Prefer interfaces over type aliases for public APIs
- Use
async/awaitover raw Promises
Testing
DojOps uses Vitest for testing. Current coverage:
| Package | Tests |
|---|---|
@dojops/cli | 672 |
@dojops/core | 592 |
@dojops/runtime | 399 |
@dojops/api | 244 |
@dojops/skill-registry | 140 |
@dojops/scanner | 110 |
@dojops/executor | 102 |
@dojops/sdk | 55 |
@dojops/planner | 49 |
@dojops/session | 47 |
@dojops/context | 32 |
| Total | 2442 |
Writing Tests
- Place test files in
__tests__/directories mirroring the source structure:src/foo.ts->src/__tests__/foo.test.ts - Mock LLM providers for deterministic tests
- Use
supertestfor API endpoint integration tests - Test both success and error paths
Adding a New Built-in Skill
All 38 built-in skills are .dops files in packages/runtime/skills/. To add a new built-in skill, create a .dops file following the format. See DevOps Skills for the full pattern.
Step-by-Step
-
Create the
.dopsskill file:packages/runtime/skills/my-tool.dopsA
.dopsfile has YAML frontmatter followed by markdown prompt sections:--- meta: name: my-tool version: "1.0.0" description: "Generates my-tool configuration" tags: [my-domain] context: technology: "my-tool" outputGuidance: "Generate a complete, valid my-tool config file." bestPractices: - "Follow official documentation conventions" - "Include comments explaining non-obvious settings" files: - path: "my-tool.conf" format: raw scope: write: - "my-tool.conf" risk: level: LOW rationale: "Generates a single configuration file" execution: mode: generate deterministic: true idempotent: true detection: paths: - "my-tool.conf" verification: structural: - rule: not_empty - rule: min_lines value: 3 permissions: filesystem: project child_process: none network: none --- ## Prompt Generate a complete my-tool configuration based on the user's requirements. {outputGuidance} {bestPractices} ## Keywords my-tool, my-domain -
Register the skill in
packages/runtime/src/built-in-skills.ts, add the filename to the skill list. -
Add a specialist agent keyword (if needed) in
packages/core/src/agents/specialists.ts, add your tool’s keywords so theAgentRoutercan route prompts to it. -
Write tests: Create
packages/runtime/src/__tests__/skills/my-tool.test.tswith mocked LLM provider, test prompt compilation, update mode, and verification.
Creating a Custom Skill
For skills that don’t need to be built into the core, use the custom skill system instead. Custom skills are declarative, no TypeScript code required.
Step-by-Step
-
Scaffold a custom skill:
dojops skills init my-toolThis creates
.dojops/skills/my-tool.dops, a single.dopsfile combining YAML frontmatter with markdown prompt sections. -
Edit the
.dopsfile, customize the prompt, input fields, output format, file specs, and permissions. -
Validate the skill:
dojops skills validate my-tool -
Test by generating a config:
dojops "Generate my-tool config for production"
Custom skills are automatically discovered and available to the Planner, Executor, and API. See DevOps Skills, Custom Skill System for the full .dops format.
Adding a New Agent
There are two ways to add agents: as a custom agent (no source code changes) or as a built-in agent (requires modifying the codebase).
Option 1: Custom Agent (Recommended for Most Cases)
Create a custom agent without modifying DojOps source code:
# LLM-generated (recommended)
dojops agents create "an SRE specialist for incident response and reliability"
# Manual creation via interactive prompts
dojops agents create --manualCustom agents are stored as structured README.md files in .dojops/agents/<name>/ (project) or ~/.dojops/agents/<name>/ (global). They participate in the same keyword-based routing as built-in agents and can override built-in agents by name.
See Specialist Agents, Custom Agents for the full README.md format and discovery rules.
Option 2: Built-in Agent (For Core Contributions)
Built-in agents are defined in packages/core/src/agents/specialists.ts.
-
Add a new entry to the specialists array:
{ name: "my-specialist", domain: "my-domain", description: "Expert in...", keywords: ["keyword1", "keyword2", "keyword3"], toolDependencies: ["optional-tool"], } -
The agent will automatically:
- Be registered in the
AgentRouter - Appear in
dojops agents list - Be available in the API (
GET /api/agents) - Be routable by keyword matching
- Be registered in the
-
Write tests for keyword routing accuracy.
PR Workflow
- Fork the repository
- Branch from
main:git checkout -b feature/my-feature - Implement your changes with tests
- Verify:
pnpm build pnpm test pnpm lint pnpm format:check - Commit with a descriptive message
- Submit a pull request against
main
PR Checklist
- All tests pass (
pnpm test) - Linting passes (
pnpm lint) - Formatting is correct (
pnpm format:check) - New features include tests
- New skills follow the
BaseSkill<T>pattern - Breaking changes are documented
License
DojOps is licensed under the MIT License .