refactor(claude): delegate programs.claude.* to nix-claude-code#851
Merged
JacobPEvans-personal merged 3 commits intoMay 30, 2026
Merged
Conversation
What changed
- Add nix-claude-code as a flake input with nixpkgs/home-manager/
ai-assistant-instructions/claude-code-plugins follows overrides.
- Drop 20 marketplace flake inputs (anthropic-agent-skills,
bills-claude-skills, bitwarden-marketplace, browser-use-skills,
cc-dev-tools, cc-marketplace, claude-code-plugins-plus,
claude-code-workflows, claude-plugins-official, claude-skills,
jacobpevans-cc-plugins, lunar-claude, obsidian-skills, openai-codex,
axton-obsidian-visual-skills, superpowers-marketplace,
visual-explainer-marketplace, wakatime, huggingface-skills,
vct-cribl-pack-validator-skills) and claude-cookbooks. All are now
transitive inputs through nix-claude-code; surface what nix-ai still
needs via nix-claude-code.inputs in flake/home-manager-modules.nix.
- Delete the migrated Claude code from nix-ai:
- modules/claude/{options-*.nix, settings.nix, plugins.nix,
components.nix, registry.nix, orphan-cleanup.nix,
marketplace-overrides.nix, default.nix, README.md}
- modules/claude/{bws_helper.py, get-api-key.py, bws-env.example,
fabric-curated-patterns.json, hooks/, scripts/, statusline/}
- modules/claude/plugins/{marketplaces.nix} (tier files
01-official..05-specialty stay; default.nix rewritten to a
smaller tier aggregator)
- modules/{claude-plugins.nix, claude-latest.nix}
- modules/permissions/claude-permissions-{allow,ask,deny}.nix
- lib/{claude-settings.nix, claude-registry.nix}
- Rewrite modules/claude-config.nix as a pure-values module (model,
marketplaces, hooks, settings.*). Marketplaces use nix-claude-code's
marketplaceCatalog + marketplaceOverrides; settings.permissions still
flow through nix-ai's modules/common formatter engine so Codex/Gemini
share the source of truth.
- Add modules/claude/automode-environment.nix (homelab trust prose for
Claude's auto-mode classifier, sourced from userConfig.user.fullName).
- Update flake/home-manager-modules.nix to import
nix-claude-code.homeModules.claude alongside ../modules/default.nix
for the `default` module and ../modules/claude-config.nix for the
standalone `claude` module. Module imports run before _module.args
are wired, so the import goes at this layer (not inside default.nix)
to avoid infinite recursion.
- Rewrite lib/checks/claude.nix to drop tests that referenced deleted
lib/claude-settings.nix; structural settings.json validation is
covered by nix-claude-code's CI. Trim fabric-marketplace-build from
lib/checks/fabric.nix (now lives in nix-claude-code).
- Rebuild lib.ci.claudeSettingsJson from nix-claude-code.lib helpers
+ nix-ai's pluginTiers + permission formatters so downstream
consumers (nix-darwin's _claude-settings.yml CI gate) see the same
byte output as pre-PR3.
Why
- Separation of concerns: nix-claude-code is the canonical owner of
programs.claude.* schema, marketplace catalog, synthetic marketplace
derivations, settings.json renderer, and hooks/MCP/statusline wiring.
nix-ai keeps the cross-tool surface (Codex, Gemini, Copilot, MCP,
MLX, Fabric, plugin enablement tiers, auto-mode trust prose).
- This is Checkpoint 2/4 of the migration plan in
nix-claude-code/docs/migration-from-nix-ai.md, executed without the
intermediate useExternalModule toggle since PR2 already landed every
option, hook, and CI shim nix-ai needs.
Byte-equivalence check
- `diff <(nix eval --raw '..main#lib.ci.claudeSettingsJson' | jq -S)
<(nix eval --raw '.#lib.ci.claudeSettingsJson' | jq -S)`
→ empty. settings.json output is byte-identical to pre-PR3.
CI failures
- agent-skills-home-files, fabric-version-sync, gemini-policy-engine
are pre-existing baseline failures (verified by stashing this PR's
changes and re-running flake check on main). Not caused by PR3.
- All claude-specific checks pass (module-eval, options-regression,
defaults-regression).
Refs: dryvist/nix-claude-code#26, #838, dryvist/nix-darwin#1141
CI Auto-Fix Attempt 1/2Claude is analyzing the CI failure and attempting a fix... |
Resolves 4 statix warnings and 4 deadnix unused-binding warnings the CI flake-check caught after PR3 was opened. statix (flake.nix): - Consolidate repeated `inputs.*.follows` into nested form - Use `inherit (nixpkgs) lib` over `lib = nixpkgs.lib` - Drop redundant parentheses around `ncc.claudeRegistry.toClaudeMarketplaceFormat` - Convert `enabledPlugins = pluginTiers.enabledPlugins` to `inherit` deadnix: - flake.nix: drop unused `claude-code-plugins` from outputs destructure (it's still imported via `inputs.claude-code-plugins.follows`) - flake/home-manager-modules.nix: drop unused `claude-code-plugins`, `fabric-src` args and the unused `claude-cookbooks` let binding - lib/checks.nix + lib/checks/fabric.nix: drop unused `fabric-src` arg No behavior change. All four checks now pass on CI parity flags (`deadnix -L --fail .`, `statix check .`, `nixfmt-tree --fail-on-change`).
6 tasks
CI Auto-Fix Attempt 2/2Claude is analyzing the CI failure and attempting a fix... |
Local statix 0-unstable-2026-05-14 missed this; CI's statix 0.5.8 flags it as "Assignment instead of inherit from". Assisted-by: Claude <noreply@anthropic.com>
JacobPEvans-personal
added a commit
to dryvist/nix-darwin
that referenced
this pull request
May 30, 2026
nix-ai PR #851 (refactor/delegate-claude-to-nix-claude-code) merged at 20fbd459106a. Bumping the lock to that SHA picks up the delegation so nix-darwin now consumes programs.claude.* via nix-claude-code through nix-ai's `imports`. Resolves the prior `inputs.nix-claude-code.follows` warning on non-existent input — PR3 added the input to nix-ai. Refs: dryvist/nix-ai#851 Assisted-by: Claude <noreply@anthropic.com>
JacobPEvans-personal
added a commit
to dryvist/nix-darwin
that referenced
this pull request
May 30, 2026
Three corrections to the migration's adoption shape, from review feedback: 1. **Drop nix-claude-code top-level input.** nix-darwin should not pull AI flakes directly — nix-ai is the only AI flake nix-darwin imports. nix-claude-code now flows transitively via nix-ai's input chain (dryvist/nix-ai#851 made nix-ai consume nix-claude-code), so this was strictly a leakage of Claude config concerns into nix-darwin's top-level. Removes the unhelpful "marketplace edge-pins cascade" comment too — that was the wrong design. 2. **Renovate: use dryvist as canonical org.** Switch `local>JacobPEvans-personal/.github:renovate-presets` → `local>dryvist/.github` (dryvist/.github/renovate.json extends the JacobPEvans preset chain via redirect; canonical owner is dryvist). 3. **Renovate: split internal-flakes off external groups.** dryvist and JacobPEvans-personal flakes merge immediately — never wait for release age on first-party repos. Critical-infrastructure group keeps its 2-day delay for nixpkgs-25.11-darwin Hydra cache lag; ai-tools-external keeps daily updates for anthropics/obra. New internal-flakes rule sits LAST so its minimumReleaseAge=0 + automerge=true override the prior groups for dryvist/**, JacobPEvans/**, JacobPEvans-personal/** matches. Also drops the Claude config block (playwright disable + 10 MCP server disables + splunk MCP definition) from hosts/macbook-m4/home.nix. These moved to nix-ai/modules/claude-config.nix in dryvist/nix-ai#853 — Claude config doesn't belong in nix-darwin. home.nix shrinks 12406 → 10886 bytes, below the 12KB file-size CI limit. nix-ai input bumped to 110a4a6 (PR #853 merge SHA) so the new MCP + playwright defaults take effect. Refs: dryvist/nix-ai#853 Assisted-by: Claude <noreply@anthropic.com>
JacobPEvans-personal
added a commit
to dryvist/nix-darwin
that referenced
this pull request
May 30, 2026
* feat(claude): adopt nix-claude-code module
Add dryvist/nix-claude-code as a direct flake input and route
nix-ai's nix-claude-code instance through it via `follows`, so a
single Renovate PR cascades through both consumers.
Changes:
- flake.nix: add nix-claude-code input with follows for nixpkgs,
home-manager, ai-assistant-instructions, claude-code-plugins,
jacobpevans-cc-plugins; channel nix-ai.inputs.nix-claude-code
through it
- flake.lock: pin nix-claude-code at PR2's merge SHA
(5276fb566c8cf8078f808d8dbd5923bcd0e00c1a)
- lib/user-config.nix: drop unused `ai.claudeSchemaUrl` (the schema
URL is now embedded in nix-claude-code's lib/to-settings-json.nix)
- renovate.json5: add dryvist/nix-claude-code to the ai-tools group
with minimumReleaseAge=1 day so nix-ai leads, nix-darwin trails
Deferred to follow-up:
- The 10-server `mcpServers = {...}` block + splunk config in
`hosts/macbook-m4/home.nix:62-95` is user-host opinion (which MCP
servers this Mac wants disabled). Plan suggested moving it to
nix-ai's MCP catalog, but that's a separate cross-repo change and
the existing block continues to work through nix-claude-code's
`mkRenamedOptionModule` shims.
Verified end-to-end: `darwin-rebuild build --flake .#jevans-mbp
--override-input nix-ai <PR3 branch>` succeeds with this flake.nix
+ PR3 merged content. Once PR3 merges, this branch's flake.lock
will also need a nix-ai bump (manual step before merge).
Refs: dryvist/nix-claude-code#26, dryvist/nix-ai#838, dryvist/nix-ai#851
Assisted-by: Claude <noreply@anthropic.com>
* chore(flake): bump nix-ai to PR3 merge
nix-ai PR #851 (refactor/delegate-claude-to-nix-claude-code) merged at
20fbd459106a. Bumping the lock to that SHA picks up the delegation so
nix-darwin now consumes programs.claude.* via nix-claude-code through
nix-ai's `imports`.
Resolves the prior `inputs.nix-claude-code.follows` warning on
non-existent input — PR3 added the input to nix-ai.
Refs: dryvist/nix-ai#851
Assisted-by: Claude <noreply@anthropic.com>
* fix(user-config): restore ai.claudeSchemaUrl
nix-ai/modules/default.nix:106 still references userConfig.ai.claudeSchemaUrl
in its validateClaudeSettings activation hook. The plan called for deleting
this on both sides, but PR3 didn't drop the nix-ai consumer — so deleting
just the nix-darwin definition breaks CI's Nix Build with "attribute 'ai'
missing".
Restoring the attribute. Delete in a follow-up after nix-ai stops
consuming it (move to inline constant or read from nix-claude-code.lib).
Assisted-by: Claude <noreply@anthropic.com>
* chore(deps): align flake.nix + renovate owners with current GitHub state
Per the JacobPEvans → dryvist org migration, four nix-darwin flake
inputs and their renovate matchPackageNames now use the canonical
dryvist owner. The previous JacobPEvans/* URLs worked via GitHub's
repo-rename redirect, but the literal owner string is what Renovate
matches — keeping flake and renovate in lockstep avoids mismatch.
Changes:
- flake.nix: `github:JacobPEvans/{ai-assistant-instructions,
claude-code-plugins,nix-ai,nix-home}` → `github:dryvist/...`
- renovate.json5: matchPackageNames updated to match
- renovate.json5: extends `local>JacobPEvans/.github:renovate-presets`
→ `local>JacobPEvans-personal/.github:renovate-presets`
(the .github repo stayed with the renamed personal account, not the
dryvist org; verified `gh api repos/dryvist/.github/contents/renovate-presets.json` returns 404)
- renovate.json5: `@JacobPEvans` assignees/reviewers
→ `@JacobPEvans-personal` (bare JacobPEvans login is now 404; mentions
don't follow GitHub's repo-rename redirect)
- flake.lock: re-resolved against dryvist URLs; nix-ai/nix-home SHAs
unchanged (same commit, different owner), ai-assistant-instructions
and claude-code-plugins picked up fresher SHAs
Assisted-by: Claude <noreply@anthropic.com>
* feat(user-config): drop ai.claudeSchemaUrl (single source in nix-claude-code)
The schemastore URL is a hard-coded constant that will never change;
the canonical home is dryvist/nix-claude-code's lib/to-settings-json.nix
where it's embedded as the generated settings.json's "$schema" field.
nix-ai stopped consuming `userConfig.ai.claudeSchemaUrl` in
dryvist/nix-ai#852 (merged), so deleting this
nix-darwin definition is now safe — the validateClaudeSettings
activation hook in nix-ai inlines the same constant.
Also bumps nix-ai input to the PR #852 merge SHA so the eval finds the
inlined URL constant.
Refs: dryvist/nix-ai#852
Assisted-by: Claude <noreply@anthropic.com>
* refactor(flake): keep nix-darwin AI-free; consolidate renovate policy
Three corrections to the migration's adoption shape, from review feedback:
1. **Drop nix-claude-code top-level input.** nix-darwin should not pull
AI flakes directly — nix-ai is the only AI flake nix-darwin imports.
nix-claude-code now flows transitively via nix-ai's input chain
(dryvist/nix-ai#851 made nix-ai consume nix-claude-code), so this
was strictly a leakage of Claude config concerns into nix-darwin's
top-level. Removes the unhelpful "marketplace edge-pins cascade"
comment too — that was the wrong design.
2. **Renovate: use dryvist as canonical org.** Switch
`local>JacobPEvans-personal/.github:renovate-presets` →
`local>dryvist/.github` (dryvist/.github/renovate.json extends the
JacobPEvans preset chain via redirect; canonical owner is dryvist).
3. **Renovate: split internal-flakes off external groups.** dryvist
and JacobPEvans-personal flakes merge immediately — never wait for
release age on first-party repos. Critical-infrastructure group
keeps its 2-day delay for nixpkgs-25.11-darwin Hydra cache lag;
ai-tools-external keeps daily updates for anthropics/obra. New
internal-flakes rule sits LAST so its minimumReleaseAge=0 +
automerge=true override the prior groups for dryvist/**,
JacobPEvans/**, JacobPEvans-personal/** matches.
Also drops the Claude config block (playwright disable + 10 MCP
server disables + splunk MCP definition) from
hosts/macbook-m4/home.nix. These moved to nix-ai/modules/claude-config.nix
in dryvist/nix-ai#853 — Claude config doesn't belong in nix-darwin.
home.nix shrinks 12406 → 10886 bytes, below the 12KB file-size CI limit.
nix-ai input bumped to 110a4a6 (PR #853 merge SHA) so the new MCP +
playwright defaults take effect.
Refs: dryvist/nix-ai#853
Assisted-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR3 of the nix-ai → nix-claude-code migration (Checkpoint 2/4 per
docs/migration-from-nix-ai.md).nix-ai now consumes the Claude module from
dryvist/nix-claude-codeinstead ofdefining its own.
nix-claude-codeas a flake input withnixpkgs/home-manager/ai-assistant-instructions/claude-code-pluginsfollows overrides.anthropic-agent-skills,bills-claude-skills,bitwarden-marketplace,browser-use-skills,cc-dev-tools,cc-marketplace,claude-code-plugins-plus,claude-code-workflows,claude-plugins-official,claude-skills,jacobpevans-cc-plugins,lunar-claude,obsidian-skills,openai-codex,axton-obsidian-visual-skills,superpowers-marketplace,visual-explainer-marketplace,wakatime,huggingface-skills,vct-cribl-pack-validator-skills) plusclaude-cookbooks. They're now transitiveinputs through
nix-claude-code; surfaced to non-Claude consumers vianix-claude-code.inputsinflake/home-manager-modules.nix.karpathy-skillsstays in nix-ai (newly added to main while PR3 was in flight; not yet in
nix-claude-code's catalog).
CI-only generators:
modules/claude/{options-*.nix, settings.nix, plugins.nix, components.nix, registry.nix, orphan-cleanup.nix, marketplace-overrides.nix, default.nix, README.md, bws_helper.py, get-api-key.py, bws-env.example, fabric-curated-patterns.json, hooks/, scripts/, statusline/}modules/{claude-plugins.nix, claude-latest.nix}modules/claude/plugins/marketplaces.nix(tier files01-official.nix..05-specialty.nixstay;default.nixrewritten to asmaller tier aggregator)
modules/permissions/claude-permissions-{allow,ask,deny}.nixlib/{claude-settings.nix, claude-registry.nix}modules/claude-config.nixas a pure-values module (model,marketplaces, hooks,
settings.*). Marketplaces come fromnix-claude-code.lib.{marketplaceCatalog, marketplaceOverrides};settings.permissionsstill flows through nix-ai'smodules/commonformatter engine so Codex/Gemini share the source of truth.
modules/claude/automode-environment.nix(homelab-trust prose forClaude's auto-mode classifier, sourced from
userConfig.user.fullName).flake/home-manager-modules.nixto importnix-claude-code.homeModules.claudealongside../modules/default.nixfor the
defaultmodule and../modules/claude-config.nixfor thestandalone
claudemodule. The import lives at this layer (not insidedefault.nix) so the import list resolves without depending on_module.args.nix-claude-code— module imports run before args arewired, which would otherwise cause infinite recursion.
lib/checks/claude.nixto drop tests that referenced deletedlib/claude-settings.nix; structural settings.json validation is nowcovered by nix-claude-code's own CI. Trim
fabric-marketplace-buildfrom
lib/checks/fabric.nix(now lives in nix-claude-code).lib.ci.claudeSettingsJsonfromnix-claude-code.libhelpersconsumers (nix-darwin's
_claude-settings.ymlCI gate) see byte-identical output.
Why
Separation of concerns:
nix-claude-codeis the canonical owner ofprograms.claude.*schema, the marketplace catalog, synthetic marketplacederivations, the settings.json renderer, and hooks/MCP/statusline wiring.
nix-ai keeps the cross-tool surface (Codex, Gemini, Copilot, MCP, MLX,
Fabric, plugin enablement tiers, auto-mode trust prose).
This is Checkpoint 2/4 of the migration plan, executed without the
intermediate
useExternalModuletoggle because PR2(dryvist/nix-claude-code#26)
already landed every option, hook, lib helper, and CI shim nix-ai needs.
Byte-equivalence (the safety contract)
The CI fixture is byte-identical to current
main. Downstream nix-darwin's_claude-settings.ymlworkflow will see the same generatedsettings.json.Test plan
nix flake check --no-build --all-systems --refreshpassesevery Claude-relevant check (
module-eval,options-regression,defaults-regression, etc.).agent-skills-home-files,fabric-version-sync,gemini-policy-engine) are pre-existing onmainand unrelated to PR3 — verified by stashing this PR's changesand re-running
flake check.nix eval --raw .#lib.ci.claudeSettingsJsonproduces byte-identicaloutput to
main.actually build).
darwin-rebuild build --flake ${HOME}/git/public/nix-darwin/mainwith this branch as the nix-ai input to validate end-to-end activation.
Deviations from the original plan
karpathy-skillsas a nix-ai-side flake input. It was added tomain(PR feat(agent-skills): add karpathy-skills + auto-discover all marketplaces #831) while PR3 was in flight and isn't in nix-claude-code'smarketplace catalog yet — promote upstream as a follow-up.
lib.mkRenamedOptionModuleshims inside nix-claude-code's module(
enabledPlugins → plugins.enabled,marketplaces → plugins.marketplaces,statusLine → statusline,hooks.extraHooks → settings.hooks), so nonix-ai-side renames were needed.
hooks.captureSessionOutputandhooks.refreshMarketplacestogglesreplace the explicit
postToolUse/sessionStartscript paths(
last-output.sh/marketplace-refresh.share vendored insidenix-claude-code now).
Refs: dryvist/nix-claude-code#26, #838, dryvist/nix-darwin#1141