Thank you for considering contributing to Confy CLI! This project was developed with dedication by Brazilian students 🇧🇷 and we value all contributions, whether they are bug fixes, new features, documentation improvements, or tests.
To ensure an organized workflow and a good experience for everyone, please follow the guidelines below.
- Code of Conduct
- Getting Started
- Development Environment Setup
- Project Structure
- Contribution Workflow
- Code Standards
- Quality Tools
- Testing the CLI
- Running the Project Locally
- Creating a Pull Request
- Review Process
- Reporting Security Issues
We are committed to maintaining a welcoming, safe, and collaborative environment. Everyone should be treated with respect, regardless of age, gender identity, sexual orientation, ethnicity, religion, or experience level.
Unacceptable behaviors include:
- Harassment, discrimination, or insults
- Sexualized language or content
- Threats or personal attacks
- Unauthorized disclosure of private information
To report violations, contact: confy@henriquesebastiao.com
Before you begin, make sure you have:
- Git installed and configured
- Python 3.13 or higher (we support Python 3.13+)
- Poetry for dependency management (recommended)
- A GitHub account
python --version
poetry --version
git --version- Go to github.com/confy-security/cli
- Click the "Fork" button in the top right corner
- This will create a copy of the repository in your account
git clone https://github.com/YOUR-USERNAME/cli.git
cd cligit remote add upstream https://github.com/confy-security/cli.git
git remote -v # Verify you have 'origin' and 'upstream'poetry installThis command will:
- Create a virtual environment (if it doesn't exist)
- Install all main and development dependencies
- Automatically activate the virtual environment
If the environment was not activated automatically:
poetry shellOr execute commands within the environment with:
poetry run <command>cli/
├── .github/
│ ├── CODEOWNERS # Code owners
│ ├── dependabot.yml # Dependabot configuration
│ └── workflows/
│ └── test.yml # Test pipeline
├── confy_cli/
│ ├── __init__.py # Main package
│ ├── main.py # Main CLI entry point
│ ├── settings.py # Configuration management
│ ├── utils.py # Utility functions
│ └── core/
│ ├── __init__.py
│ └── constants.py # Project constants
├── .env.example # Environment variables example
├── .gitignore # Git ignore rules
├── pyproject.toml # Poetry and project config
├── poetry.lock # Dependency lock file
├── CONTRIBUTING.md # This file
├── CODE_OF_CONDUCT.md
├── SECURITY.md
├── README.md
└── LICENSEAlways create a separate branch for each contribution:
# Update from the main branch
git checkout main
git pull upstream main
# Create and switch to a new branch
git checkout -b type/short-description
# Example branch names:
# - feature/add-message-encryption
# - bugfix/fix-websocket-connection
# - docs/improve-readme
# - test/add-cli-testsBranch naming conventions:
feature/- For new featuresbugfix/- For bug fixesdocs/- For documentation improvementstest/- For adding/improving testsrefactor/- For code refactoring
Make changes to the code following the project standards (see Code Standards section).
# Edit files as needed
vim confy_cli/main.py
# See the status of changes
git status
# Stage changes
git add .Write descriptive commit messages:
git commit -m "Add message signing functionality"Best practices for commit messages:
- Use the imperative mood ("add" instead of "added")
- Start with a capital letter
- Don't use a period at the end
- Limit the first line to 50 characters
- Add a more detailed description after a blank line if needed
Complete example:
Fix WebSocket connection timeout issue
- Increase default connection timeout
- Add exponential backoff retry logic
- Improve error messagesThe Confy CLI project follows rigorous quality and style standards. Understanding these standards is essential.
The project uses Ruff for static analysis and code formatting.
Active rules:
I- Import sortingF- Pyflakes errorsE- PEP 8 style errorsW- PEP 8 style warningsPL- PylintPT- PytestD- Docstrings (Pydocstyle)UP- Syntax updatesPERF- Performance optimizations
Main configurations:
- Maximum line length: 99 characters
- Quote style: Single quotes (
') - Preview: Enabled (uses experimental Ruff features)
✅ Correct:
"""Module docstring explaining the module."""
import asyncio
from typing import Final
import typer
from confy_addons import AESEncryption
from confy_cli.settings import get_settings
TIMEOUT: Final[int] = 30
class MessageHandler:
"""Handle encrypted message operations."""
def __init__(self, key: bytes) -> None:
"""Initialize message handler.
Args:
key: The encryption key.
Raises:
TypeError: If key is not bytes.
"""
if not isinstance(key, bytes):
raise TypeError('key must be bytes')
self._key = key
async def encrypt_message(self, plaintext: str) -> str:
"""Encrypt a plaintext message.
Args:
plaintext: The text to encrypt.
Returns:
str: The encrypted message in base64.
"""
aes = AESEncryption(self._key)
return aes.encrypt(plaintext)❌ Incorrect:
# Missing module docstring
import asyncio
import typer
from confy_addons import AESEncryption # Wrong order
from confy_cli.settings import get_settings
TIMEOUT = 30 # No type hint
class MessageHandler:
# Missing class docstring
def __init__(self, key: bytes) -> None: # Missing method docstring
if not isinstance(key, bytes):
raise TypeError("key must be bytes") # Double quotes
self._key = key
async def encrypt_message(self, plaintext: str) -> str: # Missing docstring
aes = AESEncryption(self._key)
return aes.encrypt(plaintext)Use type hints in all public methods:
async def receive_messages(websocket) -> None:
"""Receive and process incoming messages."""
...
def get_protocol(url: str) -> tuple[str, str]:
"""Determine WebSocket protocol from URL."""
...
@property
def is_connected(self) -> bool:
"""Return connection status."""
return self._connectedFollow the Google Style standard for docstrings:
async def send_message(self, message: str, recipient_id: str) -> None:
"""Send an encrypted message to a recipient.
Encrypts the message using the established AES key and sends it
through the WebSocket connection.
Args:
message: The plaintext message to send.
recipient_id: The ID of the recipient.
Raises:
ValueError: If AES key is not established.
websockets.ConnectionClosed: If connection is closed.
"""Use constants for magic values (already defined in confy_cli/core/constants.py):
from confy_cli.core.constants import RAW_PAYLOAD_LENGTH
# ✅ Correct
payload_parts = raw_payload.split('::')
if len(payload_parts) != RAW_PAYLOAD_LENGTH:
raise ValueError('Invalid payload format')
# ❌ Incorrect
if len(payload_parts) != 2: # Magic number!
raise ValueError('Invalid payload format')Use the utility functions from confy_cli.utils for consistent output:
from confy_cli.utils import debug, alert, received
# Debug output (only if DEBUG=true)
debug('Connected to peer')
# Alert message
alert('Waiting for recipient to connect...')
# Received message
received('Hello, World!')The project uses several tools to ensure quality. All are automatically executed by GitHub Actions.
Check code:
poetry run ruff check .Format code automatically:
poetry run ruff format .
poetry run ruff check . --fixChecks the correctness of type hints:
poetry run mypy -p confy_cli --ignore-missing-importsExample of detected error:
# MyPy will complain about this:
result: int = await async_function() # Type mismatchAnalyzes cyclomatic complexity:
poetry run radon cc ./confy_cli -a -naA = average | NA = non-aggregated (shows details per function)
Checks for security issues:
poetry run bandit -r ./confy_cliRun all quality checks before committing:
# Check code style
poetry run ruff check .
# Format code
poetry run ruff format .
# Type checking
poetry run mypy -p confy_cli --ignore-missing-imports
# Security check
poetry run bandit -r ./confy_cli
# Code complexity
poetry run radon cc ./confy_cli -a -na# 1. Create and switch to feature branch
git checkout -b feature/my-feature
# 2. Make changes to the code
vim confy_cli/main.py
# 3. Format and check code
poetry run ruff format .
poetry run ruff check . --fix
# 4. Run type checking
poetry run mypy -p confy_cli --ignore-missing-imports
# 5. Run security checks
poetry run bandit -r ./confy_cli
# 6. If all passes, stage and commit
git add .
git commit -m "Add new feature"
# 7. Push to your fork
git push origin feature/my-featureTest your changes manually:
# Build and install the package locally
poetry install
# Run the CLI
poetry run confy start my-user-id recipient-id
# Or if installed globally
confy start my-user-id recipient-idError: Poetry not found
pip install poetry
poetry --versionError: Virtual environment not activated
poetry shell
# or use 'poetry run' before each commandError: WebSocket connection fails
Check that:
- The server address is correct
- The server is running and accessible
- User IDs are valid and exist on the server
- Network connectivity is available
Before pushing, synchronize with the main branch:
git fetch upstream
git rebase upstream/mainIf there are conflicts, resolve them and continue:
git add .
git rebase --continuegit push origin feature/your-feature- Go to your fork on GitHub
- You will see a "Compare & pull request" suggestion
- Click and fill in the PR template
PR Template:
## 📝 Description
Brief and clear description of what was changed and why.
## 🎯 Type of Change
- [ ] Bug fix (fix that doesn't break existing functionality)
- [ ] New feature (adds functionality that doesn't break existing features)
- [ ] Breaking change (alters existing functionality)
- [ ] Documentation
- [ ] Code refactoring
## 🔍 Checklist
- [ ] I ran `poetry run ruff format .` and the code is formatted
- [ ] I ran `poetry run ruff check .` and there are no errors
- [ ] I ran `poetry run mypy -p confy_cli` and there are no type errors
- [ ] I ran `poetry run bandit -r ./confy_cli` and there are no security issues
- [ ] I ran `poetry run radon cc ./confy_cli -a -na` and complexity is acceptable
- [ ] I tested the changes manually
- [ ] I updated documentation if necessary
- [ ] My PR has no conflicts with the main branch
## 🖼️ Testing (if applicable)
Describe how you tested these changes or any special testing considerations.
## 📚 References
Links to related issues or relevant documentation.
Closes #123Keep the conversation professional and constructive:
- Answer all questions from reviewers
- Make requested changes with new commits
- If you disagree, explain your viewpoint educatedly
- Ask for clarification if you don't understand
- Code follows standards - Ruff, MyPy, Bandit, Radon
- Quality checks pass - All automated tests must pass
- Documentation updated - Docstrings updated if needed
- Well-structured commits - Clear and atomic messages
- No breaking changes - Unless explicitly intended
- Submit the PR
- Automated tests run in CI/CD (GitHub Actions)
- Team members review the code
- Changes are requested (if necessary)
- You make adjustments and push new commits
- After approval, the PR is merged
- Receive feedback as a learning opportunity
- Review others' code constructively
- Use professional and courteous tone
- Focus on the code, not the person
To report a security vulnerability:
- Send an email to: confy@henriquesebastiao.com
- Include:
- Detailed description of the issue
- Steps to reproduce
- Code example if possible
- Affected version
The team will respond within 48 hours. See SECURITY.md for more details.
- Fork the repository
- Clone your fork
- Create a branch (
git checkout -b feature/my-feature) - Make changes and commits
- Push to your fork
- Create a Pull Request
Use Python 3.13 or higher for development. The project requires Python 3.13+.
git clone https://github.com/YOUR-USERNAME/cli.git
cd cli
poetry install
poetry shellYou need a running Confy server to test the CLI. You can:
- Set up the server locally
- Connect to a test server if available
- Contribute to the server project as well
Run Radon to check complexity:
poetry run radon cc ./confy_cli -a -naRefactor if necessary. PRs with very high complexity may be rejected.
Check the Ruff documentation.
You can help by:
- Reporting bugs
- Improving documentation
- Translating documentation
- Testing the CLI
- Sharing ideas for features
- 🔧 Ruff Documentation
- 📚 Poetry Documentation
- 🔐 Cryptography Library
- 📡 Websockets Library
- 🎯 Typer Documentation
Your contribution makes this project better. If you have questions, open an issue or contact us through the email above.
Built with ❤️ by Brazilian students