Adding new crates to the foodshare-tools workspace. Use when scaffolding new library or binary crates, setting up Cargo.toml, registering workspace members, and following trait patterns.
<essential_principles>
mkdir -p crates/{crate-name}/src
[package]
name = "foodshare-{crate-name}"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
rust-version.workspace = true
description = "Brief description of the crate"
[dependencies]
# Use workspace dependencies where available
clap = { workspace = true }
thiserror = { workspace = true }
# Internal dependencies
foodshare-core = { path = "../core" }
Add to root Cargo.toml:
[workspace]
members = [
# ... existing members
"crates/{crate-name}",
]
//! foodshare-{crate-name}: Brief description
//!
//! This crate provides ...
mod error;
pub use error::Error;
mkdir -p bins/{binary-name}/src
[package]
name = "{binary-name}"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
rust-version.workspace = true
description = "Brief description of the binary"
[[bin]]
name = "{binary-name}"
path = "src/main.rs"
[dependencies]
clap = { workspace = true }
foodshare-core = { path = "../../crates/core" }
foodshare-{crate} = { path = "../../crates/{crate}" }
use clap::Parser;
#[derive(Parser)]
#[command(name = "{binary-name}", about = "Brief description")]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(clap::Subcommand)]
enum Commands {
/// Description of command
SomeCommand {
/// Description of arg
#[arg(short, long)]
flag: bool,
},
}
fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
Commands::SomeCommand { flag } => {
// implementation
}
}
Ok(())
}
Every crate should define its own error type:
// src/error.rs
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("E{code}: {message}")]
Structured {
code: u16,
message: String,
},
#[error(transparent)]
Io(#[from] std::io::Error),
}
Expose functionality through traits for testability:
pub trait Scanner: Send + Sync {
fn scan(&self, path: &Path) -> Result<Vec<Finding>>;
}
pub struct SecretScanner { /* ... */ }
impl Scanner for SecretScanner {
fn scan(&self, path: &Path) -> Result<Vec<Finding>> {
// implementation
}
}
# Verify workspace builds
cargo check --workspace --all-targets
# Run new crate's tests
cargo test -p foodshare-{crate-name}
# Lint
cargo clippy -p foodshare-{crate-name} -- -D warnings
</essential_principles>
<success_criteria> New crate is correct when:
cargo check --workspacecargo test -p {crate}