Skip to content

Plugins

DDx plugins extend the platform with workflow methodologies, agent skills, CLI tools, and library resources. HELIX is the reference plugin. You can create your own.

What a Plugin Provides

A plugin is a git repository that ships some combination of:

ArtifactDescriptionInstall location
RootThe entire plugin tree.ddx/plugins/<name>/
SkillsSKILL.md files agents discover as slash commands.agents/skills/ and .claude/skills/
ScriptsCLI tools~/.local/bin/
SymlinksPost-install convenience linksAnywhere

The plugin root at .ddx/plugins/<name>/ can contain any DDx resource type:

ResourcePath in pluginDescription
Promptsprompts/AI prompts and system instructions
Templatestemplates/Project and artifact templates
Patternspatterns/Reusable code patterns
Personaspersonas/AI persona definitions
MCP serversmcp-servers/MCP server configurations
Environmentsenvironments/Development environment configs
Toolstools/Tool configurations

This mirrors the DDx library structure (.ddx/library/). A plugin can ship any subset — a persona-pack might only have personas/, while a full workflow plugin like HELIX ships skills, a CLI, prompts, templates, and action docs.

How Installation Works

When you run ddx install <name>:

  1. DDx fetches the latest release tarball from the plugin’s GitHub repo
  2. Extracts it to a temp directory
  3. Copies the Root (the entire plugin) to .ddx/plugins/<name>/
  4. Symlinks each skill from .ddx/plugins/<name>/ into the agent skill directories — skills stay in sync with the plugin, no duplicates
  5. Symlinks the CLI script from .ddx/plugins/<name>/ to ~/.local/bin/
  6. Records the installation in ~/.ddx/installed.yaml

Skills and scripts are symlinked from the installed root, not copied independently. This means updates to the plugin root automatically update all skills and scripts.

Plugin Structure

A plugin repo mirrors the DDx resource layout. Include only the directories you need:

my-plugin/
├── .agents/
│   └── skills/             # agent skills (symlinked on install)
│       ├── my-build/
│       │   └── SKILL.md
│       └── my-review/
│           └── SKILL.md
├── bin/
│   └── my-plugin           # CLI entry point (symlinked on install)
├── prompts/                # AI prompts and instructions
├── templates/              # project or artifact templates
├── patterns/               # reusable code patterns
├── personas/               # AI persona definitions
└── README.md

A plugin can also include its own internal resources that skills reference at runtime. HELIX, for example, ships workflows/ with action prompts, phase templates, and reference docs — these are HELIX-specific, not a DDx convention.

Key conventions

  • Skills live in .agents/skills/<skill-name>/SKILL.md
  • CLI entry point lives in bin/<plugin-name>
  • Resources (prompts, templates, patterns, personas) follow the same directory structure as .ddx/library/
  • Path references in skills must use the installed path prefix .ddx/plugins/<name>/ so agents can resolve them from any project

Skill format

Each skill directory contains a SKILL.md with YAML frontmatter:

---
name: my-build
description: Build the current project using my methodology.
argument-hint: "[scope]"
---

# Build

Steps the agent should follow when this skill is invoked.

## When to Use

- Starting implementation work
- After design is complete

## Steps

1. Load context — read governing artifacts
2. Implement the change
3. Run tests
4. Commit with traceability

## References

- Build prompt: `.ddx/plugins/my-plugin/prompts/build.md`
- Templates: `.ddx/plugins/my-plugin/templates/`

CLI entry point

The bin/<name> script is the CLI that users invoke directly. It typically:

  1. Resolves the plugin root (from CLAUDE_PLUGIN_ROOT in plugin mode, or from its own location)
  2. Sets up context paths for shared resources
  3. Delegates to the main script logic
#!/usr/bin/env bash
set -euo pipefail

if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]]; then
  PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT}"
else
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  PLUGIN_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
fi

export PLUGIN_ROOT
exec "${PLUGIN_ROOT}/scripts/main" "$@"

Package Descriptor

Each plugin is described by a Package struct in the DDx registry. The descriptor declares what to install and where:

name: my-plugin
version: 1.0.0
description: A workflow plugin for DDx
type: workflow
source: https://github.com/you/my-plugin
keywords:
  - workflow
  - methodology
install:
  root:
    source: "."                           # entire repo
    target: ".ddx/plugins/my-plugin"      # project-local install
  skills:
    - source: ".agents/skills/"           # skills dir in repo
      target: ".agents/skills/"           # symlinked here
    - source: ".agents/skills/"
      target: ".claude/skills/"           # and here
  scripts:
    source: "bin/my-plugin"               # CLI in repo
    target: "~/.local/bin/my-plugin"      # symlinked here
  executable:                              # files that must be executable
    - "bin/my-plugin"
    - "scripts/main"

Package types

TypeDescription
workflowFull workflow methodology (skills + CLI + resources)
pluginTool plugin (e.g., quality checks)
persona-packCollection of AI personas
template-packCollection of project templates
resourceIndividual resource file

Install mappings

FieldPurposeBehavior
rootCopy entire plugin to .ddx/plugins/<name>/Full directory copy from tarball
skillsSymlink skill directories into agent pathsEach entry in source dir gets a symlink in target dir
scriptsSymlink CLI binarySingle symlink from target to root’s script
symlinksAdditional post-install symlinksArbitrary source→target symlinks
executablePaths (relative to root) that must be +xExecute bit set after root copy

When root is set, skills and scripts are symlinked from the installed root rather than copied from the tarball. This keeps everything in sync. When root is not set, skills and scripts are copied directly.

Registering Your Plugin

Currently, DDx uses a built-in Go registry. To add your plugin:

  1. Fork ddx
  2. Add your package to cli/internal/registry/registry.go in the BuiltinRegistry() function
  3. Open a PR with your Package definition

What to include in your PR

  • Package name, description, type, and source URL
  • Install mappings for root, skills, and scripts
  • Keywords for search discoverability
  • A tagged release on your plugin repo (DDx fetches release tarballs)

Example: HELIX registration

Package{
    Name:        "helix",
    Version:     "1.0.0",
    Description: "Supervisory autopilot for AI-assisted software delivery",
    Type:        PackageTypeWorkflow,
    Source:      "https://github.com/DocumentDrivenDX/helix",
    Install: PackageInstall{
        Root: &InstallMapping{
            Source: ".",
            Target: ".ddx/plugins/helix",
        },
        Skills: []InstallMapping{
            {Source: ".agents/skills/", Target: ".agents/skills/"},
            {Source: ".agents/skills/", Target: ".claude/skills/"},
        },
        Scripts: &InstallMapping{
            Source: "bin/helix",
            Target: "~/.local/bin/helix",
        },
        Executable: []string{"bin/helix", "scripts/helix"},
    },
    Keywords: []string{"workflow", "methodology", "ai", "development"},
}

Future: a registry.yaml in the ddx-library repo will replace the built-in registry so plugins can be added without modifying DDx itself.

CLI Commands

ddx search <query>           # Search available packages
ddx install <name>           # Install a plugin or workflow
ddx install <name> --force   # Reinstall even if up to date
ddx installed                # List installed packages
ddx outdated                 # Check for available updates
ddx uninstall <name>         # Remove an installed package

Individual resources

You can also install individual resources from the DDx library without creating a full plugin:

ddx install persona/strict-code-reviewer   # Install one persona
ddx install template/go-service            # Install one template

These are fetched directly from the ddx-library repo and placed in .ddx/library/<type>/.

Plugin Development

Path references

Skills and prompts reference resources using paths relative to the project root. Since the plugin is installed at .ddx/plugins/<name>/, all paths must use that prefix:

# Good — resolves from any project that installs the plugin
Read `.ddx/plugins/my-plugin/prompts/build.md`
Read `.ddx/plugins/my-plugin/templates/design-doc.md`

# Bad — only works if plugin repo is the working directory
Read `prompts/build.md`

Dev environment setup

When developing your plugin, create a symlink so the installed paths resolve from within your repo:

mkdir -p .ddx/plugins
ln -sfn ../.. .ddx/plugins/my-plugin

Add .ddx/plugins/ to your .gitignore — it’s a dev convenience, not repo content.

Doctor checks

Add a health check to your CLI’s doctor command that verifies .ddx/plugins/<name>/ exists in the target project. This catches the case where someone has skills installed but the plugin root is missing.

Pre-commit guard

Add a lefthook or pre-commit check that catches bare resource paths. The pattern depends on your plugin’s internal structure — catch any references that skip the .ddx/plugins/<name>/ prefix:

# lefthook.yml
pre-commit:
  commands:
    check-plugin-paths:
      run: |
        # Adapt the grep pattern to match your plugin's resource directories
        if grep -rn '`prompts/\|`templates/\|`patterns/' skills/ --include='*.md' 2>/dev/null \
           | grep -v '.ddx/plugins/my-plugin/'; then
          echo "ERROR: Use .ddx/plugins/my-plugin/ prefix for resource paths"
          exit 1
        fi
      glob: "skills/**/*.md"

Testing

# Install your plugin from the registry
ddx install my-plugin

# Verify the plugin root
ls .ddx/plugins/my-plugin/

# Verify skills are symlinked
ls -la .agents/skills/my-*
ls -la .claude/skills/my-*

# Verify the CLI is symlinked (if applicable)
ls -la ~/.local/bin/my-plugin

# Run your doctor (if applicable)
my-plugin doctor

Version Management

  • DDx checks GitHub for the latest tagged release when installing
  • ddx install <name> skips if already at the latest version (use --force to reinstall)
  • ddx outdated compares installed versions against latest releases
  • Plugin repos should use semver tags (v1.0.0, v1.1.0, etc.)