A Nix flake library for declaring environments for coding agents (Claude Code and Codex) as modules, and for launching them under separate logins.
An environment is a set of modules: instructions (CLAUDE.md / AGENTS.md),
skills, and agent settings. A launcher is a command that starts one agent in
one environment, with its own state directory
~/.local/agent-environments/<id> (passed as CLAUDE_CONFIG_DIR /
CODEX_HOME). Different ids mean different logins, so claude-work-acc and
claude-pers-acc can share one environment but keep separate credentials.
{
inputs.agent-environments.url = "github:<owner>/agent-environments";
inputs.nixpkgs.follows = "agent-environments/nixpkgs";
outputs = { agent-environments, nixpkgs, ... }:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
inherit (agent-environments.lib) mkEnvironment mkSkill mkSkillModule;
my-skill = mkSkill {
inherit pkgs;
name = "my-skill";
src = ./skills/my-skill; # a directory containing SKILL.md
runtimeInputs = [ pkgs.jq ]; # put on PATH for the agent
skills = [ ]; # other mkSkill packages it needs
};
in {
packages.x86_64-linux.default = (mkEnvironment {
inherit pkgs;
modules = [
(mkSkillModule my-skill) # declares modules.skills.my-skill.enable
{
claude.enable = true;
codex.enable = true;
modules.skills.my-skill.enable = true;
instructions.style.text = "Prefer small commits.";
claude.settings.includeCoAuthoredBy = false;
codex.settings.approval_policy = "on-request";
launchers = {
claude-work-acc.agent = "claude";
claude-pers-acc.agent = "claude";
codex-work-acc.agent = "codex";
};
}
];
}).package;
};
}
Runnable examples: examples/basic and
examples/multi-account. The root flake exposes only
lib and a default environment without skills: nix shell .#default puts its
claude and codex launchers on PATH.
| Option | Meaning |
|---|---|
claude.enable, codex.enable |
Make the agent available to launchers. |
claude.package, codex.package |
Agent package; defaults come from this flake's inputs. |
claude.settings |
JSON passed with --settings (layered over the account's settings.json). |
claude.plugins |
Plugin directories loaded with --plugin-dir; nothing is installed into the account. |
claude.mcpServers |
MCP servers loaded with --mcp-config (the mcpServers object of an MCP JSON file). Logins stay in the account: run /mcp once. |
codex.settings |
TOML linked as $CODEX_HOME/agent-environments.config.toml and selected with --profile agent-environments (layered over the account's config.toml). |
instructions.<name>.{text,order} |
Fragments of CLAUDE.md / AGENTS.md, sorted by order (default 1000), then name. |
skills.packages |
mkSkill packages to enable. Their skill dependencies are added automatically. |
packages |
Packages put on every launcher's PATH, e.g. tools that hooks in claude.settings call. |
modules.skills.<name>.enable |
Declared by mkSkillModule; adds that skill. |
launchers.<cmd>.{agent,id,stateDir} |
A command. id defaults to the command name; stateDir defaults to ~/.local/agent-environments/<id>; it must be absolute or start with ~/, and is taken literally. |
launchers.<cmd>.sharedDirs.<dir> |
Share one directory of the state dir with another launcher, e.g. projects = "claude-work" for sessions and memory across logins. A managed symlink to that launcher's <stateDir>/<dir>, created if missing. |
companions.enable |
Put every launcher of the environment on the agent's PATH (as companions, which cannot start companions themselves) and add a generated companions skill listing each one with its non-interactive call. Launchers export AGENT_ENV_LAUNCHER (their command name). |
On every start, under a lock on the state dir:
skills/<name>, and the Codex profile. Everything it manages is
listed in .agent-environments-managed.skills/.system, logins, settings.json,
config.toml) is never touched.CLAUDE.md. Move it away (or turn it into an
instructions fragment) and start again.CLAUDE_CONFIG_DIR / CODEX_HOME, puts packages and the skills' runtime inputs on
PATH, and runs the agent.Launchers that share an id share a login and managed files. The most recent
launch decides which files are linked, so only share an id between launchers of
the same environment.
nix flake check # behaviour tests (stub agents) + real Codex integration check
nix fmt -- $(git ls-files '*.nix')
nix build ./examples/basic --override-input agent-environments path:$PWD