Agent skill

Rust

by MadAppGang in MadAppGang/claude-code

A skill your agent uses when building Axum applications, implementing type-safe handlers, working with SQLx, setting up error handling with thiserror, or writing Rust backend services.

MITAuto-check: notesDevelopment

Install Rust

skills CLI
$ npx skills add MadAppGang/claude-code --skill rust -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install MadAppGang/claude-code rust --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/MadAppGang/claude-code.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/dev/skills/backend/rust .claude/skills/rust && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
rust
GitHub stars
284
Token cost
~3.1k tokens
SKILL.md length
35 words
Files
1
Skills in repo
69
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when building Axum applications, implementing type-safe handlers, working with SQLx, setting up error handling with thiserror, or writing Rust backend services.

  • Building Axum applications
  • SKILL.md covers Overview, Project Structure, Axum Application and Error Handling, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Implementing type-safe handlers

What it does

Rust is an agent skill from MadAppGang/claude-code. Use when building Axum applications, implementing type-safe handlers, working with SQLx, setting up error handling with thiserror, or writing Rust backend services.

Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering Type safety. It works with Rust. The repository describes itself as: claude code plugins marketplace. The licence is MIT.

When your agent uses it

  • Building Axum applications
  • Implementing type-safe handlers
  • Working with SQLx
  • Setting up error handling with thiserror

Example prompts

  • “/rust”

What it can do on your machine

Read from SKILL.md and the folder at commit 6097ad4. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are rust).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Rust loads about 3.1k tokens when it runs. Until then it costs about 42 tokens; SKILL.md has 35 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~42
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:43
    └── .env

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from MadAppGang/claude-code at commit 6097ad4, republished under its MIT licence (© MadAppGang). 35 words, ~3,094 tokens.

Download SKILL.mdSave it as .claude/skills/rust/SKILL.md (or your agent's skills folder).
name
rust
description
Use when building Axum applications, implementing type-safe handlers, working with SQLx, setting up error handling with thiserror, or writing Rust backend services.
version
1.0.0
keywords
Rust, Axum, SQLx, tokio, async, type safety, backend, thiserror
plugin
dev
updated
2026-01-20

Rust Backend Patterns

Overview

Rust patterns for building backend services with Axum.

Project Structure

project/
├── src/
│   ├── main.rs               # Entry point
│   ├── lib.rs                # Library root
│   ├── config.rs             # Configuration
│   ├── error.rs              # Error types
│   ├── routes/               # Route handlers
│   │   ├── mod.rs
│   │   └── users.rs
│   ├── services/             # Business logic
│   ├── repositories/         # Data access
│   ├── models/               # Domain models
│   └── middleware/           # HTTP middleware
├── migrations/               # SQLx migrations
├── tests/                    # Integration tests
├── Cargo.toml
└── .env

Axum Application

Main Application
rust
// src/main.rs
use axum::{
    routing::{get, post},
    Router,
};
use sqlx::postgres::PgPoolOptions;
use std::sync::Arc;
use tower_http::cors::CorsLayer;

mod config;
mod error;
mod routes;
mod services;
mod repositories;

use config::Config;

#[derive(Clone)]
pub struct AppState {
    pub db: sqlx::PgPool,
    pub config: Arc<Config>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    dotenvy::dotenv().ok();
    tracing_subscriber::init();

    let config = Config::from_env()?;

    let pool = PgPoolOptions::new()
        .max_connections(config.database.max_connections)
        .connect(&config.database.url)
        .await?;

    sqlx::migrate!().run(&pool).await?;

    let state = AppState {
        db: pool,
        config: Arc::new(config),
    };

    let app = Router::new()
        .route("/health", get(|| async { "ok" }))
        .nest("/api/users", routes::users::router())
        .with_state(state)
        .layer(CorsLayer::permissive());

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
    tracing::info!("listening on {}", listener.local_addr()?);
    axum::serve(listener, app).await?;

    Ok(())
}
Configuration
rust
// src/config.rs
use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct Config {
    pub database: DatabaseConfig,
    pub jwt: JwtConfig,
}

#[derive(Debug, Deserialize)]
pub struct DatabaseConfig {
    pub url: String,
    #[serde(default = "default_max_connections")]
    pub max_connections: u32,
}

#[derive(Debug, Deserialize)]
pub struct JwtConfig {
    pub secret: String,
    #[serde(default = "default_expiry")]
    pub expiry_hours: u64,
}

fn default_max_connections() -> u32 { 10 }
fn default_expiry() -> u64 { 24 }

impl Config {
    pub fn from_env() -> Result<Self, config::ConfigError> {
        config::Config::builder()
            .add_source(config::Environment::default().separator("__"))
            .build()?
            .try_deserialize()
    }
}

Error Handling

rust
// src/error.rs
use axum::{
    http::StatusCode,
    response::{IntoResponse, Response},
    Json,
};
use serde_json::json;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum AppError {
    #[error("Not found: {0}")]
    NotFound(String),

    #[error("Validation error: {0}")]
    Validation(String),

    #[error("Unauthorized")]
    Unauthorized,

    #[error("Forbidden")]
    Forbidden,

    #[error("Database error")]
    Database(#[from] sqlx::Error),

    #[error("Internal error")]
    Internal(#[from] anyhow::Error),
}

impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        let (status, code, message) = match &self {
            AppError::NotFound(msg) => (StatusCode::NOT_FOUND, "NOT_FOUND", msg.clone()),
            AppError::Validation(msg) => (StatusCode::BAD_REQUEST, "VALIDATION_ERROR", msg.clone()),
            AppError::Unauthorized => (StatusCode::UNAUTHORIZED, "UNAUTHORIZED", "Unauthorized".into()),
            AppError::Forbidden => (StatusCode::FORBIDDEN, "FORBIDDEN", "Forbidden".into()),
            AppError::Database(e) => {
                tracing::error!("Database error: {:?}", e);
                (StatusCode::INTERNAL_SERVER_ERROR, "DATABASE_ERROR", "Database error".into())
            }
            AppError::Internal(e) => {
                tracing::error!("Internal error: {:?}", e);
                (StatusCode::INTERNAL_SERVER_ERROR, "INTERNAL_ERROR", "Internal error".into())
            }
        };

        (
            status,
            Json(json!({
                "error": {
                    "code": code,
                    "message": message
                }
            })),
        ).into_response()
    }
}

pub type Result<T> = std::result::Result<T, AppError>;

Models and DTOs

rust
// src/models/user.rs
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use uuid::Uuid;
use validator::Validate;

#[derive(Debug, FromRow, Serialize)]
pub struct User {
    pub id: Uuid,
    pub name: String,
    pub email: String,
    #[serde(skip_serializing)]
    pub password_hash: String,
    pub created_at: DateTime<Utc>,
    pub updated_at: Option<DateTime<Utc>>,
}

#[derive(Debug, Deserialize, Validate)]
pub struct CreateUser {
    #[validate(length(min = 2, max = 100))]
    pub name: String,
    #[validate(email)]
    pub email: String,
    #[validate(length(min = 8))]
    pub password: String,
}

#[derive(Debug, Deserialize, Validate)]
pub struct UpdateUser {
    #[validate(length(min = 2, max = 100))]
    pub name: Option<String>,
    #[validate(email)]
    pub email: Option<String>,
}

#[derive(Debug, Serialize)]
pub struct UserResponse {
    pub id: Uuid,
    pub name: String,
    pub email: String,
    pub created_at: DateTime<Utc>,
}

impl From<User> for UserResponse {
    fn from(user: User) -> Self {
        Self {
            id: user.id,
            name: user.name,
            email: user.email,
            created_at: user.created_at,
        }
    }
}

Repository Pattern

rust
// src/repositories/user.rs
use sqlx::PgPool;
use uuid::Uuid;
use crate::error::{AppError, Result};
use crate::models::user::{User, CreateUser, UpdateUser};

pub struct UserRepository<'a> {
    pool: &'a PgPool,
}

impl<'a> UserRepository<'a> {
    pub fn new(pool: &'a PgPool) -> Self {
        Self { pool }
    }

    pub async fn find_by_id(&self, id: Uuid) -> Result<Option<User>> {
        sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
            .fetch_optional(self.pool)
            .await
            .map_err(AppError::Database)
    }

    pub async fn find_by_email(&self, email: &str) -> Result<Option<User>> {
        sqlx::query_as!(User, "SELECT * FROM users WHERE email = $1", email)
            .fetch_optional(self.pool)
            .await
            .map_err(AppError::Database)
    }

    pub async fn find_all(&self, limit: i64, offset: i64) -> Result<Vec<User>> {
        sqlx::query_as!(
            User,
            "SELECT * FROM users ORDER BY created_at DESC LIMIT $1 OFFSET $2",
            limit,
            offset
        )
        .fetch_all(self.pool)
        .await
        .map_err(AppError::Database)
    }

    pub async fn create(&self, input: &CreateUser, password_hash: &str) -> Result<User> {
        sqlx::query_as!(
            User,
            r#"
            INSERT INTO users (name, email, password_hash)
            VALUES ($1, $2, $3)
            RETURNING *
            "#,
            input.name,
            input.email,
            password_hash
        )
        .fetch_one(self.pool)
        .await
        .map_err(AppError::Database)
    }

    pub async fn update(&self, id: Uuid, input: &UpdateUser) -> Result<Option<User>> {
        sqlx::query_as!(
            User,
            r#"
            UPDATE users
            SET name = COALESCE($2, name),
                email = COALESCE($3, email),
                updated_at = NOW()
            WHERE id = $1
            RETURNING *
            "#,
            id,
            input.name,
            input.email
        )
        .fetch_optional(self.pool)
        .await
        .map_err(AppError::Database)
    }

    pub async fn delete(&self, id: Uuid) -> Result<bool> {
        let result = sqlx::query!("DELETE FROM users WHERE id = $1", id)
            .execute(self.pool)
            .await
            .map_err(AppError::Database)?;

        Ok(result.rows_affected() > 0)
    }
}

Route Handlers

rust
// src/routes/users.rs
use axum::{
    extract::{Path, Query, State},
    routing::{get, post, delete},
    Json, Router,
};
use uuid::Uuid;
use validator::Validate;

use crate::{
    error::{AppError, Result},
    models::user::{CreateUser, UpdateUser, UserResponse},
    repositories::user::UserRepository,
    services::user::UserService,
    AppState,
};

#[derive(Debug, serde::Deserialize)]
pub struct ListQuery {
    #[serde(default = "default_page")]
    page: i64,
    #[serde(default = "default_limit")]
    limit: i64,
}

fn default_page() -> i64 { 1 }
fn default_limit() -> i64 { 20 }

pub fn router() -> Router<AppState> {
    Router::new()
        .route("/", get(list_users).post(create_user))
        .route("/:id", get(get_user).patch(update_user).delete(delete_user))
}

async fn list_users(
    State(state): State<AppState>,
    Query(query): Query<ListQuery>,
) -> Result<Json<Vec<UserResponse>>> {
    let repo = UserRepository::new(&state.db);
    let offset = (query.page - 1) * query.limit;
    let users = repo.find_all(query.limit, offset).await?;
    Ok(Json(users.into_iter().map(Into::into).collect()))
}

async fn get_user(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
) -> Result<Json<UserResponse>> {
    let repo = UserRepository::new(&state.db);
    let user = repo
        .find_by_id(id)
        .await?
        .ok_or_else(|| AppError::NotFound("User".into()))?;
    Ok(Json(user.into()))
}

async fn create_user(
    State(state): State<AppState>,
    Json(input): Json<CreateUser>,
) -> Result<Json<UserResponse>> {
    input.validate().map_err(|e| AppError::Validation(e.to_string()))?;

    let service = UserService::new(&state.db);
    let user = service.create(input).await?;
    Ok(Json(user.into()))
}

async fn update_user(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
    Json(input): Json<UpdateUser>,
) -> Result<Json<UserResponse>> {
    input.validate().map_err(|e| AppError::Validation(e.to_string()))?;

    let repo = UserRepository::new(&state.db);
    let user = repo
        .update(id, &input)
        .await?
        .ok_or_else(|| AppError::NotFound("User".into()))?;
    Ok(Json(user.into()))
}

async fn delete_user(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
) -> Result<()> {
    let repo = UserRepository::new(&state.db);
    if !repo.delete(id).await? {
        return Err(AppError::NotFound("User".into()));
    }
    Ok(())
}

Testing

rust
// tests/users.rs
use axum::{
    body::Body,
    http::{Request, StatusCode},
};
use tower::ServiceExt;
use serde_json::json;

#[tokio::test]
async fn test_list_users() {
    let app = create_test_app().await;

    let response = app
        .oneshot(
            Request::builder()
                .uri("/api/users")
                .body(Body::empty())
                .unwrap(),
        )
        .await
        .unwrap();

    assert_eq!(response.status(), StatusCode::OK);
}

#[tokio::test]
async fn test_create_user() {
    let app = create_test_app().await;

    let response = app
        .oneshot(
            Request::builder()
                .method("POST")
                .uri("/api/users")
                .header("content-type", "application/json")
                .body(Body::from(
                    serde_json::to_string(&json!({
                        "name": "John Doe",
                        "email": "john@example.com",
                        "password": "password123"
                    }))
                    .unwrap(),
                ))
                .unwrap(),
        )
        .await
        .unwrap();

    assert_eq!(response.status(), StatusCode::OK);
}

Rust Axum patterns for backend development

© MadAppGang, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in plugins/dev/skills/backend/rust of MadAppGang/claude-code.

Open the folder on GitHubat commit 6097ad4

Compare with similar skills

Rust next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Rust compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Rust this skillMadAppGang/claude-code284—~3.1kAutomated safety check: NotesMIT
RTK Rust Design Patternsrtk-ai/rtk83k—~1.9kAutomated safety check: PassApache-2.0
Rust Path Typesopeninterpreter/openinterpreter69k2 repos~605Automated safety check: PassApache-2.0
Rust Ffiariebovenberg/whenever2.4k—~2.5kAutomated safety check: PassMIT
Strict Programming Practicescode-yeongyu/oh-my-openagent70k—~9.5kAutomated safety check: PassCustom licence
API Changesoftware-mansion/smelter732—~450Automated safety check: NotesCustom licence

Similar skills

  • Describes seven Rust design patterns for the RTK CLI filter modules, with when to use each, RTK examples, and notes on when a pattern is overkill.

    83k GitHub stars~1.9k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Rust Path Types

    openinterpreter/openinterpreter

    Rules for choosing Rust types for filesystem paths in new Codex code, covering protocol types, internal use and model tool arguments.

    69k GitHub starsUsed in 2 repos~605 tokens
    DevelopmentAuto-check passed
  • Rust Ffi

    ariebovenberg/whenever

    Instructions for using whenever's internal Rust FFI abstractions

    2.4k GitHub stars~2.5k tokensUpdated 2 days ago
    DevelopmentAuto-check passed
  • Strict Programming Practices

    code-yeongyu/oh-my-openagent

    Applies strict, type-first coding rules for Python, Rust, TypeScript and Go, loading the matching language reference before the agent writes or edits any code.

    70k GitHub stars~9.5k tokensUpdated today
    DevelopmentAuto-check passed
  • API Change

    software-mansion/smelter

    Run the full API change workflow after modifying types in smelter-api.

    732 GitHub stars~450 tokensUpdated yesterday
    DevelopmentAuto-check: notes
  • Golang Samber Mo

    samber/cc-skills-golang

    Monadic types for Golang using samber/mo — Option, Result, Either, Future, IO, Task, and State types for type-safe nullable values, error handling, and functional composition with pipeline…

    3.4k GitHub stars~2.9k tokensUpdated 7 days ago
    DevelopmentAuto-check passed

More from MadAppGang/claude-code

All 69 skills in this repo
  • API Spec Analyzer

    MadAppGang/claude-code

    Analyzes API documentation from OpenAPI specs to provide TypeScript interfaces, request/response formats, and implementation guidance.

    284 GitHub starsUsed in 1 repo~2.7k tokens
    Auto-check passed
  • Content Brief

    MadAppGang/claude-code

    Content brief template and creation methodology for SEO-optimized content.

    284 GitHub starsUsed in 1 repo~959 tokens
    Auto-check passed
  • Context Detection

    MadAppGang/claude-code

    A skill your agent uses when detecting project technology stack from files/configs/directory structure, auto-loading framework-specific skills, or analyzing multi-stack fullstack projects (e.g…

    284 GitHub stars~5.4k tokensUpdated 6 mo ago
    Auto-check passed
  • Content Optimizer

    MadAppGang/claude-code

    On-page SEO optimization techniques including keyword density, meta tags, heading structure, and readability.

    284 GitHub starsUsed in 1 repo~694 tokens
    Auto-check passed
  • Keyword Cluster Builder

    MadAppGang/claude-code

    Techniques for expanding seed keywords and clustering by topic and intent.

    284 GitHub starsUsed in 1 repo~674 tokens
    Auto-check passed
  • Serp Analysis

    MadAppGang/claude-code

    SERP analysis techniques for intent classification, feature identification, and competitive intelligence.

    284 GitHub starsUsed in 1 repo~1k tokens
    Auto-check passed

Works with

Categories

Questions about Rust

What does Rust do?

A skill your agent uses when building Axum applications, implementing type-safe handlers, working with SQLx, setting up error handling with thiserror, or writing Rust backend services. Rust is an agent skill from MadAppGang/claude-code. Use when building Axum applications, implementing type-safe handlers, working with SQLx, setting up error handling with thiserror, or writing Rust backend services.

When should I use Rust?

Rust fits situations like: building Axum applications; implementing type-safe handlers; working with SQLx; setting up error handling with thiserror.

How do I install Rust in Claude Code?

Run `npx skills add MadAppGang/claude-code --skill rust -a claude-code`. Or copy the skill folder (plugins/dev/skills/backend/rust in MadAppGang/claude-code) into .claude/skills/rust in your project. Claude Code loads it when a task matches its description.

How do I install Rust in Codex?

Run `npx skills add MadAppGang/claude-code --skill rust -a codex`. Or copy the skill folder (plugins/dev/skills/backend/rust in MadAppGang/claude-code) into .agents/skills/rust in your project. Codex loads it when a task matches its description.

Can I use Rust in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add MadAppGang/claude-code --skill rust -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/rust, .gemini/skills/rust, .github/skills/rust and .opencode/skills/rust in your project.

What does Rust need to run?

SKILL.md names no scripts, command-line tools or credentials: Rust is instructions for the agent only.

Does Rust access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Rust safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Rust use?

Rust is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Rust use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Rust?

Skills that share tags, products or a category with Rust: RTK Rust Design Patterns (rtk-ai/rtk, 83k stars), Rust Path Types (openinterpreter/openinterpreter, 69k stars), Rust Ffi (ariebovenberg/whenever, 2.4k stars) and Strict Programming Practices (code-yeongyu/oh-my-openagent, 70k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Rust?

MadAppGang (a GitHub organization) maintains it in MadAppGang/claude-code, which has 284 GitHub stars. The repository holds 69 skills in this directory. The repository was last updated on March 15, 2026.

Source: MadAppGang/claude-code on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.