Add OpenCode context: agents configuration, skills, and git worktrees (#44)

* Add OpenCode context: agents configuration, skills, and git worktrees

* Update .gitignore to include Git worktrees and remove .opencode dir

* Update AGENTS.md: add language identifiers to code blocks and test coverage note
This commit is contained in:
JeffG
2026-01-18 13:00:05 +01:00
committed by GitHub
parent 389affc233
commit ffc3bcca28
3 changed files with 197 additions and 0 deletions
+4
View File
@@ -55,3 +55,7 @@ RUST_FFI_GUIDE.md
rust/.cargo/config.toml
# Rust build artifacts (Cargo/rust-analyzer)
target/
# Git worktrees
/trees/*
!/trees/.gitkeep
+193
View File
@@ -0,0 +1,193 @@
# AGENTS.md
## Project Overview
Sloth is a playground messaging app for experimenting with the [whitenoise Rust crate](https://github.com/marmot-protocol/whitenoise-rs), which implements secure messaging using the [Marmot Protocol](https://github.com/marmot-protocol/marmot) with MLS (Messaging Layer Security) and Nostr.
**Why "Sloth"?** Sloths are slow but efficient, and you can find them in Costa Rica.
## Architecture
```text
┌─────────────────────────────────────────────────────────────┐
│ Flutter UI Layer │
│ (screens/, widgets/, hooks/, providers/) │
├─────────────────────────────────────────────────────────────┤
│ Flutter-Rust Bridge Layer │
│ (lib/src/rust/ - auto-generated bindings) │
├─────────────────────────────────────────────────────────────┤
│ Rust API Layer │
│ (rust/src/api/ - thin wrapper around whitenoise) │
├─────────────────────────────────────────────────────────────┤
│ Whitenoise Rust Crate │
│ (external dependency - core messaging logic) │
└─────────────────────────────────────────────────────────────┘
```
## Tech Stack
- **Flutter/Dart** - UI and application logic
- **Rust** - Core messaging/crypto functionality via FFI
- **flutter_rust_bridge** - Dart-Rust FFI bindings
- **Riverpod** - State management (shared state)
- **flutter_hooks** - Ephemeral widget state
- **go_router** - Navigation/routing
## Git Worktrees
**IMPORTANT:** When starting work on a new feature, bug fix, or issue, use the `/create-git-worktree` command to create an isolated development environment.
```bash
/create-git-worktree <branch-name>
```
This creates a worktree in the `trees/` directory at the repository root. Worktrees allow parallel development without affecting the main working directory.
Example: `/create-git-worktree issue-42-fix-login`
After running, you'll be working in `trees/issue-42-fix-login/` on that branch.
## Directory Structure
```text
sloth/
├── lib/ # Flutter/Dart source code
│ ├── main.dart # App entry point
│ ├── routes.dart # Route definitions (go_router)
│ ├── theme.dart # Theme colors and styles
│ ├── providers/ # Riverpod providers (shared state)
│ ├── hooks/ # Flutter hooks (ephemeral state)
│ ├── screens/ # Full-page UI components
│ ├── widgets/ # Reusable components (prefixed wn_)
│ ├── services/ # Stateless operations (API calls)
│ ├── extensions/ # Dart extensions
│ ├── utils/ # Utility functions
│ └── src/rust/ # Auto-generated Rust bridge code (DO NOT EDIT)
├── rust/ # Rust source code
│ └── src/api/ # API modules exposed to Flutter
├── test/ # Flutter tests (mirrors lib/ structure)
├── trees/ # Git worktrees for parallel development
├── assets/ # Images, SVGs, fonts
└── scripts/ # Build/CI scripts
```
## Setup Commands
```bash
# Install all dependencies
just deps
# Install Flutter dependencies only
just deps-flutter
# Install Rust dependencies only
just deps-rust
```
## Development Commands
```bash
# Format all code (Rust + Dart)
just format
# Lint all code
just lint
# Run all tests
just test-flutter
just test-rust
# Run tests with coverage (80% minimum)
just coverage
# Generate coverage HTML report
just coverage-report
# Pre-commit checks (run before submitting PRs)
just precommit
# Regenerate flutter_rust_bridge code
just generate
```
## Code Style
### Dart/Flutter
- Single quotes for strings
- `prefer_const_constructors` enabled
- `prefer_final_locals` enabled
- Line width: 100 characters
- Trailing commas: preserve
### Widget Naming
- Reusable widgets prefixed with `wn_` (e.g., `wn_filled_button.dart`)
- Widget class names use `Wn` prefix (e.g., `WnFilledButton`)
### Hook Naming
- Hook files prefixed with `use_` (e.g., `use_chat_list.dart`)
- Hook functions start with `use` (e.g., `useChatList()`)
### Provider Naming
- Files end with `_provider.dart`
- Provider variables end with `Provider` (e.g., `authProvider`)
## Testing
**IMPORTANT: Test coverage is of utmost importance. Never submit a PR that reduces test coverage.**
- Test files mirror source structure with `_test.dart` suffix
- Minimum coverage requirement: 80%
- Use helpers from `test/test_helpers.dart`:
- `setUpTestView(tester)` - Configure test view dimensions
- `mountTestApp(tester, overrides)` - Mount full app with provider overrides
- `mountHook(tester, useHook)` - Test individual hooks
- `mountWidget(child, tester)` - Mount single widget
- `mountStackedWidget(child, tester)` - Mount widget in Stack
- Mock Rust API using `RustLib.initMock(api: mockApi)`
## Sloth Mode Philosophy
Follow these principles when writing code:
1. **Simplicity over complexity** - Keep the app thin
2. **Test all code** - No untested code
3. **No dead code** - Delete commented/unused code
4. **Whitenoise is source of truth** - Don't duplicate logic from the Rust crate
5. **No caching in Flutter** - Whitenoise persists data in local DB
6. **Shared state in providers** - Use Riverpod for app-wide state
7. **Ephemeral state in hooks** - Use flutter_hooks for widget-local state
8. **Pass data to hooks, not refs** - Hooks receive data, not widget references
9. **Screens watch providers** - Screens observe providers and pass data to hooks
10. **Self-explanatory code** - Avoid comments; write clear, readable code
## State Management Pattern
```text
Screen (watches providers)
├── Providers (shared/persistent state)
│ └── Auth, account pubkey, etc.
└── Hooks (ephemeral/local state)
└── Chat list, messages, form inputs, etc.
```
## Rust API Guidelines
- Modules in `rust/src/api/` are exposed to Flutter
- Functions use `#[frb]` attribute for bridge generation
- Structs use `#[frb(non_opaque)]` for Flutter compatibility
- Errors wrapped in `ApiError` enum using `thiserror`
- Files in `lib/src/rust/` are auto-generated - DO NOT EDIT manually
## PR Checklist
1. Run `just precommit` before submitting
2. Ensure all tests pass
3. Coverage meets 80% minimum
4. Update `CHANGELOG.md` for user-facing changes
5. Follow existing code patterns and naming conventions
View File