opencrabs 0.3.37

The autonomous, self-improving AI agent. Single Rust binary. Every channel. Install with: cargo install opencrabs
Documentation
# Contributing to OpenCrabs

Thank you for your interest in contributing to OpenCrabs! We welcome contributions from the community — but we have clear standards to keep the project moving forward efficiently.

## Before You Do Anything

**Read this entire document.** PRs that ignore these guidelines will be closed without review.

## Types of Contributions

### 1. Bug Reports (Issues Only)

Found a bug? Open an issue — **do not submit a PR yet**.

**Required information:**
- Clear, descriptive title
- Steps to reproduce (exact commands, config, inputs)
- Expected vs. actual behavior
- Environment: OS, Rust version (`rustc --version`), OpenCrabs version (`opencrabs --version`)
- Full error messages and logs (redact API keys)
- Screenshots if it's a TUI/visual issue

### 2. Feature Requests (Issues Only — No Code)

Have an idea for a new feature? Open an issue with the `enhancement` label.

**What to include:**
- What problem does this solve?
- How should it work from the user's perspective?
- Why is this useful to OpenCrabs users broadly (not just your use case)?

**What NOT to do:**
- Do not submit a PR with stub/placeholder code for a feature that doesn't exist yet
- Do not submit empty implementations with `todo!()`, `vec![]`, or `unimplemented!()`
- Do not submit PRs that add files with no actual logic, no tests, and no integration

**Stub PRs will be closed immediately.** If you want a feature built but don't have the skills to implement it, that's totally fine — open an issue, describe what you need, and the community or maintainers will pick it up. A well-written issue is 10x more valuable than a stub PR.

### 3. Code Contributions (PRs)

PRs are welcome for:
- Bug fixes (reference the issue number)
- Feature implementations (must have a linked issue approved by a maintainer first)
- Performance improvements (with benchmarks showing the improvement)
- Test coverage improvements
- Documentation fixes

## Step-by-Step: Submitting a Bug Fix

1. **Find or create the issue** — Check existing issues first. If none exists, create one.
2. **Wait for confirmation** — A maintainer will confirm it's a real bug and not a duplicate.
3. **Fork and branch** — Fork the repo, create a branch from `main` (not `master`).
4. **Fix the bug** — Keep changes minimal. Fix the bug, nothing more.
5. **Add a test** — Write a test that fails without your fix and passes with it.
6. **Run CI checks locally** (see below).
7. **Submit the PR** — Reference the issue, explain what you changed and why.

## Step-by-Step: Submitting a Feature

1. **Open an issue first** — Describe the feature, get maintainer approval.
2. **Discuss the design** — For non-trivial features, discuss the approach in the issue before writing code.
3. **Fork and branch** from `main`.
4. **Implement fully** — The feature must work end-to-end. No stubs, no placeholders, no "TODO: implement later".
5. **Add tests** — Unit tests at minimum, integration tests for complex features.
6. **Run CI checks locally** (see below).
7. **Submit the PR** — Reference the issue, include before/after screenshots for UI changes.

## Development Setup

### Prerequisites

- **Rust** 1.91 or later (edition 2024)
- **SQLite** (bundled via `rusqlite`)
- **Git**

### Build & Test

```bash
# Clone your fork
git clone https://github.com/YOUR_USERNAME/opencrabs.git
cd opencrabs

# Iterate locally
cargo clippy --all-features         # USE THIS — never `cargo check` or `cargo build`
cargo test --all-features            # run the suite (incl. your new tests)
cargo fmt --all                      # auto-format before committing

# Run the EXACT CI checks (you MUST pass all three before submitting a PR)
cargo fmt --all -- --check
cargo clippy --lib --bins --tests --all-features -- -D warnings
cargo test --all-features --verbose
```

**All three commands must pass.** PRs that fail CI will not be reviewed.

`cargo clippy` is the lint pass we trust — `cargo check` only type-checks and misses the lint rules CI enforces. Iterate with clippy locally so you don't burn a CI run discovering a `-D warnings` failure.

### Running the App While You Iterate

**Use `cargo run`. Do NOT `cargo build --release` for normal development.**

```bash
cargo run --all-features                 # default debug build, fastest iteration
cargo run --all-features -- /sessions    # pass CLI flags after `--`
cargo run --all-features -- -p hermes    # named profile
```

`cargo run` compiles a debug build and launches the TUI directly. Debug builds compile ~5x faster than release, and the extra instrumentation (full backtraces, debug assertions) makes any regression you introduce surface immediately. The debug binary is what you want when chasing a bug — release optimizations strip frames that make panics impossible to read.

**Brain files just work.** `cargo run` resolves `~/.opencrabs/` (or `~/.opencrabs/profiles/<name>/` with `-p`) the same way the installed binary does. Your existing config, brain files, sessions, and memory are all picked up — no copy step, no env var override needed.

#### When You Actually Want a Release Build

Reach for `cargo build --release` only when:

- You want to **test the optimized binary** (perf-sensitive feature work, startup time benchmarks, etc.).
- You want to **replace your installed binary with the latest from `main`** so the long-running daemon / channels keep running the new code. The flow:
  ```bash
  git pull origin main
  cargo build --release --all-features
  # macOS / Linux: replace ~/.cargo/bin/opencrabs (or wherever your install lives)
  cp target/release/opencrabs ~/.cargo/bin/opencrabs
  ```
  The release binary reads the same `~/.opencrabs/` as `cargo run`, so your brain files, sessions, and config carry over seamlessly.

For everything else — bug hunting, feature work, test-driven development — stay on `cargo run`. Release builds are a deployment step, not a dev loop.

### Where Tests Live

**Every test goes under `src/tests/` as a dedicated `*_test.rs` file**, registered in `src/tests/mod.rs`. No inline `#[cfg(test)] mod tests { ... }` blocks at the bottom of source files — they are explicitly forbidden by project policy because they hide behind the source file in IDE outlines and grow unbounded.

To add a new test file:

```bash
# 1. Create the test file
$EDITOR src/tests/my_feature_test.rs

# 2. Register it in src/tests/mod.rs (alphabetical-ish neighbourhood)
echo "pub mod my_feature_test;" >> src/tests/mod.rs   # or insert manually

# 3. If the test needs internal helpers from the module under test,
#    bump those helpers from `fn` / `pub(super)` to `pub(crate)` so the
#    test file can reach them without weakening the public API.

# 4. Verify
cargo test --all-features my_feature_test
```

If you find an existing inline `#[cfg(test)] mod tests` while working on a file, move it into `src/tests/` as part of your change. Leaving the violation in place will fail review.

### Commit Discipline — Atomic Commits

**One logical change per commit.** A commit should land a single bug fix, a single feature, or a single refactor — not a mixed bag.

- **Don't bundle** `cargo fmt` drift with feature work. Run fmt in its own commit (`chore: cargo fmt`).
- **Don't bundle** rename / move / restructure with logic changes. The reviewer cannot tell what's mechanical and what's behavioural.
- **Split test additions from production fixes only if the test would compile against the un-fixed code.** Otherwise commit them together so the test demonstrates the fix.
- **Commit message body explains the WHY**, not the diff. The diff already shows what changed; the message should answer "why was that wrong?" and "what would break if we reverted this?".
- **Add `[skip ci]` to chore / docs / non-functional commits** so CI doesn't churn on whitespace and README edits. Never add `[skip ci]` to a release commit — it skips the release workflow too.
- **Never add `Co-Authored-By` lines** to commit messages. Project policy.

### Project Structure

```
src/
├── brain/           # AI agent core
│   ├── agent/       # Agent orchestration, tool loop, context management
│   ├── provider/    # LLM provider implementations (Anthropic, OpenAI, etc.)
│   └── tools/       # Built-in tools (bash, edit, browser, etc.)
├── channels/        # Communication channels (Telegram, Discord, Slack, WhatsApp)
├── config/          # Configuration management
├── database/        # SQLite database layer
├── memory/          # Long-term memory (FTS5 + vector search)
├── tui/             # Terminal UI (ratatui)
└── utils/           # Shared utilities
```

## Coding Standards

### Rust Conventions

- **Files**: `snake_case.rs` — never PascalCase, never camelCase
- **Structs/Enums**: `PascalCase`
- **Functions/Variables**: `snake_case`
- **Constants**: `SCREAMING_SNAKE_CASE`
- **Error handling**: `anyhow::Result` for application errors, `thiserror` for typed errors
- **Async**: `tokio` runtime — never block in async functions

### What We Value

- **Working code** over clever code
- **Minimal diffs** — change only what's needed
- **Tests that prove the fix** — not tests for the sake of coverage
- **Comments that explain why**, not what

### Commit Messages

Use [Conventional Commits](https://www.conventionalcommits.org/):

```
feat: add voice message support for Discord channel
fix: prevent duplicate message rendering for CLI providers
refactor: simplify tool loop iteration tracking
```

## What Gets Your PR Closed

To be transparent, here's what will get your PR closed immediately:

- **Stub/placeholder code** — Empty implementations, `todo!()`, functions that return hardcoded empty values
- **No linked issue** — Feature PRs without an approved issue
- **Fails CI** — If `cargo fmt --check`, `cargo clippy`, or `cargo test` fail
- **Unrelated changes** — Reformatting files you didn't modify, drive-by "improvements"
- **No tests** — Bug fixes without a regression test, features without any tests
- **AI-generated spam** — PRs that look like they were generated by an LLM with no understanding of the codebase

## Don't Know How to Code?

That's completely fine. You can still contribute meaningfully:

- **Report bugs** with detailed reproduction steps
- **Request features** with clear descriptions of the problem you're trying to solve
- **Improve documentation** — fix typos, clarify confusing sections, add examples
- **Test pre-release builds** and report issues
- **Answer questions** in GitHub Discussions

A well-written bug report or feature request is worth more than a stub PR. Seriously.

## License

By contributing to OpenCrabs, you agree that your contributions will be licensed under the MIT License. See [LICENSE.md](LICENSE.md) for details.