cosmian/kms/rust-clone-audit
Claude Code and agent skill by cosmian/kms
- community
Checking that the SKILL.md file is still in the repository.
Detect and eliminate abusive cloning in Rust: treat every `.clone()`, `.to_owned()`, `.to_vec()`, `Cow::into_owned()`, and equivalent owned-duplication call as a potential ownership-design defect, not a free fix for a borrow-checker error. Use when writing, reviewing, or refactoring Rust code, especially when a `.clone()` is added to make code compile.
Install
npx vskill@latest install cosmian/kms/rust-clone-auditSKILL.md
Rust Clone Audit
Companion to `rust-signature-design` (parameter identity/count) and `rust-refactor` (duplicated code blocks): this skill targets a different axis — the owned-vs-borrowed decision for a single value at the call site where a clone-equivalent call appears. It does not scan for duplicated logic or judge parameter lists.
Goal: identify and aggressively eliminate unnecessary cloning. Must not introduce .clone() merely to satisfy the borrow checker without first exhausting borrowing, lifetime, and ownership-transfer alternatives — the same rule the lint-suppression decision tree in `rust.instructions.md` already applies to clippy::redundant_clone and clippy::clone_on_copy.
Step 1 — Classify every clone-equivalent call
| Kind | Call shape | Legitimate when | KMS example | |||
|---|---|---|---|---|---|---|
| Handle clone | Arc::clone(&x), Rc::clone(&x), x.clone() on Arc/Rc | Always — O(1) ref-count bump, not a data copy | Arc::clone(&recorder.calls) (database_objects.rs:1131), Arc::clone(&barrier) (audit/pgsql.rs:2070) | |||
| Thread/task move clone | x.clone() right before tokio::spawn/`thread::spawn(move \ | \ | ...)` | The spawned task outlives the current scope and needs its own owned copy | — | |
| Copy-type clone | .clone() on a Copy type (u32, bool, small enum) | Never needed — use the value directly or .copied()/.cloned() on an Option/Iterator | — | |||
| Borrow-checker-dodge clone | .clone() added only to make an error disappear, with no owned-value requirement downstream | Never — restructure the borrow instead (see rust-unofficial/patterns, "Clone to satisfy the borrow checker") | — | |||
| Field-extraction clone | self.field.clone() returned as an owned value from &self | The caller genuinely needs ownership (stores it, moves it across an await/thread boundary); otherwise return &T/&str | — | |||
| API-forced clone | Function signature takes T but the body only reads it — every caller must .clone() to call it | Never by itself — change the parameter to &T (one signature change fixes every call site) | — | |||
| Cow-eligible clone | .to_string()/.to_owned() used because some code paths modify the value and others don't | Only on the paths that actually modify; otherwise return Cow<'_, str> or the borrow | — |
Step 2 — Discover
Step 3 — Pick the narrowest fix (checklist, in order)
- Can the parameter/field be borrowed instead? Change
T→&T(or&str/&[T]for
String/Vec<T>); update every caller — this is often the single-signature fix that removes N call-site clones at once.
- Is this `Arc::clone`/`Rc::clone`? Stop — it is already correct, leave it.
- Is the value moving into a spawned task/thread/`'static` closure? Clone is necessary;
leave it, optionally add a // moved into spawned task comment if the reason isn't obvious from context.
- Does only some code paths need an owned value? Return
Cow<'_, T>instead of
unconditionally cloning or unconditionally borrowing.
- Is the clone on a `Copy` type? Remove
.clone()entirely; use.copied()/.cloned()
for Option<&T>/Iterator<Item = &T> conversions.
- Is the clone structurally required (stored in a new owner, e.g. a struct field or a
HashMap key/value, with no shared-ownership type in use)? Keep it — this is legitimate duplication, not abuse. Do not force Arc/Rc onto a type with no concurrent/shared ownership need just to avoid a single clone.
Before / after (illustrative)
Do not
- Do not remove a clone that is structurally required (the value is stored in a new owner, or
moved into a spawned task/thread) just to reduce a clone count.
- Do not replace a single clone with
Arc/Rc/RefCellwrapping across a type with no
concurrent or shared-ownership requirement — that trades one allocation for a bigger runtime cost (atomic ops, interior-mutability panics) and a wider API change.
- Do not silence
clippy::redundant_clone/clippy::clone_on_copywith a bare#[allow]
instead of fixing the call site — forbidden on new code per rust.instructions.md.
- Do not change a
crate/kmipwire struct's field from owned to borrowed — KMIP structs are
spec-bound value types serialized independently of caller lifetimes.
- Do not flag
Arc::clone/Rc::cloneas defects — they are O(1) ref-count bumps, never a data
copy (see Step 1).
References
- rust-unofficial/patterns, "Clone to satisfy the borrow checker"
- Microsoft, "Avoiding Excessive clone()" — source of the Step 1 "legitimate when" column and the before/after example
- Rust Project Goals, "Ergonomic ref-counting"
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryChecking.github/skills/rust-clone-audit/SKILL.md
Popularity
- Repository stars
- 363
- Repository forks
- 41
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/cosmian/kms/rust-clone-audit)