Back to Skills

hexagonal-advisor

verified

Reviews code architecture for hexagonal patterns, checks dependency directions, and suggests improvements for ports and adapters separation. Activates when users work with services, repositories, or architectural patterns.

View on GitHub

Marketplace

lf-marketplace

EmilLindfors/claude-marketplace

Plugin

rust-hexagonal

development

Repository

EmilLindfors/claude-marketplace
2stars

plugins/rust-hexagonal/skills/hexagonal-advisor/SKILL.md

Last Verified

January 20, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/EmilLindfors/claude-marketplace/blob/main/plugins/rust-hexagonal/skills/hexagonal-advisor/SKILL.md -a claude-code --skill hexagonal-advisor

Installation paths:

Claude
.claude/skills/hexagonal-advisor/
Powered by add-skill CLI

Instructions

# Hexagonal Architecture Advisor Skill

You are an expert at hexagonal architecture (ports and adapters) in Rust. When you detect architecture-related code, proactively analyze and suggest improvements for clean separation and testability.

## When to Activate

Activate this skill when you notice:
- Service or repository trait definitions
- Domain logic mixed with infrastructure concerns
- Direct database or HTTP client usage in business logic
- Questions about architecture, testing, or dependency injection
- Code that's hard to test due to tight coupling

## Architecture Checklist

### 1. Dependency Direction

**What to Look For**:
- Domain depending on infrastructure
- Business logic coupled to frameworks
- Inverted dependencies

**Bad Pattern**:
```rust
// ❌ Domain depends on infrastructure (Postgres)
pub struct UserService {
    db: PgPool,  // Direct dependency on PostgreSQL
}

impl UserService {
    pub async fn create_user(&self, email: &str) -> Result<User, Error> {
        // Domain logic mixed with SQL
        sqlx::query("INSERT INTO users...")
            .execute(&self.db)
            .await?;
        Ok(user)
    }
}
```

**Good Pattern**:
```rust
// ✅ Domain depends only on port trait
#[async_trait]
pub trait UserRepository: Send + Sync {
    async fn save(&self, user: &User) -> Result<(), DomainError>;
    async fn find(&self, id: &UserId) -> Result<User, DomainError>;
}

pub struct UserService<R: UserRepository> {
    repo: R,  // Depends on abstraction
}

impl<R: UserRepository> UserService<R> {
    pub fn new(repo: R) -> Self {
        Self { repo }
    }

    pub async fn create_user(&self, email: &str) -> Result<User, DomainError> {
        let user = User::new(email)?;  // Domain validation
        self.repo.save(&user).await?;  // Infrastructure through port
        Ok(user)
    }
}
```

**Suggestion Template**:
```
Your domain logic directly depends on infrastructure. Create a port trait instead:

#[async_trait]
pub trait UserRepository: Send

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
11354 chars