~ruther/agent-environments

81614f914cf4a4cf9f280289e7ec7925d0e8e591 — František Boháček 2 months ago d024a4c
Add claude.plugins: plugin directories loaded with --plugin-dir
3 files changed, 24 insertions(+), 6 deletions(-)

M README.md
M checks/default.nix
M modules/claude.nix
M README.md => README.md +1 -0
@@ 66,6 66,7 @@ Runnable examples: [`examples/basic`](examples/basic) and
| `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. |
| `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. |

M checks/default.nix => checks/default.nix +9 -2
@@ 46,6 46,10 @@ let
    skills = [ leaf ];
  };

  fixturePlugin = pkgs.writeTextDir ".claude-plugin/plugin.json" (
    builtins.toJSON { name = "fixture"; }
  );

  full = mkEnvironment {
    inherit pkgs;
    modules = [


@@ 65,6 69,7 @@ let
          order = 10;
        };
        claude.settings.model = "opus";
        claude.plugins = [ fixturePlugin ];
        codex.settings.model = "gpt-5";
        launchers = {
          claude-work.agent = "claude";


@@ 130,10 135,12 @@ in
    [ -f $s/skills/leaf/SKILL.md ] || fail "dependency skill leaf missing"
    grep -qxF "HELLO=yes" $STUB_LOG.env || fail "skill runtime input not on PATH"

    # Settings layered via --settings, user args passed through after it.
    # Settings layered via --settings, plugins loaded with --plugin-dir, user args
    # passed through after them.
    [ "$(sed -n 1p $STUB_LOG.args)" = "--settings" ] || fail "missing --settings"
    grep -q '"model": *"opus"' "$(sed -n 2p $STUB_LOG.args)" || fail "settings file content"
    [ "$(sed -n '3,$p' $STUB_LOG.args)" = "$(printf -- '--resume\nx')" ] || fail "user args not passed through"
    [ "$(sed -n 3,4p $STUB_LOG.args)" = "$(printf -- "--plugin-dir\n${fixturePlugin}")" ] || fail "plugin not loaded"
    [ "$(sed -n '5,$p' $STUB_LOG.args)" = "$(printf -- '--resume\nx')" ] || fail "user args not passed through"
    [ ! -e $s/settings.json ] || fail "launcher must not own settings.json"

    ${full.launchers.codex-work}/bin/codex-work exec hi

M modules/claude.nix => modules/claude.nix +14 -4
@@ 20,6 20,11 @@ in
      default = { };
      description = "Settings layered over the account's settings.json via --settings.";
    };
    plugins = lib.mkOption {
      type = lib.types.listOf lib.types.path;
      default = [ ];
      description = "Plugin directories, loaded with --plugin-dir. Nothing is installed into the account.";
    };
  };

  config.build.agents.claude = lib.mkIf cfg.enable {


@@ 28,9 33,14 @@ in
    instructionsFile = "CLAUDE.md";
    # Managed links: path relative to the state dir -> store path.
    files = { };
    flags = lib.optionals (cfg.settings != { }) [
      "--settings"
      "${settingsFile}"
    ];
    flags =
      lib.optionals (cfg.settings != { }) [
        "--settings"
        "${settingsFile}"
      ]
      ++ lib.concatMap (p: [
        "--plugin-dir"
        "${p}"
      ]) cfg.plugins;
  };
}