Skip to content

Instantly share code, notes, and snippets.

@jamtur01
Created March 28, 2026 07:24
Show Gist options
  • Select an option

  • Save jamtur01/291a882076d2da0cb2fe045c563bb817 to your computer and use it in GitHub Desktop.

Select an option

Save jamtur01/291a882076d2da0cb2fe045c563bb817 to your computer and use it in GitHub Desktop.

Global Development Standards

Global instructions for all projects. Project-specific CLAUDE.md files override these defaults where they conflict; everything else here still applies.

  • Use skills proactively when they match the task — suggest relevant ones, don't block on them

Philosophy

  • No speculative features - Don't add features, flags, or configuration unless users actively need them
  • No premature abstraction - Don't create utilities until you've written the same code three times
  • Clarity over cleverness - Prefer explicit, readable code over dense one-liners
  • Justify new dependencies - Each dependency is attack surface and maintenance burden
  • No phantom features - Don't document or validate features that aren't implemented
  • Replace, don't deprecate - When a new implementation replaces an old one, remove the old one entirely. No backward-compatible shims, dual config formats, or migration paths. Proactively flag dead code — it adds maintenance burden and misleads both developers and LLMs.
  • Verify at every level - Set up automated guardrails (linters, type checkers, pre-commit hooks, tests) as the first step, not an afterthought. Prefer structure-aware tools (ast-grep, LSPs, compilers) over text pattern matching. Review your own output critically. Every layer catches what the others miss.
  • Bias toward action - Decide and move for anything easily reversed; state your assumption so the reasoning is visible. Ask before committing to interfaces, data models, architecture, or destructive/write operations on external services.
  • Finish the job (boil the lake) - Don't stop at the minimum that technically satisfies the request. Handle the edge cases you can see. Clean up what you touched. If something is broken adjacent to your change, flag it. When the complete implementation costs minutes more than the shortcut, do the complete thing. Distinguish "lakes" (boilable — full test coverage, all edge cases, complete error paths) from "oceans" (multi-quarter migrations — flag as out of scope). But don't invent new scope — there's a difference between thoroughness and gold-plating.
  • Search before building - Before designing any solution involving unfamiliar patterns, infrastructure, or anything where the runtime/framework might have a built-in: search first. Check tried-and-true patterns (Layer 1), current best practices (Layer 2), then apply first-principles reasoning (Layer 3 — most valuable). The cost of checking is near-zero. The cost of not checking is reinventing something worse.
  • Verify before asserting - IMPORTANT: Never state something as a "known issue," established fact, or best practice without evidence. If you're extrapolating, say so. If you're unsure, search or say "I don't know." Getting caught fabricating facts destroys trust. "Pre-existing" or "known issue" without receipts is a lazy claim — prove it or don't say it.
  • Agent-native by default - Design so agents can achieve any outcome users can. Tools are atomic primitives; features are outcomes described in prompts. Prefer file-based state for transparency and portability. When adding UI capability, ask: can an agent achieve this outcome too? When project-specific config is missing, ask the user and persist the answer so it's never asked again.

Code Quality

Hard limits

  1. ≤100 lines/function, cyclomatic complexity ≤8
  2. ≤5 positional params
  3. 100-char line length
  4. Absolute imports only — no relative (..) paths
  5. Google-style docstrings on non-trivial public APIs

Zero warnings policy

Fix every warning from every tool — linters, type checkers, compilers, tests. If a warning truly can't be fixed, add an inline ignore with a justification comment. Never leave warnings unaddressed; a clean output is the baseline, not the goal.

Comments

Code should be self-documenting. No commented-out code—delete it. If you need a comment to explain WHAT the code does, refactor the code instead.

Error handling

  • Fail fast with clear, actionable messages
  • Never swallow exceptions silently
  • Include context (what operation, what input, suggested fix)

Reviewing code

Evaluate in order: architecture → code quality → tests → performance. Before reviewing, sync to latest remote (jj git fetch or git fetch origin).

For each issue: describe concretely with file:line references, present options with tradeoffs when the fix isn't obvious, recommend one, and ask before proceeding.

Testing

Test behavior, not implementation. Tests should verify what code does, not how. If a refactor breaks your tests but not your code, the tests were wrong.

Test edges and errors, not just the happy path. Empty inputs, boundaries, malformed data, missing files, network failures — bugs live in edges. Every error path the code handles should have a test that triggers it.

Mock boundaries, not logic. Only mock things that are slow (network, filesystem), non-deterministic (time, randomness), or external services you don't control.

Verify tests catch failures. Break the code, confirm the test fails, then fix. Use mutation testing (cargo-mutants, mutmut) to verify systematically. Use property-based testing (proptest, hypothesis) for parsers, serialization, and algorithms.

Development

When adding dependencies, CI actions, or tool versions, always look up the current stable version — never assume from memory unless the user provides one.

CLI tools

tool replaces usage
rg (ripgrep) grep rg "pattern" - 10x faster regex search
fd find fd "*.py" - fast file finder
ast-grep - ast-grep --pattern '$FUNC($$$)' --lang py - AST-based code search
shellcheck - shellcheck script.sh - shell script linter
shfmt - shfmt -i 2 -w script.sh - shell formatter
jj git jj - Git-compatible VCS. Colocate with jj git init --colocate
trash rm trash file - moves to macOS Trash (recoverable). Never use rm -rf

Prefer ast-grep over ripgrep when searching for code structure (function calls, class definitions, imports, pattern matching across arguments). Use ripgrep for literal strings and log messages.

Python

Runtime: 3.13 with uv venv

purpose tool
deps & venv uv
lint & format ruff check · ruff format
static types ty check
tests pytest -q

Always use uv, ruff, and ty over pip/poetry, black/pylint/flake8, and mypy/pyright — they're faster and stricter. Configure ty strictness via [tool.ty.rules] in pyproject.toml. Use uv_build for pure Python, hatchling for extensions.

Tests in tests/ directory mirroring package structure. Supply chain: pip-audit before deploying, pin exact versions (== not >=), verify hashes with uv pip install --require-hashes.

Node/TypeScript

Runtime: Node 22 LTS, ESM only ("type": "module")

purpose tool
lint oxlint
format oxfmt
test vitest
types tsc --noEmit

Always use oxlint and oxfmt over eslint/prettier — they're faster and stricter. Enable typescript, import, unicorn plugins.

Enable strict tsconfig (strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes, verbatimModuleSyntax). Colocated *.test.ts files. Pin exact versions (no ^ or ~).

Rust

Runtime: Latest stable via rustup

purpose tool
build & deps cargo
lint cargo clippy --all-targets --all-features -- -D warnings
format cargo fmt
test cargo test
supply chain cargo deny check (advisories, licenses, bans)
safety check cargo careful test (stdlib debug assertions + UB checks)

Style:

  • Prefer for loops with mutable accumulators over iterator chains
  • Shadow variables through transformations (no raw_x/parsed_x prefixes)
  • No wildcard matches; avoid matches! macro—explicit destructuring catches field changes
  • Use let...else for early returns; keep happy path unindented

Type design:

  • Newtypes over primitives (UserId(u64) not u64)
  • Enums for state machines, not boolean flags
  • thiserror for libraries, anyhow for applications
  • tracing for logging (error!/warn!/info!/debug!), not println

Optimization:

  • Write efficient code by default — correct algorithm, appropriate data structures, no unnecessary allocations
  • Profile before micro-optimizing; measure after

Cargo.toml lints: Enable clippy::pedantic as warn. Deny: unwrap_used, panic, dbg_macro, todo, print_stdout, print_stderr, allow_attributes. Allow: module_name_repetitions, similar_names.

Nix

purpose tool
system config nix-darwin (macOS), NixOS (Linux)
user config home-manager
packages nixpkgs stable, nixpkgs-unstable for bleeding-edge
secrets sops-nix with age encryption
formatting alejandra
linting deadnix, statix
deploy deploy-rs for remote Linux hosts
  • Use alejandra for Nix formatting (not nixfmt or nixpkgs-fmt)
  • Use pkgs.unstable.* overlay to selectively pull packages from unstable
  • Rebuild macOS: darwin-rebuild switch --flake .#mbp
  • Rebuild Linux (remote): just deploy <host>

Bash

All scripts must start with set -euo pipefail. Lint: shellcheck script.sh && shfmt -d script.sh

Version Control

  • Prefer jj (Jujutsu) over git. When working in a git repo that doesn't have a .jj/ directory, run jj git init --colocate before starting work.
  • Use jj commands instead of git for all VCS operations in colocated repos.
  • Use the lprior-repo-claude-skills-jj skill for jj workflows and commands.

Workflow

Before committing:

  1. Re-read your changes for unnecessary complexity, redundant code, and unclear naming
  2. Run relevant tests — not the full suite
  3. Run linters and type checker — fix everything before committing

Commits (jj):

  • Imperative mood, ≤72 char subject line, one logical change per commit. When multiple changes are mixed (rename + rewrite + tests), split into separate commits before pushing
  • Use jj describe -m "msg" to set descriptions, jj commit -m "msg" to finalize and start new work
  • Amending and rebasing are normal in jj — use jj edit to modify ancestors, descendants auto-rebase
  • Use jj op restore as safety net if something goes wrong
  • Never commit secrets, API keys, or credentials — use .env files (gitignored) and environment variables

Commits (git, non-colocated repos):

  • Never amend/rebase commits already pushed to shared branches
  • Never push directly to main — use feature branches and PRs

Isolation:

  • In jj repos: use jj workspace add for parallel work, or anonymous branches with jj new main
  • In git repos: use worktrees (wt switch <branch>)
  • Parallel subagents MUST work in their own workspace/worktree, not the main repo

Pull requests: Describe what the code does now — not discarded approaches, prior iterations, or alternatives. Only describe what's in the diff.

Use plain, factual language. A bug fix is a bug fix, not a "critical stability improvement." Avoid: critical, crucial, essential, significant, comprehensive, robust, elegant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment