# AGENTS.md

## Project Overview

This is a Rust project containing multiple CLI tools:
- `git_commit_generator` - An AI-powered tool that generates conventional git commit messages from staged changes
- `another_tool` - A tool that fetches and displays IP information from https://ipinfo.io/json

The project uses `portable` as the library name and supports cross-compilation for multiple platforms (macOS Intel/ARM, Linux x86_64/ARM64, Windows x86_64).

## Project Structure

```
portable/
├── src/
│   ├── bin/                    # Binary executables (CLI tools)
│   │   ├── git_commit_generator.rs
│   │   └── another_tool.rs
│   ├── lib.rs                  # Library entry point
│   └── model/                  # Shared data models
│       ├── mod.rs              # Module exports
│       ├── api.rs              # API request/response types
│       └── cli.rs              # CLI argument parsing
├── scripts/
│   ├── install.sh              # Multi-platform build script
│   └── BUILD.md                # Chinese build documentation
├── .github/workflows/
│   ├── ci.yml                  # Quality checks and testing
│   └── release.yml             # Release automation
├── Cargo.toml                  # Project configuration
└── .env                        # Environment variables (gitignored)
```

## Essential Commands

### Development

```bash
# Build (debug mode)
cargo build

# Build (release mode)
cargo build --release

# Run specific binary
cargo run --bin git_commit_generator

# Run with arguments
cargo run --bin git_commit_generator -- --help

# Run all binaries
cargo run --bins
```

### Code Quality

```bash
# Format code
cargo fmt

# Check formatting (CI requirement)
cargo fmt --all -- --check

# Lint with clippy
cargo clippy --all-targets --all-features -- -D warnings

# Generate documentation
cargo doc --no-deps --all-features
```

### Testing

```bash
# Run all tests
cargo test --all --all-features

# Run tests for specific binary
cargo test --bin git_commit_generator
```

### Cross-Platform Building

The project uses `cargo-zigbuild` for cross-compilation to Linux targets.

```bash
# Install cross-compilation tools (one-time setup)
cargo install cargo-zigbuild
brew install mingw-w64  # For Windows builds

# Add Rust targets (one-time setup)
rustup target add x86_64-unknown-linux-gnu \
                  aarch64-unknown-linux-gnu \
                  x86_64-pc-windows-gnu

# Build all platforms
cd scripts
./install.sh

# Build current platform only
cd scripts
BUILD_MODE=local ./install.sh

# Force specific build tool
BUILD_CMD=zigbuild ./install.sh
BUILD_CMD=cargo ./install.sh

# Debug mode
DEBUG=true ./install.sh
```

**Build Artifacts:**
- Multi-platform builds: `target/releases/{platform}/`
  - Example: `target/releases/x86_64-apple-darwin/git_commit_generator`
- Local builds: `target/{target}/release/`
  - Example: `target/x86_64-apple-darwin/release/git_commit_generator`

**Environment Variables for install.sh:**
- `BUILD_MODE`: `all` (default) or `local`
- `BUILD_CMD`: `auto` (default), `cargo`, or `zigbuild`
- `DEBUG`: `true` or `false` (default)

## Code Organization and Patterns

### Module Structure

- **Library (`src/lib.rs`)**: Exports shared types and modules
- **Binaries (`src/bin/*.rs`)**: Independent CLI tools that use the shared library
- **Models (`src/model/`)**: Common data structures (API types, CLI args)

### Binary Conventions

Each binary in `src/bin/` should:
1. Use `use portable::model::*` to import shared types
2. Implement async main with `#[tokio::main]`
3. Parse CLI args with `Cli::parse()` from clap
4. Load env vars with `dotenvy::dotenv().ok()`

Example binary structure:
```rust
use clap::Parser;
use portable::model::{Cli};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cli = Cli::parse();
    dotenvy::dotenv().ok();

    // Application logic
    Ok(())
}
```

### Model Conventions

**CLI Arguments (`src/model/cli.rs`)**:
- Use clap's `#[derive(Parser)]`
- Include `author, version, about, long_about = None`
- Use `#[arg(short, long, default_value_t)]` for flags

**API Types (`src/model/api.rs`)**:
- Use `#[derive(Serialize, Deserialize)]` from serde
- Separate request/response structures
- Export from `mod.rs` for external use

## Configuration

### Environment Variables

Required for `git_commit_generator` (create `.env` in project root):
```dotenv
AI_API_KEY="your_api_key_here"
AI_API_URL="https://api.example.com/v1/models/model:generateContent"
AI_MODEL="model-name"
```

**Critical**: `.env` is gitignored. Never commit it.

### Cargo.toml

- `default-run = "git_commit_generator"`: Sets default binary for `cargo run`
- Edition: Rust 2021
- Dependencies use minimal features where possible (e.g., `reqwest` uses `rustls-tls` instead of `native-tls`)

## Naming Conventions

- **Binaries**: `snake_case` (e.g., `git_commit_generator.rs`)
- **Functions**: `snake_case`
- **Types**: `PascalCase` (e.g., `ApiRequestBody`)
- **Modules**: `snake_case` (e.g., `mod api`)
- **Constants**: `SCREAMING_SNAKE_CASE`
- **CLI args**: `--long-option` and `-s` for short options

## Code Style

- **Formatting**: Use `cargo fmt` (enforced in CI)
- **Linting**: Clippy with `-D warnings` (all warnings treated as errors)
- **Documentation**: Doc comments on public items
- **Error Handling**: Use `Result<T, Box<dyn std::error::Error>>` for main functions

## Important Gotchas

### Cross-Compilation

1. **zigbuild Target Names**: For Linux targets, zigbuild requires glibc version suffixes (e.g., `x86_64-unknown-linux-gnu.2.28`), but the output directory uses the original name (e.g., `target/x86_64-unknown-linux-gnu/`).

2. **Platform Selection**: The `install.sh` script automatically:
   - Uses `cargo` for macOS targets (native compilation)
   - Uses `cargo-zigbuild` for Linux targets (cross-compilation)
   - Uses `cargo` for Windows (requires MinGW)

3. **Binary Location**: After multi-platform build, binaries are copied from `target/{platform}/release/` to `target/releases/{platform}/` for distribution.

### Build Artifacts

- The `install.sh` script cleans intermediate build artifacts after multi-platform builds
- Windows binaries get `.exe` extension automatically
- Binaries are made executable with `chmod +x` on Unix platforms

### CLI Binary Execution

When using `cargo run` with binaries, use `--` to separate cargo args from program args:
```bash
cargo run --bin git_commit_generator -- --help
#          ^^^^^^^^^^^^^^^^^^^^^     ^^^^
#          cargo args                program args
```

### Environment Configuration

- `dotenvy::dotenv().ok()` is called at the start of binaries - it won't fail if `.env` doesn't exist
- Environment variables are loaded at runtime, not compile time
- Missing required env vars cause `expect()` to panic (e.g., `env::var("AI_API_KEY").expect("AI_API_KEY must be set")`)

### Git Integration

`git_commit_generator` requires:
- Being run from inside a Git repository
- Having staged changes (checked via `git diff --cached`)
- Git to be installed and available in PATH

## Dependencies

- **tokio**: Async runtime (full features)
- **reqwest**: HTTP client (JSON support, rustls-tls for security)
- **serde**: Serialization (derive feature enabled)
- **dotenvy**: Environment variable loading from `.env`
- **clap**: CLI argument parsing (derive feature)
- **indicatif**: Progress bars and spinners

## CI/CD Pipeline

### Quality Checks (runs on every push/PR)

- Code format check: `cargo fmt --all -- --check`
- Clippy linting: `cargo clippy --all-targets --all-features -- -D warnings`
- Documentation check: `cargo doc --no-deps --all-features` with `-D warnings`

### Multi-Platform Testing

Tests on: ubuntu-latest, macos-latest, windows-latest
- Runs: `cargo test --all --all-features`
- Builds: Debug and release versions

### Release Automation

Triggered by pushing version tags (e.g., `v1.0.0`):
- Builds for 5 platforms (macOS x86_64/ARM, Linux x86_64/ARM64, Windows x86_64)
- Uses cargo-zigbuild for Linux targets (glibc 2.28)
- Creates tar.gz (Unix) and .zip (Windows) archives
- Generates SHA256 checksums
- Publishes to GitHub Releases

## Adding New Binaries

1. Create `src/bin/{binary_name}.rs`
2. Add basic structure with `#[tokio::main]` and `clap::Parser`
3. Import shared types from `portable::model`
4. Update documentation if needed
5. Binary will be automatically built by `install.sh` and CI workflows

## Debugging

### Enable Debug Output

```bash
# Build in debug mode
cargo build

# Run with debug output
./target/debug/git_commit_generator
```

### Set Environment Variables for Debugging

```bash
# Enable rust backtraces
export RUST_BACKTRACE=1

# Set logging level (if using env_logger)
export RUST_LOG=debug
```

### Common Issues

1. **Missing Rust targets**: Run `rustup target add {target}`
2. **zigbuild not found**: Run `cargo install cargo-zigbuild`
3. **MinGW missing on macOS**: Run `brew install mingw-w64`
4. **Permission denied on binaries**: Run `chmod +x target/{target}/release/{binary}`
