Development Guide
August 25, 2026 · View on GitHub
This guide is for human contributors. AI-agent project guidance lives in AGENTS.md.
Purpose
Use this document for local setup, repository layout, repeatable development workflows, and architecture references. Public user documentation starts at docs/index.md.
Prerequisites
- Python 3.13+
pip(required)uv(recommended; required for the repository-automation checks below)
Supported Platforms
Crewplane supports Python 3.13 and newer on Linux, macOS, and WSL when the configured provider CLIs are available on that platform. Native Windows is not supported; use WSL on Windows hosts.
Pull-request CI runs on Linux for Python 3.13 and 3.14. Nightly CI runs on Linux and macOS for Python 3.13 and 3.14.
The tmux live dashboard requires tmux and is intended for Unix-like
environments. WSL supports the same tmux live mode as Linux.
Setup
cd crewplane
make setup
make setup installs the project in editable mode with development dependencies.
Local Workflows
make test # pytest suite with branch coverage
make typecheck # strict type checking for package and fixtures
make lint # project-env ruff check src tests scripts
make format # project-env ruff import fixes + format src tests scripts
make format-check # project-env ruff format --check src tests scripts
make check # lint + format-check + typing + uv pin check + tests
make uv-bootstrap-check # verify all pinned uv versions and checksums agree
make uv-bootstrap-update # update all uv pins and checksums to the latest release
make help # list package and release targets
make clean # remove caches and build artifacts
make uninstall # uninstall package from current environment
Test suite contract
make test runs the full suite with pytest entry-point plugin autoload
disabled. It loads pytest-cov explicitly and enforces 90% branch coverage.
Workspace-enabled Git tests require Git 2.34.1 or newer. CI runs the relevant source-policy tests against exactly Git 2.34.1 and fails if any selected test skips.
Nightly CI covers Linux and macOS on Python 3.13 and 3.14, shuffles the full suite with a reproducible seed, and repeats the focused reviewer-parallelism regression in fresh processes.
Repository Automation
GitHub Actions, issue templates, label automation, and community files are
tailored for the public crewplane repository. Use the same entry points
locally and in CI:
make setup
make check
make actionlint
uvx pre-commit==4.6.0 run --all-files --show-diff-on-failure
The Makefile falls back to python -m ... for project checks when uv is not
installed. The full repository-automation check uses uvx for pinned
pre-commit execution.
Current CI policy:
- Default branch:
master. - The supported platform matrix is defined in Supported Platforms.
- Production PyPI and npm publishing is local-only. Follow the
Release Workflow. After
make releasepublishes the packages and Git tag, the source repository's release Action publishes the GitHub Release and opens the Homebrew pull request. - Workflow actions and
uvare version-pinned.packaging/uv-bootstrap.jsonis the source of truth for theuvversion and installer checksums. The updater generatespackaging/uv-bootstrap-version.txtfrom this manifest for workflows; do not edit the generated file directly. This keeps scheduled updates from rewriting workflow definitions. - Weekly automation follows the Dependabot Python update. When that PR updates packaging/uv-bootstrap-version.txt, the workflow regenerates all uv bootstrap metadata and commits it to the same branch. Dependabot remains responsible for creating the PR.
Operational notes:
pull_request_targetlabel workflows do not check out or execute pull-request code.- Label definitions synchronize on
masterwhen.github/labels.jsonchanges; manual dispatch can intentionally prune labels that are no longer declared. - Before running
.github/workflows/testpypi.yml, create thetestpypiGitHub environment underSettings -> Environments, then register a free pending publisher at https://test.pypi.org/manage/account/publishing/ with projectcrewplane, ownercrewplaneai, repositorycrewplane, workflowtestpypi.yml, and environmenttestpypi. No repository secret is required.
Cleanup and Deletion
Use these commands when you need to remove generated files or reset local state:
# Remove caches and build artifacts
make clean
# Remove generated run outputs only
rm -rf .crewplane/execution-stages .crewplane/execution-results
# Full local reset (config + workflows + outputs)
rm -rf .crewplane
# Uninstall package from current environment
make uninstall
Project Structure
crewplane/
├── src/
│ └── crewplane/
│ ├── cli/ # CLI command surface, run helpers, cleanup, templates
│ ├── core/ # Config/workflow schemas, parsing, composition, preflight
│ ├── architecture/ # Stable integration contracts, loader, registry
│ ├── adapters/ # Built-in integration implementations
│ ├── bootstrap/ # Composition root for runtime components
│ ├── runtime/ # Agent invocation and workflow execution
│ ├── artifacts/ # Output directories, manifests, results, resume, workspace state
│ ├── observability/ # Runtime event model, layout/rendering, tmux dashboard
│ └── example_templates/
├── tests/
├── docs/ # Public usage docs plus architecture decision records
├── pyproject.toml
├── Makefile
├── AGENTS.md
└── DEVELOPMENT.md
Version Sources
pyproject.toml owns the package distribution version. That version identifies installable releases and should change for every published release.
The authored Python schema version lives in src/crewplane/version.py. Generated templates render schema values from that constant. Bump it when supported user-authored config or workflow files change incompatibly. Backward-compatible additions, bug fixes, documentation updates, ordinary package releases, and public-alpha persisted run-artifact hard breaks do not require a schema version bump.
See ADR 0013 for the version source-of-truth decision.
| Version | Governs | Bump When |
|---|---|---|
pyproject.toml project.version | installable package release | every published release |
SCHEMA_VERSION | current config files, workflow files, and preflight execution-plan artifacts | supported user-authored schema changes incompatibly |
During the public-alpha 0.x period, support the current schema only. Persisted run artifacts are disposable audit outputs, not migration targets; stale preflight plans may be rejected by explicit shape validation even when they carry the current SCHEMA_VERSION.
Release Workflow
Production releases publish PyPI, npm, and the Git tag locally. The release
Action then publishes the GitHub Release and opens a Homebrew pull request for
the newest stable release. Publishing the tested bottles remains a manual
brew pr-pull step.
1. Prepare and validate
Update the version in pyproject.toml and add the matching section to
CHANGELOG.md. Review the changelog content manually, then run:
make release-prepare
make release-check
Both commands must pass before publication. Preparation stops if the target
version already exists on PyPI or npm. Some install checks may be skipped when
optional local tools such as pipx, npm, or Homebrew are unavailable; review
the skip messages before continuing.
2. Publish packages and the Git tag
Configure the PyPI and npm credentials, then run:
make release
Confirm the exact version when prompted. A successful run publishes PyPI,
publishes npm with the latest dist-tag, and pushes the annotated Git tag.
For a non-interactive npm release that requires two-factor authentication, set
NPM_PUBLISH_OTP or NPM_OTP. A separate npm latest recovery uses
NPM_DIST_TAG_OTP or NPM_OTP.
3. Publish the GitHub Release
After make release pushes the tag, run the source repository's release
GitHub Action from master. Enter the full Git tag, including the v prefix:
for package version 0.1.4, enter v0.1.4.
Dispatch it before master advances; the tag must point to the currently
selected master commit.
The Action publishes the GitHub Release. For the newest stable release, it also
automatically opens a pull request in crewplaneai/homebrew-crewplane.
4. Publish the tested Homebrew pull request
-
Wait for both the macOS and Linux
brew test-botchecks to pass and upload their bottles. -
Do not click the pull request's normal Merge button.
-
In
homebrew-crewplane, run thebrew pr-pullAction with:- The pull request number.
- Preferably the pull request's current head SHA, which prevents publishing a revision that was not tested.
The brew pr-pull Action collects the tested bottles, updates the formula's
bottle metadata, and pushes the completed release to main.
Recover an interrupted release
If only part of PyPI or one registry was published, fix the reported problem and rerun the corresponding target:
make release-pypi
make release-npm
These targets verify anything already published and complete only the missing
work. Use make release-npm when the npm package exists but its latest
dist-tag is stale. Once both registries are complete, rerun make release to
finish the Git tag.
TestPyPI
Use .github/workflows/testpypi.yml for TestPyPI Trusted Publishing. It may be
dispatched from any selected ref and stops if that package version already
exists on TestPyPI.
Key Modules
src/crewplane/cli/app.py: Typer app and commands (init,run,validate)src/crewplane/core/config.py: Pydantic config models and loadersrc/crewplane/architecture/ports/: Runtime integration port contractssrc/crewplane/architecture/loader.py: Alias and dotted implementation loadersrc/crewplane/bootstrap/container.py: Runtime composition rootsrc/crewplane/core/workflow/models.py: Workflow model schemasrc/crewplane/core/workflow/loading.py: Workflow file loadingsrc/crewplane/core/workflow/markdown/: Frontmatter and Markdown parsersrc/crewplane/core/workflow/composition/: Markdown imports, aliases, params, and input bindingsrc/crewplane/core/workflow/validation/: Workflow and provider validationsrc/crewplane/core/preflight/: Compiled runtime execution-plan previews and bundlessrc/crewplane/runtime/agent/invoker.py: Provider command invocation and retry logicsrc/crewplane/runtime/execution/workflow/__init__.py: DAG scheduling and node executionsrc/crewplane/artifacts/manager.py: Artifact and output manifest managementsrc/crewplane/artifacts/results/: Consolidated result writingsrc/crewplane/artifacts/resume/: Node-boundary resume validation and hydrationsrc/crewplane/artifacts/workspace/: Workspace artifact validation and descriptorssrc/crewplane/observability/runtime.py: Observer lifecycle and snapshot publishing
Testing Expectations
- New behavior must include tests.
- Bug fixes must include regression tests.
- Keep tests deterministic and filesystem-local.
- Integration implementations must include contract tests under
tests/integration/architecture/and adapter tests undertests/integration/adapters/. - Production code and typing fixtures must pass strict mypy via
make typecheck; CI also validates the built wheel's public typing. - Tests enforce branch coverage.
Mock Invoker Local Validation
Use the mock invoker integration for deterministic orchestration and UI checks without provider CLI calls:
settings:
integrations:
invoker:
implementation: "mock"
options:
delay_seconds: 0.25
observation_delay_seconds: 5
output_mode: "lorem"
seed: 42
output_mode: "lorem" also auto-emits a deterministic findings block for non-reviewer nodes that declare findings: true, so findings-based workflows can be exercised locally without hand-written fixtures. echo mode is exact for non-reviewer invocations, and fixture-backed file output is always exact; those authored outputs must include the findings block themselves when needed. Reviewer invocations in echo, lorem, and missing-fixture fallback paths emit a deterministic no-findings review contract.
observation_delay_seconds keeps mock runs visibly active in the live dashboard for a few seconds by default; set it to 0 when a test or local check should complete immediately.
Manual validation flow:
- Run
crewplane runwith the mock invoker. - Confirm node transitions (
pending -> running -> succeeded/failed) in the CLI or tmux UI. - Validate generated artifacts under
.crewplane/execution-stages/and.crewplane/execution-results/, including findings artifacts for findings-enabled nodes, run-root logs in.crewplane/execution-stages/<workflow>-<run_id>/logs/, and review-loop status artifacts in<node>/review-state/review-loop-status.jsonwhen a node uses sequential executor/reviewer review rounds. - If using
output_mode: "file", verify fixture fallback order,strict_file_modebehavior, and optional<fixture>.mutations.jsonsidecars when testing artifact-drift handling, workspace checkout mutations, or prompt sentinel requirements.
Coding Standards
Follow these project standards:
- Keep modules cohesive and boundaries explicit.
- Use explicit type hints for public APIs and non-trivial logic.
- Keep functions focused and readable.
- Validate at boundaries and fail explicitly.
- Avoid silent failure paths.
- Add deterministic tests for new behavior and regression coverage for bug fixes.
Architecture References
Crewplane follows a blackboard architecture: agents operate independently and communicate exclusively through structured Markdown artifacts in a shared workspace. That design drives the main engineering constraints in the runtime and artifact system.
- docs/architecture/modular-orchestration-architecture.md
- docs/architecture/adr/0001-ports-adapters-runtime-integrations.md
- docs/architecture/index.md
Adapter Authoring
- Implement the relevant port contract under
src/crewplane/architecture/ports/. - Register an alias in
src/crewplane/architecture/registry.pyor use a dotted path override in config. - Add adapter behavior tests under
tests/integration/adapters/. - Add architecture wiring tests under
tests/integration/architecture/. - Run quality gates before merge:
- targeted adapter and architecture tests for changed integrations
make lintmake format-checkmake test