Plugin system (development)
This document describes how the DataRobot CLI plugin system works and how to build a plugin.
See more information on Confluence at DataRobot CLI Integration Analysis.
Overview
Plugins are external executables that extend the dr CLI with additional top-level commands.
- A plugin executable is discovered under the name pattern
dr-*. - When discovered, the CLI queries the executable for a JSON manifest.
- The manifest declares the command name and metadata shown in
dr plugin list. - When a user runs
dr <plugin-command> ..., the CLI executes the plugin binary and forwards all arguments.
Discovery
At CLI startup, plugins are discovered from:
- Project-local
.dr/plugins/directory (highest priority) - Every directory on your
PATH
Only files whose filename begins with dr- are considered.
The CLI also verifies the candidate is executable (via Go's runtime exec.LookPath).
Deduplication
Plugins are deduplicated by manifest.name (not by filename). If multiple binaries report the same manifest.name, the first discovered one wins and later ones are skipped.
Timeouts
- Overall discovery is bounded by the global flag
--plugin-discovery-timeout(default2s). - Set to
0sto disable plugin discovery entirely. - Manifest retrieval is bounded by
plugin.manifest_timeout_ms(default500ms).
Testing notes
The default 500ms timeout is occasionally exceeded under heavy test load (e.g. task test with -race).
Test suites that exercise plugin discovery should:
- Call
viperx.Reset()inSetupTest/TearDownTestto prevent config-file or env-var values from leaking into the manifest timeout. - Set a generous test-specific timeout before discovering:
viperx.Set("plugin.manifest_timeout_ms", 5000)(5 seconds).
Manifest protocol
To be recognized as a plugin, the executable must respond to the special argument:
The command must write a single JSON object to stdout and exit with code 0.
Manifest JSON schema
The CLI currently understands the following fields:
{
"name": "my-plugin",
"version": "1.2.3",
"description": "Adds extra commands to dr",
"authentication": true
}
Required fields
name(string): The command name the CLI will register.- Example:
{"name":"my-plugin",...}becomes the top-level commanddr my-plugin. - Must be non-empty (plugins missing this field are rejected).
Optional fields
version(string): Displayed indr plugin list(shown as-if empty).description(string): Displayed indr plugin listand used as the command short help when registered asdr <name>.authentication(boolean): Whentrue, the CLI will check for valid DataRobot authentication before executing the plugin.- If no valid credentials exist, the user will be prompted to log in.
- Respects the global
--skip-authflag. - Defaults to
falseif omitted.
Notes / recommendations
- Keep manifest output small and fast; it is called during discovery.
- The manifest should be deterministic and should not require network access.
- The plugin should handle
--dr-plugin-manifestbefore doing any other work (and should not print extra output in this mode).
Execution
When a user runs:
The CLI:
- Prints a short info line indicating which plugin is being run.
- If the plugin manifest has
"authentication": true, checks for valid authentication and prompts for login if needed. - Executes the plugin binary.
- Passes all remaining arguments to the plugin verbatim.
- Exits with the same exit code as the plugin.
Because plugin commands are registered as top-level commands, a plugin cannot conflict with an existing built-in command name.
Authentication
If your plugin needs to interact with the DataRobot API, set "authentication": true in your manifest. This ensures users are authenticated before your plugin runs.
Example manifest with authentication:
{
"name": "assist",
"version": "0.1.6",
"description": "AI agent design, coding, and deployment assistant",
"authentication": true
}
When authentication is enabled:
- The CLI checks for valid credentials from environment variables (DATAROBOT_ENDPOINT, DATAROBOT_API_TOKEN) or the config file.
- If no valid credentials exist, the user is automatically prompted to log in via dr auth login.
- Authentication can be bypassed with the global --skip-auth flag (for advanced users).
- Your plugin will receive a clean environment with authentication already validated
Developing a plugin
Minimum requirements:
- Name the executable
dr-<something>. - Ensure it is executable (
chmod +x). - Implement
--dr-plugin-manifestto print valid JSON with at leastname. - Put it in
.dr/plugins/or onPATH.
Troubleshooting: dr <command> not found
If you run dr <command> expecting <command> to be provided by a plugin, but the CLI reports it as an unknown command, check:
- Is the plugin discoverable? Run:
If the plugin is not listed, it was not discovered during startup.
- Is the plugin executable accessible on
PATH? The CLI discovers plugins from.dr/plugins/and fromPATH. - Ensure the plugin binary is named
dr-<something>and is executable. - Ensure the directory containing
dr-<something>is on yourPATH. -
You can verify with your shell, e.g.:
-
Did you disable or time out discovery? If
--plugin-discovery-timeoutis0s(disabled) or too low, plugins may not be registered.
Related commands
dr plugin list/dr plugins list: show discovered plugins and their manifest metadata.
Packaging and publishing plugins
The CLI provides tools to help package and publish plugins to a plugin registry.
Quick start: publish command (recommended)
The easiest way to package and publish a plugin is the all-in-one publish command:
This command does everything in one step:
1. Validates the plugin manifest
2. Creates a .tar.xz archive
3. Copies it to plugins/<plugin-name>/<plugin-name>-<version>.tar.xz
4. Updates the registry file (index.json)
Example:
# Publish to default location (docs/plugins/)
dr self plugin publish ./my-plugin
# Publish to custom location
dr self plugin publish ./my-plugin --plugins-dir dist/plugins --index dist/plugins/index.json
# Output:
# ✅ Published my-plugin version 1.0.0
# Archive: docs/plugins/my-plugin/my-plugin-1.0.0.tar.xz
# SHA256: abc123...
# Registry: docs/plugins/index.json
Advanced: manual workflow
For more control over the packaging process, you can use the individual commands:
Packaging a plugin
Use dr self plugin package to create a distributable .tar.xz archive:
Flags:
- -o, --output: Output file path or directory (default: current directory)
- If path ends with .tar.xz, uses exact filename
- Otherwise treats as directory and creates <plugin-name>-<version>.tar.xz inside
- --index-output: Save registry JSON fragment to file for use with dr self plugin add --from-file
Requirements:
- Plugin directory must contain a valid manifest.json with name and version fields
The command will:
1. Validate the manifest
2. Create a compressed .tar.xz archive
3. Calculate SHA256 checksum
4. Optionally save metadata to a file for easy registry updates
5. Output a JSON snippet ready for your plugin registry
Examples:
# Package to current directory (creates my-plugin-1.0.0.tar.xz)
dr self plugin package ./my-plugin
# Package to specific directory
dr self plugin package ./my-plugin -o dist/
# Package with custom filename
dr self plugin package ./my-plugin -o dist/custom-name.tar.xz
# Package and save metadata for later
dr self plugin package ./my-plugin -o dist/ --index-output /tmp/my-plugin.json
# Output:
# ✅ Package created: dist/my-plugin-1.0.0.tar.xz
# SHA256: abc123...
# 📝 Registry fragment saved to: /tmp/my-plugin.json
#
# Add to registry (index.json):
# ```json
# {
# "version": "1.0.0",
# "url": "my-plugin/my-plugin-1.0.0.tar.xz",
# "sha256": "abc123...",
# "releaseDate": "2026-01-28"
# }
# ```
Adding to Plugin Registry
Use dr self plugin add to add the packaged version to your plugin registry.
Option 1: Using saved metadata (recommended):
# Package and save metadata
dr self plugin package ./my-plugin --index-output /tmp/my-plugin.json
# Add to registry using the saved file
dr self plugin add docs/plugins/index.json --from-file /tmp/my-plugin.json
Option 2: Manual entry:
dr self plugin add <path-to-index.json> \
--name my-plugin \
--version 1.0.0 \
--url my-plugin/my-plugin-1.0.0.tar.xz \
--sha256 abc123... \
--release-date 2026-01-28
The add command will:
- Create the registry file if it doesn't exist
- Add a new plugin entry or append a new version to an existing plugin
- Validate that the version doesn't already exist
- Format the registry with proper JSON indentation
Complete workflow example:
# Quick: One command to do it all
dr self plugin publish ./my-plugin
# Or manual workflow:
# 1. Package the plugin and save metadata
dr self plugin package ./my-plugin -o docs/plugins/ --index-output /tmp/my-plugin.json
# 2. Add to registry using saved metadata
dr self plugin add docs/plugins/index.json --from-file /tmp/my-plugin.json
# 3. Commit and publish
git add docs/plugins/
git commit -m "Add my-plugin v1.0.0"
git push