.claude/skills/rig-vector-store/SKILL.md
<!-- This file is generated by scripts/sync_agent_instruction_files.sh. --> <!-- Do not edit this file directly; update AGENTS.md and re-run the sync script. --> --- name: rig-vector-store description: > Implement a Rig vector store companion crate. Use when adding a new vector database backend (MongoDB, LanceDB, Qdrant, etc.) or reviewing an existing vector store integration. argument-hint: "[store-backend]" allowed-tools: - Read - Glob - Grep - Edit - Write - Bash --- # Rig
npx skillsauth add 0xplaygrounds/rig .claude/skills/rig-vector-storeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
name: rig-vector-store description: > Implement a Rig vector store companion crate. Use when adding a new vector database backend (MongoDB, LanceDB, Qdrant, etc.) or reviewing an existing vector store integration. argument-hint: "[store-backend]" allowed-tools:
Implement or audit a Rig vector store companion crate.
Requirements:
VectorStoreIndex trait with both top_n and top_n_ids.Filter type for your backend.WasmCompatSend / WasmCompatSync bounds.VectorStoreError variants.rig-mongodb).Vector stores live in separate companion crates (e.g., rig-mongodb, rig-lancedb).
pub trait VectorStoreIndex: WasmCompatSend + WasmCompatSync {
type Filter: SearchFilter + WasmCompatSend + WasmCompatSync;
fn top_n<T: for<'a> Deserialize<'a> + WasmCompatSend>(
&self,
req: VectorSearchRequest<Self::Filter>,
) -> impl Future<Output = Result<Vec<(f64, String, T)>, VectorStoreError>> + WasmCompatSend;
fn top_n_ids(
&self,
req: VectorSearchRequest<Self::Filter>,
) -> impl Future<Output = Result<Vec<(f64, String)>, VectorStoreError>> + WasmCompatSend;
}
top_n and top_n_idsFilter type for your backendWasmCompatSend/WasmCompatSync bounds (see below)VectorStoreError variantsRig supports WebAssembly targets. Since WASM is single-threaded, Send/Sync bounds are unnecessary and can prevent compilation.
#[cfg(not(target_family = "wasm"))]
pub trait WasmCompatSend: Send {} // native
#[cfg(target_family = "wasm")]
pub trait WasmCompatSend {} // wasm
#[cfg(not(target_family = "wasm"))]
pub trait WasmCompatSync: Sync {} // native
#[cfg(target_family = "wasm")]
pub trait WasmCompatSync {} // wasm
Always use WasmCompatSend and WasmCompatSync instead of raw Send and Sync in trait bounds.
// Correct
pub trait MyTrait: WasmCompatSend + WasmCompatSync {
fn do_thing(&self) -> impl Future<Output = ()> + WasmCompatSend;
}
// Incorrect - will break WASM builds
pub trait MyTrait: Send + Sync {
fn do_thing(&self) -> impl Future<Output = ()> + Send;
}
Use WasmBoxedFuture for boxed futures:
pub type WasmBoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>; // native
pub type WasmBoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>; // wasm
Some error types need platform-specific bounds:
#[derive(Debug, thiserror::Error)]
pub enum MyError {
#[cfg(not(target_family = "wasm"))]
#[error("Error: {0}")]
Inner(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
#[cfg(target_family = "wasm")]
#[error("Error: {0}")]
Inner(#[from] Box<dyn std::error::Error + 'static>),
}
Use full where clause syntax for readability:
// Correct
impl<T> CompletionModel for MyModel<T>
where
T: HttpClientExt + Clone + WasmCompatSend + Debug + Default + 'static,
{
// ...
}
// Avoid inline bounds for complex signatures
impl<T: HttpClientExt + Clone + WasmCompatSend + Debug + Default + 'static> CompletionModel for MyModel<T> {
// ...
}
DO NOT use String as an error type. Define proper error enums:
// Correct
#[derive(Debug, thiserror::Error)]
pub enum MyError {
#[error("Failed to parse response: {0}")]
ParseError(#[from] serde_json::Error),
#[error("Provider returned error: {0}")]
ProviderError(String),
}
// Absolutely forbidden
fn do_thing() -> Result<(), String> // NO
DO NOT stub out error handling:
// Forbidden
let result = fallible_operation().unwrap(); // NO
let result = fallible_operation().expect("this should work"); // NO unless truly impossible
// Correct
let result = fallible_operation()?;
let result = fallible_operation().map_err(MyError::from)?;
Comments explain WHY, not WHAT.
If you need to explain what code is doing, the code itself is unclear. Rename variables, extract functions, or restructure.
// Bad - explains what
// Increment counter by one
counter += 1;
// Bad - explains what
// Check if user is admin
if user.role == Role::Admin {
// Good - explains why
// Rate limiting resets at midnight UTC, so we need the day boundary
let boundary = timestamp.truncate_to_day();
// Good - explains non-obvious business logic
// Providers may return tool calls split across multiple chunks,
// so we accumulate them by index until the stream ends
///) to all public items//!) to modulesTODO items are not allowed in submitted code.
If you need a TODO, the implementation is incomplete. Either:
// Forbidden
fn process() {
// TODO: handle edge case
}
// Forbidden
fn process() {
unimplemented!("will add later")
}
Run these commands and fix all issues before submitting:
cargo fmt
cargo clippy --all-targets --all-features
cargo test
If you cannot run these commands (e.g., environment limitations), explicitly ask the user to run them before the PR is submitted.
If your change involves:
Discuss with the user first. Do not implement major architectural changes without explicit approval. Open an issue for discussion if needed.
Before considering code complete:
.unwrap() or .expect() on fallible operations unless truly impossible)String error typesWasmCompatSend/WasmCompatSync instead of Send/Synccargo fmt passescargo clippy --all-targets --all-features passescargo test passesDO NOT MAKE COMMITS UNLESS THE USER HAS ASKED YOU TO DO SO. Users should be able to manually verify that what you have done has worked before proceeding with a commit, and may also want to write their own commit messages.
If the PR contains breaking changes, the PR message must list the public API items that have broken and the migration path for each.
PRs will be rejected if they contain:
String error types, .unwrap() everywhere, incomplete handlingSend/Sync instead of WasmCompat* variantsRemember: The quality bar exists because Rig is used in production by many projects. Every contribution must maintain that standard.
tools
Build LLM-powered applications with Rig, the Rust AI framework. Use when creating agents, RAG pipelines, tool-calling workflows, structured extraction, or streaming completions. Covers all providers with a unified API.
tools
<!-- This file is generated by scripts/sync_agent_instruction_files.sh. --> <!-- Do not edit this file directly; update AGENTS.md and re-run the sync script. --> --- name: rig-wasm-check description: > Audit Rig code for WebAssembly compatibility. Use when verifying that trait bounds use WasmCompatSend/WasmCompatSync, futures use WasmBoxedFuture, and error types have proper conditional compilation. allowed-tools: - Read - Glob - Grep --- # Rig WASM Compatibility Check Audit code fo
tools
<!-- This file is generated by scripts/sync_agent_instruction_files.sh. --> <!-- Do not edit this file directly; update AGENTS.md and re-run the sync script. --> --- name: rig-review description: > Review Rig changes against mandatory quality gates before opening a PR. Use before submitting code to verify error handling, WASM compatibility, coding style, and required checks pass. allowed-tools: - Read - Glob - Grep - Bash --- # Rig Pre-PR Review Perform a Rig-focused pre-PR revie
tools
<!-- This file is generated by scripts/sync_agent_instruction_files.sh. --> <!-- Do not edit this file directly; update AGENTS.md and re-run the sync script. --> --- name: rig-provider description: > Implement or audit a Rig model provider. Use when adding support for a new LLM API or reviewing an existing provider against the canonical checklist. Follows the OpenAI reference implementation pattern. argument-hint: "[provider-name]" allowed-tools: - Read - Glob - Grep - Edit - Wri