Skip to content
DocsAll docs
Console

Packages

Install the toolchain of a workspace from nixpkgs, pin versions, and update them.

Last updated

On this page

Overview

Packages are the toolchain of a workspace, installed from nixpkgs. The list belongs to the workspace and carries over to a clone or a restore. A base set (base_packages) is always installed. Set the list at creation, change it from code, or use kd pkg inside the workspace.

EntryExampleMeaning
NamejqThe package at the platform's nixpkgs revision.
Name and versionnodejs@22The newest cached release that matches the version, locked when added.

A name is the nixpkgs attribute: up to 64 letters, digits, _, ., +, or -. A version is latest, N, N.N, or N.N.N.

To do these tasks with an AI agent, see Agentic workflows.

Find a package

Search Nixhub for the package name and its published versions. The attribute name that Nixhub shows is the entry name, for example nodejs or python312. Nixhub lists every version, so use it to choose a value for @version. The platform resolves versions from the same index. NixOS Search also lists the attribute names, at the current nixpkgs revision only.

Locks

A versioned entry is locked to an exact release, shown in locks with its version, nixpkgs rev, and source. A lock changes only when you run update. Only releases in the public binary cache can be installed. A short version selects the newest cached release. An uncached exact version is refused, and the error lists the cached versions.

Installation

A change installs in about 30 seconds. A running workspace sees the new tools at its next shell prompt; a new workspace starts after the first installation. A failed installation keeps the previous tools. packages_status shows progress:

reasonMeaning
BuildingInstalling.
BuiltInstalled.
NotCachedA locked release has no prebuilt binary. Change the list to retry.
BuildFailedInstallation failed. Retried after 1 minute, backing off to 1 hour.
FailedInstallation exceeded the time limit. Change the list to retry.
UnresolvedA versioned entry has no lock. Set the packages again.

A declared package can install without putting a binary on the path. packages_status then names the entry in packages_missing, and the packages list shows it as missing. Check the attribute name, or change the entry.

The limit is 100 packages per workspace.

Installing language packages

The Nix store is read-only, so each language's own installer writes under the home instead. A workspace and a capsule set the variables below, and put each bin directory on PATH after the package list's bin and before the system PATH. An env entry of your own with the same name replaces ours.

ToolCommandLands in
Pythonpip install requests~/.local (no flag; a virtual environment keeps plain pip)
pipx, uvpipx install, uv tool install~/.local/bin
npm, yarnnpm i -g, yarn global add~/.local (NPM_CONFIG_PREFIX)
pnpmpnpm add -g~/.local/share/pnpm
corepackcorepack enable --install-directory ~/.local/bin~/.local/bin
Bun, Denobun add -g, deno install -g~/.bun/bin, ~/.deno/bin
Rustcargo install~/.cargo/bin
Gogo install~/go/bin
Rubygem install~/.local/share/gem (GEM_HOME)
PHPcomposer global require~/.composer/vendor/bin
.NETdotnet tool install -g~/.dotnet/tools
Perlperl Makefile.PL && make install~/perl5
Rinstall.packages() after mkdir -p ~/.local/share/R/libraryR_LIBS_USER
Lualuarocks install~/.luarocks
Elixirmix escript.install~/.mix/escripts
Haskellcabal install~/.cabal/bin

A capsule's home is lost when the capsule ends; a workspace keeps it. The Python package that provides pip must match python3: python314Packages.pip with a 3.14 python3.

Tasks

Add a package

Reason for the task

Install a tool in a workspace.

Job set-up

Procedure

  1. Add the package, with @version to pin it. The SDK call replaces the whole list, so keep the current entries.

    Python
    from kloudlite import Kodekl = Kloudlite()ws = kl.workspaces.get(workspace="backend")kl.workspaces.set_packages(workspace="backend", packages=[*ws["packages"], "nodejs@22"])
    TypeScript
    import { Kode } from "./index.ts";const kl = new Kloudlite();const ws: any = await kl.workspaces.get({ workspace: "backend" });await kl.workspaces.setPackages({ workspace: "backend", packages: [...ws.packages, "nodejs@22"] });
    Go
    kl := kloudlite.New(kloudlite.Options{})ws, err := kl.Workspaces.Get("backend")if err != nil {    log.Fatal(err)}var packages []stringfor _, p := range ws["packages"].([]any) {    packages = append(packages, p.(string))}err = kl.Workspaces.SetPackages(kloudlite.SetPackages{Workspace: "backend", Packages: append(packages, "nodejs@22")})if err != nil {    log.Fatal(err)}
    Ruby
    require_relative "kloudlite"kl = Kloudlite::Client.newws = kl.workspaces.get(workspace: "backend")kl.workspaces.set_packages(workspace: "backend", packages: ws["packages"] + ["nodejs@22"])
    Java
    var kl = new Kloudlite();// Replaces the list: name every current entry and the new one.kl.workspaces().setPackages(new Kloudlite.SetPackages().workspace("backend").packages("jq", "nodejs@22"));
    CLI
    # Replaces the list: repeat --package for every current entry.kode workspaces set-packages backend --package jq --package nodejs@22
  2. Use kd pkg inside the workspace instead. It keeps the current entries and prints the lock.

    CLI
    kd pkg add nodejs@22

Close-out

  1. List the packages as in task 002. Make sure that the entry and its lock are listed.

List the packages

Reason for the task

Check which tools and versions a workspace has.

Job set-up

Procedure

  1. List the packages and locks. Inside the workspace, kd pkg list does the same.

    Python
    ws = kl.workspaces.get(workspace="backend")print(ws["packages"], ws["locks"])
    TypeScript
    const ws: any = await kl.workspaces.get({ workspace: "backend" });console.log(ws.packages, ws.locks);
    Go
    ws, err := kl.Workspaces.Get("backend")if err != nil {    log.Fatal(err)}fmt.Println(ws["packages"], ws["locks"])
    Ruby
    ws = kl.workspaces.get(workspace: "backend")p ws["packages"], ws["locks"]
    Java
    System.out.println(kl.workspaces().get("backend"));
    CLI
    kode workspaces get backend

Close-out

  1. Make sure that every package that you expect is listed.

Remove a package

Reason for the task

Remove a tool that you no longer need.

Job set-up

Procedure

  1. Remove the package by name, without a version. Inside the workspace, kd pkg rm jq does the same.

    Python
    ws = kl.workspaces.get(workspace="backend")kl.workspaces.set_packages(workspace="backend", packages=[p for p in ws["packages"] if p.split("@")[0] != "jq"])
    TypeScript
    const ws: any = await kl.workspaces.get({ workspace: "backend" });await kl.workspaces.setPackages({ workspace: "backend", packages: ws.packages.filter((p: string) => p.split("@")[0] !== "jq") });
    Go
    ws, err := kl.Workspaces.Get("backend")if err != nil {    log.Fatal(err)}var packages []stringfor _, p := range ws["packages"].([]any) {    if strings.Split(p.(string), "@")[0] != "jq" {        packages = append(packages, p.(string))    }}if err := kl.Workspaces.SetPackages(kloudlite.SetPackages{Workspace: "backend", Packages: packages}); err != nil {    log.Fatal(err)}
    Ruby
    ws = kl.workspaces.get(workspace: "backend")kl.workspaces.set_packages(workspace: "backend", packages: ws["packages"].reject { |p| p.split("@").first == "jq" })
    Java
    // Replaces the list: name every entry that stays.kl.workspaces().setPackages(new Kloudlite.SetPackages().workspace("backend").packages("nodejs@22"));
    CLI
    # Replaces the list: repeat --package for every entry that stays.kode workspaces set-packages backend --package nodejs@22

Close-out

  1. List the packages as in task 002. Make sure that the entry is gone.

Update the locked versions

Reason for the task

Move each pinned package to the newest cached release that matches its version.

Job set-up

Procedure

  1. Run the update. Inside the workspace, kd pkg update does the same.

    Python
    kl.workspaces.update_packages(workspace="backend")
    TypeScript
    await kl.workspaces.updatePackages({ workspace: "backend" });
    Go
    if err := kl.Workspaces.UpdatePackages("backend"); err != nil {    log.Fatal(err)}
    Ruby
    kl.workspaces.update_packages(workspace: "backend")
    Java
    kl.workspaces().updatePackages("backend");
    CLI
    kode workspaces update-packages backend

Close-out

  1. List the packages as in task 002. Make sure that the locks show the expected versions.

Troubleshooting

SymptomPossible causeCorrective action
422 with "nodejs@x" is not a versionThe version format is not valid.Use latest, N, N.N, or N.N.N.
422 with is not a version anyone published; nearest: …The version does not exist.Use one of the versions in the message.
422 with has no cached build in cache.nixos.org; nearest cached: …The release has no prebuilt binary.Use one of the cached versions in the message.
packages_status is NotCachedA locked release has no prebuilt binary.Pin a cached version. See task 001.
packages_status is BuildFailed or FailedInstallation failed or timed out.Read the message, fix the list, and set it again.