This guide covers formatting and naming conventions for CliMA repositories. For Git workflow and feature-removal protocol, see onboarding.md §§5, 7.
The root .JuliaFormatter.toml is the authoritative source of truth for code formatting. Run the formatter locally before committing:
julia -e 'using JuliaFormatter; format(".")'or, on Julia 1.12+ (Pkg.Apps does not exist on 1.11 or earlier, including the 1.10 LTS; check with isdefined(Pkg, :Apps)), install JuliaFormatter as an app and use directly from the command-line:
julia> import Pkg; Pkg.Apps.add("JuliaFormatter")and add ~/.julia/bin/ to your PATH.
Then you can run the formatter directly:
jlfmt -i .Match the JuliaFormatter version used in CI to prevent unnecessary diff churn. Repos use the julia-actions/julia-format GitHub Action and pin a JuliaFormatter major version via the version: input:
- uses: julia-actions/julia-format@v4
with:
version: '1' # JuliaFormatter major version; check the repo's workflow fileNote: the JuliaFormatter major version is not uniform across CliMA repos. Some pin '1', others '2', and some leave the default. Always cross-check .github/workflows/JuliaFormatter.yml (or julia_formatter.yml) in the repo you're working in before formatting. Run the formatter with julia -e 'using JuliaFormatter; format(".")' from the repo root.
If you want formatter checks to run automatically on commit, you can follow the same general pattern used in ClimaAtmos.jl:
- add a
.pre-commit-config.yamlat repo root, - optionally use a dedicated formatter environment (for example
.dev/format/), - keep your CI formatter check and local hook behavior aligned.
Use prek to manage hooks:
# Install uv (https://docs.astral.sh/uv/getting-started/installation/)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install prek
uv tool install prek
# From your repo root: install git hooks once
prek installAfter that, hooks run automatically on each git commit (staged files).
For manual runs:
prek runchecks the files selected by normal hook matching.prek run --all-fileschecks the whole repository.
Use this when you want a full-repo sweep:
prek run --all-filespre-commit also works if you already use it; prek is a drop-in replacement.
Note
If a hook reformats staged files, the commit is aborted and files are left
modified on disk. Review, git add, and commit again.
Do not manually format code inconsistently with the formatter. If the formatter produces unwanted results, adjust .JuliaFormatter.toml rather than overriding manually.
Be cautious with git checkout -- . to undo formatting changes; this also undoes any uncommitted functional changes. Prefer git checkout -p or git add -i for selective staging.
Constants specific to a physical algorithm should be defined as local variables inside the function, not as global module constants:
function compute_gradient(x, y)
# Algorithmic constant local to this function
ε = 1e-8
# ... logic ...
endThis minimizes global namespace pollution and improves code clarity.
For large source files, use visual section headers to group related functionality:
# ============================================================================
# Quadrature Evaluators
# ============================================================================The test/ directory structure should mirror src/:
- Source:
src/parameterized_tendencies/microphysics/tendency.jl - Test:
test/parameterized_tendencies/microphysics/tendency.jl
- Modules, structs, and types use
TitleCase. - Functions and variables use
snake_case(lowercase, words separated by underscores). - Constants use
SCREAMING_SNAKE_CASE. - Functions that mutate one of their arguments (conventionally the first) end in
!, e.g.update!,compute_tendency!.
- Prefer full words over abbreviations.
compute_strain_rate_full!is better thancsrf!. A few extra characters at the definition site are a vanishingly small cost compared to the cost of decoding an unfamiliar abbreviation every time a reader encounters it. - Acceptable abbreviations are universally-understood physics/math symbols (
Φ,ρ,χ,θ) and well-established acronyms used widely in the relevant subfield (EDMF,RRTMGP,SGS,PDF,LES). When in doubt, spell it out. - Lazy field prefixes (ClimaCore-based repos): functions that return a lazy cell-center–valued field are prefixed with
ᶜ; those that return a lazy cell-face–valued field are prefixed withᶠ. Unprefixed functions are understood to be pointwise. For example,ᶜρis a lazy field at cell centers;ρ(no prefix) is a pointwise scalar.
- Abstract types: use the bare concept name, not an
Abstract-prefixed form. PreferCloudModel,SpongeModel,JacobianAlgorithmoverAbstractCloudModel,AbstractSpongeModel,AbstractJacobianAlgorithm. The concept name reads more naturally in dispatch signatures (f(x::CloudModel)) and in documentation. Some legacy code usesAbstractFoo; keep it consistent within an existing module, but new hierarchies should drop the prefix. - Common suffixes signal what kind of type a struct is. Use them to make intent obvious at the call site:
…Model: dispatch tag for a parameterization choice (e.g.SmagorinskyLilly,EDMFModel).…Method/…Algorithm: algorithmic choice (e.g.JacobianAlgorithm,TracerNonnegativityMethod).…Parametersor…Params: immutable bag of numerical parameters (e.g.ThermodynamicsParameters).…Cache: mutable workspace or precomputed state (e.g.AtmosCache).
- Avoid generic
…Typeor…Helpersuffixes: they don't tell the reader what kind of thing they are looking at.
- Follow the conventions in the Variable List.
- Avoid one-character names like
l(lowercase el),O(uppercase oh), orI(uppercase eye); they are visually ambiguous. - One-letter names from physics/math (
T,ρ,χ,Φ) are fine when they match standard notation in the surrounding code.
- Limit use of Unicode. Avoid combining accents (dot, hat, vec) that create visually ambiguous characters.
- Use only standard Greek letters (
α,β,Δ,χ,ρ, …) and common math symbols (∇,∂,∫,≤). - Exception: the modifier-letter prefixes
ᶜandᶠare idiomatic in ClimaCore-based repos for lazy center/face field functions (see "Function names" above). They are visually distinct and unambiguous.
The JuliaFormatter margin is the authoritative line-length limit. Most repos use margin = 92; check the repo's .JuliaFormatter.toml.
Group using/import statements in the following order, separated by blank lines:
- Standard library imports.
- Related third-party imports.
- Local/application-specific imports.
If this guide is discovered to be stale or missing a pattern, update it.