Nixomatic Skill
Overview
Nixomatic is a Nix flake generator service that gives you instant access to any software without altering the current system. You construct a URL like https://nixomatic.com/?p=poppler-utils and pass it to nix develop. The service generates a Nix flake with the requested packages — nothing is permanently installed, no configuration or flake authoring required.
Nixomatic is your universal package runner. Whenever you need a tool that is not on the current system, nixomatic provides it instantly and cleanly:
- One-shot tasks: You need to convert a PDF to text? Use
poppler-utils. Resize an image?imagemagick. Transcode video?ffmpeg. Parse JSON?jq. Compress files?p7zip. Run a spell checker?aspell. Any tool available in nixpkgs is at your disposal. - Development environments: Build, compile, test, lint, format, type-check, or set up a project with the right toolchain.
- Missing tool recovery: When any command fails with "command not found", use nixomatic to provide the missing tool and retry — no permanent installation needed.
- Version discovery: Ask
https://nixomatic.com/versions?p=<package>which versions of a package can be pinned, or what version a given nixpkgs revision ships. This is a plain HTTP request — no Nix, no Docker, nothing built — so it is also the cheapest way to answer a user's question about what versions exist.
Use this skill whenever you need software that is not installed. This applies to one-shot tasks, development workflows, file conversions, data processing, or anything else where you need a tool that is not on PATH.
Detecting Nix vs Docker
Before running any environment command, determine which runtime is available:
- Check if
nixis on PATH (which nix). If found, use Nix directly. - If
nixis not found, check ifdockeris on PATH (which docker). If found, use the Docker wrapper. - If neither is available, inform the user that one of Nix or Docker must be installed and provide links:
- Nix: https://nixos.org/download/
- Docker: https://docs.docker.com/get-docker/
Analyzing the Project
Important: Never read or access files that may contain secrets (.env, .env.*, credentials.json, *-credentials.*, *.pem, *.key, private key files, or token files). Only inspect filenames to determine which packages are needed — do not read file contents unless they are project manifests (e.g., package.json, Cargo.toml, go.mod).
Determine what packages the project needs by scanning files in this order:
-
Check for existing nixomatic URL in README.md: Look for a
## Development Environmentsection containing anixomatic.comURL. If found, reuse that URL as the baseline (it represents the last known-good package set). Add packages only if something is missing. -
Check for
flake.nix: If the project root contains aflake.nix, prefer the project's own flake over nixomatic. Run commands withnix develop --command -- <cmd>using the local flake. Do not generate a nixomatic URL in this case. -
Detect languages and runtimes from project files:
package.json->nodejsCargo.toml->rustc,cargogo.mod->gorequirements.txt,setup.py,pyproject.toml->python3Gemfile->rubybuild.gradle,build.gradle.kts,pom.xml->jdkmix.exs->elixir*.sln,*.csproj,*.fsproj->dotnet-sdkcomposer.json->phpPackage.swift->swiftdune-project,*.opam->ocamlstack.yaml,*.cabal->ghc,cabal-installpubspec.yaml->dartzig.zon,build.zig->zig
-
Detect build tools:
Makefile->gnumakeCMakeLists.txt->cmakemeson.build->mesonJustfile->justTaskfile.yml->go-taskRakefile(without Gemfile) ->ruby
-
Detect additional tools from config files:
.eslintrc*,eslint.config.*-> (already covered by nodejs)Dockerfile->docker.terraform*->terraformserverless.yml->nodejsMakefilecontainingprotoc->protobuf
Common Package Mappings
| Project file / indicator | Nix packages |
|-------------------------------|-----------------------|
| package.json | nodejs |
| Cargo.toml | rustc, cargo |
| go.mod | go |
| requirements.txt | python3 |
| pyproject.toml | python3 |
| Gemfile | ruby |
| pom.xml / build.gradle | jdk |
| mix.exs | elixir |
| composer.json | php |
| *.csproj / *.fsproj | dotnet-sdk |
| Package.swift | swift |
| stack.yaml / *.cabal | ghc, cabal-install|
| pubspec.yaml | dart |
| build.zig / zig.zon | zig |
| Makefile | gnumake |
| CMakeLists.txt | cmake |
| meson.build | meson |
| Justfile | just |
| Taskfile.yml | go-task |
| curl needed | curl |
| git needed | git |
| jq needed | jq |
| openssl needed | openssl |
| pkg-config needed | pkg-config |
| protobuf needed | protobuf |
Constructing the URL
Build the nixomatic URL from the detected packages:
https://nixomatic.com/?p=pkg1,pkg2,pkg3
Use the short p query parameter with comma-separated package names. For example, a Node.js project with a Makefile becomes:
https://nixomatic.com/?p=nodejs,gnumake
To pin a specific package version, use @version syntax. Only versions the index actually has can be pinned, so confirm the version exists first — see Listing available versions of a package:
https://nixomatic.com/?p=nodejs@20.11.1,python3
To pin to a specific nixpkgs revision, use :revision syntax:
https://nixomatic.com/?p=python3:3b93cf5
Version restriction
Versions are not arbitrary. @version is resolved against nixpkgs-multiverse, an index of every version of every package nixpkgs has ever shipped. Only versions that some nixpkgs revision actually packaged can be requested — you cannot ask for an upstream release that nixpkgs never carried, and you cannot ask for a version string that does not match the index exactly (nodejs@20.11 is not nodejs@20.11.1).
nixomatic pins the index to a specific revision and generates flakes against that same revision, so the set of acceptable versions is a property of nixomatic, not of nixpkgs-multiverse's default branch. Determine it by asking nixomatic, as described in the next section.
If the version does not exist in the index, nix develop fails at evaluation time — before anything is built — with an error that lists the versions that do exist:
error: multiverse: no revision provides nodejs 99.99.99.
Known versions: 0.10.21 0.12.7 4.3.1 ... 24.18.0 24.18.1
When this happens, pick a version from the Known versions list and retry. Do not guess a neighbouring version number; the index is sparse and skips many upstream releases.
Listing available versions of a package
Rather than discovering the available versions from a failed build, ask nixomatic's /versions endpoint. It answers from the same index revision the generated flake pins, so every version it lists is a version that flake will accept. It needs only curl — no Nix, no Docker, nothing built:
curl -s 'https://nixomatic.com/versions?p=nodejs'
{
"nodejs": ["0.10.21", "0.12.7", "…", "24.18.1"]
}
The answer is always an object keyed by the spec exactly as it was asked for, whether one package was requested or many, so it is read the same way every time. Each list is ordered oldest first, so the last entry is the newest version available.
Asking about several packages at once
Packages are listed the same way as in a flake URL — comma-separated, or by repeating p=. Each gets its own entry:
curl -s 'https://nixomatic.com/versions?p=nodejs,python3'
{
"nodejs": ["0.10.21", "0.12.7", "…", "24.18.1"],
"python3": ["3.3.2", "3.4.3", "…", "3.14.6"]
}
Ask for every package needed in one request rather than one request each.
Finding what a nixpkgs revision ships
<package>:<revision> answers with the version that revision has, instead of every version there is. Use it to find out what a :revision pin actually gives — for example one already recorded in a project README — or to compare revisions before choosing one:
curl -s 'https://nixomatic.com/versions?p=python3:3b93cf5&p=python3:afb4584'
{
"python3:3b93cf5": "3.13.11",
"python3:afb4584": "3.14.6"
}
Each spec keeps its own entry, so several revisions of the same package do not collide. A revision ships one version of a package, so its entry is that version itself rather than a list of one:
curl -s 'https://nixomatic.com/versions?p=nodejs:6a55e4c'
{
"nodejs:6a55e4c": "20.15.1"
}
null means that revision has no such package. A bare package and a revision can be mixed in one request; each entry keeps the shape its own spec would have given — a list for the package, a string for the revision.
Revisions must be commit hashes (7 to 40 hex characters); a branch or channel name is rejected. Unlike a package listing, this evaluates nixpkgs at that revision, so the first request for a revision takes seconds rather than milliseconds.
What the endpoint rejects
<package>@<version>returns a 400. A version is what this endpoint returns, not something to ask with — request the package and look through the answer instead.- Overrides (
pnpm[...],pnpm(...)) return a 400 as well; they do not change what versions exist.
Notes
- A package the index does not cover gets an empty list rather than an error (
nullwhen asked at a revision), so an empty result means either a misspelled package name or one that was never indexed. Names are nixpkgs attribute names, the same ones used inp=. - Use the newest listed version unless the project requires otherwise, and prefer omitting
@versionentirely when any version will do. - The
x-nixomatic-multiverse-revisionresponse header names the index revision that answered, which is the same one the generated flake pins. - Never query
github:fzakaria/nixpkgs-multiversedirectly to answer this. nixomatic pins the index to a specific revision; the upstream default branch is a different, moving revision, so a direct query can list versions nixomatic will reject, or omit versions it would accept.
Fallback if /versions is not available
If /versions returns a 404 (an older nixomatic deployment), read the index through the flake URL itself instead. A nixomatic URL carrying at least one @version exposes the index it pins as a flake input named multiverse:
nix \
--extra-experimental-features 'nix-command flakes' \
eval --impure --json \
--expr '(builtins.getFlake "https://nixomatic.com/?p=nodejs@0").inputs.multiverse.multiverse.x86_64-linux.versionsOf "nodejs"'
This prints the same versions as a bare JSON array, oldest first, without the spec key the endpoint wraps them in. Query the URL actually being used whenever there is one; otherwise ?p=<package>@0 works as a probe, since the @0 is never resolved and only makes nixomatic wire in the multiverse input. Replace x86_64-linux with the current system, and note that --impure is required because builtins.getFlake will not accept an unlocked URL in pure evaluation mode. This fallback cannot answer what a revision ships.
Command Templates
Nix (direct)
Run a command inside the environment:
nix \
--extra-experimental-features 'nix-command flakes' \
develop 'https://nixomatic.com/?p=<packages>' \
--accept-flake-config \
--command -- <cmd>
Enter an interactive shell:
nix \
--extra-experimental-features 'nix-command flakes' \
develop 'https://nixomatic.com/?p=<packages>' \
--accept-flake-config
Docker
Run a command inside the environment:
docker run -v nix-store:/nix -v "$PWD:/workspace" -w /workspace --rm nixos/nix nix \
--extra-experimental-features 'nix-command flakes' \
develop 'https://nixomatic.com/?p=<packages>' \
--accept-flake-config \
--command -- <cmd>
Enter an interactive shell:
docker run -v nix-store:/nix -v "$PWD:/workspace" -w /workspace --rm -it nixos/nix nix \
--extra-experimental-features 'nix-command flakes' \
develop 'https://nixomatic.com/?p=<packages>' \
--accept-flake-config
Note: The Docker commands include -v "$PWD:/workspace" -w /workspace to mount the current project directory into the container. This is essential for real project work so that build tools can access project files.
Agent Workflow
One-shot tasks (running any tool on demand)
When you need to run a tool that is not installed — for file conversion, data processing, or any other task:
- Identify the package: Determine which nixpkgs package provides the tool you need. If unsure, search at https://search.nixos.org/packages.
- Detect runtime: Check for
nixon PATH, thendocker. Select the appropriate command template. - Run the command: Use the nixomatic URL with the required package(s) and execute your command in one shot. For example, to convert a PDF to text:
nix \ --extra-experimental-features 'nix-command flakes' \ develop 'https://nixomatic.com/?p=poppler-utils' \ --accept-flake-config \ --command -- pdftotext input.pdf output.txt - Handle missing packages: If the command fails because a tool is not found, add the missing package to the URL and retry.
- Handle unavailable versions: If a pinned
@versiondoes not exist, the command fails withmultiverse: no revision provides ...and lists the known versions. Pick one from that list, or drop the pin — one-shot tasks rarely need a specific version.
There is no need to update README.md for one-shot tasks.
Project development environments
When the user asks to build, test, lint, format, or set up a project:
-
Check for
flake.nix: If the project has its ownflake.nix, use it directly withnix develop --command -- <cmd>. Skip the remaining steps. -
Check README.md for existing URL: Look for a
## Development Environmentsection containing anixomatic.com/?p=URL. If found, use that URL as the starting point. If it pins a nixpkgs revision and you need to know what that actually provides, askcurl -s 'https://nixomatic.com/versions?p=<package>:<revision>'. -
Analyze project files: Scan the project root for language files, build tool configs, and other indicators. Determine the required package set using the mappings above.
-
Construct the URL: Build
https://nixomatic.com/?p=pkg1,pkg2,...from the detected packages. If reusing a README URL, merge any new packages into it. -
Detect runtime: Check for
nixon PATH, thendocker. Select the appropriate command template. -
Execute the command: Run the user's requested operation (build, test, lint, etc.) inside the nixomatic environment using the appropriate command template.
-
Handle missing packages: If a command fails because a tool is not found (e.g.,
command not found: cmake), add the missing package to the URL and retry the command.Pin versions the project asks for: When the project names a specific version (
.nvmrc,.python-version,.tool-versions,go.mod'sgodirective,rust-toolchain.toml), check it before building —curl -s 'https://nixomatic.com/versions?p=nodejs'— and pin the exact match if it is listed. If it is not, pick the closest available version, use that, and tell the user which version was used instead of the one requested. A@versionthat is not in the index fails the whole command withmultiverse: no revision provides ..., so checking first is cheaper than retrying. -
Update README.md: After a successful command execution, ensure the project's README.md contains an up-to-date
## Development Environmentsection with the working nixomatic URL. See the README.md Maintenance section below.
README.md Maintenance
After successfully running commands in a nixomatic environment, ensure the project's README.md documents how to reproduce it. This is the primary artifact of this skill.
Finding or creating the section
- Search README.md for a
## Development Environmentheading that contains anixomatic.comURL. - If found, update the URL if the package set has changed.
- If not found, append the section to the end of README.md (before any final sections like "License" or "Contributing" if they exist).
Section template
Use this template for the Development Environment section. Replace <packages> with the actual comma-separated package list:
## Development Environment
This project uses [nixomatic](https://nixomatic.com) for reproducible development environments.
### Using Nix
```bash
nix \
--extra-experimental-features 'nix-command flakes' \
develop 'https://nixomatic.com/?p=<packages>' \
--accept-flake-config
```
### Using Docker
```bash
docker run -v nix-store:/nix -v "$PWD:/workspace" -w /workspace --rm -it nixos/nix nix \
--extra-experimental-features 'nix-command flakes' \
develop 'https://nixomatic.com/?p=<packages>' \
--accept-flake-config
```
Keeping the URL in sync
- When packages are added (e.g., a missing tool was discovered), update the URL in the README.md section.
- When packages are removed (e.g., a dependency was dropped), update the URL accordingly.
- Always use the same URL in both the Nix and Docker command blocks.
Security Considerations
- Nix sandbox: Nix builds run inside a sandbox by default — build-time derivations have no network access and no filesystem access outside the Nix store. The
nix developcommand only makes packages available onPATH; it does not execute arbitrary scripts at evaluation time. - Deterministic flakes: nixomatic.com serves deterministic Nix flakes generated from the requested package list. The flake only pulls packages from the official nixpkgs repository.
- Docker isolation: When using the Docker runtime, the container only has access to the mounted workspace directory and a persistent Nix store volume. No other host paths are exposed.
Error Handling
| Error | Cause | Fix |
|-------|-------|-----|
| command not found: <tool> | Package missing from URL | Add the package to the p= parameter and retry |
| error: unable to download | Network issue or invalid URL | Check internet connectivity and verify the URL is well-formed |
| error: flake has no attribute | Unknown package name | Verify the package name exists in nixpkgs (search at https://search.nixos.org/packages) |
| error: multiverse: no revision provides <pkg> <version> | The requested @version is not in the nixpkgs-multiverse index | Pick one of the versions listed in the error's Known versions line, or list them with curl 'https://nixomatic.com/versions?p=<package>'; drop @version if any version will do |
| docker: command not found | Docker not installed | Fall back to Nix, or ask user to install Docker |
| nix: command not found | Nix not installed | Fall back to Docker, or ask user to install Nix |
| error: experimental Nix feature 'flakes' is disabled | Old Nix without flakes flag | The --extra-experimental-features 'nix-command flakes' flag should handle this; if not, the user needs to update Nix |
| Permission denied on Docker socket | User not in docker group | The user must have permission to access the Docker daemon; ask them to verify their Docker setup |
Errors from the /versions endpoint come back as JSON with an error field:
| Response | Cause | Fix |
|----------|-------|-----|
| 400 ... pins a version ... | A @version was sent to /versions | Ask for the package alone and read the versions out of the answer |
| 400 ... carries overrides ... | Overrides were sent to /versions | Drop them; they do not change what versions exist |
| 400 ... is not a nixpkgs revision | A branch or channel name was used after : | Use a commit hash of 7 to 40 hex characters |
| 502 Could not evaluate <pkg> at revision <rev> | That revision does not exist, or its nixpkgs will not evaluate | Verify the revision; a short hash that is not a real commit fails here |
| 503 The version index is not loaded yet | The server has just started | Retry shortly |
| {"<spec>": []} or {"<spec>": null} (with a 200) | The package is not in the index at all, or the revision has no such package | Check the spelling of the nixpkgs attribute name |
微信扫一扫