Pagda is a package manager built on top of agda.nix. This means it inherits the nice features of nix, such as:
- Reproducable builds
- Caching
- Parallel builds
- etc.
Pagda is also completely compatible with the built-in package management functionality of Agda, so you can add it to existing code bases without breaking the workflow of users that don't use Pagda.
To see the list of supported commands, run pagda --help.
At the moment, the only supported installation method is via Nix. With flakes enabled you can run:
nix profile add github:WhatisRT/pagda # install pagda onto your PATH
This builds pagda from source on first use. A prebuilt binary cache may be added later.
If you already have installed pagda and want to update, run:
nix profile upgrade --refresh pagda
To pull pagda into a flake / NixOS / home-manager configuration, add it as an input and use the overlay:
{
inputs.pagda.url = "github:WhatisRT/pagda";
# in your nixpkgs config:
# overlays = [ pagda.overlays.default ];
# then reference pkgs.pagda (e.g. in environment.systemPackages).
}To scaffold a fresh project:
pagda init myproject # in ./myproject
pagda init myproject --here # in the current directory
This refuses to run if the target directory already contains a flake.nix,
a .agda-lib, or a Test.agda, so it never clobbers existing work.
To add pagda to an existing Agda project, run this in its directory:
pagda init --existing
This writes flake.nix and reuses the project's existing .agda-lib.
It never overwrites existing files, so it is safe to run in a populated
repository.
The .agda-lib file governs the library name and its dependencies, and
those dependencies resolve by name against whatever agdaPackages
provides (pinned, along with the rest of nixpkgs and agda.nix, by your
flake.lock). For anything beyond that, add an optional pagda.nix
next to it. It is a function of { pkgs, pagda } returning an attribute
set with these optional fields (pagda is pagda's per-system lib, also
carrying this project's default and agda packages):
overlay— an overlay applied toagdaPackages, to pin a dependency to a particular version/source or to add one thatagdaPackagesdoes not provide.overrideAttrs— anoverrideAttrsfunction applied to the generated package (genbelow) for build tweaks.meta— packagemetaattributes (description, license, homepage, …) merged into the library package.nixpkgs—{ config, overlays }for the nixpkgs import itself, to set options likeconfig.allowUnfree = trueor to pin/patch non-Agda tooling. These configure howpkgsis built, so they must not referencepkgs(the agda dependency overlay above belongs inoverlay).devShells— an attribute set of dev shells, surfaced as the flake'sdevShells(sonix developandpagda shell [name]pick them up). Adefaultshell with agda and the project's dependencies is always provided.docsAssets—{ "dest/in/output" = source; }of extra static files to fold into the docs output (pagda doc/.#docs), e.g. a rendered diagram.sourcemay be a path or a nix derivation.
# pagda.nix
{ pkgs, pagda }:
{
# Pin standard-library to a tag; anything not mentioned keeps the
# version agdaPackages provides.
overlay = final: prev: {
standard-library = prev.standard-library.overrideAttrs (_: {
version = "2.3";
src = pkgs.fetchFromGitHub {
owner = "agda";
repo = "agda-stdlib";
rev = "v2.3";
hash = "sha256-…";
};
});
};
# Library metadata.
meta = {
description = "My Agda library";
homepage = "https://example.com/my-lib";
};
# Configure the nixpkgs import (must not reference pkgs).
nixpkgs.config.allowUnfree = true;
# Other build tweaks on the generated package.
overrideAttrs = gen: {
buildInputs = (gen.buildInputs or [ ]) ++ [ pkgs.cowsay ];
};
# Docs are offline by default; override e.g. to serve over HTTP with smaller footprint.
docs = pagda.docBackends.enhancedHtml { offline = false; };
# Fold extra static files into the docs output.
docsAssets."diagram.svg" = ./diagram.svg;
# Dev shells. `default` is used by `nix develop` / `pagda shell`.
devShells.default = pkgs.mkShell {
inputsFrom = [ pagda.default ]; # agda + the project's dependencies
packages = [ pkgs.cabal-install ]; # plus extra tools
};
}Pagda has a companion agda-check executable that can be used as the
agda program for editor integrations like Emacs agda2-mode:
(setq agda2-program-name "agda-check")pagda doc builds documentation for the project. It is exposed as the
docs flake package, so nix build .#docs works too.
By default it builds enhanced docs (via agda-web-docs-lib): hyperlinked Agda HTML plus a sidebar, full-text search, dark/light theme and hover type previews.
The backend is pluggable via pagda.nix's docs field:
docs = pagda.docBackends.enhancedHtml { offline = false; }; # optimized for serving over HTTP (e.g. CI)
docs = pagda.docBackends.html; # plain agda --htmlpagda gen-ci writes a small .github/workflows/ci.yml that calls pagda's
reusable workflow to type-check the
library (nix build .#default) on every push and pull request.
Pass --pages to also build the docs and deploy them to GitHub Pages on the
default branch (set the repository's Pages source to "GitHub Actions").
Pass --cache to cache the Nix store via the GitHub Actions cache, so
reruns don't rebuild pagda/Agda from source.
The workflow supports a couple of options:
| Input | Default | Purpose |
|---|---|---|
pages |
false |
Build the docs. |
deploy |
true |
Deploy docs to GitHub Pages. Set false to instead upload them as a plain docs artifact for your own workflow to compose into an existing site. |
cache |
false |
Cache the Nix store via the GitHub Actions cache. |
working-directory |
. |
Directory of the flake. |
gc-max-store-size |
1G |
Trim the Nix store to this size before caching. |
To fold the docs into an existing Pages site instead of deploying them
standalone, use deploy: false and consume the docs artifact yourself:
jobs:
pagda:
uses: WhatisRT/pagda/.github/workflows/agda-ci.yml@main
with: { pages: true, deploy: false }
publish:
needs: pagda
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with: { name: docs, path: agda-docs } # where the docs live in your site
# ... build the rest of your site and deploy it ...There are three ways to set options for Pagda: a global configuration file, a configuration file local to the project and command line options. The syntax for command line options is --<name> <value> and the syntax for configuration files is name=value;, each on a separate line.
| Name | Possible values | Default | Description |
|---|---|---|---|
| useUntracked | true, false, ask | ask | What to do with files that are untracked by git |
| useWarnUntracked | true, false | true | Print a warning if certain files are not tracked by git |
Build pagda and run its test suites with nix:
nix build # build the executable (no tests, matches the install)
nix flake check # build and run the test suites
nix develop # dev shell with ghc, cabal, git
End-to-end tests live in test/e2e: each case starts from an initial file
tree, runs a pagda command in a sandbox, and compares the exit code,
output and resulting file tree against a golden manifest. Calls to nix
are intercepted by a stub that records the arguments, so the tests are
fast, reproducible and need no network. See
test/e2e/README.md for how to add cases and
regenerate goldens (cabal test e2e --test-options=--accept).