From 81614f914cf4a4cf9f280289e7ec7925d0e8e591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sun, 27 Sep 2026 12:42:25 +0200 Subject: [PATCH] Add claude.plugins: plugin directories loaded with --plugin-dir --- README.md | 1 + checks/default.nix | 11 +++++++++-- modules/claude.nix | 18 ++++++++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ea1ac478eb400ff93c6a77684194c1ecfbc076a6..90a86dc304952030e6202150445859f0a9a4ad88 100644 --- a/README.md +++ b/README.md @@ -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..{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. | diff --git a/checks/default.nix b/checks/default.nix index 70e3e1da7f8570f5192e7e1655a087e75b2937a0..5d17fe5d9c0521986cef7f9ab03993788ad32353 100644 --- a/checks/default.nix +++ b/checks/default.nix @@ -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 diff --git a/modules/claude.nix b/modules/claude.nix index a267b3be851c7941de1db408b800e8c983c9ea46..f6c348165262939f2484a00b1a9263af390fbb66 100644 --- a/modules/claude.nix +++ b/modules/claude.nix @@ -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; }; }