Smithery Logo
MCPsSkillsDocsPricing
Login
NewFlame, an assistant that learns and improves. Available onTelegramSlack
    Stephanvs

    software-architect

    Stephanvs/software-architect
    Design
    6

    About

    SKILL.md

    Install

    • Telegram
      Telegram
    • Slack
      Slack
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    • Download skill
    ├─
    ├─
    └─
    Smithery Logo

    Give agents more agency

    Resources

    DocumentationPrivacy PolicySystem Status

    Company

    PricingAboutBlog

    Connect

    © 2026 Smithery. All rights reserved.

    About

    Design and build software with high cohesion, low coupling, composition-first structures, and functional-style defaults (TigerStyle-inspired).

    SKILL.md

    Software Architect

    “Make things as simple as possible, but no simpler.” — Albert Einstein

    This skill is for architecting and implementing software that is:

    • Highly cohesive (each module has a clear purpose).
    • Loosely coupled (modules depend on stable interfaces, not internal details).
    • Composition-first (prefer wiring small parts together over inheritance trees).
    • Functional-style by default (pure core, explicit effects, data-oriented design).
    • Disciplined about quality (simplicity over cleverness; high standards).

    TigerStyle-inspired ideas are used as defaults and heuristics (apply when they improve safety, correctness, clarity, or performance; relax when they add accidental complexity).

    North Star

    • Optimize for correctness through understanding, then performance.
    • Prefer simple, explicit control flow over implicit behavior.
    • Choose the smallest design that fully solves the problem.
    • Treat “clever” as a code smell; prefer boring, obvious solutions.
    • Pay down confusion immediately (rename, simplify, split, delete).

    Architecture Goals

    High Cohesion

    • Each module has exactly one job and one reason to change.
    • Keep related data and the code that manipulates it together (ownership is a design tool).
    • Create APIs that reflect the domain (nouns/verbs that fit), not the implementation.

    Low Coupling

    • Depend on interfaces/ports and data contracts, not concrete implementations.
    • Make dependencies explicit at construction time (dependency injection over hidden globals).
    • Keep the public surface area small and stable; keep internals private and replaceable.
    • Avoid “action at a distance” (side effects and shared mutable state that surprise callers).

    Composition Over Inheritance / Dynamic Polymorphism

    Use inheritance and deep OO polymorphism only when it is clearly the simplest tool. Default to:

    • Composition: build behavior by wiring small components together.
    • Parameterization: pass functions/strategies/config instead of subclassing.
    • Data + functions: plain data structures and pure transformations.
    • Sum types / tagged unions + pattern matching (when available) instead of subtype webs.
    • Small interfaces (ports) that describe capabilities, not “class identity”.

    Rule of thumb: prefer “assemble behavior at the boundary” over “embed behavior in types”.

    Functional-Style Defaults

    Functional Core, Imperative Shell

    • Put domain logic in pure functions (deterministic, testable, no I/O).
    • Keep I/O, time, randomness, and external services in the imperative shell.
    • Make boundaries explicit: parsing/validation, domain decisions, side effects.

    Pseudo-structure:

    imperative shell:
      load inputs (I/O)
      validate/parse -> domain types
      call pure domain functions
      persist/emit effects (I/O)
    

    Immutability and Data Flow

    • Prefer immutable data and persistent transformations.
    • Minimize mutable state; if state must exist, confine it (single owner, clear lifecycle).
    • Prefer returning new values over mutating shared ones.
    • Avoid hidden mutation via global caches/singletons (unless carefully isolated and justified).

    Errors as Values

    • Model failures explicitly (Result/Either/Option) instead of implicit exceptions where possible.
    • Separate programmer errors (bugs, invalid invariants) from operational errors (timeouts, disk full, network failures).
    • Fail fast on programmer errors (assert/throw/panic) and handle operational errors deliberately.

    TigerStyle-Inspired Defaults (Apply When Applicable)

    These are high-leverage defaults for quality and safety. Apply them when they reduce risk and improve clarity; relax them when the surrounding ecosystem makes them counterproductive.

    Prefer Explicitness

    • Avoid magic, reflection-heavy control flow, and spooky metaprogramming.
    • Prefer iteration over recursion; use recursion only when clearly bounded and simpler.
    • Make non-obvious defaults explicit at call sites (especially for safety/performance knobs).
    • Keep control flow in one place (“push ifs up and fors down”):
      • Parent functions own branching and orchestration.
      • Leaf helpers do straight-line work and stay pure.

    Put Limits on Everything

    • Ensure loops/queues/retries have clear upper bounds and timeouts.
    • Bound work per request/event to avoid tail-latency spikes.
    • Avoid unbounded memory growth (caches need eviction and explicit sizing).

    Assert and Enforce Invariants

    • Use assertions/contracts to encode invariants at boundaries (inputs, outputs, state transitions).
    • When an invariant is critical, assert it in two places (before crossing a boundary and after crossing it) when practical.
    • Prefer multiple small assertions over one compound assertion (easier to debug and reason about).

    Design First, Then Build

    • Spend thought upfront: define invariants, data model, interfaces, failure modes.
    • Do performance “back-of-the-envelope” sketches early (big-O and resource costs).
    • Avoid premature abstraction; but also avoid “we’ll fix it later” debt.

    Zero-Technical-Debt Attitude

    • Do not ship known footguns (missing error handling, unbounded loops, fragile concurrency, unclear ownership, undocumented invariants).
    • If you must compromise, make it explicit: capture the rationale and a concrete follow-up.

    How to Design (Before Writing Code)

    1. Clarify the problem

      • What are the inputs/outputs?
      • What must always be true (invariants)?
      • What are the failure modes and recovery expectations?
    2. Choose boundaries and dependencies

      • Identify the pure domain core.
      • Identify external systems (DB, network, filesystem, clock, random, UI).
      • Define ports/interfaces for external dependencies.
    3. Model the domain

      • Use types and naming to prevent invalid states.
      • Prefer explicit units/qualifiers in names (timeout_ms, limit_items_max).
    4. Plan for testability

      • Pure functions get unit tests.
      • Adapters get integration tests.
      • Edge cases include invalid/negative tests, not only happy paths.

    Implementation Guidelines

    • Keep functions small enough to fit on a screen; split by responsibility.
    • Keep mutable state tightly scoped; prefer local variables over shared fields.
    • Keep APIs narrow: fewer parameters, simpler return types, fewer states.
    • Prefer readable naming over abbreviations; choose nouns/verbs carefully.
    • Delete dead code and unnecessary indirection.
    • Structure by feature/domain, not by technical role. Avoid folders like commands/, components/, utils/ at the top level. Instead, group by domain: auth/, calendar/, settings/. Technical groupings (if needed) should be leaves within feature folders, not roots.

    Checklists

    Architecture Checklist

    • Clear module boundaries and ownership
    • High cohesion within modules (no “misc” grab bags)
    • Low coupling across modules (interfaces/ports, no internal leaks)
    • Composition-first design (no unnecessary inheritance or frameworks-as-architecture)
    • Pure core identified; effects isolated at boundaries
    • Explicit error model and failure handling strategy
    • Work/memory bounded where relevant
    • Performance sketch done for hot paths

    Implementation Checklist

    • Core logic is testable without I/O
    • Side effects are explicit and centralized
    • Invariants asserted at boundaries
    • Error cases handled (not silently ignored)
    • Naming is precise; no misleading abstractions
    • Complexity reduced (simplify after it works)
    • Docs/comments explain why for non-obvious decisions

    Review / Simplification Checklist

    • Can a new engineer explain the design in 5 minutes?
    • Are there fewer concepts than necessary? If yes, delete/merge.
    • Are there more concepts than necessary? If yes, simplify.
    • Does each module have one reason to change?
    • Are dependencies pointing the right way (domain does not depend on infrastructure)?
    • Are there hidden side effects or shared mutable state?
    • Is any abstraction “clever”? Replace with something obvious.

    Examples (Language-Agnostic)

    Composition via Dependency Injection (no inheritance)

    def process_order(deps, command):
      validated = validate(command)
      decision  = decide(validated)         # pure
      effects   = plan_effects(decision)    # pure
      deps.outbox.publish(effects.events)   # I/O
      deps.repo.save(effects.state)         # I/O
    

    deps is explicit (repo/outbox/clock/etc.), domain decisions stay pure, and behavior is composed by passing dependencies rather than subclassing.

    Functional Core / Imperative Shell Boundary

    shell:
      raw_input -> parse/validate -> domain types
      domain types -> pure transform -> new domain types
      new domain types -> serialize/persist/emit
    

    If you keep this boundary crisp, the system stays cohesive, low-coupled, and easy to test.

    Recommended Servers
    MantleKit Launch Planner
    MantleKit Launch Planner
    Laddro Career
    Laddro Career
    Hugeicons MCP Server
    Hugeicons MCP Server
    Repository
    stephanvs/dotfiles
    Files