Thank you for your interest in contributing to afk! This document provides guidelines and information for contributors.
- Rust 1.80+ - Install via rustup
- Git - For version control
# Clone the repository
git clone https://github.com/m0nkmaster/afk.git
cd afk
# Build in debug mode
cargo build
# Build in release mode
cargo build --release
# Run the binary
./target/release/afk --helpBefore submitting a PR, ensure your code passes all quality checks:
# Format code
cargo fmt
# Check formatting (CI check)
cargo fmt -- --check
# Lint with Clippy
cargo clippy --all-targets --all-features
# Run tests (single-threaded, required for macOS)
cargo test -- --test-threads=1Tests must run single-threaded due to the notify crate's FSEvents backend on macOS. Parallel test execution can cause hangs. Always use:
cargo test -- --test-threads=1
# or
RUST_TEST_THREADS=1 cargo testsrc/
├── main.rs # Entry point
├── lib.rs # Library exports
├── path_matcher.rs # Shared utility for ignore patterns
├── cli/ # CLI commands and argument handling
│ ├── mod.rs # Clap CLI definitions
│ ├── commands/ # Subcommand implementations
│ ├── output.rs # Output formatting
│ └── update.rs # Self-update logic
├── config/ # Configuration models
├── bootstrap/ # Project analysis, AI CLI detection
├── progress/ # Session and task progress tracking
├── prompt/ # Tera template rendering
├── prd/ # PRD document model and parsing
├── runner/ # Loop controller and iteration runner
├── git/ # Git operations
├── feedback/ # Metrics and ASCII art
├── parser/ # AI CLI output parsing
├── watcher/ # File system monitoring
├── tui/ # Terminal UI (ratatui)
└── sources/ # Task source adapters
├── beads.rs # Beads integration
├── json.rs # JSON PRD files
├── markdown.rs # Markdown checklists
├── github.rs # GitHub issues
└── openspec.rs # OpenSpec change proposals
Tests are inline with modules using #[cfg(test)] mod tests. Guidelines:
- Use tempfile for temporary directories
- Mock external calls via Command patterns where appropriate
- Test edge cases - empty inputs, missing files, error conditions
- Keep tests focused - one behaviour per test
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn test_config_loads_from_file() {
let temp = TempDir::new().unwrap();
let config_path = temp.path().join(".afk/config.json");
std::fs::create_dir_all(config_path.parent().unwrap()).unwrap();
std::fs::write(&config_path, r#"{"sources": []}"#).unwrap();
let config = AfkConfig::load(Some(&config_path)).unwrap();
assert!(config.sources.is_empty());
}
}- Create
src/sources/newsource.rs - Implement
load_newsource_tasks() -> Result<Vec<UserStory>, Error> - Add variant to
SourceTypeenum inconfig/mod.rs - Add match arm to
load_from_source()insources/mod.rs - Add
mod newsource;tosources/mod.rs - Write tests inline with
#[cfg(test)] mod tests
Use conventional commits with short, single-line messages:
feat: add GitHub issues source
fix: handle empty PRD gracefully
docs: update installation instructions
refactor: simplify prompt generation
test: add coverage for edge cases
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Run quality checks (
cargo fmt && cargo clippy && cargo test -- --test-threads=1) - Commit with a clear message
- Push to your fork
- Open a PR against
main
This project uses beads for issue tracking:
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --status in_progress # Claim work
bd close <id> # Complete work
bd sync # Sync with git- Use British English in comments and documentation
- Follow Rust idioms and best practices
- Prefer explicit error handling over
.unwrap()in library code - Document public APIs with
///doc comments
Open an issue or discussion on GitHub. We're happy to help!