From 354e163ede61c66d8f2034329c3bf85601c6abc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sat, 26 Sep 2026 21:52:14 +0200 Subject: [PATCH] Add README --- README.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..85d6f4c3ec09be7e1c3aa5d806eee151f317d98b --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +# agent-environments + +A Nix flake library for declaring environments for coding agents +([Claude Code](https://github.com/sadjow/claude-code-nix) and +[Codex](https://github.com/sadjow/codex-cli-nix)) 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/` (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. + +## Use + +```nix +{ + inputs.agent-environments.url = "github:/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`](examples/basic) and +[`examples/multi-account`](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`. + +## Options + +| 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`). | +| `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..{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. | +| `modules.skills..enable` | Declared by `mkSkillModule`; adds that skill. | +| `launchers..{agent,id,stateDir}` | A command. `id` defaults to the command name; `stateDir` defaults to `~/.local/agent-environments/`; it must be absolute or start with `~/`, and is taken literally. | + +## What a launcher does + +On every start, under a lock on the state dir: + +1. Links the managed files into the state dir: the instruction file, one link per + skill in `skills/`, and the Codex profile. Everything it manages is + listed in `.agent-environments-managed`. +2. Removes managed links that are no longer wanted. Anything not in the manifest + (your own skills, Codex's `skills/.system`, logins, `settings.json`, + `config.toml`) is never touched. +3. Refuses to start if a managed path is occupied by something it does not own, + such as a hand-written `CLAUDE.md`. Move it away (or turn it into an + `instructions` fragment) and start again. +4. Sets `CLAUDE_CONFIG_DIR` / `CODEX_HOME`, puts 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. + +## Development + +```sh +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 +```