{ inputs, pkgs, lib, config, ... }: let enabled = config.mod.ai.enable; ct = inputs.ct.packages.${pkgs.stdenv.hostPlatform.system}.default; ctConfig = builtins.toJSON { addr = "127.0.0.1:7777"; open = "split"; defaultProfile = "personal"; profiles = { work = { configDir = "/home/alex/.claude-work"; tmuxSession = "w"; paths = [ "/home/alex/code/work" ]; }; personal = { configDir = "/home/alex/.claude-personal"; tmuxSession = "p"; }; }; }; # Shared statusline: show the logged-in account email. statusLine = { type = "command"; command = "jq -r '.oauthAccount.emailAddress' \"$CLAUDE_CONFIG_DIR/.claude.json\""; }; # PostToolUse hook: echoes a JSON payload that injects a comment-policy # reminder as additional context after every Write/Edit. commentPolicyPayload = builtins.toJSON { suppressOutput = true; hookSpecificOutput = { hookEventName = "PostToolUse"; additionalContext = "Comment policy: default to ZERO code comments. Review what you just wrote and delete any comment that narrates the change, restates the code, states the obvious, is tangential, or explains design/why rationale -- put that reasoning in your chat reply instead, never in the code. Never use em dashes or en dashes anywhere in file content; use a plain ASCII hyphen or reword."; }; }; settings = builtins.toJSON { inherit statusLine; theme = "dark"; editorMode = "vim"; cleanupPeriodDays = 3650; attribution = { commit = ""; pr = ""; }; hooks = { PostToolUse = [ { matcher = "Write|Edit"; hooks = [ { type = "command"; command = "echo ${lib.escapeShellArg commentPolicyPayload}"; } ]; } ]; }; }; in { options = { mod.ai = { enable = lib.mkEnableOption "enable ai module"; }; }; config = lib.mkIf enabled { home-manager.users.alex = { home.packages = [ pkgs.claude-code ct ]; programs.zsh.shellAliases = { claude = "pclaude"; wclaude = "CLAUDE_CONFIG_DIR=$HOME/.claude-work command claude"; pclaude = "CLAUDE_CONFIG_DIR=$HOME/.claude-personal command claude"; }; home.file.".claude-work/settings.json".text = settings; home.file.".claude-personal/settings.json".text = settings; xdg.configFile."ct/config.json".text = ctConfig; programs.tmux.extraConfig = lib.mkAfter '' bind-key T display-menu -T "ct" \ "New thread (full context)" t 'display-popup -EE -w 80 -h 10 -T " new thread " "ct thread --pane #{pane_id}"' \ "New thread (pick turns)" p 'display-popup -EE -w 90% -h 90% -T " pick turns " "ct thread --pick --pane #{pane_id}"' \ "" \ "Browse threads" b 'display-popup -EE -w 90% -h 90% -T " threads " "ct --pane #{pane_id}"' \ "Open in browser" w 'run-shell -b "ct web --pane #{pane_id}"' ''; systemd.user.services.ct-web = { Unit = { Description = "ct web UI"; }; Service = { Type = "simple"; ExecStart = "${lib.getExe ct} serve"; Environment = "TMUX_TMPDIR=%t"; Restart = "on-failure"; RestartSec = 5; }; Install = { WantedBy = [ "default.target" ]; }; }; }; }; }