Guidance for agentic coding agents working with Rust YouTube Uploader.
Build directory: ~/.cache/rust-build/ (cached, never mention in docs)
Edition: Rust 2024 | Error handling: anyhow::Result | Runtime: Tokio async
# Build & check
cargo build --release --bin <name> # Build specific binary
cargo check # Quick syntax check
cargo fmt # Auto-format code
cargo clippy --all-targets --all-features # Lint
# Testing
cargo test --all-features # Run all tests
cargo test test_name -- --nocapture # Run specific test with output
cargo test --lib # Library tests onlyCore Library (src/lib.rs): google_oauth, models, youtube_client, retry, progress_stream, video_process
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
Tests: tests/integration.rs (config parsing, validation); library tests in src/**/*.rs
- Standard library first, then external crates, then internal modules (separated by blank lines)
- Use glob imports sparingly; prefer explicit imports for clarity
- Re-export public types in
lib.rsfor API simplicity - Use
use anyhow::Resultfor all error-returning functions - Trait objects:
Arc<dyn Trait>for sharing (e.g.,Arc<dyn ProgressReporter>)
- Functions:
snake_case, methods starting with action verbs (update_,post_,get_) - Types:
PascalCasefor structs/enums/traits - Constants:
SCREAMING_SNAKE_CASE - Private helpers: Prefix internal functions with underscore if needed
- Type annotations: Always explicit for public functions and struct fields
- Use
anyhow::Result<T>(notstd::result::Result) everywhere - Use
anyhow::bail!()for quick errors:anyhow::bail!("Error: {}", context) - Use
?operator for propagation; wrap with.map_err()only if context needed - Log errors with
error!()before returning (uses tracing crate) - Document retriable vs. non-retriable errors in comments
- All operations are async: Use
async fnand.await - Use
tokio::spawn()for concurrent tasks;Arc<Semaphore>for rate limiting - Document which fields/methods require
Send + Synctraits - Avoid blocking operations in async contexts
- Public items: Full doc comments
///with examples and panics - Complex logic: Explain the "why" not the "what"
- Inline comments: Use
//for clarification, keep minimal - Tests: Include usage examples in doc comments for public APIs
- 4-space indentation (enforced by
cargo fmt) - Max line length: ~100 characters (soft limit)
- One statement per line; use temporary variables for readability
- Format strings: Use
{}interpolation, not.to_string()concatenation
- Return
Result<T>for fallible operations - Trait bounds in function signatures:
<P: AsRef<Path>>for flexibility - Builder pattern for complex construction (use
with_*methods) - Private constructors with public factory methods (e.g.,
YouTubeClient::new())
All commits run: cargo fmt → cargo clippy → cargo test → trailing whitespace checks
❌ NEVER use git commit --no-verify - This bypasses all pre-commit checks and will likely cause CI failures.
If you used --no-verify and CI fails:
- Fix the issues (usually formatting: run
cargo fmt) - Re-stage files:
git add . - Commit without
--no-verify:git commit -m "fix: ..." - Push and verify CI passes
| Failure | Cause | Fix |
|---|---|---|
cargo fmt |
Code formatting | Run cargo fmt then re-stage |
cargo clippy |
Lint warnings | Fix warnings or run cargo clippy --fix |
cargo test |
Test failures | Fix failing tests |
After pushing any commit, agents MUST verify CI passes:
- Push commit and note the run ID
- Run
gh run watch --repo leafyoung/rust-yt-uploader --exit-statusuntil completion - If CI fails, run
gh run view --log-failed --repo leafyoung/rust-yt-uploaderto diagnose - Fix any issues and re-push until all jobs pass
- Only proceed to next task after CI is green
// ✅ Good: context before propagation
if !response.status().is_success() {
let status = response.status();
let text = response.text().await.unwrap_or_default();
return Err(anyhow!("Failed to X with status {}: {}", status, text));
}// ✅ Good: explicit await, Arc for shared state
let client = Arc::new(YouTubeClient::new().await?);
let results = try_join_all(tasks).await?;// ✅ Good: deserialize then extract
#[derive(Deserialize)]
struct Response { items: Vec<Item> }
let resp: Response = response.json().await?;Version bumping: Each commit increments minor version (0.2.X → 0.2.X+1)
Update Cargo.toml version before committing; pre-commit hook validates changes.
- ❌ Never:
cargo clean(breaks build cache) - ❌ Never: Run binaries from
target/directly (usecargo run --bin) - ❌ Never: Commit
client_secret-{profile}.json,youtube-oauth2-{profile}.json - ✅ Always: Use
cargo testbefore committing - ✅ Always: Run
cargo fmton modified files - ✅ Always: Test both sequential and concurrent upload modes if modifying
YouTubeClient
Unit tests (#[test]): Logic validation, mocking not needed
Integration tests (tests/integration.rs): Configuration parsing, file handling
Ignored tests (#[ignore]): Run explicitly with cargo test -- --ignored
Example: cargo test test_batch_config -- --nocapture
After pushing commits, always verify CI passes using gh CLI (not direct links):
# View CI run status (get run ID from push output or list)
gh run list --repo leafyoung/rust-yt-uploader --limit 3
# Watch CI run progress with live updates
gh run watch <run-id> --repo leafyoung/rust-yt-uploader --exit-status
# If CI fails, view detailed failure logs
gh run view <run-id> --repo leafyoung/rust-yt-uploader --log-failed
# View specific job logs
gh run view <run-id> --repo leafyoung/rust-yt-uploader --job <job-id>- Rust version too old: Dependencies may require newer Rust. Update
rust-versioninCargo.tomland CI matrix. - Mold linker not available: CI runners don't have mold installed. Use
rui314/setup-mold@v1action in workflow. - Security vulnerabilities:
cargo auditmay find issues. Update vulnerable dependencies viacargo update. - Node.js deprecation warnings: Use newer action versions (e.g.,
Swatinem/rust-cache@v2instead ofactions/cache@v3).
# 1. Make changes and commit
git add . && git commit -m "fix: something"
# 2. Push and note the run ID from output
git push
# 3. Watch CI until completion
gh run watch --repo leafyoung/rust-yt-uploader --exit-status
# 4. If failed, diagnose and fix
gh run view --log-failed --repo leafyoung/rust-yt-uploader