Skip to content

feat(claude-code): enable frontend-design plugin#154

Merged
Bad3r merged 4 commits intomainfrom
feat/claude-code-frontend-design-plugin
May 3, 2026
Merged

feat(claude-code): enable frontend-design plugin#154
Bad3r merged 4 commits intomainfrom
feat/claude-code-frontend-design-plugin

Conversation

@Bad3r
Copy link
Copy Markdown
Owner

@Bad3r Bad3r commented May 3, 2026

Summary

Exposes programs.claude-code.extended.extraPlugins (attrsOf bool) in modules/apps/claude-code.nix so non-LSP Claude Code plugins can be toggled per-host without editing the Home Manager module. The Home Manager side derives enabledPlugins as the merge of the existing lspPlugins-derived map and the new extraPlugins attrset.

The default for extraPlugins enables frontend-design@claude-plugins-official, replacing the original frontend-design@claude-code-plugins entry. Upstream verification (anthropics/claude-plugins-official marketplace.json via gh api) confirmed that frontend-design lives in the same marketplace as the existing LSP plugins; anthropics/claude-code-plugins does not exist.

The module Notes block now lists both option entry points and calls out that enabledPlugins keys silently no-op when their marketplace is not registered in ~/.claude/plugins/known_marketplaces.json.

Test plan

  • nix fmt
  • nix develop -c pre-commit run --hook-stage manual --files modules/apps/claude-code.nix modules/hm-apps/claude-code.nix
  • nix flake check --accept-flake-config --no-build --offline
  • nix build .#nixosConfigurations.tpnix.config.system.build.toplevel --no-link
  • nix eval of resolved home.file.".claude/settings.json".text confirms "frontend-design@claude-plugins-official": true lands in enabledPlugins alongside the LSP entries.
  • After switch: open Claude Code and confirm the frontend-design plugin shows up enabled in ~/.claude/settings.json.

…gins

Merge "frontend-design@claude-code-plugins" into the enabledPlugins
attrset alongside the existing lspPlugins-derived map. The
lspPlugins-driven entries continue to come from the
programs.claude-code.extended.lspPlugins option, while this static
addition opts into the frontend-design plugin from the
claude-code-plugins marketplace.
@github-project-automation github-project-automation Bot moved this to Backlog in ❄️ NixOS May 3, 2026
@Bad3r Bad3r added type(enhancement) Net-new capability or intentional improvement. area(home-manager) Home Manager modules, activation, or user-environment config. area(agents) Codex, Claude Code, agent wrappers, prompts, or agent tooling. priority(p3) Normal priority. labels May 3, 2026
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 3, 2026

Claude finished @Bad3r's task in 1m 41s —— View job


Claude Code Review

  • Read changed file (modules/hm-apps/claude-code.nix)
  • Inspect diff vs origin/main
  • Verify plugin source / marketplace conventions in repo
  • Provide review feedback

Overall: small, well-scoped change. The merge with // is correct and preserves the existing lspPlugins-derived map. A few non-blocking notes:

1. Stale comment vs. new behavior — modules/hm-apps/claude-code.nix:43-44

# Derive enabledPlugins from the NixOS-level lspPlugins option so that the
# single source of truth lives in programs.claude-code.extended.lspPlugins.

After this PR, enabledPlugins is no longer purely derived — frontend-design@claude-code-plugins is hardcoded a few lines below. The PR description correctly clarifies that lspPlugins is the single source of truth for LSP-style plugins only, but the in-file comment still reads as if the whole attrset is derived. Consider tightening it to match, e.g.:

# enabledPlugins is composed of:
#   1. LSP plugins derived from programs.claude-code.extended.lspPlugins
#      (single source of truth for LSP-style plugins).
#   2. Additional non-LSP plugins from third-party marketplaces, listed
#      explicitly below.

Fix this →

2. Hardcoded true removes the per-host toggle

LSP plugins flow through a real NixOS option (programs.claude-code.extended.lspPlugins.<key>, declared at modules/apps/claude-code.nix:119-130) so a host can disable any of them without editing this module. The new entry has no such toggle — every host that enables claude-code now gets frontend-design, and the only way to opt out is to edit modules/hm-apps/claude-code.nix directly.

If you expect more third-party plugins to be added later (this is the second marketplace already), consider promoting this to an option in the same shape as lspPlugins, e.g. programs.claude-code.extended.extraPlugins mapping "plugin@marketplace" keys → bool, so the host's apps-enable.nix (or equivalent) can flip them. For just one plugin today this is overkill — file under "the moment a third one shows up, refactor".

3. Marketplace registration is implicit

The existing claude-plugins-official and the new claude-code-plugins are both marketplace names that Claude Code resolves via ~/.claude/plugins/known_marketplaces.json (per docs/claude-code/plugins.md:245-289). Nothing in this repo provisions that file — so on a fresh activation enabledPlugins["frontend-design@claude-code-plugins"] = true is a no-op until the user has run claude-plugins install anthropics/claude-code-plugins once.

That's the same trade-off as claude-plugins-official already, so this PR doesn't make it worse — but it's worth a one-liner in modules/hm-apps/claude-code.nix's top docstring (the Notes: block at lines 8-14) listing the marketplaces this module assumes are installed, so a future operator doesn't lose time wondering why enabledPlugins entries silently do nothing on a clean machine.

4. Verify the plugin slug

frontend-design is the assumed plugin id inside the anthropics/claude-code-plugins marketplace. Worth confirming against that repo's marketplace.json (the docs at docs/claude-code/plugins.md:122 describe the schema) so the key matches exactly — a typo here fails silently because Claude Code just ignores unknown plugin names.

5. Test plan

The PR description leaves these unchecked:

  • nix flake check --accept-flake-config --no-build --offline
  • nix build .#nixosConfigurations.tpnix.config.system.build.toplevel
  • Post-switch verification that ~/.claude/settings.json ends up with "frontend-design@claude-code-plugins": true

Per CLAUDE.md, this is a value-level edit inside an existing attrset (no structural module change), so a strict reading allows skipping nix flake check. Still, building one host closure is cheap insurance — recommend running at least the tpnix build before merge so the osConfig.programs.claude-code.extended.lspPlugins lookup is exercised end-to-end with the new merge.


Summary

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modifies the claude-code Home Manager module to include the frontend-design plugin by default. Feedback indicates that hardcoding this plugin prevents user customization and suggests exposing it as a configurable option to maintain consistency with existing plugin management.

Comment thread modules/hm-apps/claude-code.nix Outdated
Bad3r added 2 commits May 3, 2026 17:06
…lace plugins

Introduces `programs.claude-code.extended.extraPlugins` as an
`attrsOf bool` so hosts can toggle non-LSP Claude Code plugins
without editing `modules/hm-apps/claude-code.nix`. The Home Manager
module now derives `enabledPlugins` as a merge of the existing
`lspPlugins`-derived map and the new `extraPlugins` attrset.

Also corrects the `frontend-design` marketplace suffix from
`@claude-code-plugins` (a repo that does not exist) to
`@claude-plugins-official`, where the plugin actually lives upstream
(`anthropics/claude-plugins-official` `marketplace.json`). The stale
inline comment is rewritten to describe the new two-source derivation
rule.

Validation:
- `nix fmt`
- `nix develop -c pre-commit run --hook-stage manual --files modules/apps/claude-code.nix modules/hm-apps/claude-code.nix`
- `nix flake check --accept-flake-config --no-build --offline`
- `nix build .#nixosConfigurations.tpnix.config.system.build.toplevel --no-link`
- `nix eval` of resolved `home.file.".claude/settings.json"` confirms
  `frontend-design@claude-plugins-official: true` lands in `enabledPlugins`
  alongside the LSP entries.
…mptions

Adds two bullets to the module Notes block: one pointing to the new
`extraPlugins` option and one calling out that `enabledPlugins` keys
require the `@<marketplace>` suffix to match a marketplace already
registered in `~/.claude/plugins/known_marketplaces.json`. The default
plugins assume `claude-plugins-official`, so a fresh activation must
register that marketplace once with
`claude-plugins install anthropics/claude-plugins-official` to avoid
silent no-ops.

Validation: `nix flake check --accept-flake-config --no-build --offline`.
@Bad3r
Copy link
Copy Markdown
Owner Author

Bad3r commented May 3, 2026

Review feedback addressed

Two atomic commits land on this branch (will push after this comment):

  • c1e491c5 refactor(claude-code): expose extraPlugins option for non-LSP marketplace plugins
  • 345ab7b2 docs(hm-apps/claude-code): document extraPlugins and marketplace assumptions

Accepted

# Source Item Resolution
1 gemini-code-assist (inline modules/hm-apps/claude-code.nix:51) Hardcoded true blocks per-host opt-out; expose a real option. Added programs.claude-code.extended.extraPlugins (attrsOf bool) in modules/apps/claude-code.nix:132-153. Hosts can override via apps-enable.nix, e.g. "claude-code".extended.extraPlugins."frontend-design@claude-plugins-official" = lib.mkOverride 1100 false;. Default keeps current behavior.
2 claude review #1 Stale inline comment ("single source of truth") at modules/hm-apps/claude-code.nix:43-44. Rewrote the inline comment in c1e491c5 to describe the two-source composition (LSP-derived ∪ extraPlugins).
3 claude review #2 Promote hardcoded entry to a real option matching lspPlugins shape. Same as #1: extraPlugins mirrors lspPlugins's pattern (mapAttrs/attrsOf + lib.mkOverride 1100).
4 claude review #3 Marketplace registration is implicit; document the assumption. Added two bullets to the module Notes (modules/hm-apps/claude-code.nix:14-20) pointing to extraPlugins and to claude-plugins-official as the assumed marketplace.
5 claude review #4 Verify the plugin slug. Upstream verification surfaced a real bug: anthropics/claude-code-plugins does not exist. The frontend-design plugin lives in anthropics/claude-plugins-official (marketplace.json confirmed via gh api). Corrected the suffix from @claude-code-plugins to @claude-plugins-official in the extraPlugins default.
6 claude review #5 Test plan items unchecked. Ran nix fmt, pre-commit hooks, nix flake check --accept-flake-config --no-build --offline, and nix build .#nixosConfigurations.tpnix.config.system.build.toplevel --no-link (all green). Final ~/.claude/settings.json confirmed via nix eval of home.file.".claude/settings.json".text: "frontend-design@claude-plugins-official": true lands alongside the LSP entries.

Rejected

None. All feedback was either valid or, in the case of #5 (slug verification), surfaced an upstream-name bug worth fixing.

Production-grade rationale

  • Single source of truth: extraPlugins lives next to lspPlugins in modules/apps/claude-code.nix, so all enable/disable decisions for Claude Code plugins now flow through declared NixOS options consumed by the Home Manager module via osConfig lookup. No host needs to edit modules/hm-apps/claude-code.nix to toggle a plugin.
  • Idiomatic option shape: attrsOf bool keyed by the exact "<plugin>@<marketplace>" string used in ~/.claude/settings.json keeps the option semantically identical to what Claude Code consumes, with no extra mapping layer that could drift.
  • Override-friendly: hosts already use lib.mkOverride 1100 for claude-code.extended.* toggles in modules/{tpnix,system76}/apps-enable.nix; the new option follows the same convention.
  • Bug fix folded in: the marketplace name correction is part of the option's default value, so downstream consumers automatically get the fix without separate intervention.
  • Failure mode documented: the Notes block calls out that an unregistered marketplace silently no-ops, so a future operator hitting that won't burn time debugging.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 3, 2026

Claude finished @Bad3r's task in 1m 55s —— View job


Claude Code Review

  • Read changed files (modules/apps/claude-code.nix, modules/hm-apps/claude-code.nix)
  • Inspect diff vs origin/main
  • Verify option shape, defaults, and merge semantics
  • Provide review feedback

Solid follow-up — the hardcoded toggle is now a real NixOS option, the comment drift from review #1 is resolved, the marketplace assumption is documented, and the upstream-name bug fix is folded into the default. The new option mirrors the lspPlugins shape, so hosts can flip individual entries via apps-enable.nix exactly like the LSP plugins. Pre-existing host overrides in modules/{tpnix,system76}/apps-enable.nix:47-64 use the same lib.mkOverride 1100 convention, so the override path is consistent.

A few non-blocking observations on the new code:

1. Merge precedence — silent override of LSP keys (modules/hm-apps/claude-code.nix:56-60)

enabledPlugins =
  (lib.mapAttrs' (
    pluginKey: enabled: lib.nameValuePair "${pluginKey}@claude-plugins-official" enabled
  ) (lib.attrByPath [ "programs" "claude-code" "extended" "lspPlugins" ] { } osConfig))
  // (lib.attrByPath [ "programs" "claude-code" "extended" "extraPlugins" ] { } osConfig);

Because // lets the right operand win, a user-supplied extraPlugins."pyright-lsp@claude-plugins-official" = false would override the LSP-derived true in enabledPlugins, but the LSP program (pyright) would still be installed via the lib.mkOverride 1050 block in modules/apps/claude-code.nix:190-195. End state: binary present, plugin disabled in settings.json — a silent inconsistency.

This is an edge case (no one is likely to mirror LSP keys into extraPlugins), but worth either:

  • A short comment in the HM module noting that LSP keys should not be put in extraPlugins, or
  • An assertion in modules/apps/claude-code.nix that lib.intersectLists (lib.attrNames cfg.extraPlugins) (lspKeysWithMarketplace) == [].

2. No shape validation on extraPlugins keys (modules/apps/claude-code.nix:132-153)

The option type is attrsOf bool, so a typo like "frontend-design" (missing @<marketplace> suffix) is accepted at eval time but silently ignored by Claude Code at runtime — exactly the failure mode the Notes block warns about. A lib.types.addCheck on the key shape would catch this at evaluation:

type = lib.types.attrsOf lib.types.bool // {
  check = v:
    builtins.isAttrs v
    && lib.all (k: builtins.match ".+@.+" k != null) (lib.attrNames v);
};

(Or a cleaner version with a custom addCheck.) Optional — the docstring already covers it, and over-validating user input has its own costs.

3. Default-replacement semantics worth a one-liner

The description says "override the whole attrset to drop defaults entirely." That's accurate for mkForce / direct assignment, but per-key opt-out (extraPlugins."frontend-design@claude-plugins-official" = lib.mkOverride 1100 false;) also works because attrsOf merges per-key. Worth noting that flipping to false keeps the entry registered (and visible in settings.json) while disabling it — which differs subtly from omitting it. The docstring partially says this; just consider showing the per-key override in example so consumers see both patterns.

4. lib.attrByPath fallbacks are redundant but harmless

Both lib.attrByPath calls fall back to {} even though the HM block is guarded by lib.mkIf nixosEnabled (line 174), which can only be true when programs.claude-code.extended.enable = true, which in turn implies the option is declared. Cosmetic — current form is defensive in case the NixOS module is ever absent (e.g., on hosts that import the HM module without the NixOS one), so leaving it is fine.

5. No automated coverage of the new merge

The manual nix eval of home.file.".claude/settings.json".text (per the test plan) is good due-diligence, but nothing in the repo locks it in. Since lspPlugins doesn't have a regression test either, this is consistent with current practice — flagging only because the merge semantics in #1 above could regress silently. Not blocking.


Summary

Nice work folding the upstream-marketplace fix into the same change.
· branch: feat/claude-code-frontend-design-plugin

…on assertions

Adds two assertions in `modules/apps/claude-code.nix` so misconfigured
`programs.claude-code.extended.extraPlugins` fails at evaluation
instead of silently no-opping at Claude Code runtime:

* Key-shape assertion rejects entries that lack a `@<marketplace>`
  suffix (e.g. a typo `"frontend-design" = true;`), since Claude Code
  ignores unsuffixed keys when scanning `~/.claude/settings.json`'s
  `enabledPlugins`.
* LSP-collision assertion rejects entries whose key matches an
  `lspPlugins.<key>@claude-plugins-official` identifier. Without this,
  setting `extraPlugins."pyright-lsp@claude-plugins-official" = false`
  would disable the plugin in `settings.json` while leaving the LSP
  binary installed via the `lib.mkOverride 1050` block, producing a
  confusing inconsistency.

Also clarifies the option `example` to show the per-key opt-out
pattern (`"<plugin>@<marketplace>" = false;` keeps the entry registered
but disabled) alongside the third-party-marketplace pattern, and adds
a sentence to the option `description` documenting the
LSP-collision rejection.

Validation:
- `nix fmt`
- `nix flake check --accept-flake-config --no-build --offline`
- `nix build .#nixosConfigurations.tpnix.config.system.build.toplevel --no-link`
- `nix eval` of the assertion predicates against four input cases
  (valid default, missing-suffix typo, LSP collision, both) confirms
  the right keys are flagged as `malformedKeys` / `lspCollisions`.
@Bad3r
Copy link
Copy Markdown
Owner Author

Bad3r commented May 3, 2026

Round 2 feedback addressed

72c2e157 feat(claude-code): harden extraPlugins with key-shape and LSP-collision assertions lands on this branch (will push after this comment).

Accepted

# Item Resolution
1 Merge precedence — silent override of LSP keys (modules/hm-apps/claude-code.nix:56-60) Added an LSP-collision assertion in modules/apps/claude-code.nix:195-208. extraPlugins."pyright-lsp@claude-plugins-official" = false (or any other LSP key with the @claude-plugins-official suffix) now fails at evaluation with a message that explains why the binary/state would diverge. Predicate verified via nix eval against four test cases.
2 No shape validation on extraPlugins keys Added a key-shape assertion in modules/apps/claude-code.nix:184-194. Entries missing the @<marketplace> suffix (e.g. a typo "frontend-design" = true;) now fail at evaluation rather than being silently ignored at Claude Code runtime. Implemented as an assertion (rather than lib.types.addCheck) for clearer error messages naming the offending key(s).
3 Default-replacement semantics worth a one-liner Updated the option example to explicitly show the per-key opt-out pattern ("<plugin>@<marketplace>" = false; keeps the entry registered in settings.json but disabled) alongside the third-party-marketplace pattern. Added a sentence to the description documenting the LSP-collision rejection so consumers see the constraint inline.

Rejected (with reason)

# Item Reason
4 lib.attrByPath fallbacks are redundant Reviewer explicitly said "current form is defensive in case the NixOS module is ever absent (e.g., on hosts that import the HM module without the NixOS one), so leaving it is fine." No change.
5 No automated coverage of the new merge Reviewer explicitly said "Not blocking" and noted it is consistent with current practice (no per-option regression tests for lspPlugins either). The new assertions in #1 and #2 cover the most likely regression modes.

Production-grade rationale

  • Fail-fast at evaluation: both new assertions surface misconfiguration before activation rather than as silent no-ops at Claude Code session start. Errors name the offending keys so the operator can fix them without digging through ~/.claude/settings.json diffs.
  • Coupled invariants stay in one place: the LSP-collision assertion derives its key set from lib.attrNames cfg.lspPlugins, so adding a new LSP plugin in lspPluginProgramMap automatically extends the rejection set without manual sync.
  • No type-system overreach: assertions provide better error messages than lib.types.addCheck for this case (which would only say "value is not of type"), and avoid coupling the option type definition to the LSP plugin enumeration.
  • Documentation co-located with constraint: option description mentions the LSP-key rejection inline, so a consumer reading nixos-help sees the constraint without needing to discover the assertion separately.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 3, 2026

Claude finished @Bad3r's task in 1m 52s —— View job


Claude Code Review (round 3)

  • Read both changed files at current SHAs
  • Inspect diff vs origin/main and just the latest commit (72c2e15)
  • Validate the new key-shape and LSP-collision assertions
  • Provide review feedback

The assertions in 72c2e15 cleanly close the two edge cases I flagged in round 2. Both predicates derive their data from declared options (cfg.extraPlugins, cfg.lspPlugins), so they stay in sync with lspPluginProgramMap automatically — adding a new LSP entry there will extend the rejection set without manual bookkeeping. Error messages name the offending keys, which is exactly what an operator needs to fix a misconfiguration without spelunking through ~/.claude/settings.json diffs.

A few small, non-blocking observations on the new code:

1. Key-shape regex is permissive (modules/apps/claude-code.nix:174)

malformedKeys = lib.filter (k: builtins.match ".+@.+" k == null) extraKeys;

.+@.+ catches the obvious typo ("frontend-design" missing the suffix), which is the failure mode the assertion was added for. It still accepts oddities like "@bar" (no — .+ requires a leading char, so this is rejected), "foo@" (rejected), "foo@@bar" (accepted), or " foo @ bar " (accepted). Claude Code would silently ignore the latter two, so they regress to the original failure mode.

If you want full coverage, something like ^[A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+$ would be tighter. But the cost/benefit on tightening past the common-case typo is marginal — the docstring already documents the contract and the assertion catches the realistic mistake. Leave as-is unless a real-world misconfiguration shows up.

2. Assertions are gated by cfg.enable (modules/apps/claude-code.nix:161)

config = lib.mkIf cfg.enable (
  lib.mkMerge ([ { ... assertions = ...; } ] ++ ...)
);

Because the assertions list lives inside lib.mkIf cfg.enable, a host that sets extraPlugins."typo" = true; but leaves claude-code.extended.enable = false; will not trip the new checks. That is consistent with the two pre-existing assertions in the same block (and arguably correct — the value isn't consumed when the module is disabled), but worth knowing if you're tempted to lint inactive configs. Not a change request.

3. intersectLists argument order is fine, but worth noting

lspKeysWithMarket = map (k: "${k}@claude-plugins-official") (lib.attrNames cfg.lspPlugins);
lspCollisions = lib.intersectLists extraKeys lspKeysWithMarket;

lib.intersectLists e: filter (x: elem x e) returns a subset of the second list, so lspCollisions is a subset of the LSP-key universe filtered by membership in extraKeys. The error message says "Conflicting keys: …" — accurate for either reading. If you wanted the collision list to be reported in the order the user wrote them in extraPlugins, swap the args (intersectLists lspKeysWithMarket extraKeys); cosmetic only.

4. Docstring matches behavior

description now states the LSP-key rejection inline, and example shows both the third-party marketplace pattern and the per-key opt-out (= false). The Notes block in the HM module documents the marketplace-registration prerequisite. Reads cleanly, no drift from code.

5. No automated coverage for the new merge or assertions

Same observation as round 2 — flagging only for completeness. The two new assertions cover the most likely regression modes (collision, malformed key), so the residual surface is small. Not blocking.


Summary

  • Correctness: ✓ — assertions are well-formed, gated correctly, and use canonical sources for their inputs.
  • Security / perf: not applicable — pure attrset operations at evaluation time.
  • Documentation: ✓ — Notes block, option description, and example are all accurate post-revision.
  • Suggested follow-ups: optional regex tightening (feat: add nixos app helpers #1) only if real-world typos slip past .+@.+. Nothing else worth doing.

Nice tight follow-up — assertions are the right tool here (clearer messages than lib.types.addCheck, and the LSP-collision rule would be awkward to express in the type anyway).
· branch: feat/claude-code-frontend-design-plugin

@Bad3r
Copy link
Copy Markdown
Owner Author

Bad3r commented May 3, 2026

Round 3: no further code changes

The latest Claude review raises five non-blocking observations and explicitly suggests no code changes:

# Observation Reviewer verdict Action
1 Key-shape regex .+@.+ accepts oddities like "foo@@bar". "Leave as-is unless a real-world misconfiguration shows up." None. The regex catches the realistic typo (missing @<marketplace>); tightening past common-case is YAGNI per project guidelines (CLAUDE.md: "Don't add validation for scenarios that can't happen"). Documented contract + assertion error message remains the source of truth.
2 Assertions gated by cfg.enable won't fire on disabled hosts. "Not a change request." None. Consistent with the two pre-existing assertions in the same block, and correct: the value is not consumed when the module is disabled.
3 lib.intersectLists arg order is cosmetic. "Cosmetic only." None. The error message reads correctly with either ordering, and the assertion is rare-path; not worth a churn commit.
4 Docstring matches behavior. Positive (no action requested). None.
5 No automated coverage of the new merge / assertions. "Not blocking", consistent with current practice (no per-option regression tests for lspPlugins either). None. The two new assertions cover the most likely regression modes.

Reviewer summary verbatim: "Suggested follow-ups: optional regex tightening (#1) only if real-world typos slip past .+@.+. Nothing else worth doing."

The branch state is the merge candidate.

@Bad3r Bad3r merged commit ecd8399 into main May 3, 2026
1 check passed
@Bad3r Bad3r deleted the feat/claude-code-frontend-design-plugin branch May 3, 2026 14:21
@github-project-automation github-project-automation Bot moved this from Backlog to Done in ❄️ NixOS May 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area(agents) Codex, Claude Code, agent wrappers, prompts, or agent tooling. area(home-manager) Home Manager modules, activation, or user-environment config. priority(p3) Normal priority. type(enhancement) Net-new capability or intentional improvement.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant