Install ct from its flake, with its config, a tmux menu on prefix T and a user service for the web UI. Also keep Claude Code transcripts for ten years instead of 30 days, since threads are meant to be revisited.
122 lines
3.4 KiB
Nix
122 lines
3.4 KiB
Nix
{
|
|
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" ];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|