a declarative and reproducible setup for all of your coding agents!
all of your skills, plugins and MCP servers are declared once, grouped into bundles. You pick the agents you use and the bundles each one gets; a small adapter per agent maps them onto that agent's config format. Add an agent, and it can take the whole stack. Add a skill, and every agent you choose gets it
catalog/*.nix ─► lib/resolve.nix ─► agents/*.nix, one per agent ─► ~/.<agent>/…
(every bundle) (your bundles + claude-code.nix, codex.nix, …
skips, per agent)
catalog/: every bundle, pinned via flake inputs. A bundle is one attrset with the same optional fields everywhere:skills,plugin(a plugin dir in Claude Code layout),native(the plugin's own loader file per agent),commands,rules,subagents,scripts,context(CLAUDE.md sections) anddepends.catalog/spartan.nix: one bundle per Spartan pack, read from the toolkit's ownpacks/*.yamlbylib/pack.nix. A Spartan update brings its new commands in without edits here.lib/resolve.nix: turns one agent's bundle list into its content. It addsdepends, loads a plugin natively when the bundle has anativeentry for that agent, flattens the plugin'sskills/in otherwise, and removesskipnames.module.nix: the options, the assertions, and theanikonistackLibmodule argument (anikonistackLib.for "<agent>") that adapters read.agents/: one adapter per agent, listed inagents/default.nix. Each writes nothing unlessanikonistack.agents.<agent>.enableis set.flake.nix+flake.lock: every upstream repo pinned to a commit. Same lock, same result, any machine.nix flake checkreads the whole catalog and fails if any path it points at is missing, so a lock bump that breaks a bundle fails CI first.
Requires nix (the package manager!) with flakes enabled! Nix runs on NixOS, any Linux, macOS, and WSL; NixOS itself is not required!
Since this is also a home-manager module, home-manager is also necessary in order to reproduce this setup!
- install nix (the package manager!)
- then
nix run home-manager -- initto get a starterflake.nixandhome.nix, then continue below
# flake.nix
inputs.anikonistack.url = "github:kidskoding/anikonistack";
# home.nix
imports = [ inputs.anikonistack.homeManagerModules.default ];
anikonistack = {
bundles = [ "custom" "superpowers" "spartan-core" ];
agents.claude-code.enable = true;
};nix flake lock --update-input anikonistack
home-manager switch --flake . # or nixos-rebuild switchEvery agent config under $HOME becomes a read-only symlink into the nix store, rebuilt from the pinned inputs.
Nothing is on by default. Pick bundles once; every enabled agent gets them unless it sets its own list:
anikonistack = {
bundles = [ "custom" "mattpocock" "superpowers" "caveman" "spartan-core" "spartan-backend-micronaut" ];
skip = [ "resolving-merge-conflicts" ]; # single skills, commands, rules or subagents
agents = {
claude-code = {
enable = true;
statusline = true; # hooks/statusline.sh
};
codex.enable = true;
cursor = {
enable = true;
bundles = [ "custom" "superpowers" ]; # replaces the list above for cursor only
};
};
};- A misspelled bundle name fails evaluation and lists the valid names. An unknown
skipname fails too. skipalso settles a clash: skip the name and neither bundle provides it.- A plugin an agent loads natively is installed whole, so skipping one of its skills only works for agents that flatten it. For the others you get a warning; leave out the plugin's bundle instead.
- Choosing a bundle also brings in its
depends. - Evaluation fails if two bundles an agent gets define the same name, of the same kind, pointing at different files.
- MCP servers are yours: set
programs.mcp = { enable = true; servers = { … }; };and every enabled agent picks them up. Withoutenable = true, home-manager gives the agents no servers.
| bundle | what | contains | depends on |
|---|---|---|---|
caveman |
terse caveman-style output | plugin, skills | |
custom |
this repo's own skills and CLAUDE.md sections | skills, context | |
duet |
claude-duet commands (Claude Code only) | plugin | |
extras |
single skills from assorted repos | skills | |
firecrawl |
Firecrawl web scraping and search | plugin, skills | |
frontend-design |
Anthropic's frontend-design plugin | plugin, skills | |
last30days |
research what happened in the last 30 days | plugin, skills | |
mattpocock |
Matt Pocock's engineering and productivity skills | skills | |
obsidian |
kepano's Obsidian skills | skills | |
ponytail |
ponytail plugin | plugin, skills | |
spartan-backend-micronaut |
Kotlin + Micronaut backend | skills, commands, rules, subagents, context | spartan-core, spartan-database, spartan-shared-backend |
spartan-core |
Core workflow (always installed) | commands, rules, subagents, context | |
spartan-database |
Database patterns, migrations, Exposed ORM | skills, commands, rules, context | spartan-core |
spartan-frontend-react |
React + Next.js frontend | skills, commands, rules, context | spartan-core |
spartan-infrastructure |
Terraform + AWS infrastructure | skills, commands, rules, subagents, context | spartan-core |
spartan-ops |
Deploy & infrastructure | skills, commands, context | spartan-core |
spartan-product |
Product thinking before building | skills, commands, context | spartan-core |
spartan-research |
Startup research pipeline — from idea to investor-ready | skills, commands, subagents, context | spartan-core, spartan-product |
spartan-shared-backend |
Shared backend architecture concepts | rules | spartan-core |
spartan-ux-design |
UX design workflow — research, define, ideate, design system, prototype, test, AI asset generation | skills, commands, rules, subagents, scripts, context | spartan-core |
superpowers |
obra's superpowers workflow skills | plugin, skills | |
understand-anything |
codebase knowledge graphs | plugin, skills |
plugin means agents with a native loader for it load the whole plugin; the others get its skills/.
| agent | takes |
|---|---|
claude-code |
plugins, skills, commands, rules, subagents, scripts (~/.claude/scripts), context; optional statusline |
codex |
native plugins (caveman, ponytail, superpowers, last30days), skills |
opencode |
native plugins (ponytail, superpowers), skills |
antigravity |
skills |
cursor |
skills, ~/.cursor/mcp.json |
Kinds an agent does not take are left out for that agent.
One file. Read anikonistackLib.for "<agent>" and feed it into whatever the agent's home-manager module accepts:
# agents/myagent.nix
{ anikonistackLib, config, lib, ... }: let
s = anikonistackLib.for "myagent";
in {
config = lib.mkIf config.anikonistack.agents.myagent.enable {
programs.myagent = {
enable = true;
enableMcpIntegration = true;
inherit (s) skills;
};
};
}Add ./myagent.nix to imports in agents/default.nix and "myagent" to agentNames in module.nix.
anikonistackLib.for "<agent>" returns:
| field | what |
|---|---|
plugins |
{ <bundle> = <path>; }, the plugins this agent loads natively |
skills |
{ <name> = <path>; }, bundle skills plus flattened skills of the other plugins |
commands, rules, subagents, scripts |
{ <name> = <path>; } |
context |
list of CLAUDE.md sections, in key order |
Agent-specific options go in the adapter, like statusline in agents/claude-code.nix.
| what | where |
|---|---|
| a skill you wrote | dir with SKILL.md under skills/ (bundle custom) |
| an upstream skill | flake input, one line in a catalog/*.nix bundle |
| a plugin | flake input, one bundle in catalog/plugins.nix; add native.<agent> if the plugin ships a loader for that agent |
| a new group | a new catalog/<name>.nix, listed in catalog/default.nix |
Secrets never go in the repo. Reference them as ${VAR} in programs.mcp.servers and export the variable before launching.
Lives in your own home-manager config, not here: which agents and bundles, MCP servers, agent settings (model, permissions), which package provides a binary.
programs.claude-code.package = null; # binary already installed another wayPer-agent selection replaced the global toggles:
anikonistack.bundles.<name>.enableis gone. List bundles instead:anikonistack.bundles = [ … ]. The old form fails with a message pointing here.- Agents are opt-in: set
anikonistack.agents.<agent>.enable = truefor each one you use. - Bundles were renamed:
own→custom,spartan→spartan-<pack>(all of today's Spartan content isspartan-core,spartan-database,spartan-shared-backend,spartan-backend-micronaut,spartan-frontend-react,spartan-ux-design,spartan-infrastructure,spartan-product,spartan-ops,spartan-research). - The repo no longer sets MCP servers, Claude Code settings or packages. Move whatever you relied on into your own config.
nix flake update # here, commit flake.lock
nix flake lock --update-input anikonistack # in your home-manager repoanikonistack/
├── flake.nix pins every upstream repo
├── module.nix options, assertions, module argument
├── catalog/ every bundle, one file per group
├── lib/ pack.nix (Spartan packs), resolve.nix, skill-dirs.nix
├── agents/ one adapter per agent
├── skills/ own skills (bundle `custom`)
├── hooks/ statusline.sh
└── claude-md/ own CLAUDE.md sections (bundle `custom`)