Contributing
dmx is open source under AGPL-3.0. Contributions are welcome.
Repository
Getting started
git clone https://github.com/deepmodel-ai/dmx
cd dmx
# Install with dev dependencies
uv sync --all-extras
# Run tests
uv run pytest
# Run linting
uv run ruff check .
uv run ruff format --check .
uv run mypy src/
Tests require Python 3.11+ and cover Python 3.11, 3.12, and 3.13 on Ubuntu and macOS in CI.
Project structure
src/dmx/
├── catalog.py # Skill and rule loading: parse, validate, template substitution
├── cli.py # CLI entrypoint
├── http_auth.py # Bearer token auth for HTTP transport
├── loop_memory.py # Memory bank read/write helpers
├── loop_schema.py # Pydantic schema for loop config YAML
├── loop_state.py # Job and task state persistence
├── loop_tools.py # MCP tools: run_loop, loop_advance, loop_continue
├── repeat_until.py # Evaluator for repeat_until conditions
├── server.py # FastMCP server assembly
├── tools.py # MCP tools: detect_invoking_ide, setup_ide_rules
├── validator_runner.py # Subprocess runner for validators
├── ide/
│ ├── detect.py # IDE detection from workspace paths
│ └── emitters.py # IDE-specific rule file writers
├── loops/
│ └── *.yaml # Bundled default loop configs
├── rules/
│ └── system-prompt.md # Always-apply system prompt rules
├── skills/
│ ├── loop/ # Loop runtime skills (run-loop, loop-continue)
│ ├── specialist/ # Specialist skills (docs, review, secure, test)
│ ├── utility/ # Utility skills (commit, status, sync-branch, ...)
│ └── workflow/ # Workflow skills (init, create-ticket, plan, ...)
└── validators/
├── check_plan_complete.py
├── check_pr_ready.py
├── check_spec_complete.py
├── run_tests.py
└── spec_adherence.py
Adding a skill
Skills are Markdown files with YAML frontmatter. Create a new .md file in the appropriate skills/ subdirectory:
---
name: my-skill
title: My Skill
description: Short description shown in the IDE command palette.
arguments:
- name: target
description: What to operate on.
required: true
- name: mode
description: "Operation mode. Accepted values: fast, thorough."
required: false
---
You are performing the my-skill operation. Follow every step in order.
## Step 1 — ...
Skill name rules:
- Must be a lowercase slug:
[a-z0-9_-]+ - Must be unique within the skill set
- Argument names must be valid Python identifiers:
[a-z][a-z0-9_]*(no hyphens)
Adding a validator
Create a Python file in src/dmx/validators/{name}.py. The contract:
- Read JSON from stdin
- Write JSON to stdout
- Exit 0 on pass, 1 on failure
import json
import sys
if __name__ == "__main__":
contract = json.loads(sys.stdin.read() or "{}")
workspace_root = contract.get("loop_context", {}).get("workspace_root", ".")
# Your validation logic here
result = {
"pass": True,
"message": "Check passed",
"checks": [{"name": "my_check", "pass": True}],
}
print(json.dumps(result))
sys.exit(0 if result["pass"] else 1)
See Writing Validators for the full contract reference.
Adding a loop config
Add a YAML file to src/dmx/loops/{name}.yaml. See Loop YAML Schema for the full schema.
Test the new loop by running it against a test repo with /dmx/run-loop name.
Testing
The test suite is in tests/. Coverage threshold is 75%.
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=dmx --cov-report=term-missing
# Run a specific test file
uv run pytest tests/test_loop_schema.py
CI
GitHub Actions runs tests on every push and PR:
- Python 3.11, 3.12, 3.13
- Ubuntu and macOS
- ruff check, ruff format, mypy, pytest with 75% coverage threshold
All checks must pass before a PR is merged.
Publishing
Releases are published to PyPI automatically on push to a v* tag:
git tag v0.3.0
git push origin v0.3.0
The publish workflow uses OIDC trusted publishing. No API tokens are stored in CI.
Code style
- Conventional Commits for commit messages
rufffor linting and formatting (configuration inpyproject.toml)mypystrict mode- Docstrings for all public functions and classes
Issues and PRs
Open issues on GitHub for bugs, feature requests, and questions. For significant changes, open an issue to discuss the approach before submitting a PR.