Contributing
Contributing Guide
Thank you for taking the time to contribute. Every bug report, doc fix, and pull request makes Ferret better.
Full guide in the repo
The complete contributing guide — including extension walkthroughs for new AI providers, platforms, slash commands, vector stores, and agent channels — lives in CONTRIBUTING.md.
Development setup
| Tool | Version |
|---|---|
| Rust | stable ≥ 1.78 (rustup update stable) |
| Cargo | bundled with Rust |
| Git | any recent |
| Ollama | optional, for RAG tests |
| Docker | optional, for Qdrant / ChromaDB |
shell
git clone https://github.com/Arunachalamkalimuthu/merlin-ai-code-review.gitcd ferretcargo build # debug build — verifies everything compilescargo test # run all 93+ tests
Local quality gate
All three commands must pass before opening a PR.
shell
cargo fmt --check # formattingcargo clippy -- -D warnings # zero warnings requiredcargo test # all tests
Project structure
| Path | Purpose |
|---|---|
src/ai/ | AI provider backends (Anthropic, OpenAI, Gemini, Bedrock, Ollama, Claude Code) |
src/platform/ | VCS platform clients (GitHub, GitLab, Bitbucket, Azure, Gitea) |
src/tools/ | Slash command implementations |
src/rag/ | RAG pipeline (embedder, stores, indexer, retriever) |
src/agent/ | ReAct agent (runtime, memory, tools, channels) |
src/review/ | Core review orchestration engine |
src/diff/ | Unified diff parser |
src/webhook/ | Axum webhook server (bot mode) |
Adding a new slash command
- Create
src/tools/<name>.rsand implement theFerretTooltrait - Register in
src/tools/mod.rs→route_command() - Add an entry to the agent's
builtin_tools()insrc/agent/tools.rs - Document in README and this docs site
- Add unit tests
shell
# Minimal FerretTool implementation# src/tools/my_tool.rsuse async_trait::async_trait;use crate::tools::{FerretTool, ToolContext};use crate::error::Result;pub struct MyTool;#[async_trait]impl FerretTool for MyTool {fn name(&self) -> &'static str { "my_tool" }async fn run(&self, ctx: &ToolContext) -> Result<String> {let diff = ctx.platform.get_diff().await?;let result = ctx.ai.generate("system prompt", &diff).await?;ctx.platform.post_summary(&result).await?;Ok(result)}}
Commit convention
Use Conventional Commits:
text
feat(rag): add Pinecone vector store backendfix(platform/github): handle 404 when PR has no diffdocs: update README with RAG quick-start guidechore: bump reqwest to 0.12.5
Pull request checklist
cargo fmt --checkpassescargo clippy -- -D warningspassescargo testpasses- New behaviour is covered by tests
- Documentation is updated (README, this docs site, CONTRIBUTING.md)
- Branch is rebased on
main