Everything runs in containers. There is no host Python environment to set up,
and you should not create one — make shells into the devctl image for every
check, so what you run locally is what CI runs.
Default branch is dev. Branch from it, open the PR against it.
git clone https://github.com/hkyss/devctl
cd devctl
make install && make boot && make doctormake doctor tells you what is missing. If it is unhappy about the workspace
root, devctl expects sibling repos under one parent directory (default
~/Projects/Github/, override with DEVCTL_WORKSPACE_ROOT).
make check # compile, ruff lint, ruff format --check, example profile validation
make test # unit testsBoth are what CI runs, so a green pair locally means a green PR. To apply formatting rather than just check it:
docker compose -f .docker/docker-compose.yml run --rm --entrypoint sh devctl \
-c 'cd "$DEVCTL_REPO_ROOT" && ruff format .'Rebuild the image after changing source, or the CLI keeps running the old code:
make build- Ruff with
E,F,I,UP,B,SIM, line length 140. Config lives inpyproject.toml. - No comments and no docstrings. If a piece of code needs explaining, the
explanation belongs in
docs/or in a name that makes the comment redundant. - Tests are plain
unittest, one file per command or module, namedtest_*.pyundertests/.
.devctl.json is a public contract — other repositories depend on it. Any
change to it means updating all three of:
schemas/devctl.profile.schema.json- the validation rules in
src/devctl/standard.py - the examples in
examples/profiles/
Adding a field is fine. Renaming or removing one is a breaking change and needs a major version.
Maintainers only:
devctl release minor # or major / patch / an explicit X.Y.ZThis tags and pushes; CI runs the checks and publishes the GitHub Release. The
version is baked into the image at build time, so run make build afterwards.
Include the output of devctl doctor, your .devctl.json, and the exact
command you ran. Local Docker setups differ enough that a report without them
is usually not actionable.