From 2756faadc254fd23f4ce49145b83f4e07bfd1c5c Mon Sep 17 00:00:00 2001 From: yangjingping Date: Tue, 7 Jul 2026 17:51:31 +0800 Subject: [PATCH 1/8] Personalize dotfiles for local Mac --- AGENTS.md | 4 ++-- README.md | 21 +++++++++------------ configuration.nix | 4 ++-- flake.nix | 2 +- home.nix | 13 +++---------- home/AGENTS.md | 23 ++++++++++------------- 6 files changed, 27 insertions(+), 40 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b45e563..3d631f8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,5 +2,5 @@ Deliberate decisions in this repo - do NOT silently revert them: -- `homebrew.onActivation.cleanup = "zap"` in `configuration.nix` is intentional. It forces the good habit of declaring every Homebrew package in the Nix config instead of installing things ad-hoc, which keeps the machine reproducible. Do not soften it to `uninstall` or `none`. Users are warned about its effect in README.md; this note is for anyone tempted to change the setting itself. -- Never commit `.no-mistakes/` validation evidence to this public repo. `.no-mistakes/` is gitignored; if a validation pipeline stages evidence into a branch, drop it before merging. \ No newline at end of file +- `homebrew.onActivation.cleanup = "none"` in `configuration.nix` is intentional for first adoption on an existing Mac. Do not change it to `zap` until every Homebrew package and cask that should be kept has been declared in `configuration.nix`. +- Never commit `.no-mistakes/` validation evidence to this public repo. `.no-mistakes/` is gitignored; if a validation pipeline stages evidence into a branch, drop it before merging. diff --git a/README.md b/README.md index 928c0e4..874ab87 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Running the switch builds: - Shell (zsh, aliases, starship prompt) - Editor (Neovim config) - Terminal (WezTerm config) -- Agent configs (Claude, Codex, opencode all share one AGENTS.md) +- Claude settings, without replacing existing local agent instruction files ## Prerequisites @@ -84,8 +84,8 @@ No separate build-and-copy step. This repo is mine. If you clone it, review these before you run `bootstrap.sh`: -- **Username**: run `./bootstrap.sh` (it detects your macOS username and offers to set it) OR change the single `user = "kunchen"` line in `flake.nix`. - Everything else (`configuration.nix`, `home.nix`, home directory paths) is threaded from that one variable. +- **Username**: this copy is configured for `user = "yangjingping"` in `flake.nix`. + The home directory is explicitly set to `/Users/bytedance` in `configuration.nix` and `home.nix`, because this Mac's short username and home directory name differ. - **Host label** `"mac"`, in three places: `flake.nix` (the `darwinConfigurations."mac"` name), `rebuild.sh:5` (the `#mac` at the end of the flake reference), and `bootstrap.sh`'s first-switch command (also `#mac`). All three have to match. - **CPU architecture**, `hostPlatform` in `configuration.nix` (see Prerequisites above). @@ -104,10 +104,9 @@ programs.git = { }; ``` -**Homebrew cleanup warning:** `configuration.nix` sets `homebrew.onActivation.cleanup = "zap"`. -That means every time you switch, Homebrew removes any package or cask on your machine that isn't listed in the `brews` and `casks` arrays in `configuration.nix`. -If you already have Homebrew stuff installed that isn't in that list, the first switch will uninstall it. -Read through `brews` and `casks` before you run `bootstrap.sh` or `rebuild.sh` for the first time, and add anything you want to keep. +**Homebrew cleanup warning:** this copy starts with `homebrew.onActivation.cleanup = "none"`. +That keeps existing Homebrew packages and casks on the first switch, which is safer on a Mac that already has software installed. +After everything you want to keep is listed in the `brews` and `casks` arrays in `configuration.nix`, you can choose whether to tighten this later. **About `herdr`:** it's in the `brews` list. It's a real public Homebrew formula (`brew info herdr` finds it in homebrew-core, no tap needed), so it will install fine. @@ -115,10 +114,8 @@ If you don't use it, just remove it from `brews` in your copy. **Heads-up:** -- `home/AGENTS.md` is my personal agent policy, and `home.nix` installs it for Claude, Codex, and opencode. - If you clone this repo, you'd silently inherit my agent instructions - edit or delete `home/AGENTS.md` if you don't want that. -- The `cc` and `co` shell aliases in `home.nix` are high-agency shortcuts: `claude --dangerously-skip-permissions` and `codex --full-auto`. - They're convenient for me, but know what they do before you use them. +- `home/AGENTS.md` is kept as an optional template only. This copy does not install it over local Claude, Codex, or opencode instruction files. +- The `cc` and `co` shell aliases in `home.nix` are conservative shortcuts for `claude` and `codex`. ## Repo tour @@ -128,7 +125,7 @@ If you don't use it, just remove it from `brews` in your copy. - `home.nix` - user-level config: shell, packages, prompt, and the symlinks described below. - `rebuild.sh` - re-applies the config after the first switch. Run this every time you make a change. -- `home/` - the actual config files that get symlinked into place (Neovim, WezTerm, herdr, Claude settings, the shared `AGENTS.md`). +- `home/` - the actual config files that get symlinked into place (Neovim, WezTerm, herdr, Claude settings). `home/AGENTS.md` is an optional template and is not installed automatically. ## How the symlinks work diff --git a/configuration.nix b/configuration.nix index 74baa39..ae194ef 100644 --- a/configuration.nix +++ b/configuration.nix @@ -9,7 +9,7 @@ system.primaryUser = user; users.users.${user} = { - home = "/Users/${user}"; + home = "/Users/bytedance"; }; system.stateVersion = 6; system.defaults = { @@ -31,7 +31,7 @@ }; homebrew = { enable = true; - onActivation.cleanup = "zap"; # remove anything not listed here + onActivation.cleanup = "none"; # first switch: keep existing Homebrew installs onActivation.autoUpdate = true; onActivation.extraFlags = [ "--force" ]; brews = [ diff --git a/flake.nix b/flake.nix index 96b6b8d..7573f55 100644 --- a/flake.nix +++ b/flake.nix @@ -18,7 +18,7 @@ let # The one username line to change if this isn't your machine. # bootstrap.sh offers to rewrite this for you if your macOS username differs. - user = "kunchen"; + user = "yangjingping"; in { darwinConfigurations."mac" = nix-darwin.lib.darwinSystem { diff --git a/home.nix b/home.nix index 365a1cb..8d42ab7 100644 --- a/home.nix +++ b/home.nix @@ -6,7 +6,7 @@ in { home.username = user; - home.homeDirectory = "/Users/${user}"; + home.homeDirectory = "/Users/bytedance"; home.stateVersion = "24.11"; home.packages = with pkgs; [ # cli i use constantly @@ -35,8 +35,8 @@ in push = "git push"; pull = "git pull"; m = "git switch main"; - cc = "claude --dangerously-skip-permissions"; - co = "codex --full-auto"; + cc = "claude"; + co = "codex"; }; }; @@ -62,11 +62,4 @@ in config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.config/herdr"; home.file.".claude/settings.json".source = config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.claude/settings.json"; - - home.file.".claude/CLAUDE.md".source = - config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/AGENTS.md"; - home.file.".codex/AGENTS.md".source = - config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/AGENTS.md"; - home.file.".config/opencode/AGENTS.md".source = - config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/AGENTS.md"; } diff --git a/home/AGENTS.md b/home/AGENTS.md index f9145ba..aa272f7 100644 --- a/home/AGENTS.md +++ b/home/AGENTS.md @@ -1,15 +1,12 @@ -# global agent instructions - -- Never use the em dash "—". Use plain dash "-" instead -- When writing commit messages, NEVER auto-add your agent name as co-author -- Never manually modify CHANGELOG.md files or any files that are marked as auto-generated -- When making technical decisions, do not give much weight to development cost. - Instead, prefer quality, simplicity, robustness, scalability, and long term maintainability. -- When doing bug fixes, always start with reproducing the bug in an E2E setting as closely aligned with how an end user would experience it as possible. - This makes sure you find the real problem so your fix will actually solve it. -- When end-to-end testing a product, be picky about the UI you see and be obsessed with pixel perfection. - If something clearly looks off, even if it is not directly related to what you are doing, try to get it fixed along the way. -- Apply that same high standard to engineering excellence: lint, test failures, and test flakiness. - If you see one, even if it is not caused by what you are working on right now, still get it fixed. +# Global agent instructions +- Use Chinese for user-facing replies by default. +- Do not use em dashes. Use plain hyphens instead. +- When writing commit messages, never auto-add your agent name as co-author. +- Never manually modify CHANGELOG.md files or any files marked as auto-generated. +- Protect existing user changes. Do not reset, stash, overwrite, or delete unrelated work unless explicitly asked. +- Keep changes surgical. Match the existing style and touch only the files needed for the task. +- Prefer simple, robust, maintainable solutions over shortcuts chosen only to reduce development effort. +- When fixing bugs, reproduce the issue first in a setting close to how the user experiences it. +- Verify meaningful changes with focused tests, lint, type checks, or a clear manual check when automated tests are unavailable. From 011c435d433f5f1f433a97810949b063942d6292 Mon Sep 17 00:00:00 2001 From: yangjingping Date: Tue, 7 Jul 2026 19:07:26 +0800 Subject: [PATCH 2/8] Fix local activation settings --- README.md | 9 +++++---- configuration.nix | 1 + flake.nix | 3 ++- home.nix | 20 +++++++++++++++++--- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 874ab87..c02ad57 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Running the switch builds: - Shell (zsh, aliases, starship prompt) - Editor (Neovim config) - Terminal (WezTerm config) -- Claude settings, without replacing existing local agent instruction files +- Dotfile symlinks for Neovim, WezTerm, and herdr ## Prerequisites @@ -84,8 +84,8 @@ No separate build-and-copy step. This repo is mine. If you clone it, review these before you run `bootstrap.sh`: -- **Username**: this copy is configured for `user = "yangjingping"` in `flake.nix`. - The home directory is explicitly set to `/Users/bytedance` in `configuration.nix` and `home.nix`, because this Mac's short username and home directory name differ. +- **Username**: this copy is configured for `user = "bytedance"` in `flake.nix`. + The home directory is explicitly set to `/Users/bytedance` in `configuration.nix` and `home.nix`. - **Host label** `"mac"`, in three places: `flake.nix` (the `darwinConfigurations."mac"` name), `rebuild.sh:5` (the `#mac` at the end of the flake reference), and `bootstrap.sh`'s first-switch command (also `#mac`). All three have to match. - **CPU architecture**, `hostPlatform` in `configuration.nix` (see Prerequisites above). @@ -115,6 +115,7 @@ If you don't use it, just remove it from `brews` in your copy. **Heads-up:** - `home/AGENTS.md` is kept as an optional template only. This copy does not install it over local Claude, Codex, or opencode instruction files. +- `home/.claude/settings.json` is kept in the repo as an optional template only. This copy does not install it over local Claude settings. - The `cc` and `co` shell aliases in `home.nix` are conservative shortcuts for `claude` and `codex`. ## Repo tour @@ -125,7 +126,7 @@ If you don't use it, just remove it from `brews` in your copy. - `home.nix` - user-level config: shell, packages, prompt, and the symlinks described below. - `rebuild.sh` - re-applies the config after the first switch. Run this every time you make a change. -- `home/` - the actual config files that get symlinked into place (Neovim, WezTerm, herdr, Claude settings). `home/AGENTS.md` is an optional template and is not installed automatically. +- `home/` - the actual config files that get symlinked into place (Neovim, WezTerm, herdr). `home/AGENTS.md` and `home/.claude/settings.json` are optional templates and are not installed automatically. ## How the symlinks work diff --git a/configuration.nix b/configuration.nix index ae194ef..17f342e 100644 --- a/configuration.nix +++ b/configuration.nix @@ -27,6 +27,7 @@ }; nix-homebrew = { enable = true; + autoMigrate = true; inherit user; }; homebrew = { diff --git a/flake.nix b/flake.nix index 7573f55..16ef865 100644 --- a/flake.nix +++ b/flake.nix @@ -18,7 +18,7 @@ let # The one username line to change if this isn't your machine. # bootstrap.sh offers to rewrite this for you if your macOS username differs. - user = "yangjingping"; + user = "bytedance"; in { darwinConfigurations."mac" = nix-darwin.lib.darwinSystem { @@ -30,6 +30,7 @@ { home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; + home-manager.backupFileExtension = "before-nix"; home-manager.extraSpecialArgs = { inherit user; }; home-manager.users.${user} = import ./home.nix; } diff --git a/home.nix b/home.nix index 8d42ab7..6bcecc1 100644 --- a/home.nix +++ b/home.nix @@ -20,7 +20,23 @@ in nerd-fonts.hack ]; fonts.fontconfig.enable = true; - home.sessionVariables.EDITOR = "nvim"; + home.sessionPath = [ + "${config.home.homeDirectory}/.npm-global/bin" + "${config.home.homeDirectory}/.local/bin" + "${config.home.homeDirectory}/go/bin" + "${config.home.homeDirectory}/flutter/bin" + "${config.home.homeDirectory}/.pub-cache/bin" + "${config.home.homeDirectory}/.larklink/bin" + "${config.home.homeDirectory}/.bun/bin" + "/usr/local/go/bin" + "/opt/homebrew/bin" + ]; + home.sessionVariables = { + EDITOR = "nvim"; + GOPATH = "${config.home.homeDirectory}/go"; + GOROOT = "/usr/local/go"; + BUN_INSTALL = "${config.home.homeDirectory}/.bun"; + }; programs.zsh = { enable = true; @@ -60,6 +76,4 @@ in config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.config/nvim"; home.file.".config/herdr".source = config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.config/herdr"; - home.file.".claude/settings.json".source = - config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.claude/settings.json"; } From d434addb73824e8a18c621372f28fcc62a51bde0 Mon Sep 17 00:00:00 2001 From: yangjingping Date: Tue, 7 Jul 2026 19:29:49 +0800 Subject: [PATCH 3/8] Stop forcing dark mode --- configuration.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/configuration.nix b/configuration.nix index 17f342e..210ff12 100644 --- a/configuration.nix +++ b/configuration.nix @@ -14,7 +14,6 @@ system.stateVersion = 6; system.defaults = { NSGlobalDomain = { - AppleInterfaceStyle = "Dark"; KeyRepeat = 2; # fast key repeat InitialKeyRepeat = 15; # short delay before repeat _HIHideMenuBar = true; # auto-hide the menu bar From 3fdd8ac47d19429c5b2493514fc043840182585d Mon Sep 17 00:00:00 2001 From: yangjingping Date: Tue, 7 Jul 2026 19:54:06 +0800 Subject: [PATCH 4/8] Persist local macOS UI defaults --- configuration.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configuration.nix b/configuration.nix index 210ff12..e149a97 100644 --- a/configuration.nix +++ b/configuration.nix @@ -18,12 +18,20 @@ InitialKeyRepeat = 15; # short delay before repeat _HIHideMenuBar = true; # auto-hide the menu bar AppleShowAllExtensions = true; + "com.apple.mouse.tapBehavior" = 1; # tap to click }; dock.autohide = true; finder.FXPreferredViewStyle = "Nlsv"; # list view by default finder.CreateDesktop = false; # clean desktop trackpad.Clicking = true; # tap to click }; + system.activationScripts.postActivation.text = '' + # Keep local UI choices that nix-darwin does not fully model as first-class defaults. + launchctl asuser "$(id -u -- ${user})" sudo --user=${user} -- defaults delete -g AppleInterfaceStyle || true + launchctl asuser "$(id -u -- ${user})" sudo --user=${user} -- defaults -currentHost write -g com.apple.mouse.tapBehavior -int 1 + killall -qu ${user} cfprefsd || true + killall -qu ${user} SystemUIServer || true + ''; nix-homebrew = { enable = true; autoMigrate = true; From 62f1acc902fa8a16dcf0dcda0bb68be8f8f631f6 Mon Sep 17 00:00:00 2001 From: yangjingping Date: Tue, 7 Jul 2026 19:58:27 +0800 Subject: [PATCH 5/8] Silence dark mode cleanup during activation --- configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration.nix b/configuration.nix index e149a97..e2dc6d3 100644 --- a/configuration.nix +++ b/configuration.nix @@ -27,7 +27,7 @@ }; system.activationScripts.postActivation.text = '' # Keep local UI choices that nix-darwin does not fully model as first-class defaults. - launchctl asuser "$(id -u -- ${user})" sudo --user=${user} -- defaults delete -g AppleInterfaceStyle || true + launchctl asuser "$(id -u -- ${user})" sudo --user=${user} -- defaults delete -g AppleInterfaceStyle >/dev/null 2>&1 || true launchctl asuser "$(id -u -- ${user})" sudo --user=${user} -- defaults -currentHost write -g com.apple.mouse.tapBehavior -int 1 killall -qu ${user} cfprefsd || true killall -qu ${user} SystemUIServer || true From 6df0cc58118e835a22fc5131bb0777fa6a79c26f Mon Sep 17 00:00:00 2001 From: yangjingping Date: Tue, 7 Jul 2026 20:10:07 +0800 Subject: [PATCH 6/8] Harden lazy.nvim bootstrap --- home/.config/nvim/lua/plugin.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/home/.config/nvim/lua/plugin.lua b/home/.config/nvim/lua/plugin.lua index e528a1c..2c0a597 100644 --- a/home/.config/nvim/lua/plugin.lua +++ b/home/.config/nvim/lua/plugin.lua @@ -1,8 +1,14 @@ local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' -if not vim.uv.fs_stat(lazypath) then - vim.fn.system({ 'git', 'clone', '--filter=blob:none', +local lazy_init = lazypath .. '/lua/lazy/init.lua' + +if not vim.uv.fs_stat(lazy_init) then + vim.fn.delete(lazypath, 'rf') + local output = vim.fn.system({ 'git', 'clone', '--filter=blob:none', 'https://github.com/folke/lazy.nvim.git', '--branch=stable', lazypath }) + if vim.v.shell_error ~= 0 then + error('Failed to install lazy.nvim:\n' .. output) + end end + vim.opt.rtp:prepend(lazypath) require('lazy').setup('plugins') -- load every file in lua/plugins/ - From 01f5e1a2a6a9f24209d0b322a90d95294f4381d0 Mon Sep 17 00:00:00 2001 From: yangjingping Date: Tue, 7 Jul 2026 20:59:21 +0800 Subject: [PATCH 7/8] Fix WezTerm Hack font loading --- configuration.nix | 6 +++++- home.nix | 4 ++-- home/.config/wezterm/wezterm.lua | 5 ++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/configuration.nix b/configuration.nix index e2dc6d3..4bdac15 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,4 +1,4 @@ -{ user, ... }: +{ pkgs, user, ... }: { # Determinate already manages the Nix daemon, so nix-darwin shouldn't. @@ -7,6 +7,10 @@ nixpkgs.config.allowUnfree = true; nixpkgs.hostPlatform = "aarch64-darwin"; # use x86_64-darwin for Intel CPU + fonts.packages = with pkgs; [ + nerd-fonts.hack + ]; + system.primaryUser = user; users.users.${user} = { home = "/Users/bytedance"; diff --git a/home.nix b/home.nix index 6bcecc1..54cb8a6 100644 --- a/home.nix +++ b/home.nix @@ -16,8 +16,6 @@ in jq # json on the command line lazygit neovim - # the font everything renders in - nerd-fonts.hack ]; fonts.fontconfig.enable = true; home.sessionPath = [ @@ -76,4 +74,6 @@ in config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.config/nvim"; home.file.".config/herdr".source = config.lib.file.mkOutOfStoreSymlink "${dotfiles}/home/.config/herdr"; + home.file.".local/share/fonts/hack-nerd-font".source = + "${pkgs.nerd-fonts.hack}/share/fonts/truetype/NerdFonts/Hack"; } diff --git a/home/.config/wezterm/wezterm.lua b/home/.config/wezterm/wezterm.lua index 8bb9ce8..efc9b21 100644 --- a/home/.config/wezterm/wezterm.lua +++ b/home/.config/wezterm/wezterm.lua @@ -3,7 +3,10 @@ local wezterm = require("wezterm") local config = wezterm.config_builder() config.color_scheme = "rose-pine-moon" -config.font = wezterm.font("Hack Nerd Font") +config.font_dirs = { + os.getenv("HOME") .. "/.local/share/fonts/hack-nerd-font", +} +config.font = wezterm.font("Hack Nerd Font Mono") config.font_size = 15.0 config.window_background_opacity = 0.8 config.macos_window_background_blur = 50 From 2a0ffdef4cf8460d9240c84e3ad4d19151e98dfd Mon Sep 17 00:00:00 2001 From: yangjingping Date: Wed, 8 Jul 2026 10:50:31 +0800 Subject: [PATCH 8/8] Add WezTerm split pane shortcuts --- home/.config/wezterm/wezterm.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/home/.config/wezterm/wezterm.lua b/home/.config/wezterm/wezterm.lua index efc9b21..6c0288f 100644 --- a/home/.config/wezterm/wezterm.lua +++ b/home/.config/wezterm/wezterm.lua @@ -1,4 +1,5 @@ local wezterm = require("wezterm") +local act = wezterm.action local config = wezterm.config_builder() @@ -12,5 +13,17 @@ config.window_background_opacity = 0.8 config.macos_window_background_blur = 50 config.hide_tab_bar_if_only_one_tab = true config.window_decorations = "RESIZE" +config.keys = { + { + key = "d", + mods = "CMD", + action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }), + }, + { + key = "d", + mods = "CMD|SHIFT", + action = act.SplitVertical({ domain = "CurrentPaneDomain" }), + }, +} return config