Contributing Guide
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

ToolVersion
Ruststable ≥ 1.78 (rustup update stable)
Cargobundled with Rust
Gitany recent
Ollamaoptional, for RAG tests
Dockeroptional, for Qdrant / ChromaDB
shell
git clone https://github.com/Arunachalamkalimuthu/merlin-ai-code-review.git
cd ferret
cargo build # debug build — verifies everything compiles
cargo test # run all 93+ tests

Local quality gate

All three commands must pass before opening a PR.

shell
cargo fmt --check # formatting
cargo clippy -- -D warnings # zero warnings required
cargo test # all tests

Project structure

PathPurpose
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

  1. Create src/tools/<name>.rs and implement the FerretTool trait
  2. Register in src/tools/mod.rsroute_command()
  3. Add an entry to the agent's builtin_tools() in src/agent/tools.rs
  4. Document in README and this docs site
  5. Add unit tests
shell
# Minimal FerretTool implementation
# src/tools/my_tool.rs
use 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 backend
fix(platform/github): handle 404 when PR has no diff
docs: update README with RAG quick-start guide
chore: bump reqwest to 0.12.5

Pull request checklist

  • cargo fmt --check passes
  • cargo clippy -- -D warnings passes
  • cargo test passes
  • New behaviour is covered by tests
  • Documentation is updated (README, this docs site, CONTRIBUTING.md)
  • Branch is rebased on main