Cursor Rules for Rust: Ownership, Errors, and Tests

Practical Cursor rules for Rust covering crate boundaries, error type conventions, unsafe code review, and verification commands, with fenbs retaining the design decisions that generic Rust guidance cannot supply.

Updated 4 min read

Cursor rules for Rust steer the assistant toward the ownership patterns, error-handling conventions, and crate layout your project has settled on. A language with strong compiler guarantees still has plenty of room for style variation: how you model errors, where you draw crate boundaries, and when unsafe code is acceptable.

Generic Rust rules cover the language. The decisions specific to your project, such as which error library to use or how workspace crates are organized, belong in a record only your team can supply. fenbs keeps those decisions alongside the tasks that rely on them, so the assistant does not rediscover them by reading the codebase every session.

What Rust rules should specify

The Rust compiler catches many mistakes. Rules focus on the choices it does not enforce: error propagation style, crate granularity, feature flag usage, and the steps required before finishing a task. Without them, the assistant picks its own approach and your codebase gradually diverges.

  • Crate layout: which crates live in the workspace, their purpose, and where public types are defined.
  • Error type convention: whether to use a shared error enum, thiserror, anyhow, or a combination.
  • Unsafe code policy: whether it is allowed, where it may appear, and what review is required.
  • Feature flags: naming conventions and which features are stable versus experimental.
  • Verification commands: the exact cargo commands to run before a task is done.

Crate boundaries and public APIs

A Rust workspace can have many crates. An assistant without guidance will add code to whichever crate is open rather than thinking about where it belongs. A rule that names the workspace layout and each crate's responsibility helps it make better placement decisions from the start.

Public types and traits deserve special attention. A type that leaks from an internal crate into several dependents is hard to change later. The rule can state which crates expose public APIs and which are internal-only, so the assistant avoids introducing a public dependency that was meant to stay private.

.cursor/rules/rust.mdc
---
description: Rust project conventions
globs: "**/*.rs,Cargo.toml,Cargo.lock"
alwaysApply: false
---

## Crate layout
- Public types are defined in `crates/core` and re-exported from the workspace root.
- Internal helpers stay in `crates/internal`; never expose them from a public API.
- Add new functionality to an existing crate before creating a new one.

## Error handling
- Use `thiserror` for library errors; use `anyhow` only in binary targets.
- Do not use `unwrap` or `expect` in library code; propagate errors with `?`.
- Name error variants to describe the cause, not the site (e.g., `InvalidInput`, not `ParseFailed`).

## Unsafe code
- Unsafe blocks require a SAFETY comment explaining the invariant that makes it valid.
- Do not add unsafe code without a task note explaining the decision and who approved it.

## Verification
- Run `cargo test --workspace` before marking a task done.
- Run `cargo clippy --workspace -- -D warnings` and fix all warnings.
- Run `cargo fmt --check` and format if needed.

Visibility also matters for the public API boundary between crates. A function that returns a type from an internal crate forces every downstream crate to take a dependency on that internal. The rule can state that public API functions should only reference types defined in the public crate, and that any internal type crossing a boundary is a signal to move it or wrap it. That boundary is easy to violate accidentally and hard to fix later when callers have built on it.

Error handling conventions

Rust's Result and ? operator make error propagation explicit, but they leave the shape of the error type entirely up to you. Using thiserror in one crate and anyhow in another, or returning Box<dyn Error> from a function meant to be stable, creates inconsistency that is hard to catch in review.

Avoid unwrap and expect in library code is a companion rule worth stating explicitly. These panic on None or Err values and give callers no opportunity to handle the failure. The rule can permit them in tests, where a panic is acceptable, and in main entry points where an unchecked error is intentional. In library code, the rule should require ? propagation or an explicit error conversion instead.

A single rule line that says "use thiserror for library crates; use anyhow in binary targets" removes that decision from every future task. The assistant picks the right dependency without being reminded. If your project deviates from the convention in one place, a task note explains why and prevents the next session from undoing the exception.

Unsafe code review

Unsafe Rust is sometimes necessary, but it should be visible. Requiring a SAFETY comment for every unsafe block is a convention many Rust projects adopt, and it is easy to specify in a rule. The comment explains the invariant that makes the block correct, making review faster and future changes safer.

You can go further: require that any unsafe addition includes a task note recording who approved it and why. That connects the code to a decision in your project record, so a future refactor can confirm whether the original invariant still holds.

How fenbs helps

Keep architecture decisions where the assistant reads them

When your team decides on an error-handling library, approves a new crate boundary, or agrees that a specific unsafe pattern is acceptable, record it in fenbs as a Decision. The rule points the assistant to read those decisions before planning related work. Rules encode the stable style; decisions capture the choices that shaped them. fenbs does not run cargo or enforce types; it keeps the reasoning that made them the right choice for your project.

Create a free account

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

How to set up Rust rules with fenbs

  1. Create a free account and add your Rust project.
  2. Record the key architectural decisions already in place: which error library you use, how the workspace is organized, the unsafe policy. Each one is a Decision in fenbs with the reason.
  3. Place the .cursor/rules/rust.mdc file at the workspace root and adjust the crate names to match your layout.
  4. Connect Cursor via Integrations and ask it to read the project context before planning any work that touches crate boundaries or error types.
  5. When a task reveals a new convention, add it to the rule file and record the decision in fenbs before the session ends.

See cursor rules examples for more language-specific patterns. For managing several rule files across a large workspace, see cursor rules hierarchy and cursor rules globs. For how Cursor compares to other editors, see Cursor vs VS Code.

Questions people ask.

Should Cursor rules include Rust lifetime examples?

Only if your project has a specific lifetime pattern the assistant keeps getting wrong. General lifetime guidance is already in the model. Focus rules on project-specific conventions the assistant cannot infer from the code.

How should the rule handle feature flags?

Name the feature flags your project uses, explain what each enables, and specify whether new functionality should be feature-gated. An assistant that knows the flag names can add them consistently rather than inventing new ones.

What verification should a Rust rule require?

At a minimum: cargo test, cargo clippy with warnings as errors, and cargo fmt. If your project uses specific test categories or integration test commands, add those too.

Can the rule prevent the assistant from using unsafe code?

The rule can require a SAFETY comment and a task note for any unsafe block. It cannot prevent the assistant from writing unsafe code entirely, but it makes any addition visible and subject to review.

Where do project-specific design decisions go in fenbs?

Record them in Decisions and rules: what was decided, who decided it, and the reason. The rule tells the assistant to read those decisions before working on related code. Rules hold stable style conventions; decisions hold the choices that might change.

Start with one thing.

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

There is nothing to set up first. Write one line and you’ve started.