From cd807b550fb5f2cc791b90f3b6d8dab074f733eb Mon Sep 17 00:00:00 2001 From: Alexander Heldt Date: Tue, 27 Oct 2026 14:23:57 +0100 Subject: [PATCH] pinwheel: Add `ct` for side threads in Claude Code sessions 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. --- flake.lock | 22 ++++++++++++ flake.nix | 6 ++++ hosts/pinwheel/modules/ai/default.nix | 49 +++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/flake.lock b/flake.lock index e47542b..88fb2bf 100644 --- a/flake.lock +++ b/flake.lock @@ -56,6 +56,27 @@ "type": "github" } }, + "ct": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1793028894, + "narHash": "sha256-V0LaVoOrYJIaXO57+0U/i+X8lmLpVNHMuyzT/Uv5YuE=", + "ref": "main", + "rev": "277bab546659c448c4a90fa10d553d1ed83864ef", + "revCount": 3, + "type": "git", + "url": "file:///home/alex/code/own/ct" + }, + "original": { + "ref": "main", + "type": "git", + "url": "file:///home/alex/code/own/ct" + } + }, "dagbok": { "inputs": { "nixpkgs": [ @@ -915,6 +936,7 @@ "root": { "inputs": { "agenix": "agenix", + "ct": "ct", "dagbok": "dagbok", "disko": "disko", "emacs-overlay": "emacs-overlay", diff --git a/flake.nix b/flake.nix index dbc847f..b60c9d4 100644 --- a/flake.nix +++ b/flake.nix @@ -116,6 +116,12 @@ # url = "git+file:///home/alex/code/own/dagbok?ref=main"; inputs.nixpkgs.follows = "nixpkgs"; }; + + ct = { + url = "git+file:///home/alex/code/own/ct?ref=main"; + # url = "git+ssh://gitea@git.ppp.pm:1122/alex/ct.git?ref=main"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = diff --git a/hosts/pinwheel/modules/ai/default.nix b/hosts/pinwheel/modules/ai/default.nix index 5d9e6f9..1458115 100644 --- a/hosts/pinwheel/modules/ai/default.nix +++ b/hosts/pinwheel/modules/ai/default.nix @@ -1,4 +1,5 @@ { + inputs, pkgs, lib, config, @@ -7,6 +8,25 @@ 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"; @@ -27,6 +47,7 @@ let inherit statusLine; theme = "dark"; editorMode = "vim"; + cleanupPeriodDays = 3650; attribution = { commit = ""; pr = ""; @@ -57,6 +78,7 @@ in home-manager.users.alex = { home.packages = [ pkgs.claude-code + ct ]; programs.zsh.shellAliases = { @@ -67,6 +89,33 @@ in 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" ]; + }; + }; }; }; }