The prior commit switched the recipe to `[source] path = "source"`, but .gitignore:77 still listed `local/recipes/shells/brush/source` (a leftover from when brush was a transient upstream git fetch), so the vendored tree was not tracked — a fresh clone would have no brush source and the build would fail. Drop that ignore line and commit the vendored working tree (reubeno/brush @ 897b373e, with the Redox port patches pre-applied). brush is now a durable local fork like the other path=source recipes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
11 KiB
Agent Development Guide for brush
This guide helps AI agents work efficiently on the brush codebase by providing essential context about architecture, patterns, and development workflows.
1. Architecture Overview & Navigation
Project Structure
The brush project is organized into several key crates:
brush-core/: Core shell functionality, builtins, and runtimebrush-parser/: Shell script parsing (AST generation)brush-builtins/: Implementation of shell builtins (e.g., echo, cd)brush-interactive/: Interactive shell interfaces (readline, etc.)brush-shell/: Main CLI application and entry point
Key Files & Entry Points
Critical files to understand first:
brush-core/src/shell.rs- MainShellstruct and creation logicbrush-core/src/lib.rs- Public API exportsbrush-shell/src/main.rs- CLI application entry point
Architecture patterns:
- Shell instances are created via
Shell::builder() - The project uses builder patterns for type-safe configuration
- We try to keep platform-specific code in
brush-coreunder thesysmodule - Follows Rust 2024 edition standards
Module Dependencies
brush-shell → brush-interactive → brush-core → brush-parser
↘ brush-builtins ↗
2. Testing Strategy
Test Execution Priority
Recommended development workflow:
Using xtask (Recommended)
The project provides a cargo xtask command that centralizes common development tasks:
# Run quick inner-loop checks (~7s warm): fmt, build, lint, unit tests
cargo xtask ci quick
# Run full pre-commit checks (~45s warm): quick + deps, schemas, integration tests
cargo xtask ci pre-commit
# Run with --continue-on-error to see all failures at once
cargo xtask ci pre-commit -k
# Add -v for verbose output showing exact commands being run
cargo xtask -v ci pre-commit
Individual Test Commands
# Run unit tests (fast tests excluding integration binaries)
cargo xtask test unit
# Run integration tests (all workspace tests including compat tests)
cargo xtask test integration
# Run tests with coverage
cargo xtask test integration --coverage --coverage-output codecov.xml
Manual Approach (Alternate)
For finer-grained control:
Inner Loop (Fast Iteration)
- Quick validation:
cargo check --package <changed-package>- Fast syntax/type checking - Correctness validation:
cargo test --package <changed-package>- Target specific crates for faster feedback
Outer Loop (Comprehensive Testing)
- Compatibility tests:
cargo test --test brush-compat-tests- Bash compatibility validation - Full workspace tests:
cargo test --workspace- Complete test suite
Pre-Finish Quality Validation
Recommended: Run the xtask pre-commit workflow:
cargo xtask ci pre-commit
Manual approach: Before considering work complete, run these validation steps:
- Compatibility tests:
cargo test --test brush-compat-tests - Linting:
cargo clippy - Formatting:
cargo fmt --check - Security/License audit:
cargo deny check all - Full test suite:
cargo test --workspace
When tests fail:
- Focus on failures in the area you changed first
- Compatibility test failures often indicate shell behavior changes
- Check if new functionality needs corresponding test cases
- Format/clippy failures should be fixed before proceeding
Common pitfalls:
- Test scope mistakes: Running full test suite too early instead of targeting specific areas first
- Skipping test-driven development: Add tests that specify desired behavior before implementing
Test-driven development approach:
- When possible, write tests first that specify the desired behavior
- Use unit tests for logic changes, compatibility tests for shell behavior changes
- Use these tests as validation that your implementation is working correctly
Pro tip: For specific compatibility test cases, use:
cargo test --test brush-compat-tests -- '<name of test case>'
Fast iteration strategies:
- Target specific crates:
cargo test --package <changed-package> - Target specific test cases:
cargo test <test-name>orcargo test --test <test-file> - Requires knowledge of which tests best exercise the code being changed
Testing approach:
- Follow good software engineering practice: start by validating the specific area being changed, then iteratively move to incrementally broader sets of tests
Test Organization
Testing expectations for new public APIs:
- Unit tests are expected if feasible
- Examples are nice to have and worthwhile for sufficiently critical APIs
Test patterns and conventions:
- Compatibility tests: For any compatibility-related fixes, it's critical to add new test cases to the compat tests (see docs/how-to/run-tests.md and section 3 for when breaking changes apply)
Test categories:
- Unit tests: In
src/files with#[cfg(test)] - Integration tests: In
tests/directories - Examples: In
examples/directories (must be runnable) - Shell script tests: YAML-based test cases in
brush-shell/tests/cases/
Performance Testing
Performance regression testing:
- Not a chief concern for most changes
- For performance-specific work, benchmarks are available (see docs/how-to/run-benchmarks.md)
- Performance sensitivity will be identified in the initial brief if relevant
3. Breaking Changes & Compatibility
API Stability Guidelines
Breaking change policy:
- Non-backwards compatible changes to public APIs are considered breaking
- Breaking changes are still in consideration, but need to be highlighted and carefully reviewed
- Any APIs exported from crates are considered public because all of the crates are published to crates.io
Adding new fields to public structs:
- New optional fields are fine to add as long as the struct implements the Default trait and as long as the defaulted value is a sensible one
Dependency Impact
When changing public APIs in brush-core (see section 3 for breaking change policy):
- Check
brush-shell/src/main.rsfor struct initialization sites - Check
brush-interactive/for any usage
4. Documentation & Examples Standards
Documentation Requirements
Rustdoc documentation standards:
- At minimum we must have good rustdoc documentation for exported types, functions, traits, etc. as well as on all exported modules and crates
- Documentation for internal components should be a best-effort, nice to have thing
Examples for new features:
- Unless explicitly requested, only major feature additions warrant an example.
Documentation style:
- Follow general best practices for Rust
Example Standards
Examples should:
- Be self-contained and runnable with
cargo run --package brush-core --example <name> - Include comprehensive error handling
- Demonstrate both basic and advanced usage patterns
- Include output examples in comments when helpful
5. Build & Release Process
Development Tools
The project uses several tools for code quality:
Using xtask (Recommended):
The project provides a cargo xtask command that centralizes common development tasks:
# Run all pre-commit checks (comprehensive)
cargo xtask ci pre-commit
# Individual checks
cargo xtask check fmt # Format check
cargo xtask check lint # Clippy
cargo xtask check deps # cargo-deny
cargo xtask check build # Compilation check
cargo xtask check schemas # Schema drift check
# Tests
cargo xtask test unit # Fast unit tests (excludes integration binaries)
cargo xtask test integration # All workspace tests (unit + compat)
# Analysis
cargo xtask analyze bench # Run benchmarks
Manual approach (Alternate):
- Standard cargo commands (e.g., check, test, build, run, clippy)
- You may need to reverse engineer some of the args looking at CI checks in .github/*.yml
Command frequency guidelines:
- Frequent (inner loop):
cargo xtask ci quick,cargo check,cargo test --package <pkg> - Regular (before commits):
cargo xtask ci pre-commitorcargo fmt+cargo clippy - Occasional (outer loop):
cargo xtask test integrationorcargo test --workspace - Rare (pre-finish only):
cargo xtask check depsorcargo deny check
Pre-commit validation:
- Recommended:
cargo xtask ci pre-commit - Quick check:
cargo xtask ci quickfor fast feedback - Manual: Run
cargo fmtandcargo clippybefore committing
Outer loop validation:
cargo deny check allshould pass (security/license auditing) - not for frequent use during development
6. Performance & Error Handling Patterns
Error Handling
Error handling patterns:
thiserroris used for implementing crate-specific errors- Use
anyhowonly in tests
Logging and tracing patterns:
- Use
tracingfor debug logging with predefined categories - Categories are defined in
trace_categories.rsmodules (e.g.,COMMANDS,COMPLETION,EXPANSION,FUNCTIONS,INPUT,JOBS,PARSE,PATTERN,UNIMPLEMENTED) - Usage pattern:
tracing::debug!(target: trace_categories::CATEGORY_NAME, "message") - Example:
tracing::debug!(target: trace_categories::JOBS, "Polling job {} for completion...", job_id)
Performance Considerations
Clone vs references:
- Avoid cloning by default, no reason to make extra copies
- Only use cloning when you really must capture a separate copy for async safety or similarly important reasons
7. Commit Message Conventions
Following the Linux kernel convention, when AI assistants or advanced coding tools have been used in the development of a change, include an Assisted-by: tag in the commit message. This provides transparency about the use of such tools in the development process.
The format for the Assisted-by tag is:
Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]
Example:
Assisted-by: Mistral Vibe:mistral-medium-3.5
Quick Reference Checklist
When making changes to brush:
Before Starting
- Understand which crate(s) are affected
- Check if changes might break dependent crates
- Identify relevant test files and examples
During Development
- Run
cargo checkfrequently during development - Test changes with package-specific tests first (see section 2 for testing workflow)
- Update dependent crate usage if needed (see section 3 for compatibility considerations)
- Add/update examples for major feature additions only (see section 4)
Before Committing
- Run full test suite:
cargo test(see section 2 for complete testing workflow) - Format code:
cargo fmt(see section 5 for tool details) - Check linting:
cargo clippy - Use conventional commit format
- If using AI assistants or advanced coding tools, include an
Assisted-by:tag in the formatAGENT_NAME:MODEL_VERSION(following Linux kernel convention)
Documentation
- Add rustdoc to exported APIs (see section 4 for documentation standards)
- Include working examples for major features only
- Update this guide if new patterns emerge