hermes

Swift style rules

Standing rules for Swift an assistant writes, covering value types, optionals without force unwraps, structured concurrency, access control and API Design Guidelines naming.

When you write or change Swift code in this project:

Tooling and versions

  • Use the Swift language version and concurrency checking level the project already sets (in Package.swift or the Xcode build settings). Do not raise or lower them as a side effect.
  • Follow the project's formatter and linter (swift-format or SwiftLint) if configured. Do not reformat code you are not changing.

Types and values

  • Prefer struct and enum for models and values. Use a class only for identity, shared mutable state or framework requirements, and mark it final unless it is designed for subclassing.
  • Prefer let over var. Keep mutation local and explicit with mutating methods.
  • Model closed sets of states with enums with associated values instead of several optionals or boolean flags.
  • Use Codable with explicit CodingKeys when the wire format differs from Swift naming. Decode dates and numbers with explicit strategies.

Optionals and errors

  • No force unwraps (postfix !), try! or forced casts (as!) in production code. Use guard let, if let, ?? with a meaningful default, or throw. The only exceptions are values that are guaranteed by construction (such as a URL literal), and they get a comment saying why.
  • Use guard for early exit and keep the happy path unindented.
  • Throw errors for recoverable failures with an error type that callers can match on. Do not return nil to signal an error the caller needs to understand.
  • Use precondition or fatalError only for programmer errors, never for bad input or network failures.

Concurrency

  • Use async/await and structured concurrency (async let, task groups) for new asynchronous code. Wrap callback-based APIs with checked continuations rather than mixing styles.
  • Annotate UI-facing types and functions with @MainActor. Protect shared mutable state with an actor rather than locks or dispatch queues in new code.
  • Types crossing concurrency domains must be Sendable. Do not silence warnings with @unchecked Sendable or nonisolated(unsafe) unless you document the synchronisation that makes it safe.
  • Do not create unstructured Task { } without an owner. Store and cancel long-lived tasks, and check Task.isCancelled or call try Task.checkCancellation() in long loops.
  • In escaping closures that capture self in classes, use [weak self] when the closure can outlive the object.

Access control

  • Default to private, then fileprivate, then internal. Make something public or open only when it is part of a module's intended API.
  • Keep properties private(set) when callers need to read but not write.

Naming (Swift API Design Guidelines)

  • Aim for clarity at the point of use: remove(at: index), users.filter(isActive), not abbreviations.
  • Types and protocols in UpperCamelCase, everything else in lowerCamelCase. Booleans read as assertions (isEmpty, hasAccess).
  • Methods with side effects read as verbs (sort()), and non-mutating counterparts use the "ed" or "ing" form (sorted()).
  • Document public API with /// comments that describe what it does, its parameters, what it throws and its complexity if not obvious.

SwiftUI (when used)

  • Mark view-owned state @State private. Pass bindings down only when the child must write.
  • Keep views small and free of business logic. Put logic in an observable model (@Observable on the deployment targets that support it, otherwise ObservableObject) that can be tested without the view.
  • Do not start work in a view's init; use .task so it is tied to the view's lifetime and cancelled automatically.

Tests

  • Use the test framework the project already uses (Swift Testing or XCTest). Write tests for behaviour, one scenario each, with clear names.
  • Test async code with async tests, not sleeps or expectations with long timeouts.
  • Inject dependencies (network, clock, storage) through protocols or closures so tests do not hit real services.

details

kind
Rule: standing instructions for everything the assistant does
domain
Software engineering
category
Conventions
made for
Mobile engineer, Software engineer, Backend engineer
risk
read-only
version
v1.0.0 · incubating
reviewed
2026-10-03
works in
Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Antigravity, OpenCode, Windsurf, Zed, Continue, AGENTS.md, ChatGPT, claude.ai

Edit on GitHubReport a problem

use in

Hodios CLI
npx @hermes-hq/hodios install swift-style-rules --target claude-code
Agent Skills
npx skills add hermes-hq/hodios-dist --skill swift-style-rules -a claude-code

Rules are always-on instructions, so they are not in the plugins: add the skill, or paste the text into CLAUDE.md.

pairs well with

All of Conventions
RuleTesting

Test-writing rules

Standing rules for tests an assistant writes, covering behaviour over implementation, no sleeps, deterministic data, mocks only at boundaries and one reason to fail per test.

test-writing-rules
PersonaImplementation

Mobile engineer

Acts as a mobile engineer who designs for flaky networks, battery and memory limits, platform conventions and app-store releases. Use for iOS, Android or cross-platform work.

mobile-engineer
RuleConventions

HTTP API design rules

Rules for HTTP APIs covering resource naming, status codes, problem+json errors, cursor pagination, idempotency keys and versioning. Load when designing or changing HTTP endpoints.

api-design-rules
RuleConventions

C# style rules

Standing rules for C# an assistant writes, covering nullable reference types, async all the way with cancellation tokens, records and pattern matching, dependency injection and xUnit tests.

csharp-style-rules
RuleConventions

Go style rules

Standing rules for Go an assistant writes, covering wrapped errors, context propagation, small consumer-side interfaces, table-driven tests and no goroutines without an owner.

go-style-rules
RuleConventions

Java style rules

Standing rules for Java an assistant writes, covering modern language features, immutability, Optional and null handling, exceptions, restrained streams, records and JUnit 5 tests.

java-style-rules