This repo has two equal parts:
- the Nixantic Nix-driven renderer and module framework for agentic config generation
- built-in instructions with workflows, commands, instructions, skills, agents, and related source content
Together they render authored instruction fragments into Claude Code, OpenCode, and Pi config trees.
If you consume this repo as a dependency, the stable surface is the module API. The internal renderer layout is not the public contract.
The framework pieces exposed through the flake are:
- the renderer in
framework/ - the main
lib.evalModulessurface inmodules/core.nix - a small Home Manager adapter in
modules/home-manager.nix - the flake-parts exposure layer in
modules/flake-parts.nix
The built-in instructions source lives in instructions/.
nixanticModules.default/nixanticModules.core: standalone core modulehomeManagerModules.default/homeModules.default: Home Manager adapterflakeModules.default: flake-parts exposure modulepackages.<system>.builtin: rendered built-in instruction profilepackages.<system>.claude: wrapper that setsCLAUDE_CONFIG_DIRpackages.<system>.opencode: wrapper that setsOPENCODE_CONFIG_DIR
The canonical rendered outputs, including the built-in instructions, live under config.nixantic.instructions.*.
README.md is for consumers. The root CLAUDE.md is for contributors and agents working on this repo.
Add the flake input:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixantic.url = "github:OWNER/nixantic-standalone";
nixantic.inputs.nixpkgs.follows = "nixpkgs";
};
}Use a local path during development:
{
inputs.nixantic.url = "path:/home/me/src/nixantic-standalone";
}Then pick the integration surface that matches your setup.
Use the core module when you want rendered packages without Home Manager. Pass pkgs through specialArgs. The module imports the renderer with that package set.
{ inputs, nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
evaluated = nixpkgs.lib.evalModules {
specialArgs = { inherit pkgs; };
modules = [
inputs.nixantic.nixanticModules.core
{
nixantic.instructions.profile = "none";
nixantic.sources.example.instructions.main =
{ scope }:
{
heading = "Project instructions";
content = "Use the project conventions.";
outputPath = scope.forHarness {
claude = "CLAUDE.md";
opencode = "AGENTS.md";
pi = "AGENTS.md";
};
};
}
];
};
in
evaluated.config.nixantic.instructions.packageLeave nixantic.instructions.profile at its default ("builtin") to render the built-in instructions before your extra sources. Set it to "none" for a blank profile.
The Home Manager module imports the core module and adds install behavior. Shared options stay in the core module.
{ inputs, ... }:
{
imports = [ inputs.nixantic.homeManagerModules.default ];
nixantic.instructions.install.files = [
{
harness = "claude";
source = "CLAUDE.md";
target = ".claude/CLAUDE.md";
}
{
harness = "opencode";
source = "AGENTS.md";
target = ".config/opencode/AGENTS.md";
}
{
harness = "pi";
source = "AGENTS.md";
target = ".pi/agent/AGENTS.md";
}
{
harness = "pi";
source = "agents/reviewer.md";
target = ".pi/agent/agents/reviewer.md";
}
];
}Set nixantic.instructions.wrappers.install = true; if you want Home Manager to install the generic Claude Code and OpenCode wrapper packages. Keep personal wrappers, sandboxing, shell aliases, and local runtime glue in your own Home Manager modules. Consumers install and activate Pi and any Pi extensions themselves.
Pi uses AGENTS.md for the main context, prompt templates under prompts/, Agent Skills under skills/, and neutral generated agent files under agents/. Map generated agent files to Pi's global ~/.pi/agent/agents/ directory or project .pi/agents/ directory. Pi defaults to merging rules into AGENTS.md, while Claude Code and OpenCode default to standalone rule files. Set rules.output per harness when you need a different layout:
{
nixantic.instructions.harnesses = {
claude.rules.output = "files";
opencode.rules.output = "files";
pi = {
rules.output = "merge-main";
agents = "tintinweb";
tasks = "tintinweb";
questions = "rpiv-ask-user-question";
};
};
}The Pi adapter options describe the tools and file format expected by the consumer's Pi environment. They do not install, enable, or configure Pi, extensions, models, providers, credentials, themes, or mutable settings.
Import the flake-parts module when a flake should publish a rendered package and renderer check.
{
imports = [ inputs.nixantic.flakeModules.default ];
perSystem = { ... }: {
nixantic.enable = true;
nixantic.packageName = "my-instructions";
nixantic.checkName = "my-instructions";
nixantic.modules = [
{
nixantic.instructions.profile = "builtin";
}
];
};
}This module is an exposure layer. It evaluates the core module and publishes packages.<name> and checks.<name>.
Build the built-in profile:
nix build .#builtinThe result contains all three harness trees:
claude/CLAUDE.md
claude/commands/...
claude/agents/...
opencode/AGENTS.md
opencode/commands/...
opencode/agents/...
pi/AGENTS.md
pi/prompts/...
pi/skills/...
pi/agents/...
Run wrappers from the flake if claude or opencode is on PATH:
nix run .#claude -- --help
nix run .#opencode -- --helpEach wrapper sets the harness config directory to the generated tree, then execs the configured executable.
| Package | Binary | Env var | Config dir |
|---|---|---|---|
packages.<system>.claude |
nixantic-claude |
CLAUDE_CONFIG_DIR |
<package>/claude |
packages.<system>.opencode |
nixantic-opencode |
OPENCODE_CONFIG_DIR |
<package>/opencode |
Override the executable or wrapper name through the core module:
{
nixantic.instructions.wrappers.claude.executable = "/path/to/claude";
nixantic.instructions.wrappers.opencode.executable = "/path/to/opencode";
}Direct renderer imports are useful for renderer development and low-level tests. For consumer configs, prefer the core module because it owns the supported option surface.
let
instructions = import "${inputs.nixantic}/framework" {
inherit pkgs lib;
postProcess = true;
sourceRoots = [ ./instructions ];
sources = { };
settings.versionControl.mode = "jj";
};
in
instructions.packageA source root is a fragment-only tree. Every non-reserved .nix file under it is imported and must return an attrset with nixantic.sources.
{
nixantic.sources.example.commands.hello = {
description = "Say hello";
content = "Hello from a generated command.";
};
}Reserved paths are skipped during discovery:
_support/for helper codetests/for source-tree tests and fixtures
Duplicate artifact keys fail evaluation. Duplicate Home Manager install targets also fail evaluation.
The renderer currently ships three harnesses:
claude, output directoryclaude/opencode, output directoryopencode/pi, output directorypi/
All harnesses receive the same normalized source declarations. Harness files decide frontmatter fields and output names, for example CLAUDE.md versus AGENTS.md. Pi uses the Agent Skills and prompt-template paths shown above.
Run the repo checks with:
nix flake check --show-traceThe check set covers renderer behavior, core module evaluation without Home Manager, Home Manager install mapping, built-in corpus rendering, wrapper environment variables, and README example contracts.