Contributing to Ciri
Thank you for your interest in making Ciri better. This guide covers how to set up a development environment, the project structure, contribution workflows, and how to extend Ciri with new skills, toolkits, and subagents.
Ways to Contribute
- Bug reports — detailed reproduction steps help enormously
- Documentation improvements — correct inaccuracies, add examples, expand thin sections
- New built-in skills — add a skill to
src/skills/for the community - New subagents — add specialized agent configs to
src/subagents/ - Core improvements — middleware, CLI, persistence, streaming
- Tests — we always need more coverage
Development Setup
Prerequisites
- Python 3.12+
- uv (recommended) or pip
- Git
Clone and Install
git clone https://github.com/adimis-ai/ciri.git
cd ciri/ciri-cli-v1
# Install with uv (recommended)
uv sync
# Or with pip in a virtualenv
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Set Up API Keys
export ANTHROPIC_API_KEY="sk-ant-..." # or your preferred provider
Run Ciri
# Via uv
uv run ciri
# Or directly
python -m src
Project Structure
ciri-cli-v1/
├── src/
│ ├── __main__.py # CLI entrypoint, REPL, CiriCompleter
│ ├── agent.py # Ciri agent class, tool registration, MiddlewareBuilder
│ ├── copilot.py # create_copilot() — full LangGraph assembly
│ ├── controller.py # CiriController — stream, run, state management
│ ├── middlewares/ # All custom middleware classes
│ │ ├── memory.py # MemoryMiddleware
│ │ ├── skills.py # SkillsMiddleware + bootstrap
│ │ ├── subagents.py # SubAgentMiddleware
│ │ ├── toolkits.py # ToolkitInjectionMiddleware
│ │ └── inject_names.py # InjectAvailable{Tool,SubAgent,Skill}NamesMiddleware
│ ├── subagents/ # Built-in subagent implementations
│ │ ├── trainer_agent.py
│ │ ├── skill_builder.py
│ │ ├── toolkit_builder.py
│ │ ├── subagent_builder.py
│ │ └── web_researcher.py
│ ├── toolkit/ # Built-in tools
│ │ ├── web_crawler_tool.py
│ │ ├── script_executor_tool.py
│ │ └── human_follow_up_tool.py
│ ├── skills/ # Built-in skill packages (SKILL.md per skill)
│ └── utils.py # Shared utilities, harness dir helpers, autocomplete discovery
├── docs-site/ # Docusaurus documentation site
├── tests/ # Test suite
└── pyproject.toml # Build config, dependencies
Code Style
We use ruff for linting and black for formatting:
# Lint (with auto-fix)
ruff check src/ --fix
# Format
black src/
# Type check
mypy src/
Run these before every commit. CI will reject PRs that fail linting or type checks.
Testing
# Run all tests
pytest
# Run with coverage
pytest --cov=src --cov-report=term-missing
# Run a specific test file
pytest tests/test_middlewares.py
When adding new functionality:
- Write unit tests for pure functions and utilities
- Write integration tests that call
create_copilot()with a mock input and assert stream behavior - Use
controller.get_state()andcontroller.run()withserialize=Truefor snapshot tests
PR Workflow
-
Fork the repository and create a feature branch from
main:git checkout -b feature/my-feature -
Make your changes — keep commits focused and atomic.
-
Run checks locally:
ruff check src/ --fix && black src/ && mypy src/ && pytest -
Open a PR to
mainwith a clear description of:- What problem this solves
- How it was implemented
- How to test it
-
CI will run linting, type checks, and tests automatically.
-
Address review comments — maintainers aim to review within a week.
Commit Message Convention
Use conventional commits:
feat: add @harness: autocomplete trigger
fix: prevent ToolRetryMiddleware from retrying GraphInterrupt
docs: expand HITL security guide
refactor: extract harness discovery into utils.py
test: add integration test for SkillsMiddleware bootstrap
Adding a Built-in Skill
- Create a directory under
src/skills/<skill-name>/ - Add a
SKILL.mdwith YAML frontmatter:---
name: skill-name
description: Use this skill when... [trigger conditions]. Handles [capabilities].
license: MIT
---
# Skill Name Guide
[Playbook instructions] - Include any supporting reference files (
REFERENCE.md,FORMS.md, etc.) - Test by running Ciri —
SkillsMiddlewarebootstraps fromsrc/skills/on first run - Open a PR with the new skill directory
Quality bar for built-in skills:
descriptionmust be trigger-condition-oriented (not a feature list)- Playbook must be actionable with concrete examples
- No dependencies on private/internal APIs
- Include a license compatible with the project
Adding a Built-in Subagent
- Add implementation to
src/subagents/<subagent-name>.py - Register in
src/copilot.pyalongside the other builder subagents - If it needs a YAML config template, add it to the appropriate location
- Add tests that verify the subagent builds and produces valid output
Adding a Middleware
- Extend
AgentMiddlewarefrom the deepagents library:from langchain.agents.middleware import AgentMiddleware
class MyMiddleware(AgentMiddleware):
def wrap_model_call(self, request, handler):
request.system_prompt += "\n\nMy injected context"
return handler(request) - Register in
create_copilot()insrc/copilot.py - Add documentation in
docs-site/docs/internals/middlewares.md - Add tests covering the middleware's behavior in isolation
Documentation
The docs site lives in docs-site/ (Docusaurus 3). To run locally:
cd docs-site
npm install
npm start
The site will be at http://localhost:3000. Hot-reload is enabled.
Documentation standards:
- Write from Ciri's perspective — "Ciri does X" not "the system does X"
- Include Mermaid diagrams for architecture and sequence flows
- Keep individual pages under 300 lines
- Link to source files (e.g.,
src/middlewares/skills.py) for accuracy - Every new feature needs a corresponding docs page before merge
Reporting Bugs
When opening a bug report, include:
- Steps to reproduce — minimal, exact steps
- Expected behavior — what should happen
- Actual behavior — what actually happens, including any error output
- Environment:
- OS and version
- Python version (
python --version) - Ciri version (
pip show ciri) - Model provider and model name
- Logs — relevant lines from the terminal output
Use GitHub Issues: github.com/adimis-ai/ciri/issues
Code of Conduct
Be respectful. We're building something useful together. Harassment, discrimination, or bad-faith arguments are not welcome.