dotfiles/.claude/CLAUDE.md

5 KiB

Project Instructions

Core Rules

  • When asked to do ONE thing, do exactly that. Do not proactively migrate dependencies, refactor adjacent code, or expand scope. You may suggest further edits, but wait for confirmation before any scope expansion.
  • Prefer the simplest, most localized solution. Changes should target the most-relevant section of code — for example, catch errors in the scope that best handles them rather than injecting data up or down the stack. Take time to think about the best approach rather than quickly jumping to an implementation.

Tool Usage Preferences

For simple factual lookups (package versions, release dates), use targeted, purpose-built commands and local CLI tools first before attempting web searches — e.g. pip index versions <pkg> for Python, npm view <pkg> versions for Node. Prefer fast local approaches over web research.

Container Environment (Podman)

This environment runs inside a container with access to a Podman socket shared from the host. There is no docker or podman CLI available, but you can interact with containers via the Docker-compatible API.

Socket: /var/run/docker.sock (Podman with Docker-compatible API)

Environment Variable: DOCKER_HOST=unix:///var/run/docker.sock

Example API calls using curl:

# Get version info
curl -s --unix-socket /var/run/docker.sock http://localhost/version

# List images
curl -s --unix-socket /var/run/docker.sock http://localhost/images/json

# List containers (quote URLs with query params)
curl -s --unix-socket /var/run/docker.sock "http://localhost/containers/json?all=true"

Coding Style

Consistency is paramount. New code should look like it belongs naturally and blend with its surroundings. This improves readability for people already familiar with the project. Always match the existing style in the file or module you're working in.

Style preferences (when not conflicting with existing patterns):

  • Functional-inspired style with high modularity
  • Dependency injection over direct access to global resources
  • Avoid mutation of inputs
  • Pure functions where practical

Style changes should be separate from implementation. If you notice style inconsistencies or want to improve patterns, do so in dedicated refactor commits or branches rather than mixing with feature work.

Test Coverage

Maintain full test coverage of the code. Every new feature, bug fix, or refactor should include corresponding tests that exercise the changed code paths.

Why this matters:

  • 100% coverage is achievable and maintainable
  • Tests serve as living documentation of expected behavior
  • Full coverage catches regressions immediately, before they reach users
  • It enables confident refactoring—if tests pass, the change is safe
  • Gaps in coverage tend to grow; maintaining full coverage prevents technical debt accumulation

When adding or modifying code, verify that tests cover the new logic. If coverage drops, add tests before merging.

Coverage Exclusions and Test Quality

Pure I/O code is excluded from coverage requirements. Code whose sole purpose is performing I/O (reading files, making network calls, rendering output) cannot be effectively tested without manual interaction. However, this has a direct design implication: keep the I/O layer as thin and trivial as possible. All business logic, validation, transformation, and decision-making must live in testable modules that the I/O layer merely calls into. A fat I/O layer is a design smell, not an excuse for missing tests.

When business logic is tightly coupled to real I/O, and separating them would genuinely undermine testability (not just convenience), prefer integration tests against an emulated service dedicated for testing. The emulated service must have reliable compatibility with the real target. For example, S3-dependent code can use MinIO via testcontainers or similar tooling to run tests that genuinely need I/O access. This approach is preferable to either mocking away the I/O (which hides real failure modes) or leaving the logic untested.

Tests must exercise actual code paths, not reproduce them. In rare cases, code is so trivial that the only apparent way to test it is to restate it in the test. Such tests verify nothing — they pass by construction and remain passing even when the code changes, which demonstrates that they provide no actual validation. Do not write these. Instead, explicitly exclude the code from coverage. Note that this situation is rare and usually signals a design gap (logic that should be extracted or combined with something more substantive) rather than inherent untestability.

CLI Style

Prefer long option names over short ones in command-line applications and examples.

# Preferred
command --verbose --output file.txt

# Avoid
command -v -o file.txt

Long options are self-documenting and make scripts and examples easier to understand without consulting help text. Short options are acceptable for interactive use but should not appear in committed code, documentation, or examples.