# Home Profile Restructuring Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Restructure nixos-config/home/ from host-based to profile-based organization with clear separation between base, coding, profiles, desktop, and server layers. **Architecture:** Three-layer model: Base (always loaded) → Coding (profile-independent) → Profiles/Context (freely combinable with constraints). Desktop and Server contexts are mutually exclusive. **Tech Stack:** NixOS, Home Manager, Nix flakes --- ## File Structure ``` home/ ├── base/ # IMMER geladen │ ├── default.nix │ ├── shell/ │ │ ├── default.nix │ │ ├── nushell.nix # PRIMARY Shell │ │ └── starship.nix │ ├── cli-tools/ │ │ ├── default.nix │ │ ├── fzf.nix │ │ ├── zellij.nix │ │ ├── nitch.nix │ │ └── television.nix │ └── secrets/ │ └── secrets.nix │ ├── coding/ # Profil-unabhängig │ ├── default.nix │ ├── editor/ │ │ ├── default.nix │ │ └── neovim.nix # Basis NeoVim (aus nixpkgs referenziert) │ ├── lsp/ │ │ ├── default.nix │ │ └── servers.nix │ ├── git/ │ │ └── git.nix │ └── agents/ │ └── agents.nix # Agent-System (aus nixpkgs referenziert) │ ├── profiles/ # FREI KOMBINIERBAR │ ├── gaming/ │ │ ├── default.nix │ │ ├── steam.nix │ │ └── gamescope.nix │ │ │ └── media/ │ ├── default.nix │ ├── obs.nix │ ├── ffmpeg.nix │ ├── yt-dlp.nix │ ├── kdenlive.nix │ └── handbrake.nix │ ├── desktop/ # NUR wenn context=desktop │ ├── default.nix │ ├── wm/ │ │ ├── default.nix │ │ ├── hyprland.nix │ │ ├── wayland.nix │ │ └── rofi.nix │ ├── apps/ │ │ ├── default.nix │ │ ├── obsidian.nix │ │ ├── office.nix │ │ ├── webapps.nix │ │ └── crypto.nix │ └── theme/ │ ├── default.nix │ ├── fonts.nix │ ├── theme.nix │ └── wallpapers.nix │ └── server/ └── default.nix ``` **Key Integration Points:** | Component | Source | Notes | |-----------|--------|-------| | NeoVim Config | `inputs.m3ta-nixpkgs.pkgs.neovim-config` | Custom package in nixpkgs | | OpenCode Desktop | `inputs.m3ta-nixpkgs.pkgs.opencode-desktop` | Custom package | | Agent-System | `inputs.m3ta-nixpkgs.homeModules.coding.agents` | OpenCode, Claude Code, Pi | | Zed Editor | `inputs.m3ta-nixpkgs.homeModules.coding.editors` | Desktop-only via Zed Remote | | Editor Module | `inputs.m3ta-nixpkgs.homeModules.coding.editors` | NeoVim (base) + Zed (desktop) | --- ## Phase 1: Create New Structure ### Task 1: Create Directory Structure **Files:** - Create: `home/base/default.nix` - Create: `home/base/shell/default.nix` - Create: `home/base/shell/nushell.nix` - Create: `home/base/shell/starship.nix` - Create: `home/base/cli-tools/default.nix` - Create: `home/base/cli-tools/fzf.nix` - Create: `home/base/cli-tools/zellij.nix` - Create: `home/base/cli-tools/nitch.nix` - Create: `home/base/cli-tools/television.nix` - Create: `home/base/secrets/secrets.nix` - Create: `home/coding/default.nix` - Create: `home/coding/editor/default.nix` - Create: `home/coding/editor/neovim.nix` - Create: `home/coding/lsp/default.nix` - Create: `home/coding/lsp/servers.nix` - Create: `home/coding/git/git.nix` - Create: `home/coding/agents/agents.nix` - Create: `home/profiles/gaming/default.nix` - Create: `home/profiles/gaming/steam.nix` - Create: `home/profiles/gaming/gamescope.nix` - Create: `home/profiles/media/default.nix` - Create: `home/profiles/media/obs.nix` - Create: `home/profiles/media/ffmpeg.nix` - Create: `home/profiles/media/yt-dlp.nix` - Create: `home/profiles/media/kdenlive.nix` - Create: `home/profiles/media/handbrake.nix` - Create: `home/desktop/default.nix` - Create: `home/desktop/wm/default.nix` - Create: `home/desktop/wm/hyprland.nix` - Create: `home/desktop/wm/wayland.nix` - Create: `home/desktop/wm/rofi.nix` - Create: `home/desktop/apps/default.nix` - Create: `home/desktop/apps/obsidian.nix` - Create: `home/desktop/apps/office.nix` - Create: `home/desktop/apps/webapps.nix` - Create: `home/desktop/apps/crypto.nix` - Create: `home/desktop/theme/default.nix` - Create: `home/desktop/theme/fonts.nix` - Create: `home/desktop/theme/theme.nix` - Create: `home/desktop/theme/wallpapers.nix` - Create: `home/server/default.nix` - Modify: `home/default.nix` (Hauptaggregator) - [ ] **Step 1: Create home/base/default.nix** ```nix # home/base/default.nix # Basis-Konfiguration: Shell + CLI-Tools + Secrets # Wird IMMER geladen (kein enable-Flag) { inputs, lib, pkgs, ... }: { imports = [ ./shell ./cli-tools ./secrets ]; } ``` - [ ] **Step 2: Create home/base/shell/default.nix** ```nix # home/base/shell/default.nix { inputs, lib, pkgs, ... }: { imports = [ ./nushell.nix ./starship.nix ]; } ``` - [ ] **Step 3: Create home/base/shell/nushell.nix** Migrated from: `home/features/cli/nushell.nix` ```nix # home/base/shell/nushell.nix # Primary shell - Nushell { lib, pkgs, ... }: { programs.nushell = { enable = true; configFile = ...; }; home.packages = with pkgs; [ nushell ]; } ``` - [ ] **Step 4: Create home/base/shell/starship.nix** Migrated from: `home/features/cli/starship.nix` - [ ] **Step 5: Create home/base/cli-tools/default.nix** ```nix # home/base/cli-tools/default.nix { ... }: { imports = [ ./fzf.nix ./zellij.nix ./nitch.nix ./television.nix ]; } ``` - [ ] **Step 6: Create CLI tool modules** Migrate from `home/features/cli/`: - `fzf.nix` → `home/base/cli-tools/fzf.nix` - `zellij.nix` → `home/base/cli-tools/zellij.nix` - `nitch.nix` → `home/base/cli-tools/nitch.nix` - `television.nix` → `home/base/cli-tools/television.nix` - [ ] **Step 7: Create home/base/secrets/secrets.nix** Migrated from: `home/features/cli/secrets.nix` - [ ] **Step 8: Create home/coding/default.nix** ```nix # home/coding/default.nix # Coding-Konfiguration: Editor + LSP + Git + Agents # Wird geladen wenn coding Profil aktiviert { inputs, lib, pkgs, ... }: { imports = [ ./editor ./lsp ./git ./agents ]; } ``` - [ ] **Step 9: Create home/coding/editor/default.nix** References: `inputs.m3ta-nixpkgs.homeModules.coding.editors` ```nix # home/coding/editor/default.nix { inputs, lib, pkgs, ... }: { # Importiert NeoVim (immer) + Zed (desktop) imports = [ inputs.m3ta-nixpkgs.homeModules.coding.editors ]; # NeoVim Config Package home.packages = [ inputs.m3ta-nixpkgs.packages.${pkgs.system}.neovim-config ]; } ``` - [ ] **Step 10: Create home/coding/lsp/default.nix + servers.nix** Migrate LSP configuration from existing setup - [ ] **Step 11: Create home/coding/git/git.nix** ```nix # home/coding/git/git.nix { lib, pkgs, ... }: { programs.git = { enable = true; # Git configuration }; } ``` - [ ] **Step 12: Create home/coding/agents/agents.nix** References: `inputs.m3ta-nixpkgs.homeModules.coding.agents` ```nix # home/coding/agents/agents.nix { inputs, lib, pkgs, ... }: { imports = [ inputs.m3ta-nixpkgs.homeModules.coding.agents ]; # Agent-Konfiguration coding.agents.opencode = { enable = true; agentsInput = inputs.agents; # modelOverrides... }; } ``` - [ ] **Step 13: Create home/profiles/gaming/default.nix** ```nix # home/profiles/gaming/default.nix # Gaming Profile - frei kombinierbar { lib, pkgs, ... }: { imports = [ ./steam.nix ./gamescope.nix ]; } ``` - [ ] **Step 14: Create gaming profile modules** - `steam.nix` - Steam + Steam Deck Tools - `gamescope.nix` - Gamescope Session - [ ] **Step 15: Create home/profiles/media/default.nix** ```nix # home/profiles/media/default.nix # Media Profile - Content Creation / Streaming { lib, pkgs, ... }: { imports = [ ./obs.nix ./ffmpeg.nix ./yt-dlp.nix ./kdenlive.nix ./handbrake.nix ]; } ``` - [ ] **Step 16: Create media profile modules** Migrate from `home/features/desktop/media.nix`: - `obs.nix` - OBS Studio - `ffmpeg.nix` - FFmpeg + Tools - `yt-dlp.nix` - YouTube Downloader - `kdenlive.nix` - Kdenlive Video Editor - `handbrake.nix` - HandBrake - [ ] **Step 17: Create home/desktop/default.nix** ```nix # home/desktop/default.nix # Desktop-Konfiguration - nur wenn context=desktop { lib, pkgs, ... }: { # Zed Remote: Server-Zugriff via SSH programs.zed-editor = { enable = true; # Remote Connections Config }; imports = [ ./wm ./apps ./theme ]; } ``` - [ ] **Step 18: Create home/desktop/wm modules** Migrate from `home/features/desktop/`: - `hyprland.nix` → `home/desktop/wm/hyprland.nix` - `wayland.nix` → `home/desktop/wm/wayland.nix` - `rofi.nix` → `home/desktop/wm/rofi.nix` - [ ] **Step 19: Create home/desktop/apps modules** Migrate from `home/features/desktop/`: - `obsidian.nix` → `home/desktop/apps/obsidian.nix` - `office.nix` → `home/desktop/apps/office.nix` - `webapps.nix` → `home/desktop/apps/webapps.nix` - `crypto.nix` → `home/desktop/apps/crypto.nix` - [ ] **Step 20: Create home/desktop/theme modules** Migrate from `home/features/desktop/`: - `fonts.nix` → `home/desktop/theme/fonts.nix` - `theme.nix` → `home/desktop/theme/theme.nix` - `wallpapers.nix` → `home/desktop/theme/wallpapers.nix` - [ ] **Step 21: Create home/server/default.nix** ```nix # home/server/default.nix # Server-Konfiguration - nur wenn context=server # Minimal da primär via Zed Remote gearbeitet wird { lib, pkgs, ... }: { # Server-spezifische Konfiguration falls nötig } ``` - [ ] **Step 22: Commit Phase 1** ```bash git add home/ git commit -m "feat(home): create new directory structure - Add base/ with shell, cli-tools, secrets - Add coding/ with editor, lsp, git, agents - Add profiles/ with gaming, media - Add desktop/ with wm, apps, theme - Add server/ minimal config - Reference m3ta-nixpkgs modules where appropriate" ``` --- ## Phase 2: Create Profile System with Constraints ### Task 2: Implement Profile Loader with Mutual Exclusion **Files:** - Create: `home/lib/default.nix` (Profile loading utilities) - Modify: `flake.nix` (Host-spezifische Home-Config) - Modify: `hosts/common/users/home.nix` - [ ] **Step 1: Create home/lib/default.nix** ```nix # home/lib/default.nix # Profile loading utilities { lib }: { # Generiert Home-Manager Konfiguration basierend auf Profilen mkHomeConfig = { profiles ? [], context ? null, # "desktop" | "server" | null }: let inherit (lib) optionalAttrs mkIf; # Profile die immer geladen werden baseModules = [ ./base ]; # Profile die optional geladen werden profileModules = optionalAttrs (builtins.elem "coding" profiles) [ ./coding ]; # Context-spezifische Module contextModules = { desktop = [ ./desktop ]; server = [ ./server ]; }; # Profile-spezifische Module profileSpecific = { gaming = [ ./profiles/gaming ]; media = [ ./profiles/media ]; }; in { imports = baseModules ++ profileModules ++ (contextModules.${context} or []) ++ (builtins.map (p: ./profiles.${p}) (builtins.filter (p: builtins.hasAttr p profileSpecific) profiles)); }; # Assertion: desktop und server schließen sich aus mutualExclusiveContexts = builtins.hasAttr "desktop" && builtins.hasAttr "server"; } ``` - [ ] **Step 2: Update flake.nix for m3-ares (Desktop)** ```nix # hosts/m3-ares/ (Desktop Beispiel) { inputs, lib, pkgs, ... }: { # Home-Manager für m3tam3re auf m3-ares home-manager.users.m3tam3re = { config, ... }: { # NEU: Profile-System m3ta.profiles = [ "coding" "gaming" "media" ]; # Freie Kombination m3ta.context = "desktop"; # Schließt "server" aus # Alternativ: Legacy-Kompatibilität # imports = [ ./home ]; }; } ``` - [ ] **Step 3: Update flake.nix for m3-atlas (Server)** ```nix # hosts/m3-atlas/ (Server Beispiel) { inputs, lib, pkgs, ... }: { home-manager.users.m3tam3re = { config, ... }: { m3ta.profiles = [ "coding" ]; # Nur Coding auf Server m3ta.context = "server"; # Schließt "desktop" aus }; } ``` - [ ] **Step 4: Add assertions in flake.nix** ```nix # Validation: Context constraints assertion = hostConfig.m3ta.context != "desktop" || hostConfig.m3ta.context != "server" || (hostConfig.m3ta.context == null); # Mutually exclusive ``` - [ ] **Step 5: Commit Phase 2** ```bash git add flake.nix hosts/ git commit -m "feat: implement profile system with constraints - Add home/lib for profile loading utilities - Add m3ta.profiles option (list of profiles) - Add m3ta.context option (desktop|server|null) - Add mutual exclusion assertion - Update m3-ares and m3-atlas as examples" ``` --- ## Phase 3: Migrate Existing Configuration ### Task 3: Migrate home/features to new Structure **Files:** - Modify: Multiple files in `home/features/` (move content, update paths) - [ ] **Step 1: Map existing features to new structure** | Old Location | New Location | Notes | |--------------|--------------|-------| | `home/features/cli/nushell.nix` | `home/base/shell/nushell.nix` | ✓ Done in Task 1 | | `home/features/cli/starship.nix` | `home/base/shell/starship.nix` | ✓ Done in Task 1 | | `home/features/cli/fzf.nix` | `home/base/cli-tools/fzf.nix` | ✓ Done in Task 1 | | `home/features/cli/zellij.nix` | `home/base/cli-tools/zellij.nix` | ✓ Done in Task 1 | | `home/features/cli/nitch.nix` | `home/base/cli-tools/nitch.nix` | ✓ Done in Task 1 | | `home/features/cli/television.nix` | `home/base/cli-tools/television.nix` | ✓ Done in Task 1 | | `home/features/cli/secrets.nix` | `home/base/secrets/secrets.nix` | ✓ Done in Task 1 | | `home/features/coding/opencode.nix` | Reference via `m3ta-nixpkgs` | Update import | | `home/features/coding/pi.nix` | Reference via `m3ta-nixpkgs` | Update import | | `home/features/desktop/hyprland.nix` | `home/desktop/wm/hyprland.nix` | ✓ Done in Task 1 | | `home/features/desktop/wayland.nix` | `home/desktop/wm/wayland.nix` | ✓ Done in Task 1 | | `home/features/desktop/rofi.nix` | `home/desktop/wm/rofi.nix` | ✓ Done in Task 1 | | `home/features/desktop/obsidian.nix` | `home/desktop/apps/obsidian.nix` | ✓ Done in Task 1 | | `home/features/desktop/office.nix` | `home/desktop/apps/office.nix` | ✓ Done in Task 1 | | `home/features/desktop/webapps.nix` | `home/desktop/apps/webapps.nix` | ✓ Done in Task 1 | | `home/features/desktop/crypto.nix` | `home/desktop/apps/crypto.nix` | ✓ Done in Task 1 | | `home/features/desktop/fonts.nix` | `home/desktop/theme/fonts.nix` | ✓ Done in Task 1 | | `home/features/desktop/theme.nix` | `home/desktop/theme/theme.nix` | ✓ Done in Task 1 | | `home/features/desktop/wallpapers.nix` | `home/desktop/theme/wallpapers.nix` | ✓ Done in Task 1 | | `home/features/desktop/media.nix` | `home/profiles/media/*.nix` | Split into modules | | `home/features/desktop/gaming.nix` | `home/profiles/gaming/*.nix` | Split into modules | - [ ] **Step 2: Archive old structure** ```bash # After migration, archive old features/ git mv home/features home/features.old ``` - [ ] **Step 3: Verify all configurations are imported** ```bash # Check that all features are accessible in new structure nix flake check home-manager dry-activate ``` - [ ] **Step 4: Commit Phase 3** ```bash git add -A git commit -m "chore: migrate features to profile structure - Move all cli features to base/shell and base/cli-tools - Move desktop features to desktop/* subdirectories - Split media into individual profile modules - Split gaming into individual profile modules - Archive old features/ directory" ``` --- ## Phase 4: Test and Validate ### Task 4: Test Profile Combinations **Files:** - Test: Manual testing on m3-ares (Desktop) - Test: Manual testing on m3-atlas (Server) - [ ] **Step 1: Test m3-ares (Desktop with all profiles)** ```bash # Build and test on m3-ares nixos-rebuild dry-build --flake .#m3-ares home-manager dry-activate --flake .#m3tam3re@m3-ares ``` Expected: Loads base + coding + desktop + gaming + media - [ ] **Step 2: Test m3-atlas (Server with coding only)** ```bash # Build and test on m3-atlas nixos-rebuild dry-build --flake .#m3-atlas home-manager dry-activate --flake .#m3tam3re@m3-atlas ``` Expected: Loads base + coding + server (no desktop modules) - [ ] **Step 3: Test assertion (should fail)** ```nix # This SHOULD fail - desktop and server together m3ta.context = "desktop"; m3ta.profiles = [ "coding" ]; # Nix should throw assertion error ``` - [ ] **Step 4: Commit Phase 4** ```bash git commit -m "test: validate profile combinations on all hosts - m3-ares: base + coding + desktop + gaming + media ✓ - m3-atlas: base + coding + server ✓ - Constraint assertion working ✓" ``` --- ## Phase 5: Cleanup ### Task 5: Remove Old Structure **Files:** - Delete: `home/features.old/` (after verification) - [ ] **Step 1: Verify no broken imports** ```bash # Search for any references to old paths grep -r "home/features" --include="*.nix" ``` Expected: No results - [ ] **Step 2: Delete old directory** ```bash git rm -rf home/features.old ``` - [ ] **Step 3: Final format and check** ```bash nix fmt nix flake check ``` - [ ] **Step 4: Final commit** ```bash git commit -m "chore: remove old features directory Cleanup complete. New structure: - home/base/ (always loaded) - home/coding/ (profile-independent) - home/profiles/ (gaming, media) - home/desktop/ (context=desktop) - home/server/ (context=server)" ``` --- ## Summary | Phase | Tasks | Description | |-------|-------|-------------| | 1 | 1 | Create new directory structure | | 2 | 2 | Implement profile system with constraints | | 3 | 3 | Migrate existing features | | 4 | 4 | Test profile combinations | | 5 | 5 | Remove old structure | **Total:** 5 tasks, ~22 steps **Expected Duration:** 2-4 hours (depending on migration complexity) --- ## Migration Notes 1. **NeoVim Config**: Already in nixpkgs, reference via `inputs.m3ta-nixpkgs.packages.neovim-config` 2. **Agent-System**: Already in nixpkgs, reference via `inputs.m3ta-nixpkgs.homeModules.coding.agents` 3. **Zed Remote**: Desktop-only feature, works via SSH. No server-side installation needed. 4. **Fish Shell**: Removed from base (Nushell is primary). Can be added as optional profile if needed. 5. **Feature Flags**: Old `features.*.enable` options → New profile lists `m3ta.profiles = [ "gaming" "media" ]`