Skip to content

Commit 7d44013

Browse files
committed
Improve AGENTS.md with detailed code style guidelines and testing patterns
1 parent 97fc795 commit 7d44013

1 file changed

Lines changed: 99 additions & 106 deletions

File tree

AGENTS.md

Lines changed: 99 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,144 @@
1-
# CLAUDE.md
1+
# AGENTS.md
22

3-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
3+
Guidance for agentic coding agents working with Rust YouTube Uploader.
44

5-
## Project Overview
5+
## Quick Start
66

7-
Rust YouTube Uploader is a high-performance YouTube video uploader library with CLI tools. It uses OAuth 2.0 (PKCE flow) for authentication and supports both sequential and concurrent uploads with retry logic and progress tracking.
7+
**Build directory**: `~/.cache/rust-build/` (cached, never mention in docs)
8+
**Edition**: Rust 2024 | **Error handling**: `anyhow::Result` | **Runtime**: Tokio async
89

9-
**Build directory**: `~/.cache/rust-build/` (never mention this in documentation or code).
10-
11-
**Key Design**: Async-first architecture using Tokio runtime. All operations are async and the library uses `anyhow` for error handling.
12-
13-
## Development Commands
14-
15-
### Building
10+
### Essential Commands
1611

1712
```bash
18-
# Build specific binaries (never run from target/ directly)
19-
cargo build --release --bin yt-upload
20-
cargo build --release --bin yt-list
21-
cargo build --release --bin yt-update-lang
22-
23-
# Quick check (faster than full build)
24-
cargo check
13+
# Build & check
14+
cargo build --release --bin <name> # Build specific binary
15+
cargo check # Quick syntax check
16+
cargo fmt # Auto-format code
17+
cargo clippy --all-targets --all-features # Lint
18+
19+
# Testing
20+
cargo test --all-features # Run all tests
21+
cargo test test_name -- --nocapture # Run specific test with output
22+
cargo test --lib # Library tests only
2523
```
2624

27-
### Testing
25+
## Project Structure
2826

29-
```bash
30-
# Run all tests
31-
cargo test --all-features
27+
**Core Library** (`src/lib.rs`): `google_oauth`, `models`, `youtube_client`, `retry`, `progress_stream`, `video_process`
3228

33-
# Run specific test
34-
cargo test test_name
29+
**CLI Binaries** (`src/bin/`): `yt-upload`, `yt-list`, `yt-append-description`, `yt-add-pin-comment`, `yt-add-tags`, `yt-update-lang`, `yt-update-date`, `yt-upload-subtitle`
3530

36-
# Run tests with output
37-
cargo test --all-features -- --nocapture
38-
```
31+
**Tests**: `tests/integration.rs` (config parsing, validation); library tests in `src/**/*.rs`
3932

40-
### Code Quality
33+
## Code Style & Conventions
4134

42-
```bash
43-
# Format code
44-
cargo fmt
35+
### Imports & Organization
4536

46-
# Check formatting without changes
47-
cargo fmt -- --check
37+
- **Standard library first**, then external crates, then internal modules (separated by blank lines)
38+
- Use glob imports sparingly; prefer explicit imports for clarity
39+
- Re-export public types in `lib.rs` for API simplicity
40+
- Use `use anyhow::Result` for all error-returning functions
41+
- Trait objects: `Arc<dyn Trait>` for sharing (e.g., `Arc<dyn ProgressReporter>`)
4842

49-
# Run linter
50-
cargo clippy --all-targets --all-features
43+
### Naming & Types
5144

52-
# Pre-commit hooks (configured in .pre-commit-config.yaml)
53-
pre-commit install # Install git hooks
54-
pre-commit run --all-files # Run manually
55-
pre-commit autoupdate # Update hooks to latest versions
56-
```
45+
- **Functions**: `snake_case`, methods starting with action verbs (`update_`, `post_`, `get_`)
46+
- **Types**: `PascalCase` for structs/enums/traits
47+
- **Constants**: `SCREAMING_SNAKE_CASE`
48+
- **Private helpers**: Prefix internal functions with underscore if needed
49+
- **Type annotations**: Always explicit for public functions and struct fields
5750

58-
## Architecture
51+
### Error Handling
5952

60-
### Module Structure
53+
- Use `anyhow::Result<T>` (not `std::result::Result`) everywhere
54+
- Use `anyhow::bail!()` for quick errors: `anyhow::bail!("Error: {}", context)`
55+
- Use `?` operator for propagation; wrap with `.map_err()` only if context needed
56+
- Log errors with `error!()` before returning (uses tracing crate)
57+
- Document retriable vs. non-retriable errors in comments
6158

62-
**Core Library** (`src/lib.rs`):
59+
### Async & Concurrency
6360

64-
- `google_oauth/`: OAuth 2.0 authentication with PKCE support
65-
- `credentials.rs`: Client secret loading
66-
- `google.rs`: `GoogleOAuth` main client (token management, auto-refresh)
67-
- `oauth.rs`: Interactive OAuth flow with local HTTP server for code exchange
68-
- `models.rs`: Configuration models with validation (individual/batch YAML formats)
69-
- `youtube_client.rs`: Core upload logic, progress reporting, playlist management
70-
- `retry.rs`: Exponential backoff with jitter for retriable HTTP errors
71-
- `progress_stream.rs`: Stream wrapper for progress tracking + bandwidth throttling
72-
- `video_process.rs`: FFmpeg integration for merging multiple video files
61+
- **All operations are async**: Use `async fn` and `.await`
62+
- Use `tokio::spawn()` for concurrent tasks; `Arc<Semaphore>` for rate limiting
63+
- Document which fields/methods require `Send + Sync` traits
64+
- Avoid blocking operations in async contexts
7365

74-
**CLI Binaries** (`src/bin/`):
66+
### Comments & Documentation
7567

76-
- `yt-upload`: Main uploader (sequential/concurrent modes)
77-
- `yt-list`: List/export channel videos (table/JSON/JSONL formats)
78-
- `yt-update-lang`: Update language metadata for videos
79-
- `yt-update-date`: Update recording date metadata
80-
- `yt-update-description`: Update video descriptions
81-
- `yt-upload-subtitle`: Upload caption/subtitle files
82-
- `yt-add-tags`: Add tags to existing videos
68+
- **Public items**: Full doc comments `///` with examples and panics
69+
- **Complex logic**: Explain the "why" not the "what"
70+
- **Inline comments**: Use `//` for clarification, keep minimal
71+
- **Tests**: Include usage examples in doc comments for public APIs
8372

84-
### Key Patterns
73+
### Formatting
8574

86-
**OAuth Flow**:
75+
- 4-space indentation (enforced by `cargo fmt`)
76+
- Max line length: ~100 characters (soft limit)
77+
- One statement per line; use temporary variables for readability
78+
- Format strings: Use `{}` interpolation, not `.to_string()` concatenation
8779

88-
1. First run: Interactive flow displays auth URL → opens browser → user pastes code → tokens saved to `youtube-oauth2.json`
89-
2. Subsequent runs: Loads existing tokens, auto-refreshes on expiry
90-
3. Credentials files (`client_secret.json`, token files) are **never** committed to git
80+
### API Design
9181

92-
**Configuration Formats**:
82+
- Return `Result<T>` for fallible operations
83+
- Trait bounds in function signatures: `<P: AsRef<Path>>` for flexibility
84+
- Builder pattern for complex construction (use `with_*` methods)
85+
- Private constructors with public factory methods (e.g., `YouTubeClient::new()`)
9386

94-
- **Batch format**: `common` section + separate `titles` and `files` arrays (recommended)
95-
- **Individual format**: `videos` array with per-video configuration
96-
- Both support comma/semicolon/space-separated file lists for merging multiple videos
87+
## Pre-commit Hooks
9788

98-
**Upload Modes**:
89+
All commits run: `cargo fmt``cargo clippy``cargo test` → trailing whitespace checks
9990

100-
- **Sequential**: One video at a time with progress bars (default)
101-
- **Concurrent**: Configurable concurrency (default 3), uses `Semaphore` for throttling
91+
**To bypass** (never recommended): `git commit --no-verify`
92+
**To fix formatting failures**: Run `cargo fmt` then re-stage files
10293

103-
**Error Handling**:
94+
## Key Patterns in Codebase
10495

105-
- Library uses `anyhow::Result` for error propagation
106-
- Retriable errors: HTTP 500-504, connection errors, timeouts, IO errors
107-
- Non-retriable: Client errors (4xx), validation failures
96+
### Error Context
10897

109-
**Progress Tracking**:
110-
111-
- `ProgressReporter` trait with implementations: `NoProgress`, `ProgressBarReporter`
112-
- `ProgressStream` wraps upload streams for real-time tracking
113-
114-
### File Handling
98+
```rust
99+
// ✅ Good: context before propagation
100+
if !response.status().is_success() {
101+
let status = response.status();
102+
let text = response.text().await.unwrap_or_default();
103+
return Err(anyhow!("Failed to X with status {}: {}", status, text));
104+
}
105+
```
115106

116-
**Video Merging**:
107+
### Async Patterns
117108

118-
- File entries can contain multiple paths separated by `,` or `;`
119-
- Automatically calls `merge_videos_with_ffmpeg()` to concatenate before upload
120-
- Uses concat demuxer (no re-encoding, fast operation)
109+
```rust
110+
// ✅ Good: explicit await, Arc for shared state
111+
let client = Arc::new(YouTubeClient::new().await?);
112+
let results = try_join_all(tasks).await?;
113+
```
121114

122-
**MIME Types**:
115+
### Response Handling
123116

124-
- Uses `mime_guess` for auto-detection
125-
- Special handling for `.mts` files → `video/mp2t`
117+
```rust
118+
// ✅ Good: deserialize then extract
119+
#[derive(Deserialize)]
120+
struct Response { items: Vec<Item> }
121+
let resp: Response = response.json().await?;
122+
```
126123

127124
## Versioning
128125

129-
**Version Bumping**: Each commit shall bump the minor version in `Cargo.toml`. For example:
130-
131-
- After committing, the version changes from `0.2.9``0.2.10``0.2.11`, etc.
132-
- This automatic versioning is managed during the commit process
133-
- Patch version increments only; major/minor versions remain stable unless explicitly changed
126+
**Version bumping**: Each commit increments minor version (`0.2.X``0.2.X+1`)
127+
Update `Cargo.toml` version before committing; pre-commit hook validates changes.
134128

135129
## Important Constraints
136130

137-
- **Never run `cargo clean`** (build directory is cached)
138-
- **Never run binaries** from `target/debug/` or `target/release/` directly
139-
- Always use `cargo run --bin <name>` for execution
140-
- Rust 2024 edition required
141-
- Build directory location is an implementation detail - never expose it in docs/code
142-
143-
## Test
131+
- ❌ Never: `cargo clean` (breaks build cache)
132+
- ❌ Never: Run binaries from `target/` directly (use `cargo run --bin`)
133+
- ❌ Never: Commit `client_secret.json`, `youtube-oauth2.json`
134+
- ✅ Always: Use `cargo test` before committing
135+
- ✅ Always: Run `cargo fmt` on modified files
136+
- ✅ Always: Test both sequential and concurrent upload modes if modifying `YouTubeClient`
144137

145-
Integration tests are in `tests/integration.rs`. They test:
138+
## Testing Strategy
146139

147-
- Configuration parsing (individual/batch formats)
148-
- Validation logic (playlist IDs, categories, privacy status)
149-
- File format detection
140+
**Unit tests** (`#[test]`): Logic validation, mocking not needed
141+
**Integration tests** (`tests/integration.rs`): Configuration parsing, file handling
142+
**Ignored tests** (`#[ignore]`): Run explicitly with `cargo test -- --ignored`
150143

151-
Tests with `#[ignore]` are meant for explicit running (e.g., retry logic tests with delays).
144+
Example: `cargo test test_batch_config -- --nocapture`

0 commit comments

Comments
 (0)