Skip to content

feat(home/ai): install the atomic coding agent - #2728

Merged
mergify[bot] merged 2 commits into
mainfrom
fm/vx-atomic-install
Aug 16, 2026
Merged

feat(home/ai): install the atomic coding agent#2728
mergify[bot] merged 2 commits into
mainfrom
fm/vx-atomic-install

Conversation

@cameronraysmith

@cameronraysmith cameronraysmith commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Follow-up to #2727, not a revision of it.

#2727 added the derivation at pkgs/by-name/atomic/, which builds correctly, but nothing in the repo installed it.
Packaging and installing are separate steps here and only the first was done, which is why atomic never appeared in an activation diff.
This is the second step.

What changed

modules/home/ai/atomic/default.nix contributes to the flake.modules.homeManager.ai aggregate.

It follows the tuicr shape rather than the hunk shape: atomic ships no upstream home-manager, nixos, or darwin module, so the module declares options.programs.atomic itself and is self-enabling, with the enable flag defined via lib.mkDefault so a machine or user module can disable it without a definition collision.

The one difference from tuicr is the package accessor.
tuicr's package comes from the llm-agents flake input, so it declares a plain lib.mkOption and explicitly avoids lib.mkPackageOption.
atomic is local to this repository, and pkgs/by-name derivations reach machine and home-manager pkgs through flake.overlays.default, which merges the perSystem packages set into the overlay chain (modules/nixpkgs/compose.nix:31-39, wired into machines by modules/nixpkgs/base-defaults.nix).
lib.mkPackageOption pkgs "atomic" { } therefore resolves the local derivation directly, and the same accessor is already in use for local packages elsewhere in this aggregate (modules/home/ai/firstmate/default.nix).

Scope is install-only.
No configuration surface is declared: the wrapper in pkgs/by-name/atomic/package.nix already supplies the runtime tool lookups and suppresses the update check, and that package's tests.help exercises the finished store path against nothing but a writable $HOME.
pkgs/by-name/atomic/ is unmodified; installing it exposed no defect in the derivation.

Positive evidence that atomic is actually installed

Evaluation success is not the criterion here, since #2727 evaluated fine and installed nothing.
The darwin system closure for this host was built before and after the change and its requisites compared.

Before (the new module untracked, so outside the flake source):

$ nix build --no-link --print-out-paths .#darwinConfigurations.stibnite.system
/nix/store/zvcn2r0c00c9jdpwb4fajy18xv52lv5q-darwin-system-26.11.15abb8c

$ nix-store -q --requisites /nix/store/zvcn2r0c00c9jdpwb4fajy18xv52lv5q-darwin-system-26.11.15abb8c | grep -c .
2805

$ nix-store -q --requisites /nix/store/zvcn2r0c00c9jdpwb4fajy18xv52lv5q-darwin-system-26.11.15abb8c | grep -i -- '-atomic'
$ echo $?
1

After:

$ nix build --no-link --print-out-paths .#darwinConfigurations.stibnite.system
/nix/store/f9hjkfd244sadmbxkh31jrkgf7fdacng-darwin-system-26.11.15abb8c

$ nix-store -q --requisites /nix/store/f9hjkfd244sadmbxkh31jrkgf7fdacng-darwin-system-26.11.15abb8c | grep -c .
2806

$ nix-store -q --requisites /nix/store/f9hjkfd244sadmbxkh31jrkgf7fdacng-darwin-system-26.11.15abb8c | grep -i -- '-atomic'
/nix/store/8p7x1hnzs7h671rpd84gqskphqbd49ar-atomic-0.9.13

Reached through the user environment, not merely present as a transitive input:

$ nix-store -q --requisites /nix/store/f9hjkfd244sadmbxkh31jrkgf7fdacng-darwin-system-26.11.15abb8c | grep home-manager-path
/nix/store/6wmnp04pwcpspi1mfdgxal52pl64snxa-home-manager-path

$ ls -l /nix/store/6wmnp04pwcpspi1mfdgxal52pl64snxa-home-manager-path/bin/atomic
... -> /nix/store/8p7x1hnzs7h671rpd84gqskphqbd49ar-atomic-0.9.13/bin/atomic

Build only. Nothing was activated: no darwin-rebuild switch, no activate.

Checks run and why that selection

The narrowest selection that would still fail if this change were wrong is the set covering a new homeManager.ai aggregate member plus the derivation it pulls in. All on aarch64-darwin, all pass:

$ nix build --no-link -L \
    .#checks.aarch64-darwin.structure-aggregate-eval-failure \
    .#checks.aarch64-darwin.structure-home-configurations \
    .#checks.aarch64-darwin.structure-darwin-configurations \
    .#checks.aarch64-darwin.structure-inventory-class-discovery \
    .#checks.aarch64-darwin.structure-inventory-machines \
    .#checks.aarch64-darwin.structure-nixos-configurations \
    .#checks.aarch64-darwin.package-atomic \
    .#checks.aarch64-darwin.package-atomic-test-help \
    .#checks.aarch64-darwin.home-manager-crs58 \
    .#checks.aarch64-darwin.home-manager-cameron \
    .#checks.aarch64-darwin.home-manager-christophersmith \
    .#checks.aarch64-darwin.home-manager-janettesmith \
    .#checks.aarch64-darwin.home-manager-raquel \
    .#checks.aarch64-darwin.home-manager-tara

The six home-manager-<user> checks are the activationPackage build-realization checks from modules/checks/home.nix; the ai aggregate reaches users only through those, so a broken member fails there.
The structure-* checks from modules/checks/structure/ cover flake shape and aggregate resolution, which is what adding an aggregate member perturbs.
package-atomic and package-atomic-test-help come from modules/checks/packages.nix and cover the derivation this module now depends on.

Deliberately left out: the rest of the suite (devshells, containers, security, nixidy, performance, the other packages), which this change does not touch.

Platforms not verified

x86_64-linux and aarch64-linux are evaluation-verified only.
nix eval .#checks.<system>.home-manager-crs58.drvPath resolves on both, so the module wires up without type or accessor errors there, but neither closure was built: ssh-ng://rosetta-builder refused the connection (the builder VM is not running) and ssh-ng://builder@magnetite could not read its key (/run/secrets/vars/per-machine/stibnite/nix-remote-build/key, root-only) from this session.
Treat the two linux platforms as unbuilt here; CI covers them.

x86_64-darwin is not a concern: this flake's system set is aarch64-darwin, aarch64-linux, x86_64-linux, all three of which pkgs/by-name/atomic supports, so its platform == null branch is never taken and pkgs.atomic is never null in any evaluated configuration.

What determines the installed config on stibnite

Asked in review; answered by evaluation rather than by reading the module.

just activate --ask on this host resolves to just activate-darwin stibnite --ask (justfile:75-90), which runs nix run .#darwin -- stibnite . --ask, which execs nh darwin switch . -H stibnite --accept-flake-config --ask (modules/darwin/app.nix:80). That builds .#darwinConfigurations.stibnite.system — the exact attribute built above — and --ask prompts before applying, so the diff it shows is the diff between your current system and that store path.

The chain that puts atomic in it:

$ nix eval --json .#darwinConfigurations.stibnite.config.home-manager.users \
    --apply 'us: builtins.mapAttrs (n: u: { atomic = u.programs.atomic.enable; pkg = u.programs.atomic.package.name or null; }) us'
{"crs58":{"atomic":true,"pkg":"atomic-0.9.13"}}

crs58 is the only home-manager user on stibnite, and its aggregates list includes ai (modules/home/users/crs58/meta.nix:16-26), so this module is imported into that home configuration. Nothing else in the repo defines programs.atomic, so the only definition of enable is this module's lib.mkDefault true at priority 1000; it evaluates to true, and a machine or user module can still override it at normal priority without a collision. package resolves through lib.mkPackageOption pkgs "atomic" to atomic-0.9.13, the local pkgs/by-name/atomic derivation reached via flake.overlays.default.

The observable end of that chain is home-manager-path/bin/atomic, shown above as a requisite of the built system. On --ask it appears as an addition in the nvd diff, which is what did not happen for #2727.

One precision worth stating: the darwin-system store path moves with the flake source, so the second review round's comment-only edit changed it from xm229fpr1s31b9gqn41xb2b9v5vz88vn to f9hjkfd244sadmbxkh31jrkgf7fdacng. The requisite count (2806) and the atomic store path (8p7x1hnzs7h671rpd84gqskphqbd49ar-atomic-0.9.13) are identical across both.

Review round 1

  • Header comment editorialized. Trimmed 21 lines to 9 in 7bd1631. Three of the four paragraphs restated the code — that the module declares its own options, that it is self-enabling, that no configuration surface exists — or narrated the choice by comparing to sibling modules. What remains is the accessor rationale, which a reader cannot recover from this file given that every llm-agents-sourced sibling uses an input accessor and tuicr's own header warns against mkPackageOption.
  • Config-determination question answered in the section above.

Both were re-verified after the trim rather than assumed: the same 14 checks pass and the rebuilt system still carries atomic.

Draft on purpose

Opened as a draft so Mergify's queue does not pick it up before review. Mark ready when you have reviewed it.

pkgs/by-name/atomic packages the derivation but nothing installed it, so
atomic never reached any user environment. Add a homeManager.ai aggregate
member following the tuicr shape: atomic ships no upstream home-manager
module, so the module declares options.programs.atomic itself and is
self-enabling with lib.mkDefault.

The package is local to this repository rather than sourced from a flake
input, and pkgs/by-name derivations reach machine and home-manager pkgs
through flake.overlays.default (modules/nixpkgs/compose.nix), so
lib.mkPackageOption resolves it and no input accessor is needed. No
configuration surface is declared; the package wrapper already supplies
the runtime tool lookups and suppresses the update check.

Verification selected as the checks that cover a new ai aggregate member
plus the derivation it pulls in, all on aarch64-darwin: the six
home-manager-<user> activationPackage checks (the ai aggregate reaches
users through these, and they are the only surface a new member changes),
the five structure-* checks over flake shape and aggregate resolution,
and package-atomic with package-atomic-test-help. All pass. The wider
suite was left out as untouched by this change.

Positive install evidence, not merely evaluation:

  nix build --no-link --print-out-paths .#darwinConfigurations.stibnite.system
  nix-store -q --requisites <result> | grep -- -atomic

Before: 2805 requisites, no match. After: 2806 requisites, matching
/nix/store/8p7x1hnzs7h671rpd84gqskphqbd49ar-atomic-0.9.13, reached via
home-manager-path/bin/atomic.

x86_64-linux and aarch64-linux are evaluation-verified only; neither
remote builder was reachable from this session.
Review feedback: the header editorialized. Three of its four paragraphs
restated the code (that the module declares its own options is visible in
the options block; that it is self-enabling is visible in
`enable = lib.mkDefault true`; that no configuration surface exists is
visible in its absence) or narrated the decision process by comparing the
module to its siblings.

What survives is the one thing a reader cannot recover from this file: why
lib.mkPackageOption resolves a pkgs/by-name derivation, since every other
llm-agents-sourced member of this aggregate uses an input accessor and
tuicr's header explicitly warns against mkPackageOption.

Comment-only change to the module. Re-verified rather than assumed, because
the flake source is itself an input and the darwin-system store path moves
with it: the same 14 aarch64-darwin checks pass, and the rebuilt system
/nix/store/f9hjkfd244sadmbxkh31jrkgf7fdacng-darwin-system-26.11.15abb8c
still carries 2806 requisites including atomic-0.9.13.
@cameronraysmith cameronraysmith added the author-approved Owner self-approval marker; triggers Mergify auto-approve label Aug 16, 2026
@cameronraysmith
cameronraysmith marked this pull request as ready for review August 16, 2026 23:17
@mergify mergify Bot added the queued label Aug 16, 2026
@mergify

mergify Bot commented Aug 16, 2026

Copy link
Copy Markdown

Merge Queue Status

  • Entered queue2026-08-16 23:17 UTC · Rule: default · triggered by rule queue human PRs
  • Checks skipped · PR is already up-to-date
  • Merged2026-08-16 23:18 UTC · at 7bd1631b2ae4d162c09885809f10ce2acb1e5e3f · fast-forward

This pull request spent 27 seconds in the queue, including 5 seconds running CI.

Required conditions to merge
  • any of [🛡 GitHub repository ruleset rule buildbot]:
    • check-success = buildbot/nix-build
    • check-neutral = buildbot/nix-build
    • check-skipped = buildbot/nix-build

@mergify
mergify Bot merged commit 7bd1631 into main Aug 16, 2026
7 checks passed
@mergify
mergify Bot deleted the fm/vx-atomic-install branch August 16, 2026 23:18
@mergify mergify Bot removed the queued label Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author-approved Owner self-approval marker; triggers Mergify auto-approve

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant