Files
RedBear-OS/local/recipes/shells/brush/source/.github/copilot-instructions.md
T
vasilito 25fb843c40 brush: vendor the source tree (un-ignore) to complete the local fork
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>
2026-07-26 23:34:31 +09:00

13 KiB

GitHub Copilot Coding Agent Instructions for brush

Project Overview

brush (Bourne Rusty Shell) is a POSIX- and bash-compatible shell implemented in Rust. It's a multi-crate workspace (~60K lines of Rust code) targeting Linux, macOS, and WSL, with experimental Windows and WASM support. The project emphasizes compatibility testing against bash as an oracle.

Key Stats: Rust 2024 edition, MSRV 1.88.0, 5 main crates, 1500+ compatibility test cases, published to crates.io.

Critical: Read AGENTS.md First

BEFORE making any changes, read /AGENTS.md. It contains detailed architecture patterns, testing workflows, and development guidelines specific to this project. The information below supplements (not replaces) AGENTS.md.

Code Review Checklist

When reviewing PRs, verify:

  • Documentation: All exported APIs have rustdoc comments (missing docs = CI failure)
  • Forbidden patterns: No panic, unwrap_in_result, expect_used, or todo (all denied by clippy)
  • Error handling: Uses thiserror for crate errors; anyhow only in tests
  • Logging: Uses tracing::debug!(target: trace_categories::CATEGORY, "msg") pattern
  • Testing: Compatibility fixes include YAML test cases in brush-shell/tests/cases/
  • Testing: Builtin changes have tests in brush-shell/tests/cases/builtin/
  • Testing: Unit tests expected for new public APIs (when feasible) (see AGENTS.md section 2)
  • Platform code: Platform-specific code is in brush-core/src/sys/ modules
  • Breaking changes: Public API changes are clearly highlighted and documented
  • Builder pattern: Configuration uses builder pattern (see Shell::builder())
  • Code quality: Passes cargo fmt --check and cargo clippy without warnings
  • Commit format: Follows Conventional Commits (feat:, fix:, docs:, test:)
  • Dependencies: No unnecessary cloning (use references when possible)
  • Cross-platform: Uses appropriate cfg(unix), cfg(windows), cfg(target_family = "wasm")

Workspace Structure

brush/
├── brush-shell/        # CLI application & main entry point
├── brush-interactive/  # Interactive shell (readline, completion)
├── brush-core/         # Core shell runtime & builtins
├── brush-builtins/     # Shell builtin implementations
├── brush-parser/       # AST generation & parsing
├── xtask/             # Build automation tasks
└── docs/              # Diátaxis-structured documentation

Dependency flow: brush-shell → brush-interactive → brush-core → brush-parser ↘ brush-builtins ↗

Build & Validation Commands

Terminal Command Execution

When running commands that may take more than a few seconds (cargo build, cargo check, cargo test, cargo clippy, cargo xtask, etc.), run them in background mode and poll for results rather than blocking. This prevents commands from being cancelled due to timeouts. Use isBackground: true with run_in_terminal, then use get_terminal_output to check results.

The project provides a cargo xtask command that centralizes common development tasks. This is the recommended approach for running checks and tests.

Quick Development Cycle

# 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 Checks

# Format check
cargo xtask check fmt

# Lint check (clippy)
cargo xtask check lint

# Dependency check (cargo-deny)
cargo xtask check deps

# Build check
cargo xtask check build

# Schema check (regenerates and diffs)
cargo xtask check schemas

Running Tests

# 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 or when xtask isn't available:

Quick Development Cycle (Use These Frequently)

# Fast syntax/type checking (< 5 seconds)
cargo check --workspace

# Package-specific checking (even faster)
cargo check --package brush-core

# Format code (ALWAYS run before committing)
cargo fmt --all

# Lint code (ALWAYS run before committing)
cargo clippy --workspace --all-features --all-targets

# Run package-specific tests (fast iteration)
cargo test --package brush-parser
cargo test --package brush-core

Note: cargo fmt --check may show warnings about unstable rustfmt features (wrap_comments, comment_width) on stable Rust. These are harmless and expected.

Comprehensive Testing Workflow

Follow this exact order for efficient testing:

  1. Inner loop (during development):

    cargo check --package <changed-package>
    cargo test --package <changed-package>
    
  2. Compatibility tests (critical for shell behavior):

    cargo test --test brush-compat-tests
    
    # Run specific test case:
    cargo test --test brush-compat-tests -- 'builtin/echo'
    
  3. Full workspace tests (before considering work complete):

    cargo test --workspace
    

Test timing: Package tests: 3-20 seconds. Compat tests: ~18 seconds build + test time. Full workspace: several minutes.

Pre-Commit Validation (Before Every Commit)

Recommended: Run the xtask pre-commit workflow:

cargo xtask ci pre-commit

Manual approach: Run these before every commit:

cargo fmt --check --all
cargo clippy --workspace --all-features --all-targets

Pre-PR Validation (Before Opening Pull Request)

Recommended: Run pre-commit checks which includes full test suite:

cargo xtask ci pre-commit

Manual approach: In addition to pre-commit checks, also run:

cargo test --workspace

Pre-Finish Quality Gates (Run Before Completing Task)

Recommended: Run the xtask pre-commit workflow which covers all essential checks:

cargo xtask ci pre-commit

Manual approach:

cargo test --test brush-compat-tests
cargo deny check all       # License/security audit (run LAST, not frequently)
cargo clippy --workspace --all-features --all-targets
cargo fmt --check --all
cargo test --workspace

Timing note: cargo deny check all takes ~1-5 seconds. Only run as final validation step.

Build Variants

# Standard debug build
cargo build

# Release build (takes ~2+ minutes, avoid during iteration)
cargo build --release

# Check all targets and features
cargo check --all-features --all-targets

Testing Philosophy

Test-driven approach: When fixing bugs or adding features, write test cases in brush-shell/tests/cases/*.yaml BEFORE implementation. Use these to validate your changes.

Integration test structure: Tests are YAML-based, run shell commands, compare stdout/stderr/exit codes against bash oracle. See docs/reference/integration-testing.md and AGENTS.md section 2 for detailed testing strategy.

Test categories:

  • Unit tests: In-file with #[cfg(test)]
  • Integration tests: brush-shell/tests/ directory
  • Compatibility tests: YAML cases in brush-shell/tests/cases/
  • Benchmarks: brush-shell/benches/ and crate-level benches/

Common Pitfalls & Solutions

Don't Do This

  • Run full test suite on every change (too slow)
  • Skip cargo fmt and cargo clippy before committing
  • Use cargo deny check during development iteration
  • Clone values unnecessarily (use references)
  • Add breaking changes to public APIs without highlighting them
  • Forget to add compat test cases for compatibility fixes

Do This

  • Target specific packages/tests during development
  • Run fmt/clippy before every commit
  • Follow builder pattern for configuration (see Shell::builder())
  • Keep platform-specific code in brush-core/src/sys/
  • Document all exported APIs with rustdoc
  • Use tracing::debug!(target: trace_categories::CATEGORY, "msg") for logging
  • Add test cases to brush-shell/tests/cases/ for compatibility changes

Error Handling & Logging

// Use thiserror for crate-specific errors
use thiserror::Error;

#[derive(Error, Debug)]
pub enum MyError { ... }

// Use anyhow ONLY in tests
#[cfg(test)]
use anyhow::Result;

// Logging with trace categories
use crate::trace_categories;
tracing::debug!(target: trace_categories::COMMANDS, "executing: {}", cmd);

Available trace categories: COMMANDS, COMPLETION, EXPANSION, FUNCTIONS, INPUT, JOBS, PARSE, PATTERN, UNIMPLEMENTED

Linting Configuration

The project uses extremely strict linting (workspace-level in Cargo.toml):

  • All Rust warnings denied
  • All clippy warnings denied (pedantic, cargo, nursery, perf)
  • expect_used, panic, todo, unwrap_in_result are forbidden
  • Missing docs on exported items are errors

Your code MUST pass cargo clippy without warnings.

Cross-Platform Considerations

  • Primary targets: Linux (x86_64, aarch64), macOS (aarch64)
  • Secondary: Windows (x86_64), WASM (wasm32-unknown-unknown, wasm32-wasip2)
  • Platform-specific code goes in brush-core/src/sys/ modules
  • Use cfg(unix), cfg(windows), cfg(target_family = "wasm") appropriately
  • See .cargo/config.toml for target-specific configurations

CI Pipeline (What Will Run on Your PR)

GitHub Actions runs these checks (from .github/workflows/ci.yaml):

  1. Build on multiple platforms (x86_64/aarch64 Linux, macOS, Windows, WASM)
  2. Tests on Linux x86_64, Linux aarch64, macOS
  3. Static checks (format, clippy, cargo-deny) on stable + MSRV (1.88.0)
  4. Compatibility tests with bash as oracle
  5. Code coverage reports (70% overall threshold, no 5% negative delta)
  6. External test suites (bash-completion test suite)
  7. OS compatibility (Arch, Debian, Fedora, NixOS, openSUSE)
  8. Benchmarks (performance regression detection on PRs)
  9. Public API analysis (breaking change detection)

All of these must pass for PR to merge.

Making Changes

Editing Core Shell Behavior

  1. Check brush-core/src/shell.rs for Shell struct
  2. Use Shell::builder() for construction
  3. Update brush-shell/src/main.rs if CLI changes needed

Adding/Modifying Builtins

  1. Edit files in brush-builtins/src/
  2. Register in brush-builtins/src/factory.rs
  3. Add test cases in brush-shell/tests/cases/builtin/

Parser Changes

  1. Modify brush-parser/src/
  2. Update AST definitions
  3. Test with cargo test --package brush-parser

Breaking Changes Policy

  • Avoid breaking public APIs (all crate exports are public)
  • If unavoidable, highlight clearly and document thoroughly
  • New optional fields on public structs are OK if struct implements Default
  • See AGENTS.md section 3 for complete breaking change policy

Performance & Benchmarking

# Run benchmarks (using xtask)
cargo xtask analyze bench

# Run benchmarks with output file
cargo xtask analyze bench --output benchmarks.txt

# Run benchmarks (manual)
cargo bench --workspace --benches

# Collect flamegraphs (10 second profiling)
cargo bench --workspace --benches -- --profile-time 10
# Output: target/criterion/<benchmark_name>/profile/*.svg

Note: Performance regression testing runs automatically on PRs. Don't worry about it unless working on performance-specific features.

Documentation Standards

Rustdoc: REQUIRED for all exported types, functions, traits, modules. Missing docs = CI failure. Examples: Only needed for major feature additions. Style: Follow Rust documentation best practices.

Commit Messages

Use Conventional Commits:

feat: add support for X
fix: correct behavior of Y
docs: update Z documentation
test: add test cases for W

AI-Assisted Contributions

If using AI assistance significantly, add to PR description or commit message:

Assisted-by: GitHub Copilot

When Something Fails

  1. Test failures: Focus on affected area first, check if new tests are needed
  2. Format/clippy failures: Fix immediately before proceeding
  3. Compat test failures: Indicates shell behavior change, may need test updates
  4. Build failures: Check dependencies, verify Rust version (1.88.0+)
  5. Timeout issues: Build from scratch can take 2+ minutes

Quick Reference

Command When Time
cargo xtask ci quick Rapid iteration (inner loop) ~7s
cargo xtask ci pre-commit Before commit (comprehensive) ~45s
cargo xtask ci pre-commit -k See all failures at once ~45s
cargo check Constantly during dev ~3-5s
cargo test --package X After each change 3-20s
cargo xtask test unit Fast unit tests ~4.5s
cargo xtask test integration All workspace tests ~36s
cargo xtask check fmt Before every commit <1s
cargo xtask check lint Before commit ~5-10s
cargo xtask check deps Final validation only ~1-5s

Trust These Instructions

Only search the codebase if information here or in AGENTS.md is incomplete, contradictory, or proven incorrect. These instructions are validated against the actual working repository.