| name | add-application-or-service |
| description | Add, install, configure, or enable an application or long-running service in this NixOS, nix-darwin, and Home Manager flake while preserving its Registry architecture and quality bar. Use for new GUI or CLI applications, packages, daemons, background services, application-service pairs, cross-platform installations, profile adoption, or substantial extensions to an existing application or service unit. |
Add Application or Service
Add the smallest complete Registry unit change that has a clear owner, an
explicit dependency path, and evidence that every affected host class
evaluates. Treat AGENTS.md as the authoritative repository contract; never
replace it with generic Nix conventions.
Follow the workflow
1. Establish the baseline
- Read
AGENTS.md completely before editing.
- Run
git status --short. Preserve all pre-existing user changes and identify
which later diffs belong to this task.
- Translate the request into observable outcomes: package or program, desired
configuration, supported host classes, required daemon or permissions, and
the profile or user intent that should select it.
- Inspect the nearest existing units, relevant profiles,
hosts/default.nix,
and Registry implementation. Prefer repository evidence over memory.
- Verify current package names, module options, external module exports, and
Homebrew cask names from the locked inputs or authoritative upstream
documentation. Do not guess an option path.
- Read references/review-checklist.md before
choosing files or dependencies.
2. Choose ownership before code
Classify each concern independently:
- Put the user-facing program and its settings in
modules/applications/<name>/.
- Put a daemon, long-running process, firewall rule, permission, or user/group
membership in
modules/services/<name>/.
- Split an application and independently meaningful daemon into two units.
Let the application include the service only when the service is a technical
requirement of that application.
- Put adoption of otherwise independent units in the narrowest coherent
modules/profiles/ composition.
- Use another documented owner when the request is actually a system,
hardware, user, overlay, or host concern. Do not force it into an application
or service directory merely because this skill was invoked.
Choose only the reserved fragments that contain real configuration. Use
common.nix, nixos.nix, and darwin.nix for system-side configuration; use
home.nix or home/{common,nixos,darwin}.nix for Home Manager. Use meta.nix
only for description, fully qualified includes, and external module imports.
Before editing, formulate a short implementation contract containing:
- the unit ID and owner;
- each file to create or change and why;
- technical dependencies versus profile-level choices;
- supported and affected host classes;
- the evaluations or builds that will prove the change.
Rework the design if an ordinary addition appears to require Registry changes,
new global specialArgs, _module.args, direct host selection, or an overlay.
Use those mechanisms only with concrete evidence that the documented extension
points cannot express the requirement.
3. Implement the minimum complete change
- Return configuration directly from every reserved fragment. Do not add
top-level
imports, options, or config, and do not reproduce Registry
mkEnableOption, cfg, or mkIf boilerplate.
- Put upstream NixOS, nix-darwin, or Home Manager modules in
meta.imports.<class>. Import ordinary helper files explicitly from the
fragment that uses them.
- Declare unit-to-unit technical dependencies only through fully qualified
meta.includes. Never enable another unit by assigning its
my.<path>.enable option inside a fragment.
- Add an independent application or service to an existing coherent profile,
or create a justified profile when no existing one expresses the user
intent. Do not use
hosts/default.nix application or unit escape hatches for
normal composition.
- Keep cross-platform purpose shared and installation differences in the
owning unit. Do not create thin
*-linux profiles.
- Use existing module arguments and standard options. Do not inject a
dependency through global arguments, Registry internals, import ordering, or
lib.mkForce. Use explicit module priorities only when a real ownership
boundary requires them and make that reason visible in the code or handoff.
- Avoid speculative abstraction. Create a helper only when it separates
meaningful configuration or prevents real duplication. Do not add empty
fragments, compatibility aliases, unused options, redundant comments, or
copied boilerplate.
- Update
modules/profiles/README.md, AGENTS.md, profile selections, or
other contract documentation whenever the change makes an existing
statement stale. Do not edit them performatively when their meaning remains
accurate.
4. Prove the change
Run the validation matrix in
references/review-checklist.md. At minimum:
- Format the task-owned files with the repository formatter and run
git diff --check.
- Inspect the complete task diff for accidental files, duplication, leaked
secrets, forced values, direct enable assignments, and unrelated rewrites.
- Run
nix flake check.
- Run
pre-commit run --all-files.
- Evaluate every affected real host without switching it. For a
cross-platform unit or profile, evaluate both NixOS and nix-darwin even if
only one class changed. Build an affected configuration with
--no-link
when the current platform can build it.
- Verify selection as well as syntax: confirm that the expected package,
program, service, group, cask, or external module appears in the resulting
configuration.
If a command is unavailable, blocked by the environment, or fails for a
pre-existing reason, diagnose it and report the exact gap. Never silently skip
a required check or weaken the implementation to make a check pass.
5. Audit before completion
Reject the change until all of the following are true:
- Every line has one clear owner and is required by the requested behavior.
- Every dependency is either technical and declared in
meta.includes, or a
user choice owned by a profile.
- The unit is reachable from the intended profile or has an explicit reason to
remain independently selectable.
- No host, Registry, flake root, global argument, or overlay was changed as a
shortcut.
- Reserved fragments, metadata, and profile documentation satisfy the current
repository contract.
- Validation covers every affected host class and all failures are resolved or
explicitly reported.
Conclude with the owner and selection rationale, affected hosts or profiles,
validation commands and results, and any manual activation or runtime check
that remains. Do not claim runtime behavior that was only evaluated.