Contributions are welcome! Whether it's a bug fix, new command, documentation improvement, or plugin — we appreciate your help.
# Fork and clone
git clone https://github.com/YOUR_USERNAME/cli.git
cd cli
# Install dependencies
uv sync --group dev
# Run all checks
make dev # format + lint + test
make check # format + lint + typecheck (no tests)- Create a branch from
main - Make your changes following the conventions below
- Run
make devto ensure everything passes - Run
make readmesif you added or modified packages - Submit a pull request
We use Conventional Commits:
feat(speak): add --speed flag for playback rate
fix(keys): handle expired key gracefully
docs(readme): update installation section
test(models): add filter edge case tests
chore: update dependencies
- Formatter/linter:
ruff(line-length 88, target py310) - Type checker:
mypy(strict mode) - Imports: Use
from __future__ import annotationsfor forward references - Type-only imports: Move into
TYPE_CHECKINGblocks
The fastest way is to use the scaffolding skill:
dg new-commandOr manually create a package under packages/ following the existing pattern. Every new package needs updates to:
packages/<name>/pyproject.toml— package metadata and entry point- Root
pyproject.toml— dependency +[tool.uv.sources] .github/release-please-config.json— component definition.github/.release-please-manifest.json— initial version.github/workflows/test.yml— test path
Then run make readmes to update all READMEs.
See AGENTS.md for detailed architecture documentation.
- Unit tests:
packages/*/tests/unit/ - Integration tests:
tests/ - Run all:
uv run pytest - Run one package:
uv run pytest packages/deepctl-cmd-speak/tests/ -v - CI matrix: Python 3.10-3.14, Linux/Windows/macOS
Create external plugins that extend the CLI:
from deepctl_core.base_command import BaseCommand
class MyCommand(BaseCommand):
name = "mycommand"
help = "My custom command"
def handle(self, config, auth_manager, client, **kwargs):
passRegister in your plugin's pyproject.toml:
[project.entry-points."deepctl.plugins"]
mycommand = "my_plugin.command:MyCommand"See packages/deepctl-plugin-example for a complete example.
- Bugs: Use the bug report template
- Features: Use the feature request template
- Docs: Use the docs improvement template
- Security: See SECURITY.md
Please read and follow our Code of Conduct.
By contributing, you agree that your contributions will be licensed under the MIT License.