Skip to content

Development Environment

This page describes the generated project development environment, not the Anvil contributor environment used to build Anvil itself. After anvil init, the project owns ordinary files in ordinary locations: a language-specific flake.nix, a unified Makefile, pre-commit hook configuration, lint/test/audit tooling, AGENTS.md, .anvil.lock, and seed/reference code when the repository is greenfield.

The environment exists to create backpressure for humans and coding agents. A prompt can say “write clean code”; Anvil turns that preference into local tools that reject vague comments, weak error handling, missing tests, unused code, insecure dependencies, and other drift before review.

SurfaceWhat it doesWhy it matters
flake.nixProvides the language-specific Nix development shell plus shared tools such as Git, Make, gitleaks, and pre-commit.Agents should not assemble artisanal host environments. The generated shell makes validation reproducible.
MakefileExposes the same target names for every supported language: lint, format, typecheck, security, test, coverage, deadcode, crap, audit, mutate, check, quality, and fix.Humans, agents, hooks, and CI can all use one command vocabulary even though the underlying tools differ.
.pre-commit-config.yamlWires pre-commit and pre-push safety nets around the Makefile targets.Hooks catch forgotten checks, but agents should run the Make targets proactively before hooks fire.
AGENTS.mdGives repo-local instructions: where to find examples, which commands to run, and how to treat validation failures.Agents get a bounded local operating model instead of relying on a generic system prompt.
.anvil.lockRecords Anvil version, language, scaffold context, toolchain versions, generated-file checksums, and write status.Re-running anvil init can classify generated-file changes safely and avoid blind overwrites.
Seed/reference codeDemonstrates file organization, typed errors, constants, enums, structured logging, and tests.Agents learn conventions from real code in the repository, not from abstract style guidance.

Generated project validation follows the same policy as Anvil itself: required tools are hard requirements. make check and make quality should fail clearly when a required tool is missing; they must never silently omit required targets. When in doubt, run through Nix:

Terminal window
nix develop path:. --command make check
CategoryTypeScript/JavaScriptGoPython
Built-in lintESLint with @eslint/js, typescript-eslint, import ordering, eslint-plugin-security, and strict TypeScript rulesgolangci-lint with errcheck, err113, gocognit, exhaustive, gosec, govet, unused, revive, staticcheck, funlen, and global/init checksRuff rule sets: E, W, F, I, N, UP, BLE, S, C90, SIM, PIE, PT, PTH, RUF, and D
Custom lintLocal ESLint plugin under tools/lint-rules/go vet -vettool=tools/go-analyzers/bin/anvil-lintLocal Flake8 plugin selected as ANV
FormatPrettiergofmt for make format; gofmt and goimports via make fixRuff format
Type checktsc --noEmitgo vet and staticcheckmypy in strict mode
TestVitestgo testpytest
CoverageVitest coverage with the v8 providergo test -coverprofile with 80% line coverage enforcementpytest-cov with 80% coverage enforcement
Dead codeKnipdeadcodeVulture
CRAP scoretools/crap-score.tstools/go-analyzers/bin/crap-reportpytest-crap
Dependency auditbun audit --audit-level high or the detected package manager’s audit commandgovulncheckpip-audit
MutationStrykerJSgo-mutestingmutmut
Secret scangitleaksgitleaksgitleaks
TierCommand surfaceSignalsAgent expectation
Fast local loopmake lint, make format, make typecheck, make securityLint rules, formatting, type checks, and secret scanning.Run the narrowest relevant target first while iterating.
Handoff gatemake checkFast local checks plus tests, coverage, dead-code detection, CRAP scoring, and dependency audit.Run make check before handoff.
Final quality boundarymake qualitymake check plus mutation testing.Run make quality at the final quality boundary when mutation evidence matters.
Automated safety netpre-commit and pre-push hooksThe same target families, triggered by Git operations.Do not wait for hooks as the first signal; use them as the backstop.

Anvil does not own deployment infrastructure. The generated make check target is CI-ready, but the deployment system remains a project decision.

Anvil deploys custom rules where ecosystem tools do not already cover the agent-specific failure mode. The names differ by language plugin, but the intent is consistent.

Rule intentTypeScript/JavaScriptGo analyzerPython code
Catch handlers that only log and continueno-log-and-continuenologcontinueANV001
Error paths that obscure or discard the caught errorno-error-obscuringnoerrorobscuringANV002
Vague placeholder comments without actionable contextno-placeholder-commentsnoplaceholderANV003
Pass-through wrappers with identical argumentsno-pass-through-wrappernopassthroughANV004
Log and throw/return on the same error pathno-log-and-thrownologthrowANV005
Unstructured logging or formatted logger messagesrequire-structured-loggingstructuredlogANV006
Source files without corresponding testsrequire-test-filesrequiretestsANV007
Empty catch/except handlers with no intentional handlingno-silent-error-swallownosilenterrorswallowANV009
Redundant async wrappersno-async-noiseNot applicableNot applicable

These rules exist because agents often produce plausible-looking code that hides failure modes: broad catches, default returns, “temporary” comments, wrappers that add no behavior, or logs that make errors look handled without actually handling them.

Rule intentTypeScript/JavaScriptGo analyzerPython code
File length limitsESLint max-linesfilelengthANV101
Function length limitsESLint max-lines-per-functionfunlen from golangci-lintANV102
Exported types live in types.*types-file-organizationSeed convention onlyANV103
Exported errors live in errors.*errors-file-organizationSeed convention onlyANV104
Exported constants live in constants.*constants-file-organizationSeed convention onlyANV105
Exported enums live in enums.*enums-file-organizationSeed convention onlyANV106
Single-export filenames match the exportfilename-match-exportNot applicableANV107
Exported function values use declarationsno-exported-function-expressionsnoexportedfunctionexpressionsANV108
Dense barrel filesno-barrel-densityNot applicableNot applicable
Over-fragmented directoriesno-over-fragmentationNot applicableNot applicable

Structural rules keep a repository navigable as an agent adds files. They make exported API surface predictable, stop sprawling files, and also stop the opposite failure mode: many tiny files that hide simple behavior behind unnecessary indirection.

Rule intentTypeScript/JavaScriptGo analyzerPython code
Empty testsno-empty-testsnoemptytestANV201
Tautological assertionsno-tautological-assertionsnotautologicalANV202
Disabled tests without a reasonno-disabled-tests-without-reasonnodisabledtestANV203
Error-handling source without error-path testsrequire-error-path-testsrequireerrortestANV204
Snapshot-only testsno-snapshot-only-testsNot applicableNot applicable

These rules force tests to be evidence, not decoration. An agent should not create an empty test, assert a constant, skip a test without explaining why, or add error handling without proving the error path.

The human-facing docs explain the model; generated AGENTS.md owns the repo-local instruction contract. Inside an Anvil-generated project, expect an agent to use this loop:

  1. Read the generated README and AGENTS.md. Identify the language, setup command, validation targets, and seed/reference code path before editing.
  2. Use the Nix shell when tools are missing. Prefer nix develop path:. --command make check so required tools come from flake.nix.
  3. Run the narrowest relevant target first. Use make lint, make typecheck, make test, or the specific failing target while iterating.
  4. Fix the first failing target. Do not stack speculative fixes across unrelated failures. Fix the root cause, then rerun that target.
  5. Run make check before handoff. This is the standard local contract for review, push, and CI-style validation.
  6. Run make quality at the final quality boundary. Mutation testing is intentionally slower and belongs at delivery boundaries.
  7. Report evidence. Summarize changed files, commands run, failures fixed, remaining risks, and any human decisions required.

When validation fails, the failure is not noise; it is Anvil’s backpressure doing its job. The agent should shrink the loop, read the tool output, fix the source of the failure, and prove the fix with fresh command output.