About core-principles
core-principles is a software development guideline skill for projects, covering pure functions, explicit error handling, code organization, naming, and security practices. It favors clear failures for missing required configuration or data while allowing context-based deviations with stated trade-offs.
Key features
- 01Prefer pure functions
- 02Fail clearly on missing required configuration
- 03Organize code by responsibility
- 04Use meaningful variable names
- 05Follow credential and secret security practices
Use cases
- 01Set coding conventions across a team
- 02Check whether defaults conceal configuration or data errors
- 03Review module boundaries and error handling
- 04Review how secrets and credentials are stored and fetched
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ loxosceles-dev/ dev-skills --skill core-principlesAfter installing, type/core-principlesin Claude Code to confirm it loaded.
Details
From the project READMECore Principles
This is a strict guideline. Follow these rules. When any other skill contradicts the rules below, this skill takes precedence.
Essential guidelines that apply to ALL projects.
Important: These are guiding principles, not absolute rules. Project context matters. If you need to deviate, explain your reasoning and trade-offs.
Note on Examples: Code examples may use specific languages (JavaScript, Python, etc.) for clarity, but principles apply universally. Adapt patterns to your project's language and context.
1. Prefer Pure Functions
Helper functions should accept data as parameters rather than reading from globals or environment.
// ✅ Preferred: Pure, testable, moveable
function buildResourceName(environment: string, type: string, name: string): string {
return `${environment}-${type}-${name}`;
}
// ⚠️ Less ideal: Reads from global
const ENV = process.env.ENVIRONMENT;
function buildResourceName(type: string, name: string): string {
return `${ENV}-${type}-${name}`;
}
When impurity is necessary (AWS calls, DB access): Keep scope minimal, pass clients as parameters when feasible.
2. No Silent Defaults — Fail Fast, Fail Loud
Almost never use fallback values. Missing configuration, missing data fields, and unexpected states should cause immediate, loud failures with meaningful error messages.
// ❌ Silent fallback — masks misconfiguration
const region = process.env.AWS_REGION || 'us-east-1';
// ✅ Fail fast with actionable error
if (!process.env.AWS_REGION) {
throw new Error('AWS_REGION is required. Set in environment or SSM.');
}
const region = process.env.AWS_REGION;
# ❌ Silent default — hides corrupt data
source = status.get("scrape_source", "")
# ✅ Required field — let it fail if missing
source = status["scrape_source"]
The one exception — user-facing resilience: API endpoints and frontend code must not crash entirely because of a single bad record or missing non-essential field. In these cases:
- Catch the error at the loop/item level (not the field level)
- Log the full error with identifying context (pk, sk, etc.)
- Skip the bad record, serve the rest
- Never scatter
.get("field", "")defaults across every field — that silently hides data bugs
# ✅ Correct: required fields fail loud, but one bad record doesn't crash the endpoint
for item in items:
try:
result.append(format_item(item)) # format_item uses item["field"] — no defaults
except (KeyError, ValueError):
logging.exception("Skipping corrupt item: pk=%s sk=%s", item.get("pk"), item.get("sk"))
When in doubt whether something is "non-essential": stop and discuss. The default stance is fail loud.
3. Code Structure and Organization
Aim for consistent file structure and clear separation of concerns.
Recommended File Structure:
- Imports
- Environment variable validation (fail fast on cold start)
- Constants
- AWS clients and expensive initializations
- Types/Interfaces
- Pure helper functions
- Impure functions (AWS calls, I/O)
- Entry point (handler, main, etc.)
Separation of Concerns:
- Prefer separate files for schemas, prompts, and business logic
- Avoid mixing unrelated functionality
- Balance between separation and over-fragmentation
Function Declaration:
- Simple/inline: Arrow functions
const fn = () => {} - Complex logic: Function keyword
function fn() {}
4. Project Identifiers in Configuration
Avoid hardcoding project identifiers. Use configuration instead.
// ❌ Avoid
const paramPath = `/myapp/${environment}/api-key`;
// ✅ Preferred
const PROJECT_ID = process.env.PROJECT_ID;
const paramPath = `/${PROJECT_ID}/${environment}/api-key`;
5. Error Handling
The default is to fail fast and loud. Graceful degradation is the rare exception, not the norm.
- Throw/crash: Missing configuration, missing required data fields, invalid setup, critical dependencies. This is the default.
- Log + skip item: Only at user-facing boundaries (API responses, frontend rendering) where one bad item must not take down the whole response. Catch at the item level, log with context, skip the item.
- Never: Scatter silent defaults (
.get("field", "")) to avoid errors. That hides bugs. - Always: Include actionable context in errors — what record, what field, what was expected.
6. Variable Naming
Use meaningful variable names. Avoid single-letter names except in well-established conventions.
// ❌ Avoid
arr.map((a) => a.id);
catch (e) { console.error(e); }
// ✅ Preferred
users.map((user) => user.id);
catch (err) { console.error(err); }
Acceptable abbreviations: err, evt, req, res, ctx, idx, fn
Exceptions: Math formulas (x, y, i, j), trivial arrow functions ([1,2,3].map(n => n * 2))
7. Security Baseline
- Keep secrets, API keys, and credentials out of repositories
- Use AWS Secrets Manager or SSM Parameter Store (SecureString)
- Fetch secrets at runtime, not build time
- Prefer IAM roles over hardcoded credentials
- Separate resources and secrets per environment
Progressive Improvement
If the developer corrects a behavior that this skill should have prevented, suggest a specific amendment to this skill to prevent the same correction in the future.