supgit 0.2.0

A simple Git CLI wrapper for common Git operations
# AGENTS.md - SupGIT Project Guidelines

## Project Overview

SupGIT (Simple Git) is a Rust CLI wrapper around Git that provides simplified workflows for common Git operations. It is a single-binary project with a modular code structure.

## Build/Lint/Test Commands

```bash
# Build the project
cargo build

# Build with optimizations
cargo build --release

# Run the binary directly
cargo run -- <command>

# Check for compilation errors (faster than build)
cargo check

# Run all tests
cargo test

# Run a specific test by name
cargo test <test_name>

# Run a specific test file (for integration tests)
cargo test --test <test_file>

# Run tests with output shown
cargo test -- --nocapture

# Run a single test with pattern matching
cargo test <pattern>

# Lint with clippy
cargo clippy

# Format code
cargo fmt

# Check formatting without applying
cargo fmt -- --check
```

## Code Style Guidelines

### Imports

- Group imports logically: standard library first, then external crates, then local modules
- Use `use` statements at the top of the file
- Import specific items rather than glob imports (`use anyhow::{bail, Context, Result}` not `use anyhow::*`)
- Rename imports to avoid conflicts (e.g., `use std::process::Command as StdCommand`)

```rust
use std::process::Command as StdCommand;

use anyhow::{bail, Context, Result};
use dialoguer::{Confirm, Input, Select};

use crate::git::run_git_silent;
use crate::status::get_repo_root;
```

### Formatting

- Use 4 spaces for indentation (Rust standard)
- Maximum line length: 100 characters
- Place opening braces on the same line
- Use `cargo fmt` to auto-format before committing

### Types

- Use `Result<T>` as the return type for fallible functions (aliased from `anyhow::Result`)
- Use `Option<T>` for optional values
- Prefer `String` for owned strings, `&str` for borrowed
- Use `Vec<T>` for collections

### Naming Conventions

- **Functions**: snake_case (`run_git`, `get_staged_files`, `stage_targets`)
- **Structs/Enums**: PascalCase (`Cli`, `SupgitCommand`)
- **Constants**: SCREAMING_SNAKE_CASE (`NOT_IN_REPO_HINT`, `NO_STAGED_HINT`)
- **Variables**: snake_case
- **Enum variants**: PascalCase (`SupgitCommand::Init`, `SupgitCommand::Stage`)

### Error Handling

- Use `anyhow` crate for error handling
- Use `bail!` macro for early returns with an error message
- Use `.context()` or `.with_context()` to add context to operations that may fail

```rust
pub fn check_in_repo() -> Result<()> {
    StdCommand::new("git")
        .args(["rev-parse", "--git-dir"])
        .status()
        .context("failed to execute git - is git installed?")?
        .success()
        .then_some(())
        .ok_or_else(|| anyhow::anyhow!("{}", NOT_IN_REPO_HINT))
}
```

### CLI Structure

- Use `clap` derive macros (`#[derive(Parser, Subcommand)]`)
- Document commands and arguments with doc comments (`///`)
- Use `#[arg(long)]` for long flags, `#[arg(short, long)]` for both
- Use `#[command(subcommand)]` for subcommands

```rust
#[derive(Parser)]
#[command(name = "supgit", about = "Description", version)]
pub struct Cli {
    #[arg(long, global = true)]
    pub explain: bool,

    #[command(subcommand)]
    pub command: Option<SupgitCommand>,
}
```

### Functions

- Keep functions focused on a single responsibility
- Use `-> Result<()>` for functions that may fail
- Pattern match on `is_interactive` to handle CLI vs interactive modes
- Extract helper functions for repeated logic

### Pattern Matching

- Use `match` for enum dispatch
- Handle all variants explicitly
- Use `_ => Ok(())` for no-op default cases when appropriate

### Command Execution

- Use `std::process::Command` for running Git commands
- Check `output.status.success()` before returning `Ok(())`
- Use `.output()` when you need to capture stdout/stderr

```rust
let output = StdCommand::new("git")
    .args(["status", "--porcelain"])
    .output()
    .context("running git status --porcelain")?;
```

### String Handling

- Use `String::from_utf8_lossy()` for converting command output
- Use `.trim()` to clean up output strings
- Use `.lines()` for iterating over multi-line output
- Use `.as_str()` to convert `String` to `&str` when needed

## Architecture Notes

- Modular architecture under `src/`:
  - `main.rs` - Entry point, command dispatch
  - `cli.rs` - CLI definitions (Cli struct, SupgitCommand enum)
  - `git.rs` - Git command execution helpers (`run_git`, `run_git_silent`, etc.)
  - `status.rs` - Repository status utilities (`get_staged_files`, `get_branches`, etc.)
  - `commands/` - Individual command implementations
- Entry point is `fn main()` which calls `run()` and handles errors
- All Git operations use helpers from `git.rs` module
- Interactive prompts use the `dialoguer` crate
- User-facing errors are printed via `eprintln!` with error chain

## Adding New Commands

1. Add a new variant to `SupgitCommand` enum in `src/cli.rs` with doc comment
2. Add any required arguments as fields with `#[arg]` attributes
3. Create a new file in `src/commands/` for the implementation
4. Export the function from `src/commands/mod.rs`
5. Add a match arm in `main.rs` to call the new command function
6. Update `print_explanations()` in `main.rs` to document the new command

## Dependencies

- `anyhow`: Error handling
- `clap`: CLI argument parsing (derive feature enabled)
- `dialoguer`: Interactive prompts (Select, Input, Confirm, MultiSelect)