Package Development

39.1 Create a package

Or minimal: pkg> generate MyPackage.

using PkgTemplates
t = Template(; user="yourname", authors=["Your Name"],
             plugins=[Git(), GitHubActions(), Codecov(), Documenter{GitHubActions}(), License(name="MIT")])
t("MyPackage")

39.2 Structure

MyPackage/
├── Project.toml          # name, uuid, version, deps, compat
├── src/
│   ├── MyPackage.jl      # module MyPackage ... end (includes other files)
│   └── utils.jl
├── test/
│   └── runtests.jl
├── docs/
│   ├── make.jl
│   └── src/index.md
├── ext/                  # package extensions (optional)
├── README.md
└── LICENSE
# src/MyPackage.jl
module MyPackage

export greet

include("utils.jl")

"""
    greet(name)

Return a greeting.
"""
greet(name::AbstractString) = "Hello, $(name)!"

end

39.3 Development workflow

Semantic versioning; set [compat] bounds for every dependency.

Use package extensions for optional integrations.

Use public/export to declare the API.

CI with GitHub Actions (julia-actions/setup-julia, julia-runtest), coverage with Codecov, docs with Documenter deployed to GitHub Pages.

CompatHelper keeps compat entries updated; TagBot creates releases.

pkg> dev ~/MyPackage          # track local source
using Revise, MyPackage       # Revise reloads edits automatically
pkg> test MyPackage
using Aqua; Aqua.test_all(MyPackage)   # ambiguities, unbound type params, stale deps, piracy
using JET; JET.test_package(MyPackage)

39.4 Registering

Install the JuliaRegistrator GitHub app and comment @JuliaRegistrator register on a commit; after a short waiting period (and automated checks), the package joins the General registry. Private registries: LocalRegistry.jl.