Skip to content
Development
Skill

/software-engineer

Core software engineering philosophy and design principles based on Structure and Interpretation of Computer Programs (SICP). Use for all software development tasks including writing code, designing systems, refactoring, or making architectural decisions. MUST ALWAYS be loaded

From plugin
opinionated-claude-skills
919 skills3 agents
Install
$ npx -y skills add Pyroxin/opinionated-claude-skills --skill software-engineer --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/software-engineer

Context preview

The summary Claude sees to decide when to auto-load this skill.

Core software engineering philosophy and design principles based on Structure and Interpretation of Computer Programs (SICP). Use for all software development tasks including writing code, designing systems, refactoring, or making architectural decisions. MUST ALWAYS be loaded

SKILL.md

software-engineer.SKILL.md
name: software-engineer
description: Core software engineering philosophy and design principles based on Structure and Interpretation of Computer Programs (SICP). Use for all software development tasks including writing code, designing systems, refactoring, or making architectural decisions. MUST ALWAYS be loaded when working on any kind of software development or design task!

Software Engineer

<skill_scope skill="software-engineer">

Overview

This skill provides fundamental software engineering philosophy and design principles derived from _Structure and Interpretation of Computer Programs_ (SICP) by Abelson and Sussman. Apply these principles to all software development work to create well-designed, maintainable, and robust systems.

**Related skills:**

  • `functional-programmer` — Functional paradigm principles and patterns
  • `object-oriented-programmer` — OOP principles including SOLID
  • `logic-programmer` — Logic/relational programming patterns
  • `test-driven-development` — Testing philosophy and practices
  • `git-version-control` — Version control workflows

</skill_scope>

<core_philosophy>

Core Philosophy

<program_as_expression>

Program as Expression of Ideas

Computer programming is fundamentally about expressing ideas, not just getting computers to do things. Code is written for humans to read and understand; execution by computers is incidental. Prioritize clarity and expressiveness in all code. </program_as_expression>

<utilitarian_code>

Write Utilitarian Code

Code exists to solve problems, not to demonstrate cleverness. Write code that does what's right because it's right, not because it's an opportunity to show off language features or clever tricks.

**Utilitarian principles:**

  • Choose the simplest approach that solves the problem correctly
  • Don't write clever code for the writer's satisfaction—but do use advanced techniques when they're genuinely the best tool
  • A boring solution that works is better than an elegant solution that confuses
  • Cleverness for its own sake is a cost; cleverness that solves a real problem is engineering
  • If a technique requires explanation, that's fine—just make sure the explanation is "this is the right approach" not "I wanted to try this," and document it thoroughly

**The test:** Would a tired engineer at 2am understand this code? If not, simplify it. </utilitarian_code>

<manage_complexity>

Manage Complexity Through Abstraction

Complexity is the primary challenge in software engineering. Combat complexity through:

1. **Procedural abstraction** - Encapsulate operations as procedures/functions with clear contracts 2. **Data abstraction** - Separate the use of data from its representation 3. **Conventional interfaces** - Use standard protocols to combine components 4. **Linguistic abstraction** - Create domain-specific languages when appropriate

> "Piles of kludges make a big complicated mess." — Gerald Jay Sussman </manage_complexity>

<naming_and_scope>

Control Through Naming and Scope

Use naming and scope to control what parts of the program can see and affect other parts. Well-chosen names make programs self-documenting. Minimize scope to reduce coupling and increase modularity. </naming_and_scope>

<language_layers>

Build Language Layers

Complex systems benefit from layers of language, where each layer provides abstractions for the layer above. Design programs as a series of language levels, each suitable for expressing ideas at that level of abstraction.

> "You can gain control of complexity by inventing new languages sometimes." — Hal Abelson </language_layers>

<delayed_commitment>

Delayed Commitment

Defer decisions about implementation details to maintain flexibility in discovering the right interfaces. The goal is not delay for its own sake, but rather:

  • **Explore interface ergonomics**: Experiment with different API designs to find the most natural interaction patterns for consumers
  • **Separate interface from implementation**: Design and refine public interfaces before committing to internal representations
  • **Maintain flexibility**: Keep implementation options open until the best abstraction boundaries are clear
  • **Finalize deliberately**: Once interfaces provide ergonomic interactions, then commit to specific implementations

The commitment being delayed is to internal representations and algorithms, not to understanding what makes a good interface. Use scaffolding and test-writing to explore interface designs before implementation. </delayed_commitment> </core_philosophy>

<code_as_ontology>

Code as Ontology: Names, Stability, and Evolution

Public APIs are ontologies—systems of names carrying semantic commitments. This perspective, drawn from knowledge representation, shapes how we approach API design and system evolution.[^hickey-speculation]

<semantic_commitments>

Names Create Semantic Commitments

When you name something in a public API, you make a promise about what that name means. `User`, `createAccount`, `/api/users`—these establish concepts in your system's ontology. Changing what a name means changes the ontology itself.

**Design implications:**

  • Choose names carefully; they're long-term commitments
  • Names should reveal semantic concepts, not implementation details
  • Never reuse names for different concepts (even across versions)
  • When meaning must change, create a new name

</semantic_commitments>

<open_world_assumption>

The Open-World Assumption

Design systems as if unknown facts might exist. From knowledge representation: what you don't know might be true, not merely false.

**In practice:** Data structures should tolerate unknown fields. Systems should ignore what they don't understand. Don't fail on unexpected information.

// Open-world: tolerates unknown fields
function processUser(user) {
  const { id, name, email } = user;
  // Ignores any other fields—system can evolve independently
  return { id, processedName: name.toUppe
Read more
Ships withopinionated-claude-skills

This project descends from the personal prompts I'd been keeping for Claude Code prior to the release of skills and plugins. Over time it's also evolved into a sandbox where I figure out what makes Claude reliably good at a task, and find prompts that work.

Get the whole plugin

Other skills on opinionated-claude-skills.