跳到主要内容

Contributing

Thank you for contributing to KOPI O Agent! This guide covers setting up your dev environment, understanding the codebase, and getting your PR merged.

Contribution Priorities

We value contributions in this order:

  1. Bug fixes — crashes, incorrect behavior, data loss
  2. Cross-platform compatibility — macOS, different Linux distros, WSL2
  3. Security hardening — shell injection, prompt injection, path traversal
  4. Performance and robustness — retry logic, error handling, graceful degradation
  5. New skills — broadly useful ones (see Creating Skills)
  6. New tools — rarely needed; most capabilities should be skills
  7. Documentation — fixes, clarifications, new examples

Common contribution paths

Development Setup

Prerequisites

RequirementNotes
GitWith --recurse-submodules support, and the git-lfs extension installed
Python 3.11+uv will install it if missing
uvFast Python package manager (install)
Node.js 20+Optional — needed for browser tools and WhatsApp bridge (matches root package.json engines)

Clone and Install

git clone --recurse-submodules https://github.com/XingBaoKu/kopi-agent.git
cd kopi-agent

# Create venv with Python 3.11
uv venv venv --python 3.11
export VIRTUAL_ENV="$(pwd)/venv"

# Install with all extras (messaging, cron, CLI menus, dev tools)
uv pip install -e ".[all,dev]"
# tinker-atropos is a git submodule — needs `git submodule update --init` first
# if you didn't clone with `--recurse-submodules`
uv pip install -e "./tinker-atropos"

# Optional: browser tools
npm install

Configure for Development

mkdir -p ~/.kopi/{cron,sessions,logs,memories,skills}
cp cli-config.yaml.example ~/.kopi/config.yaml
touch ~/.kopi/.env

# Add at minimum an LLM provider key:
echo 'OPENROUTER_API_KEY=sk-or-v1-your-key' >> ~/.kopi/.env

Run

# Symlink for global access
mkdir -p ~/.local/bin
ln -sf "$(pwd)/venv/bin/kopi" ~/.local/bin/kopi

# Verify
kopi doctor
kopi chat -q "Hello"

Run Tests

pytest tests/ -v

Code Style

  • PEP 8 with practical exceptions (no strict line length enforcement)
  • Comments: Only when explaining non-obvious intent, trade-offs, or API quirks
  • Error handling: Catch specific exceptions. Use logger.warning()/logger.error() with exc_info=True for unexpected errors
  • Cross-platform: Never assume Unix (see below)
  • Profile-safe paths: Never hardcode ~/.kopi — use get_kopi_home() from kopi_constants for code paths and display_kopi_home() for user-facing messages. See AGENTS.md for full rules.

Cross-Platform Compatibility

Kopi officially supports Linux, macOS, WSL2, and native Windows (early beta — via PowerShell install). Native Windows uses Git Bash (from Git for Windows) for shell commands. A few features require POSIX kernel primitives and are gated: the dashboard's embedded PTY terminal pane (/chat tab) is WSL2-only. The native-Windows path is new and moves fast — if you're doing Windows-heavy dev, expect to hit and fix rough edges.

When contributing code, keep these rules in mind:

  • Don't add unguarded signal.SIGKILL references. It's not defined on Windows. Either route through gateway.status.terminate_pid(pid, force=True) (the centralized primitive that does taskkill /T /F on Windows and SIGKILL on POSIX), or fall back with getattr(signal, "SIGKILL", signal.SIGTERM).
  • Catch OSError alongside ProcessLookupError on os.kill(pid, 0) probes. Windows raises OSError (WinError 87, "parameter is incorrect") for an already-gone PID instead of ProcessLookupError.
  • Don't force the terminal to POSIX semantics. os.setsid, os.killpg, os.getpgid, os.fork all raise on Windows — gate them with if sys.platform != "win32": or if os.name != "nt":.
  • Open files with an explicit encoding="utf-8". The Python default on Windows is the system locale (often cp1252), which mojibakes or crashes on non-Latin text.
  • Use pathlib.Path / os.path.join — never manually concat with /. This matters less for strings the OS gives us back and more for strings we construct to hand to subprocesses.

Key patterns:

1. termios and fcntl are Unix-only

Always catch both ImportError and NotImplementedError:

try:
from simple_term_menu import TerminalMenu
menu = TerminalMenu(options)
idx = menu.show()
except (ImportError, NotImplementedError):
# Fallback: numbered menu
for i, opt in enumerate(options):
print(f" {i+1}. {opt}")
idx = int(input("Choice: ")) - 1

2. File encoding

Some environments may save .env files in non-UTF-8 encodings:

try:
load_dotenv(env_path)
except UnicodeDecodeError:
load_dotenv(env_path, encoding="latin-1")

3. Process management

os.setsid(), os.killpg(), and signal handling differ across platforms:

import platform
if platform.system() != "Windows":
kwargs["preexec_fn"] = os.setsid

4. Path separators

Use pathlib.Path instead of string concatenation with /.

Security Considerations

Kopi has terminal access. Security matters.

Existing Protections

LayerImplementation
Sudo password pipingUses shlex.quote() to prevent shell injection
Dangerous command detectionRegex patterns in tools/approval.py with user approval flow
Cron prompt injectionScanner blocks instruction-override patterns
Write deny listProtected paths resolved via os.path.realpath() to prevent symlink bypass
Skills guardSecurity scanner for hub-installed skills
Code execution sandboxChild process runs with API keys stripped
Container hardeningDocker: all capabilities dropped, no privilege escalation, PID limits

Contributing Security-Sensitive Code

  • Always use shlex.quote() when interpolating user input into shell commands
  • Resolve symlinks with os.path.realpath() before access control checks
  • Don't log secrets
  • Catch broad exceptions around tool execution
  • Test on all platforms if your change touches file paths or processes

Pull Request Process

Branch Naming

fix/description        # Bug fixes
feat/description # New features
docs/description # Documentation
test/description # Tests
refactor/description # Code restructuring

Before Submitting

  1. Run tests: pytest tests/ -v
  2. Test manually: Run kopi and exercise the code path you changed
  3. Check cross-platform impact: Consider macOS and different Linux distros
  4. Keep PRs focused: One logical change per PR

PR Description

Include:

  • What changed and why
  • How to test it
  • What platforms you tested on
  • Reference any related issues

Commit Messages

We use Conventional Commits:

<type>(<scope>): <description>
TypeUse for
fixBug fixes
featNew features
docsDocumentation
testTests
refactorCode restructuring
choreBuild, CI, dependency updates

Scopes: cli, gateway, tools, skills, agent, install, whatsapp, security

Examples:

fix(cli): prevent crash in save_config_value when model is a string
feat(gateway): add WhatsApp multi-user session isolation
fix(security): prevent shell injection in sudo password piping

Reporting Issues

  • Use GitHub Issues
  • Include: OS, Python version, Kopi version (kopi version), full error traceback
  • Include steps to reproduce
  • Check existing issues before creating duplicates
  • For security vulnerabilities, please report privately

Community

  • Discord: discord.gg/XingBaoKu
  • GitHub Discussions: For design proposals and architecture discussions
  • Skills Hub: Upload specialized skills and share with the community

License

By contributing, you agree that your contributions will be licensed under the MIT License.