Concerns (6 files): - coding-style.md (163 lines): patterns, anti-patterns, error handling, SOLID - naming.md (105 lines): naming conventions table per language - documentation.md (149 lines): docstrings, WHY vs WHAT, README standards - testing.md (134 lines): AAA pattern, mocking philosophy, TDD - git-workflow.md (118 lines): conventional commits, branch naming, PR format - project-structure.md (82 lines): directory layout, entry points, config placement Languages (4 files): - python.md (224 lines): uv, ruff, pyright, pytest, pydantic, idioms, anti-patterns - typescript.md (150 lines): strict mode, discriminated unions, satisfies, as const - nix.md (129 lines): flake structure, module patterns, alejandra, anti-patterns - shell.md (100 lines): set -euo pipefail, shellcheck, quoting, POSIX Frameworks (1 file): - n8n.md (42 lines): workflow design, node patterns, Error Trigger, security Context budget: 975 lines (concerns + python) < 1500 limit Refs: T6-T16 of rules-system plan
130 lines
2.5 KiB
Markdown
130 lines
2.5 KiB
Markdown
# Nix Code Conventions
|
|
|
|
## Formatting
|
|
|
|
- Use `alejandra` for formatting
|
|
- camelCase for variables, `PascalCase` for types
|
|
- 2 space indentation (alejandra default)
|
|
- No trailing whitespace
|
|
|
|
## Flake Structure
|
|
|
|
```nix
|
|
{
|
|
description = "Description here";
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
flake-utils.url = "github:numtide/flake-utils";
|
|
};
|
|
outputs = { self, nixpkgs, flake-utils, ... }:
|
|
flake-utils.lib.eachDefaultSystem (system:
|
|
let
|
|
pkgs = nixpkgs.legacyPackages.${system};
|
|
in {
|
|
packages.default = pkgs.hello;
|
|
devShells.default = pkgs.mkShell {
|
|
buildInputs = [ pkgs.hello ];
|
|
};
|
|
}
|
|
);
|
|
}
|
|
```
|
|
|
|
## Module Patterns
|
|
|
|
Standard module function signature:
|
|
|
|
```nix
|
|
{ config, lib, pkgs, ... }:
|
|
{
|
|
options.myService.enable = lib.mkEnableOption "my service";
|
|
config = lib.mkIf config.myService.enable {
|
|
services.myService.enable = true;
|
|
};
|
|
}
|
|
```
|
|
|
|
## Conditionals and Merging
|
|
|
|
- Use `mkIf` for conditional config
|
|
- Use `mkMerge` to combine multiple config sets
|
|
- Use `mkOptionDefault` for defaults that can be overridden
|
|
|
|
```nix
|
|
config = lib.mkMerge [
|
|
(lib.mkIf cfg.enable { ... })
|
|
(lib.mkIf cfg.extraConfig { ... })
|
|
];
|
|
```
|
|
|
|
## Anti-Patterns (AVOID)
|
|
|
|
### `with pkgs;`
|
|
Bad: Pollutes namespace, hard to trace origins
|
|
```nix
|
|
{ pkgs, ... }:
|
|
{
|
|
packages = with pkgs; [ vim git ];
|
|
}
|
|
```
|
|
|
|
Good: Explicit references
|
|
```nix
|
|
{ pkgs, ... }:
|
|
{
|
|
packages = [ pkgs.vim pkgs.git ];
|
|
}
|
|
```
|
|
|
|
### `builtins.fetchTarball`
|
|
Use flake inputs instead. `fetchTarball` is non-reproducible.
|
|
|
|
### Impure operations
|
|
Avoid `import <nixpkgs>` in flakes. Always use inputs.
|
|
|
|
### `builtins.getAttr` / `builtins.hasAttr`
|
|
Use `lib.attrByPath` or `lib.optionalAttrs` instead.
|
|
|
|
## Home Manager Patterns
|
|
|
|
```nix
|
|
{ config, pkgs, lib, ... }:
|
|
{
|
|
home.packages = with pkgs; [ ripgrep fd ];
|
|
programs.zsh.enable = true;
|
|
xdg.configFile."myapp/config".text = "...";
|
|
}
|
|
```
|
|
|
|
## Overlays
|
|
|
|
```nix
|
|
{ config, lib, pkgs, ... }:
|
|
let
|
|
myOverlay = final: prev: {
|
|
myPackage = prev.myPackage.overrideAttrs (old: { ... });
|
|
};
|
|
in
|
|
{
|
|
nixpkgs.overlays = [ myOverlay ];
|
|
}
|
|
```
|
|
|
|
## Imports and References
|
|
|
|
- Use flake inputs for dependencies
|
|
- `lib` is always available in modules
|
|
- Reference packages via `pkgs.packageName`
|
|
- Use `callPackage` for complex package definitions
|
|
|
|
## File Organization
|
|
|
|
```
|
|
flake.nix # Entry point
|
|
modules/ # NixOS modules
|
|
services/
|
|
my-service.nix
|
|
overlays/ # Package overrides
|
|
default.nix
|
|
```
|