This repository contains a copier template.
You can use it to bootstrap the following types of project:
- eccenca Corporate Memory Python Plugin: Bootstrapping and keeping plugin repositories up-to-date was the initial idea of this template.
- Generic Python Project: After tons of commits, we wanted to use this template not only for plugins, but for all kinds of python projects.
Table of contents
- Python / poetry project with
- pytest (incl. memray + pytest-dotenv + code coverage) as the testing framework,
- ruff as all-hands linter and formatter,
- mypy as type checker,
- deptry as dependency issue checker, and
- trivy as dependency vulnerability scanner.
- A build plan for the host you name, never both
- gitlab when
github_pageis left blank, - github when it is given, and
- locally with task (tested for Linux, MacOS and Windows/MinGW).
- Including
- badge generation,
- JUnit XML file and
- coverage stat generation.
- gitlab when
- Agent support for Claude Code: rules, permissions and skills in every project, with extra skills for plugin projects.
The following command will create a new project directory with the latest released template. This produces a plugin which is compatible with the latest release of eccenca Corporate Memory.
Note: Select 'Generic Python Project' as an answer to the initial question to skip creation of plugin specific code.
$ copier copy gh:eccenca/cmem-plugin-template cmem-plugin-my
The following command will use the latest develop version of the template: This produces a plugin which is compatible with the latest development snapshot of eccenca Corporate Memory.
$ copier copy -r develop gh:eccenca/cmem-plugin-template cmem-plugin-my
After that, you need to initialize the repository and optionally install the git pre-commit hooks:
$ cd cmem-plugin-my
$ git init; git add .; git commit -m "init"
$ pre-commit install
Then you can run the local test suite and build a first deployment artefact:
task build
We continuously update this repository. This includes maintenance of dependencies, build plan updates and the adoption of new features from the plugin base library.
In order to upgrade your project to the latest template release, use the following command:
copier update
In order to prepare your project for the upcoming next release, use this command:
copier update -r develop
Please also have a look at the copier documentation.
The available tasks for your project can be listed like this (note that install and uninstall are only available in case you started a plugin project):
∴ task
task: Available tasks for this project:
* build: Build a tarball and a wheel package
* check: Run whole test suite incl. unit and integration tests
* clean: Removes dist, *.pyc and some caches
* install: Install plugin package in Corporate Memory
* uninstall: Uninstall plugin package in Corporate Memory
* check:deptry: Complain about unused or missing dependencies
* check:linters: Run all linter and static code analysis tests
* check:mypy: Complain about typing errors
* check:pytest: Run unit and integration tests
* check:ruff: Complain about everything else
* check:trivy: Scan for vulnerabilities using Trivy
* format:fix: Format Python files and fix obvious issues
* format:fix-unsafe: Format Python files and fix 'unsafe' issues
* poetry:install: Install dependencies managed by Poetry
You can extend this task list by creating a file TaskfileCustom.yaml in your repository root:
$ cat TaskfileCustom.yaml
---
version: '3'
tasks:
ttt:
desc: just a test
cmds:
- task --list
The following tools are needed for local task execution:
- Python 3.13.x
- copier (>= v9) for project template rendering and updating
- task (>= v3.29) for running build tasks (make sure to follow the installation instructions to avoid confusion with taskwarrior)
- poetry (>= v2.1) for packaging and dependency managing (needed plugins such as poetry-dynamic-versioning are declared with
[tool.poetry.requires-plugins]and installed automatically) - pre-commit (>= v2.20) for managing pre-commit hooks (optional)
Example installation of the requirements with pipx on Ubuntu:
sudo sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
python3 -m pip install --user pipx
python3 -m pipx ensurepath
pipx install copier
pipx install pre-commit
pipx install poetry
This template uses the pytest testing framework. Testing your plugin is crucial and should be done locally as well as integrated with eccenca Corporate Memory.
In order to setup access to a Corporate Memory deployment, you need to provide correct environment variables (see Corporate Memory Environment).
Without these variables, only standalone tests can be executed (see 2 skipped):
$ task check:pytest
...
... ===== 2 passed, 2 skipped in 0.09s =====
Whichever pipeline your project received needs the same environment variables as secrets:
- For github, go to Settings > Secret > Actions > New Repository Secret
- For gitlab, go to Settings > CI/CD > Variables (Expand) > Add Variable (protected, masked, all environments)
An example github pipeline can be seen at this github project.
In addition to the eccenca Corporate Memory credential secrets, a PYPI_TOKEN secret is needed by the publish path, which is generated only when the pypi question is answered yes.
In order to have the best PyCharm experience, when starting a project with this template, we suggest the following PyCharm plugins:
- Ruff will provide the linting hints which will be raised by the pipeline anyway.
- Taskfile will allow for starting tasks.
Generated projects ship a .claude/ directory for Claude Code. It is maintained in the template and updated with copier update.
.claude/rules/holds the instructions an agent reads in every session: which files belong to the template and are lost on the next update, that lint findings are fixed rather than silenced, and that user-visible changes need aCHANGELOG.mdentry..claude/settings.jsonallows the everyday commands (task check,task format:fix,task build,pytest,ruff,mypy) without a prompt, and formats edited files withtask format:fix.task installandtask uninstall, which change what is installed in a Corporate Memory deployment, are deliberately not allowed, so an agent has to ask for those. Note that the allowedtask checkruns the integration tests, which create and delete their own assets in the deployment configured in.env..claude/skills/holds the procedures an agent loads when it needs them:copier-updatein every project, andreleasein projects with a github URL, since the release procedure it describes is the tag-triggered GitHub one.
The template never writes a CLAUDE.md. That file belongs to your project - put your own instructions there, and they are read alongside the rules above. This also means an existing CLAUDE.md is never touched when you update the template.
Personal settings belong in .claude/settings.local.json, which is git-ignored.
Note that the allowed commands and the formatting hook only take effect once the workspace is trusted, which happens when you start Claude Code interactively in the project for the first time.
Plugin projects additionally receive:
plugin-documentation- how to write the text a user reads in Corporate Memory: what belongs in the task documentation as opposed to a parameter description, how choice parameters explain their values, and how tasks refer to each other.plugin-implementation- the conventions the eccenca plugin fleet converged on for the code itself: reaching a deployment withcmem-client, logging throughself.log, referencing the icon, declaring ports, honouring workflow cancellation, reporting progress while the task runs, typing secrets asPassword, and writing custom parameter types with autocompletion.plugin-testing- what can be tested standalone, when a test needs a deployment and how to mark it, and how test assets are created and cleaned up.
They also receive a rules file covering cmem-plugin-base, that cmem.cmempy.* is deprecated in favour of cmem-client, the needs_cmem marker, and the fact that task install and task uninstall change a running deployment.
An agent can talk to your deployment directly through the MCP servers Corporate Memory provides. These describe your deployment rather than a project, so they are not shipped with generated projects - add them once, for yourself:
$ claude mcp add --transport http cmem-build "$CMEM_BASE_URI/dataintegration/mcp"
$ claude mcp add --transport http cmem-explore "$CMEM_BASE_URI/dataplatform/mcp/streamable"
The following applies to plugin projects only. Generic Python projects are created without these files and settings.
By providing the correct cmemc environment variables in an .env file or directly in your environment, your plugin can be tested in an integrated way:
# Environment as direct variables:
$ export CMEM_BASE_URI="https://cmem.example.org"
$ export OAUTH_CLIENT_ID="cmem-service-account"
$ export OAUTH_CLIENT_SECRET="..."
$ export OAUTH_GRANT_TYPE="client_credentials"
# Environment as .env files
$ cat .env
CMEM_BASE_URI="https://cmem.example.org"
OAUTH_CLIENT_ID="cmem-service-account"
OAUTH_CLIENT_SECRET="..."
OAUTH_GRANT_TYPE="client_credentials"