knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
Packaging your code is the most reliable way to ensure reproducibility and
reusability. Instead of relying on loose scripts, packaging encourages you to
organize your functions, document them, and test them. This vignette
demonstrates how to create packages in R and Python within a Nix environment
managed by {rix}.
We will cover:
1. Creating an R package using {devtools} and {usethis}.
2. Creating a Python package using uv.
3. Defining the correct Nix environments to develop and use these packages.
{usethis} and {devtools}The R ecosystem provides excellent tools for package development. We will use
{usethis} to set up the package structure and {devtools} for documentation
and testing.
Start by generating a default.nix that includes the necessary development
tools:
library(rix) rix( r_ver = "frozen-edge", r_pkgs = c("devtools", "usethis", "roxygen2", "testthat"), ide = "rstudio", # or "code", "none" project_path = ".", overwrite = TRUE )
Build the environment with nix-shell.
From inside your Nix shell (or RStudio started from Nix), create a new package:
usethis::create_package("~/Documents/projects/cleanR")
This creates the standard R package directory structure (R/, DESCRIPTION,
NAMESPACE).
Create a function:
r
usethis::use_r("clean_names")
Add your function to R/clean_names.R and use roxygen2 comments (#')
for documentation.
Document:
r
devtools::document()
This generates the man/*.Rd files and updates NAMESPACE.
Test:
r
usethis::use_testthat()
usethis::use_test("clean_names")
Write unit tests in tests/testthat/test-clean_names.R, then run them:
r
devtools::test()
Check:
r
devtools::check()
This runs the standard R package check to ensure everything is correct.
Once your package is hosted on GitHub, you can use it in other project-specific
Nix environments by adding it to the git_pkgs argument in rix():
rix( r_ver = "frozen-edge", r_pkgs = c("dplyr"), git_pkgs = list( package_name = "cleanR", repo_url = "https://github.com/yourusername/cleanR", commit = "commit_hash_here" ), ide = "rstudio", project_path = ".", overwrite = TRUE )
uvFor Python, we will use uv to manage the project configuration (pyproject.toml) and build process, while Nix manages the actual Python interpreter and environment.
Generate a default.nix with Python, uv, and your package's dependencies:
library(rix) rix( date = "2025-10-07", py_conf = list( py_version = "3.12", py_pkgs = c("pytest", "pandas", "numpy") # Runtime and test deps ), system_pkgs = "uv", ide = "none", project_path = ".", overwrite = TRUE )
Inside the Nix shell, create a directory and initialize the project components:
mkdir pyclean
cd pyclean
uv init --bare
mkdir -p src/pyclean tests
touch src/pyclean/__init__.py
uv init --bare creates a pyproject.toml without creating a virtual
environment (since we are using Nix).
pyproject.tomlEdit pyproject.toml to define dependencies and test configuration. Critical
sections include:
[project] name = "pyclean" version = "0.1.0" dependencies = [ "pandas>=2.0.0", ] [project.optional-dependencies] test = [ "pytest", ] # Essential for running pytest from source layout [tool.pytest.ini_options] pythonpath = ["src"]
src/pyclean/.tests/.bash
pytestbash
uv build
This produces a wheel in dist/.When developing a Python package locally within a Nix shell, you want changes to
be reflected immediately. Update your default.nix shellHook to add your
source directory to PYTHONPATH.
rix (>= 0.17.4) makes this easy with the py_src_dir argument:
rix( date = "2025-10-07", py_conf = list( py_version = "3.12", py_pkgs = c("pytest", "pandas"), py_src_dir = "src" # Adds src/ to PYTHONPATH automatically ), system_pkgs = "uv", # ... )
This injects export PYTHONPATH=$PWD/src:$PYTHONPATH into the shell hook,
allowing you to import pyclean and run tests against the live source code.
To use your Python package in another Nix environment (e.g., for an analysis
project), use pkgs.python3Packages.buildPythonPackage in your default.nix.
You can point to a GitHub repository:
pyclean = pkgs.python313Packages.buildPythonPackage rec { pname = "pyclean"; version = "0.1.0"; src = pkgs.fetchgit { url = "https://github.com/yourusername/pyclean"; rev = "commit_hash"; sha256 = "sha256-hash"; }; pyproject = true; propagatedBuildInputs = [ pkgs.python313Packages.pandas ]; };
Then add pyclean to the buildInputs list alongside your other Python packages.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.