Team Setup
dmx turns your team's process into versioned and tracked artifacts in the repo. Loops, validators, and project memory are committed and reviewed like code, so every developer works the same way from their first clone.
Across an engineering organization, shared config repos carry one process to every team, and every team can still adapt it.
Step 1: Initialize the repo once
One person runs /dmx/init in the repository. This creates the .dmx/ directory with the project config and scaffolded memory bank.
Commit the .dmx/ directory:
git add .dmx/
git commit -m "chore: initialize dmx memory bank"
git pushEvery developer who pulls this commit gets the project context automatically. No further setup per developer beyond connecting their IDE.
Step 2: Each developer connects their IDE
Each team member's IDE runs dmx as an MCP server. Skip the per-developer setup by committing the IDE config to the repo, pinned to one dmx version so everyone runs the same release:
{
"mcpServers": {
"dmx": {
"command": "uvx",
"args": ["--from", "deepmodel-dmx==0.5.0", "dmx", "serve"]
}
}
}| IDE | File to commit |
|---|---|
| Cursor | .cursor/mcp.json |
| Claude Code and VS Code (GitHub Copilot) | .mcp.json |
Claude Code asks each developer to approve the shared .mcp.json once. To upgrade the team, bump the version in a PR. See Upgrading dmx.
If you manage developer machines with Jamf or Intune, you can deploy dmx to every machine instead. See Enterprise Deployment.
No secrets to share. dmx reads project config from .dmx/config.md in the repo.
Step 3: Commit .dmx/ files as you work
As developers work on features, spec.md, tasks.md, and the core memory files (systemPatterns.md, techContext.md, productContext.md, activeContext.md) are updated. These should be committed alongside code changes.
Include .dmx/ in your standard commit workflow. The memory bank is project state, not developer scratch. It belongs in the repo.
What to gitignore
Nothing. .dmx/ is project state, and the loop runtime commits each run's final state when the run finishes. Job history travels with the PR, so reviewers can see which validators ran.
If .dmx/jobs/ grows too large, you can stop committing it. Add it to your .gitignore:
.dmx/jobs/If job records are already committed, you can untrack them by using:
git rm -r --cached .dmx/jobs/dmx keeps writing job state to disk, so you can still pause and resume loops on your machine. Teammates and reviewers just won't see the job history. The value is in the context files and loop configs, not the execution records.
Never ignore .dmx/vendor/. It holds your organization's shared config (see below).
Customizing dmx for your repo
Loop configs, skills, and validators committed to the repo are shared with everyone who clones it. No per-developer configuration.
Loop configs
Custom loop configs in .dmx/loops/ are committed to the repo and shared across the team. Every developer runs the same loops with the same validators.
To change a loop config:
- Edit
.dmx/loops/{name}.yaml - Commit and open a PR
- The change is reviewed like any other code change
This is the principle that makes loops reliable for teams: loop configs are versioned artifacts, not personal preferences.
Skills
Custom skills live in .dmx/skills/. A file there adds a skill your team can use, or replaces the bundled skill with the same name when a loop runs it.
your-project/
└── .dmx/
├── skills/
│ ├── commit.md # Team's version of the bundled commit skill
│ └── deploy-preview/ # Folder-shaped skill
│ ├── SKILL.md
│ └── scripts/
└── loops/
└── dev.yaml # References deploy-previewA skill is either a flat {name}.md file or a {name}/SKILL.md folder, the format Claude Code and agentskills.io use. Skills written for those tools drop in as-is.
Nobody has to memorize them. Developers ask their agent ("is there a skill for preview deploys?") and it finds the match. See Custom Skills.
Validators
Custom validators in validators/ at the repo root are already shared. They're in the repo. No additional configuration needed; dmx looks there first.
your-project/
├── validators/
│ ├── run_tests.py # Team's custom test runner
│ └── security_scan.py # Team's security validator
└── .dmx/
└── loops/
└── dev.yaml # References the custom validatorsSharing dmx config across your organization
A repo's loops capture how one team works on one codebase. An engineering organization's process spans dozens of repos.
Without a shared home, every repo carries its own copy of the spec loop, the security validator, the commit conventions. The copies drift. Improving the process means opening the same PR in every repo, and most of them never get it.
Shared sources fix this. Put loops, skills, and validators in a git repository of their own. Each app repo declares it, pins a version, and vendors it with /dmx/sync. The organization defines the process once. Teams build on it. Repos adjust it where they need to.
Three layers
| Layer | Lives in | Typical contents |
|---|---|---|
| Organization | A shared repo, e.g. acme/dmx-org | The standard process: spec and release loops, security and compliance validators, house skills for commits and PRs |
| Team | A shared repo, e.g. acme/dmx-payments | How one team works: a dev loop with a PCI validator, skills for the team's services |
| Repo | .dmx/ and validators/ in the app repo | One codebase's needs: a custom run_tests, a one-off loop |
Each layer only contains what it changes. Anything a layer doesn't define falls through to the next one down, and finally to the defaults bundled with dmx. A team that's happy with the org's spec loop doesn't copy it; it only ships the loops and skills it does differently.
Declare the layers in order
Each app repo lists its sources in .dmx/shared-sources.yaml. When two sources define the same name, the one listed first wins, so list the most specific first:
shared_sources:
- name: payments # team layer: checked first
source: "git::https://github.com/acme/dmx-payments.git//?ref=v2.1.0"
- name: org # organization layer: the baseline
source: "git::https://github.com/acme/dmx-org.git//?ref=v1.4.0"Every lookup for a loop config, skill, or validator checks the app repo, then payments, then org, then the bundled defaults. With the config above:
| Name | Defined in | What runs |
|---|---|---|
spec.yaml | org | The org's Spec Loop |
dev.yaml | org, payments | The payments team's Dev Loop |
security_scan.py | org | The org's security validator |
run_tests.py | org, app repo | The repo's own test runner |
create-ticket | Not shared | The bundled skill |
An override replaces the whole file. The payments team's dev.yaml doesn't extend the org's; it takes its place.
dmx doesn't treat an "org" source differently from a "team" source. Both are shared sources, and order decides which wins. A team repo doesn't pull in the org repo on its own, so each app repo lists both.
Roll out changes on your own schedule
Every source is pinned to a tag, branch, or commit SHA. A change to the org repo changes nothing until an app repo bumps its ref.
That's what keeps teams flexible. The org ships v1.5.0 of its loops. Each team adopts it when it's ready, in an ordinary PR, with the vendored diff in front of reviewers. A team mid-release can stay on v1.4.0 until it's done.
To roll out a change:
- Merge it into the shared repo and tag a release
- In each app repo, bump the
refin.dmx/shared-sources.yamlon a branch - Run
/dmx/sync. It vendors the new version, warns about name collisions, and commits. - Open a PR. Reviewers see exactly which loops, skills, and validators changed.
No network access is needed at loop-run time. Loops read the vendored copy in .dmx/vendor/.
Keep overrides visible
Flexibility cuts both ways: a repo can override anything, including the org's security validator. dmx doesn't block that. It makes it visible.
/dmx/syncwarns about every name collision and names which copy wins. The warnings land in the sync PR.- Overrides are files in the repo. They go through code review like any other change.
If your organization needs a harder line, use the governance you already have. A CODEOWNERS entry for .dmx/shared-sources.yaml, .dmx/vendor/, .dmx/loops/, .dmx/skills/, and validators/ puts your platform team on every change to the process.
Skills your whole organization can find
Shared skills don't need a launch announcement. Once a source is vendored, every developer in every app repo can find its skills by asking their agent:
what skills do we have for helm updates?The agent lists the matches from your repo and every shared source, with where each one comes from, and runs one only when asked. A platform team ships a new skill by tagging a release; each repo picks it up when it bumps the ref and runs /dmx/sync. See Custom Skills.
Getting started
- Create the org repo. Add any of
loops/,skills/, andvalidators/at the root. Start by copying in the bundled loops you want to standardize, then change them. - Tag a release.
v1.0.0is fine. - Add team repos as needed. Same layout, only the files that differ from the org's.
- Adopt it in each app repo. Add
.dmx/shared-sources.yaml, run/dmx/syncon a branch, and merge the PR.
See Shared Sources for the address format, skill formats, sync failures, and private-repo credentials.
Handling merge conflicts in .dmx/
Because spec.md and tasks.md are branch-level files, they rarely conflict. The context files (techContext.md, systemPatterns.md) can conflict if two developers are updating them simultaneously.
Resolve context file conflicts like documentation conflicts: read both versions, keep the most current and accurate content, commit the merge.
jobs/ conflicts almost never happen — each ticket writes to its own jobs/{job_id}/ subdirectory, so two branches only collide here if they somehow share a job id. If you do see one, keep both sides; job history is additive, not a single mutable file.
Onboarding new developers
A new developer on the team:
- Clones the repo (gets
.dmx/with full project context, plus the org and team config already vendored) - Configures their IDE to use dmx (MCP Setup)
- Starts their first ticket with
/dmx/run-loop spec
No onboarding document needed for dmx itself. The memory bank is the onboarding document.