Getting Started

cikit is a lightweight CI helper framework for building local development and CI workflows from reusable Python components.

The cikit console command combines commands from installed command-provider packages with optional project-local commands. Local commands can extend the installed command set or override individual provider commands.

Installation

Install cikit with pip:

pip install cikit

or add it as a development dependency with uv:

uv add --dev cikit

The package provides the cikit console command.

Command Setup

A project can obtain commands in two ways:

  • install a reusable command-provider package

  • define project-local commands in a root-level ci_commands package

Both approaches can be combined.

Installed Provider

A command provider registers a Python package through the cikit.commands entry-point group. Once that package is installed, its commands are discovered automatically.

For example, a project may keep cikit and a shared provider in its development dependencies:

[dependency-groups]
dev = [
    "cikit",
    "company-ci-commands",
]

No local ci_commands package is required when all needed commands come from installed providers.

Project-Local Commands

Create a root-level ci_commands package when the project needs its own commands, orchestration, or overrides:

project/
|-- ci_commands/
|   |-- __init__.py
|   `-- check.py
|-- src/
|-- tests/
`-- pyproject.toml

The package name ci_commands is fixed. Public modules inside it are discovered automatically.

A local command with the same COMMAND_NAME as an installed provider command overrides that provider command.

First Project Command

Every command module declares a logical command name and provides a register() function.

A minimal command can look like this:

import argparse

from cikit import CiSection
from cikit.ci import run_ci_script


COMMAND_NAME = "check"


def run(env, status, _args: argparse.Namespace):
    with CiSection("Checking project", status=status):
        print(f"Project: {env['PROJECT_NAME']}")


def command(args: argparse.Namespace) -> int:
    return run_ci_script(
        COMMAND_NAME,
        lambda env, status: run(env, status, args),
        args=args,
    )


def register(subparsers: argparse._SubParsersAction):
    parser = subparsers.add_parser(COMMAND_NAME, help="Run project checks.")
    parser.set_defaults(func=command)

With this module stored as:

ci_commands/check.py

the command is available as:

uv run cikit check

Use:

uv run cikit --help

to list the effective commands from installed providers and the current project.

For the complete discovery rules, provider-package structure, conflict handling, and recommended command module structure, see CI Commands.

Global Options

The cikit command provides global options before the selected command.

Verbose logging can be enabled with:

uv run cikit --verbose check

The logical run name can be overridden with:

uv run cikit --name custom-check check

The logical run name is used by cikit data and artifact metadata.

Reusable Workflows

Commands normally orchestrate reusable cikit macros instead of implementing tool integration themselves.

For example, a command set may provide commands for:

  • linting

  • tests

  • coverage

  • CMake or PlatformIO builds

  • report generation

  • Sphinx documentation

Reusable commands can live in an installed command provider. Project-specific policy and orchestration can remain in local ci_commands.

The cikit repository itself uses commands such as:

init
ruff
pylint
test
coverage
sphinx
all

These names are examples of one workflow and are not built-in commands that every cikit installation receives automatically.

Local Workflow

Projects may optionally provide an orchestration command such as:

uv run cikit all

Such a command can combine existing provider and local commands into one local workflow.

The orchestration strategy, step order, and command arguments remain project-specific.

See Local Pipeline for the recommended approach.

Output

The standard cikit environment uses:

PUBLIC_DIR=${PROJECT_ROOT}/public
CIKIT_DATA_DIR=${PUBLIC_DIR}/cikit_data

Registered artifacts are stored below PUBLIC_DIR according to their artifact type.

Projects should use the cikit artifact API rather than constructing artifact paths directly.

For details, see:

Coverage Example

If a project collects coverage data across several test runs, the test commands can write intermediate data into a shared directory such as:

build/coverage

A coverage command can then process that directory.

For a project using the same command interface as the cikit repository, this would look like:

uv run cikit --name unittests test tests/unittests --coverage-dir build/coverage

uv run cikit --name systemtests test tests/systemtests --coverage-dir build/coverage

uv run cikit coverage build/coverage

The availability and arguments of these commands depend on the installed command providers and optional local overrides.

Documentation

Projects can integrate generated cikit reports and artifacts into Sphinx.

A project using a corresponding command implementation can build documentation with a command such as:

uv run cikit sphinx docs

The command normally wraps the reusable cikit.macros.sphinx functionality.

See:

CI Providers

The same commands can be used locally and in supported CI environments.

cikit currently provides CI-provider integration for:

  • GitLab CI

  • Azure DevOps

  • local Git execution

CI providers are separate from command providers. CI-provider detection and metadata are exposed through the common cikit environment regardless of where a command implementation was discovered.

For provider-specific setup, see:

Next Steps

After the first command is working, the following guides provide the next level of detail: