Skip to content

Latest commit

 

History

History
332 lines (213 loc) · 11 KB

File metadata and controls

332 lines (213 loc) · 11 KB

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 runtime
  • brush-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 - Main Shell struct and creation logic
  • brush-core/src/lib.rs - Public API exports
  • brush-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-core under the sys module
  • 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)
  1. Quick validation: cargo check --package <changed-package> - Fast syntax/type checking
  2. Correctness validation: cargo test --package <changed-package> - Target specific crates for faster feedback
Outer Loop (Comprehensive Testing)
  1. Compatibility tests: cargo test --test brush-compat-tests - Bash compatibility validation
  2. 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> or cargo 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):

  1. Check brush-shell/src/main.rs for struct initialization sites
  2. 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-commit or cargo fmt + cargo clippy
  • Occasional (outer loop): cargo xtask test integration or cargo test --workspace
  • Rare (pre-finish only): cargo xtask check deps or cargo deny check

Pre-commit validation:

  • Recommended: cargo xtask ci pre-commit
  • Quick check: cargo xtask ci quick for fast feedback
  • Manual: Run cargo fmt and cargo clippy before committing

Outer loop validation:

  • cargo deny check all should pass (security/license auditing) - not for frequent use during development

6. Performance & Error Handling Patterns

Error Handling

Error handling patterns:

  • thiserror is used for implementing crate-specific errors
  • Use anyhow only in tests

Logging and tracing patterns:

  • Use tracing for debug logging with predefined categories
  • Categories are defined in trace_categories.rs modules (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 check frequently 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 format AGENT_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