This guide walks you through creating and developing a T project — a data analysis project that uses T packages.
Package vs Project: A package is a reusable library of T functions. A project is a data analysis workspace that depends on packages.
Create a new project interactively:
$ t init project
Initializing new T package/project...
Name [my_project]: housing-analysis
Author [User]: Alice
License [EUPL-1.2]: EUPL-1.2
Nixpkgs date [2026-02-19]: 2026-02-19
✓ Project 'housing-analysis' created successfully!This creates the following structure:
pipeline.t).Projects use Nix for reproducibility. Enter the development shell:
$ nix developThis ensures all dependencies (T, packages, R, Nix) are available at
the exact versions specified in flake.lock.
Dependencies on T packages are declared in
tproject.toml:
[project]
name = "housing-analysis"
description = "Analyzing housing data with T"
[dependencies]
my_stats = { git = "https://github.com/user/my-stats", tag = "v0.1.0" }
data_utils = { git = "https://github.com/user/data-utils", tag = "v0.2.0" }
[t]
min_version = "0.5.0"After adding or changing dependencies, run:
$ t update
Syncing 2 dependency(ies) from tproject.toml → flake.nix...
Running nix flake update...This regenerates flake.nix so new dependencies appear as
proper flake inputs with locked versions. Then re-enter the shell:
$ nix developOnce inside nix develop, you can use the
import statement in your T scripts to load package
functions.
import my_stats
This makes all public functions from my_stats available
in scope.
import my_stats[weighted_mean, correlation]
Only weighted_mean and correlation are
imported.
import my_stats[wmean=weighted_mean, cor=correlation]
weighted_mean is available as wmean,
correlation as cor.
All functions in a package are public by default.
Package authors can mark internal helpers as private using
@private in T-Doc comments — those functions will not be
visible to importers.
Write your analysis in src/. For example,
src/pipeline.t:
import my_stats
import data_utils[read_clean]
p = pipeline {
data = read_csv("data/housing.csv")
clean = read_clean(data)
avg_price = mean(clean.$price)
price_by_area = clean |>
group_by($area) |>
summarize(avg=mean($price), sd=sd($price))
}
build_pipeline(p)
print(price_by_area)
Run your script:
$ t run src/pipeline.tOr use the REPL for interactive exploration:
$ t replYou can add tests in tests/ following the same
conventions as packages:
-- tests/test-pipeline.t
import my_stats
result = weighted_mean([1, 2, 3], [0.5, 0.3, 0.2])
assert(result == 1.7)
Run them with:
$ t testYour project is fully reproducible through Nix:
flake.nix declares exact dependency
sources (managed by t update)flake.lock pins exact versions of all
inputstproject.toml is the human-readable
source of truth for dependenciesAnyone can reproduce your environment:
$ git clone https://github.com/user/housing-analysis
$ cd housing-analysis
$ nix develop
$ t run src/pipeline.tThe same T version, same package versions, same R packages, and same system libraries are used every time.