From f3649945cb26bdb0e9a0e5752008d610bb6234ea Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Thu, 11 Jun 2026 01:45:40 -0700 Subject: [PATCH] git-sync: sync ~/.codex history repo across machines Mirror the claude-history setup for Codex: ~/.codex is now a git repo (github.com/colonelpanic8/codex-history) holding session rollouts and history.jsonl from all machines, synced by git-sync-rs in watch mode. - Generalize the nixos host gate (claudeHistoryHosts -> aiHistoryHosts) and add codex-history alongside claude-history on both NixOS and darwin. - Drop the old HM-managed dotfiles/codex/.gitignore; the repo ships its own real .gitignore (git won't read a symlinked one). - Shield dotfiles/codex/* in the root .gitignore so nested codex history can't be committed into dotfiles on darwin (where ~/.codex resolves into dotfiles/codex). Co-Authored-By: Claude Opus 4.8 --- .gitignore | 8 ++++++++ dotfiles/codex/.gitignore | 8 -------- nix-darwin/home/git-sync.nix | 8 ++++++++ nixos/git-sync.nix | 22 +++++++++++++++------- 4 files changed, 31 insertions(+), 15 deletions(-) delete mode 100644 dotfiles/codex/.gitignore diff --git a/.gitignore b/.gitignore index 32ff3550..0f1e3624 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,11 @@ gotools !/dotfiles/claude/settings.json !/dotfiles/claude/settings.local.json !/dotfiles/claude/settings.local.json.example + +# Same story for Codex: ~/.codex resolves into dotfiles/codex on nix-darwin, +# so the codex-history repo and live Codex state nest inside this worktree. +# Allowlist only the HM-managed config. +/dotfiles/codex/* +!/dotfiles/codex/AGENTS.md +!/dotfiles/codex/config.toml +!/dotfiles/codex/skills diff --git a/dotfiles/codex/.gitignore b/dotfiles/codex/.gitignore deleted file mode 100644 index 2fe5f524..00000000 --- a/dotfiles/codex/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -* -!.gitignore -!AGENTS.md -!config.toml -!skills - -# Legacy generated/local Codex state under this repo stays ignored. Active -# host-local Codex fragments now live under ~/.codex. diff --git a/nix-darwin/home/git-sync.nix b/nix-darwin/home/git-sync.nix index 47cb6496..a0405c95 100644 --- a/nix-darwin/home/git-sync.nix +++ b/nix-darwin/home/git-sync.nix @@ -11,6 +11,7 @@ orgPath = "${config.home.homeDirectory}/org"; passwordStorePath = "${config.home.homeDirectory}/.password-store"; claudePath = "${config.home.homeDirectory}/.claude"; + codexPath = "${config.home.homeDirectory}/.codex"; in { services.git-sync = { enable = true; @@ -30,6 +31,11 @@ in { uri = "git@github.com:colonelpanic8/claude-history.git"; interval = 600; }; + codex-history = { + path = codexPath; + uri = "git@github.com:colonelpanic8/codex-history.git"; + interval = 600; + }; }; }; @@ -43,5 +49,7 @@ in { # untracked session files and throttle event-driven syncs. git-sync-claude-history.config.ProgramArguments = lib.mkForce ["${gitSyncPackage}/bin/git-sync-rs" "-d" claudePath "watch" "--new-files" "true" "--min-interval" "300"]; + git-sync-codex-history.config.ProgramArguments = + lib.mkForce ["${gitSyncPackage}/bin/git-sync-rs" "-d" codexPath "watch" "--new-files" "true" "--min-interval" "300"]; }; } diff --git a/nixos/git-sync.nix b/nixos/git-sync.nix index 30715ab9..a90eb0bd 100644 --- a/nixos/git-sync.nix +++ b/nixos/git-sync.nix @@ -5,11 +5,11 @@ ... }: let gitSyncServicePath = lib.makeBinPath [pkgs.coreutils pkgs.git pkgs.openssh]; - # ~/.claude history sync is being rolled out machine-by-machine; each new - # machine needs its existing history merged into the repo first (see - # github.com/colonelpanic8/claude-history). - claudeHistoryHosts = ["ryzen-shine" "railbird-sf" "jay-lenovo" "strixi-minaj"]; - syncClaudeHistory = builtins.elem config.networking.hostName claudeHistoryHosts; + # AI chat-history sync (Claude Code + Codex) is rolled out machine-by-machine; + # each new machine needs its existing history merged into the repo first (see + # github.com/colonelpanic8/claude-history and .../codex-history). + aiHistoryHosts = ["ryzen-shine" "railbird-sf" "jay-lenovo" "strixi-minaj"]; + syncAiHistory = builtins.elem config.networking.hostName aiHistoryHosts; mkGitSyncTrayOverrides = icon: { Service = { Environment = lib.mkMerge [ @@ -40,12 +40,17 @@ in { uri = "git@github.com:IvanMalison/.password-store.git"; }; } - // lib.optionalAttrs syncClaudeHistory { + // lib.optionalAttrs syncAiHistory { claude-history = { path = config.home.homeDirectory + "/.claude"; uri = "git@github.com:colonelpanic8/claude-history.git"; interval = 600; }; + codex-history = { + path = config.home.homeDirectory + "/.codex"; + uri = "git@github.com:colonelpanic8/codex-history.git"; + interval = 600; + }; }; }; @@ -55,13 +60,16 @@ in { lib.nameValuePair "git-sync-${name}" (mkGitSyncTrayOverrides (repoIcons.${name} or "git"))) config.services.git-sync.repositories) - (lib.optionalAttrs syncClaudeHistory { + (lib.optionalAttrs syncAiHistory { # Live sessions append to their transcript on every message; sync # untracked session files and throttle event-driven syncs so an # active session doesn't push once per append. git-sync-claude-history.Service.ExecStart = lib.mkForce "${pkgs.git-sync-rs}/bin/git-sync-rs watch --new-files true --min-interval 300"; + git-sync-codex-history.Service.ExecStart = + lib.mkForce + "${pkgs.git-sync-rs}/bin/git-sync-rs watch --new-files true --min-interval 300"; }) ]; };