Help us improve
Share bugs, ideas, or general feedback.
From genie
Enforces code quality standards when writing or editing code. Use when implementing features, fixing bugs, or refactoring. Ensures error handling, no hardcoded values, proper patterns, and security considerations.
npx claudepluginhub elmmly/genie-team --plugin genieHow this skill is triggered — by the user, by Claude, or both
Slash command
/genie:code-qualityThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Apply these standards when writing or editing code.
Provides checklists for code reviews assessing correctness, security vulnerabilities, performance, and maintainability. Use for pull requests, audits, and feedback.
Provides a structured code review checklist covering correctness, security, performance, and maintainability. Activates when reviewing pull requests, code audits, or identifying vulnerabilities.
Provides language-agnostic guidelines for code quality, comments, error handling, and formatting when writing or reviewing code in any language. Project-specific conventions take priority.
Share bugs, ideas, or general feedback.
Apply these standards when writing or editing code.
| Language | Bad | Good |
|---|---|---|
| TypeScript | const timeout = 5000; | const timeout = config.timeout; |
| Go | url := "https://api.example.com" | url := cfg.APIURL |
| Rust | let port = 8080; | let port = config.port; |
| C# | var connStr = "Server=localhost"; | var connStr = configuration["ConnectionString"]; |
| Java | int timeout = 5000; | int timeout = appConfig.getTimeout(); |
| Swift | let apiUrl = "https://api.example.com" | let apiUrl = Configuration.apiURL |
| Kotlin | val timeout = 5000 | val timeout = BuildConfig.TIMEOUT |
| Elixir | @timeout 5000 | @timeout Application.compile_env(:app, :timeout) |
Errors must be logged with context and propagated meaningfully. Never swallow errors silently.
| Language | Pattern |
|---|---|
| TypeScript | try { ... } catch (error) { logger.error('context', { error }); throw new AppError('message', { cause: error }); } |
| Go | if err != nil { return fmt.Errorf("functionName: %w", err) } — NEVER bare return err |
| Rust | operation().context("what failed")? or operation().map_err(|e| AppError::new(e))? |
| C# | catch (Exception ex) { logger.LogError(ex, "context"); throw new AppException("message", ex); } |
| Java | catch (Exception e) { log.error("context", e); throw new AppException("message", e); } |
| Swift | do { try operation() } catch { logger.error("context: \(error)"); throw AppError.operationFailed(cause: error) } |
| Kotlin | runCatching { operation() }.onFailure { e -> logger.error("context", e); throw AppException("message", e) } |
| Elixir | case operation() do {:error, reason} -> Logger.error("context", reason: reason); {:error, {:wrapped, reason}} end |
any in TS, interface{} in Go, Object in Java)| Anti-Pattern | Fix |
|---|---|
Bare return err | return fmt.Errorf("context: %w", err) |
Manual loops for slices operations (Go 1.21+) | Use slices.Contains, slices.Sort, etc. |
interface{} (Go 1.18+) | Use any |
if a > b { return a } (Go 1.21+) | Use max(a, b) |
| Unbounded goroutines | Use errgroup.Group for bounded concurrency |
Missing context.Context | Always pass as first parameter |
| Anti-Pattern | Fix |
|---|---|
.unwrap() in library code | Use ? operator with proper error types |
.clone() to escape borrow checker | Restructure ownership or use references |
Manual error types without thiserror | Use thiserror for library, anyhow for apps |
| Blocking in async context | Use tokio::spawn_blocking |
| Anti-Pattern | Fix |
|---|---|
any type | Use proper types or unknown with type guards |
@ts-ignore / @ts-expect-error | Fix the type error properly |
Not running tsc --noEmit | Always verify types compile |
== null without strictNullChecks | Enable strict mode in tsconfig |
| Anti-Pattern | Fix |
|---|---|
new HttpClient() per request | Use IHttpClientFactory |
Startup.cs on .NET 6+ | Use minimal hosting with WebApplication.CreateBuilder |
Task.Result / Task.Wait() | Use await — blocking on async causes deadlocks |
| Nullable warnings ignored | Enable <Nullable>enable</Nullable> |
| Anti-Pattern | Fix |
|---|---|
| JPA entities in WebFlux pipelines | Use R2DBC for reactive data access |
javax.* on Jakarta EE 10+ | Use jakarta.* namespace |
Raw @Autowired field injection | Use constructor injection |
Catching Exception broadly | Catch specific exception types |
| Anti-Pattern | Fix |
|---|---|
ObservableObject / @Published on iOS 17+ | Use @Observable macro |
NavigationView | Use NavigationStack / NavigationSplitView |
foregroundColor() | Use foregroundStyle() |
DispatchQueue.main.async | Use @MainActor |
Force unwrap (!) outside tests | Use guard let or if let |
Modifying .pbxproj directly | Create files, add to Xcode manually |
| Anti-Pattern | Fix |
|---|---|
GlobalScope for coroutines | Use viewModelScope or lifecycleScope |
LiveData in Compose code | Use StateFlow + collectAsStateWithLifecycle() |
kapt for annotation processing | Migrate to KSP |
| Blocking calls on Main dispatcher | Use withContext(Dispatchers.IO) |
| Allocations inside composable functions | Use remember {} |
MaterialTheme.colors (Material2) | Use MaterialTheme.colorScheme (Material3) |
| Anti-Pattern | Fix |
|---|---|
try/catch for flow control | Use tagged tuples {:ok, _} / {:error, _} and with chains |
String.to_atom/1 with user input | Use String.to_existing_atom/1 — atoms are not garbage collected |
Blocking handle_call with long operations | Offload to Task.Supervisor, handle result in handle_info/2 |
Missing handle_info/2 catch-all | Add def handle_info(_msg, state), do: {:noreply, state} |
| Hardcoded config values | Use Application.compile_env(:app, :key) |
| Writing macros when functions suffice | Use regular functions — macros are hard to debug and AI-generated macros are frequently incorrect |
Add observability with structured logging at boundaries:
| Language | Example |
|---|---|
| TypeScript | logger.info('operation completed', { operation: 'createUser', userId, duration }) |
| Go | slog.Info("operation completed", "operation", "createUser", "userId", userId, "duration", duration) |
| Rust | tracing::info!(operation = "create_user", user_id = %id, duration = ?elapsed, "operation completed") |
| C# | logger.LogInformation("Operation {Op} completed for {UserId} in {Duration}ms", op, userId, duration) |
| Java | log.info("Operation {} completed for userId={} in {}ms", op, userId, duration) |
| Swift | Logger().info("Operation \(op) completed for userId=\(userId) in \(duration)ms") |
| Kotlin | Timber.i("Operation %s completed for userId=%s in %dms", op, userId, duration) |
| Elixir | Logger.info("operation completed", operation: :create_user, user_id: id, duration_ms: elapsed) |
Logging levels:
Before finishing, verify: