c++-conventions
C++ coding conventions and best practices for modern C++ development. Use when writing, reviewing, or refactoring C++ code to ensure consistency with project standards, const-correctness, RAII principles, and C++23 features.
rust-conventions
Rust coding conventions and best practices for idiomatic Rust development. Use when writing, reviewing, or refactoring Rust code to ensure consistency with error handling, RAII principles, naming conventions, and Rust edition best practices.
Full skill instructions
rustfmt and clippy)Result<T, E> for error handling over panics&)UpdateOptions) to aggregate related arguments rather than passing many individual parameters. Prefer a single source of truth for data.Use Result<T, E> for all fallible operations
Use anyhow crate for error handling; re-export from lib.rs:
pub use anyhow::Result;
Use anyhow!() macro for constructing errors:
Err(anyhow!("Config file not found"))
Err(anyhow!("Failed to download {}: {}", url, e))
Use ? operator for error propagation
Avoid .unwrap() in library code; only use in application entry points after proper error handling
Use .ok_or_else() or .ok_or() to convert Option to Result with meaningful error messages
Never panic in library code unless documenting preconditions with #[panic] doc comments
Use the require! macro for precondition checks with early return:
require!(config_file.exists() == true, Err(anyhow!("Config not found")));
require!(name.is_empty() == false, None);
require!(count > 0, Ok(()));
require!(condition, return_expression)Result, Option, or bare valuesrequire! only for precondition checks at the top of a function (before any real work), mimicking design-by-contractrequire! for conditional logic deep inside function bodies; those should remain as regular if blocks== true and == false instead of bare conditionals or negationif condition == true, if value == falseif condition, if !valueOption and Result checksNone: if option_value.is_none() == true or if option_value == NoneAvoid if condition { continue; } guards at the top of loop bodies; they add visual noise especially with AlwaysNextLine brace style
Instead, combine guard conditions with the subsequent logic using &&, if/else if/else chains, or let-chains
Examples:
❌ Incorrect:
for entry in &files
{
if entry.is_skippable() == true
{
continue;
}
if let Some(value) = entry.process()
{
handle(value);
}
}
✅ Correct:
for entry in &files
{
if entry.is_skippable() == false &&
let Some(value) = entry.process()
{
handle(value);
}
}
For multi-branch dispatch, use if/else if/else instead of continue to skip to the next branch
Exception: continue inside match error arms (log-and-skip) is acceptable since it serves as early return from an error handler, not a guard
Use module structure to organize code by functionality
One public struct or major component per file
Related utility functions in dedicated utils.rs
Module declaration order in lib.rs:
mod)pub use)Example:
mod template_manager;
mod utils;
pub use anyhow::Result;
pub use template_manager::TemplateManager;
pub use utils::copy_dir_all;
Document all public APIs with doc comments (///)
Use doc comment structure:
# Description header)# Arguments section for parameters# Returns section for return values (when non-obvious)# Errors section for fallible functions# Examples section when helpful# Panics section if function can panicExample:
/// Creates a new TemplateManager instance
///
/// Initializes paths to local data and cache directories using the `dirs` crate.
/// Templates are stored in the local data directory and backups in the cache directory.
///
/// # Errors
///
/// Returns an error if the local data directory cannot be determined
pub fn new() -> Result<Self>
Pass by reference (&) for complex types, by value for Copy types
Use immutable references (&) unless mutation is required (&mut)
Keep function signatures on one line when under max width (167 chars)
Private helper functions should have single-line doc comments when logic is non-trivial
#[derive] for common traits when appropriateDefault for structs with sensible defaultsOption; use empty collections instead:
Option<Vec<T>>, Option<HashMap<K,V>> — creates redundant states (None vs empty)Vec<T>, HashMap<K,V> — empty collection represents absence#[serde(default, skip_serializing_if = "Vec::is_empty")] or "HashMap::is_empty"Option is appropriate for non-collection types where the default/zero value differs from absence (e.g., Option<Config>)Vec<T> via a getter, return &[T] (slice) not &Vec<T>TemplateManager, FileMapping, Result)download_file, create_backup, load_template_config)config_dir, source_path, file_name)MAX_WIDTH, DEFAULT_TIMEOUT)T, E, Error)'a, 'static)template_manager, utils)Use descriptive variant names in PascalCase
Derive common traits when appropriate
Use #[derive(Debug)] for all types when possible for better error messages
Use exhaustive pattern matching; avoid _ => catch-alls when possible
Use if let for single-pattern matching
Use match for multiple patterns or when you need exhaustiveness checking
Use let...else for early returns with single pattern:
let Some(value) = option else {
return Err(anyhow!("Missing value"));
};
Use clap's derive API for argument parsing
Define main CLI struct with #[derive(Parser)]
Use #[derive(Subcommand)] for command structure
Add helpful descriptions with #[command] attributes
Example:
#[derive(Parser)]
#[command(name = "vibe-check")]
#[command(about = "A manager for coding agent instruction files", long_about = None)]
struct Cli
{
#[command(subcommand)]
command: Commands
}
Use clear, descriptive field names that match CLI conventions
Provide defaults with #[arg(default_value = "...")]
Add documentation comments to show in --help output
max_width = 167 - Allow longer lines for readabilitybrace_style = "AlwaysNextLine" - Opening braces on new linescontrol_brace_style = "AlwaysNextLine" - Consistent brace placementtrailing_comma = "Never" - No trailing commasedition = "2024" - Use latest Rust editiontab_spaces = 4 - Standard indentationimports_granularity = "Crate" - Group imports by crategroup_imports = "StdExternalCrate" - Organize imports logicallycargo fmt before committing codeGroup imports in order:
std::)crate::)Use explicit imports over glob imports
Example:
use std::{
fs,
io::{self, Write},
path::{Path, PathBuf}
};
use chrono::{DateTime, Utc};
use owo_colors::OwoColorize;
use serde::{Deserialize, Serialize};
use crate::{Result, utils::copy_dir_all};
Re-export commonly used items from lib.rs for convenience
Use feature flags for optional functionality
Document feature requirements in doc comments
Use #[cfg(feature = "...")] for conditional code
Specify features in Cargo.toml dependencies when needed:
reqwest = { version = "0.12", features = ["blocking", "json"] }
Write unit tests alongside implementation in the same file
Use #[cfg(test)] module for tests
Name test functions descriptively: test_<scenario>_<expected_outcome>
Use assert!, assert_eq!, assert_ne! macros
Test both success and error cases
Example:
#[cfg(test)]
mod tests
{
use super::*;
#[test]
fn test_parse_github_url_valid()
{
// Test implementation
}
}
Use /// for public API documentation (appears in generated docs)
Use //! for module-level documentation at file top
Use // for implementation comments and explanations
Document the "why" not the "what" in implementation comments
Keep comments up-to-date with code changes
Use full sentences with proper punctuation in doc comments
Example:
//! Template management functionality for vibe-check
/// Creates a timestamped backup of a directory
///
/// Backups are stored in the cache directory with timestamp: `backups/YYYY-MM-DD_HH_MM_SS/`
fn create_backup(&self, source_dir: &Path) -> Result<()>
{
// Skip backup if source doesn't exist
if source_dir.exists() == false
{
return Ok(());
}
// ... rest of implementation
}
Allow specific clippy lints when project style differs from defaults
Configure in Cargo.toml:
[lints.clippy]
bool_comparison = "allow"
Can also use module-level attributes:
#![allow(clippy::bool_comparison)]
Document reasoning for lint exceptions
Entry point: src/main.rs (minimal, delegates to library)
Library API: src/lib.rs (public interface)
Implementation: Feature modules in src/
Keep main.rs focused on CLI handling and error reporting
Put business logic in library modules for reusability
Example structure:
src/
├── main.rs # CLI entry point
├── lib.rs # Public API
├── template_manager.rs # Core functionality
└── utils.rs # Shared utilities
Use std::env::current_dir() over hardcoding paths
Use Path and PathBuf for filesystem paths
Use Path::starts_with() for path prefix/subpath checks; avoid string-based path comparison (e.g. path.starts_with("foo/")) to ensure cross-platform behavior (Windows uses \, Unix uses /)
When resolving placeholders in paths (e.g. $workspace/AGENTS.md), use Path::join() with the suffix instead of string replace; string replace can produce mixed separators on Windows
Leverage std::io::Write trait for flushing output buffers
Use owo-colors or similar crate for terminal output styling
Use platform-appropriate paths via dirs crate (prefer over $HOME env var)
Implement flush() when printing without newline for immediate output:
print!("{} Processing... ", "→".blue());
io::stdout().flush()?;
Use early returns to reduce nesting depth
Prefer iterators and functional patterns over loops when clear
Use colored output for user-facing messages (owo-colors)
Format: "{} {}", symbol.color(), message.color()
Symbols: ✓ (success/green), ✗ (error/red), → (info/blue), ! (warning/yellow), ? (prompt/yellow)
Provide actionable error messages
Include file paths and operation details in errors
Example:
println!("{} Creating backup in {}", "→".blue(), backup_dir.display().to_string().yellow());
eprintln!("{} Failed to download {}: {}", "✗".red(), url, error.to_string().red());
Use Rust 2024 edition for latest language features
Specify in Cargo.toml:
[package]
edition = "2024"
Keep dependencies up-to-date but specify versions explicitly
Use semantic versioning in package version
Result consistently.unwrap() calls in library codecargo fmtcargo testC++ coding conventions and best practices for modern C++ development. Use when writing, reviewing, or refactoring C++ code to ensure consistency with project standards, const-correctness, RAII principles, and C++23 features.
Determine whether a version bump is required after code changes and apply semantic versioning (SemVer). Use when making code changes, fixing bugs, adding features, or introducing breaking changes to a project that uses SemVer.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience